386 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			386 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
| <!DOCTYPE html5>
 | |
| <html>
 | |
| <head>
 | |
|     {% import "header.html" as header %}
 | |
|     {% import "clipboard_tray.html" as clipboard_tray %}
 | |
|     <title>Clipboard</title>
 | |
|     <meta charset="UTF-8">
 | |
|     <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
 | |
|     <link rel="stylesheet" href="/static/css/common.css">
 | |
|     <link rel="stylesheet" href="/static/css/photo_card.css">
 | |
|     <link rel="stylesheet" href="/static/css/clipboard_tray.css">
 | |
|     {% if theme %}<link rel="stylesheet" href="/static/css/theme_{{theme}}.css">{% endif %}
 | |
|     <script src="/static/js/common.js"></script>
 | |
|     <script src="/static/js/api.js"></script>
 | |
|     <script src="/static/js/hotkeys.js"></script>
 | |
|     <script src="/static/js/photo_clipboard.js"></script>
 | |
|     <script src="/static/js/spinner.js"></script>
 | |
|     <script src="/static/js/tag_autocomplete.js"></script>
 | |
| 
 | |
| <style>
 | |
| #left
 | |
| {
 | |
|     word-break: break-word;
 | |
| }
 | |
| #right
 | |
| {
 | |
|     grid-row-gap: 8px;
 | |
|     grid-template:
 | |
|         "toolbox" auto
 | |
|         "message_area" 1fr
 | |
|         / 1fr;
 | |
| }
 | |
| #toolbox
 | |
| {
 | |
|     display: grid;
 | |
|     grid-auto-rows: min-content;
 | |
|     grid-row-gap: 8px;
 | |
| }
 | |
| #toolbox > *
 | |
| {
 | |
|     display: flex;
 | |
| }
 | |
| #toolbox input
 | |
| {
 | |
|     margin: 0;
 | |
| }
 | |
| #toolbox .spinner_holder
 | |
| {
 | |
|     display: flex;
 | |
|     flex: 1;
 | |
| }
 | |
| #toolbox button
 | |
| {
 | |
|     flex: 1;
 | |
| }
 | |
| #toolbox { grid-area: toolbox; }
 | |
| #message_area { grid-area: message_area; }
 | |
| #add_tag_area input,
 | |
| #remove_tag_area input
 | |
| {
 | |
|     flex: 1;
 | |
| }
 | |
| #add_tag_area button,
 | |
| #remove_tag_area button
 | |
| {
 | |
|     flex: initial;
 | |
| }
 | |
| 
 | |
| @media screen and (max-width: 800px)
 | |
| {
 | |
|     #content_body
 | |
|     {
 | |
|         grid-template:
 | |
|             "left" 1fr
 | |
|             "right" 200px
 | |
|             / 1fr !important;
 | |
|     }
 | |
|     #right
 | |
|     {
 | |
|         top: unset !important;
 | |
|         width: unset !important;
 | |
|         left: 8px;
 | |
|         right: 8px;
 | |
|         bottom: 8px;
 | |
|         height: 200px;
 | |
| 
 | |
|         grid-template:
 | |
|             "toolbox message_area" 1fr
 | |
|             /1fr     minmax(50px, 200px);
 | |
|     }
 | |
| }
 | |
| </style>
 | |
| </head>
 | |
| 
 | |
| 
 | |
| <body>
 | |
| {{header.make_header(session=session)}}
 | |
| <div id="content_body" class="sticky_side_right">
 | |
| <div id="left">
 | |
|     <div class="panel">The clipboard contains <span class="clipboard_count">0</span> items.
 | |
|     <button id="clear_clipboard_button" class="red_button" onclick="photo_clipboard.clear_clipboard()">Clear it.</button>
 | |
|     </div>
 | |
| 
 | |
|     <div id="photo_card_holder">
 | |
|     </div>
 | |
| </div>
 | |
| <div id="right">
 | |
|     <div id="toolbox">
 | |
|         <div id="add_tag_area">
 | |
|             <input type="text" id="add_tag_textbox" list="tag_autocomplete_datalist">
 | |
|             <button class="add_tag_button green_button" id="add_tag_button" onclick="add_tag_form();">Add tag</button>
 | |
|         </div>
 | |
| 
 | |
|         <div id="remove_tag_area">
 | |
|             <input type="text" id="remove_tag_textbox" list="tag_autocomplete_datalist">
 | |
|             <button class="red_button" id="remove_tag_button" onclick="remove_tag_form();">Remove tag</button>
 | |
|         </div>
 | |
| 
 | |
|         <div id="refresh_metadata_area">
 | |
|             <button class="green_button button_with_spinner" id="refresh_metadata_button" data-spinner-delay="500" data-onclick="refresh_metadata_form();">Refresh metadata</button>
 | |
|         </div>
 | |
| 
 | |
|         <div id="searchhidden_area">
 | |
|             <button class="yellow_button" id="set_searchhidden_button" onclick="set_searchhidden_form()">Searchhide</button>
 | |
|             <button class="yellow_button" id="unset_searchhidden_button" onclick="unset_searchhidden_form()">Unhide</button>
 | |
|         </div>
 | |
| 
 | |
|         <div id="download_zip_area">
 | |
|             <button class="yellow_button" id="download_zip_button" onclick="download_zip_form()">Download .zip</button>
 | |
|         </div>
 | |
|     </div>
 | |
| 
 | |
|     <div id="message_area">
 | |
|     </div>
 | |
| </div>
 | |
| </div>
 | |
| </body>
 | |
| 
 | |
| 
 | |
| <script type="text/javascript">
 | |
| var divs = {};
 | |
| var needed = new Set();
 | |
| var holder = document.getElementById("photo_card_holder");
 | |
| 
 | |
| var add_box = document.getElementById("add_tag_textbox");
 | |
| var add_button = document.getElementById("add_tag_button");
 | |
| add_box.addEventListener("keyup", common.entry_with_history_hook);
 | |
| common.bind_box_to_button(add_box, add_button);
 | |
| 
 | |
| var remove_box = document.getElementById("remove_tag_textbox");
 | |
| var remove_button = document.getElementById("remove_tag_button");
 | |
| remove_box.addEventListener("keyup", common.entry_with_history_hook);
 | |
| common.bind_box_to_button(remove_box, remove_button);
 | |
| 
 | |
| function recalculate_needed()
 | |
| {
 | |
|     needed = new Set();
 | |
|     photo_clipboard.clipboard.forEach(function(photo_id)
 | |
|     {
 | |
|         if (!(photo_id in divs))
 | |
|         {
 | |
|             needed.add(photo_id);
 | |
|         }
 | |
|     });
 | |
| }
 | |
| 
 | |
| function refresh_divs()
 | |
| {
 | |
|     for (var photo_id in divs)
 | |
|     {
 | |
|         var photo_div = divs[photo_id];
 | |
|         var should_keep = photo_clipboard.clipboard.has(photo_id);
 | |
|         var on_page = holder.contains(photo_div);
 | |
|         if (on_page && !should_keep)
 | |
|         {
 | |
|             holder.removeChild(photo_div)
 | |
|         }
 | |
|         if (!on_page && should_keep)
 | |
|         {
 | |
|             holder.appendChild(photo_div)
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| function request_more_divs()
 | |
| {
 | |
|     if (needed.size == 0)
 | |
|     {
 | |
|         return;
 | |
|     }
 | |
|     var url = "/batch/photos/photo_card";
 | |
|     var data = new FormData();
 | |
|     var photo_ids = Array.from(needed).join(",");
 | |
|     data.append("photo_ids", photo_ids);
 | |
|     function callback(response)
 | |
|     {
 | |
|         if (response["meta"]["status"] !== 200)
 | |
|         {
 | |
|             return;
 | |
|         }
 | |
|         response = response["data"];
 | |
|         var holder = document.getElementById("photo_card_holder");
 | |
|         for (photo_id in response)
 | |
|         {
 | |
|             photo_div = common.html_to_element(response[photo_id]);
 | |
|             divs[photo_id] = photo_div;
 | |
|             needed.delete(photo_id)
 | |
|             holder.appendChild(photo_div);
 | |
|         }
 | |
|         photo_clipboard.apply_check_all();
 | |
|     }
 | |
|     common.post(url, data, callback);
 | |
| }
 | |
| 
 | |
| function my_clipboard_load_save_hook()
 | |
| {
 | |
|     recalculate_needed();
 | |
|     request_more_divs();
 | |
|     refresh_divs();
 | |
| }
 | |
| 
 | |
| tag_autocomplete.init_datalist();
 | |
| photo_clipboard.on_load_hooks.push(my_clipboard_load_save_hook);
 | |
| photo_clipboard.on_save_hooks.push(my_clipboard_load_save_hook);
 | |
| 
 | |
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | |
| 
 | |
| function add_remove_tag(action, tagname)
 | |
| {
 | |
|     if (photo_clipboard.clipboard.size == 0)
 | |
|         {return;}
 | |
|     var url = "/batch/photos/" + action + "_tag";
 | |
|     var photo_ids = Array.from(photo_clipboard.clipboard).join(",");
 | |
|     var data = new FormData();
 | |
|     data.append("photo_ids", photo_ids);
 | |
|     data.append("tagname", tagname);
 | |
|     common.post(url, data, add_remove_tag_callback);
 | |
| }
 | |
| function add_remove_tag_callback(response)
 | |
| {
 | |
|     response = response["data"];
 | |
|     var tagname = response["tagname"];
 | |
|     var message_area = document.getElementById("message_area");
 | |
|     var message_positivity;
 | |
|     var message_text;
 | |
| 
 | |
|     if ("error_type" in response)
 | |
|     {
 | |
|         message_positivity = "message_negative";
 | |
|         message_text = response["error_message"];
 | |
|     }
 | |
|     else if ("action" in response)
 | |
|     {
 | |
|         var action = response["action"];
 | |
|         message_positivity = "message_positive";
 | |
|         if (action == "add")
 | |
|         {message_text = "Added tag " + tagname;}
 | |
| 
 | |
|         else if (action == "remove")
 | |
|         {message_text = "Removed tag " + tagname;}
 | |
|     }
 | |
|     common.create_message_bubble(message_area, message_positivity, message_text, 8000);
 | |
| }
 | |
| function add_tag_form()
 | |
| {
 | |
|     var box = document.getElementById("add_tag_textbox");
 | |
|     var tagname = box.value.trim();
 | |
|     if (! tagname)
 | |
|         {return}
 | |
| 
 | |
|     box.value = "";
 | |
|     return add_remove_tag("add", tagname);
 | |
| }
 | |
| function remove_tag_form()
 | |
| {
 | |
|     var box = document.getElementById("remove_tag_textbox");
 | |
|     var tagname = box.value.trim();
 | |
|     if (! tagname)
 | |
|         {return}
 | |
| 
 | |
|     box.value = "";
 | |
|     return add_remove_tag("remove", tagname);
 | |
| }
 | |
| 
 | |
| ////////////////////////////////////////////////////////////////////////////////
 | |
| 
 | |
| function download_zip_callback(response)
 | |
| {
 | |
|     var zip_token = response["data"]["zip_token"];
 | |
|     var url = `/batch/photos/download_zip/${zip_token}.zip`;
 | |
|     window.location.href = url;
 | |
| }
 | |
| function download_zip_form()
 | |
| {
 | |
|     if (photo_clipboard.clipboard.size == 0)
 | |
|         {return;}
 | |
| 
 | |
|     var url = "/batch/photos/download_zip";
 | |
|     var photo_ids = Array.from(photo_clipboard.clipboard).join(",");
 | |
|     var data = new FormData();
 | |
|     data.append("photo_ids", photo_ids);
 | |
|     common.post(url, data, download_zip_callback);
 | |
| }
 | |
| 
 | |
| ////////////////////////////////////////////////////////////////////////////////
 | |
| 
 | |
| var refresh_metadata_button = document.getElementById("refresh_metadata_button");
 | |
| 
 | |
| function refresh_metadata_callback(response)
 | |
| {
 | |
|     response = response["data"];
 | |
|     window[refresh_metadata_button.dataset.spinnerCloser]();
 | |
|     if ("error_type" in response)
 | |
|     {
 | |
|         var message_area = document.getElementById("message_area");
 | |
|         var message_positivity = "message_negative";
 | |
|         var message_text = response["error_message"];
 | |
|         common.create_message_bubble(message_area, message_positivity, message_text, 8000);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         common.refresh();
 | |
|     }
 | |
| }
 | |
| 
 | |
| function refresh_metadata_form()
 | |
| {
 | |
|     if (photo_clipboard.clipboard.size == 0)
 | |
|     {
 | |
|         window[refresh_metadata_button.dataset.spinnerCloser]();
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     var url = "/batch/photos/refresh_metadata";
 | |
|     var photo_ids = Array.from(photo_clipboard.clipboard).join(",");
 | |
|     var data = new FormData();
 | |
|     data.append("photo_ids", photo_ids);
 | |
|     common.post(url, data, refresh_metadata_callback);
 | |
| }
 | |
| 
 | |
| ////////////////////////////////////////////////////////////////////////////////
 | |
| 
 | |
| function set_unset_searchhidden_callback(response)
 | |
| {
 | |
|     response = response["data"];
 | |
|     var message_area = document.getElementById("message_area");
 | |
|     var message_positivity;
 | |
|     var message_text;
 | |
|     if ("error_type" in response)
 | |
|     {
 | |
|         message_positivity = "message_negative";
 | |
|         message_text = response["error_message"];
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         message_positivity = "message_positive";
 | |
|         message_text = "Success."
 | |
|     }
 | |
|     common.create_message_bubble(message_area, message_positivity, message_text, 8000);
 | |
| }
 | |
| function set_searchhidden_form()
 | |
| {
 | |
|     if (photo_clipboard.clipboard.size == 0)
 | |
|         {return;}
 | |
| 
 | |
|     var url = "/batch/photos/set_searchhidden";
 | |
|     var data = new FormData();
 | |
|     var photo_ids = Array.from(photo_clipboard.clipboard).join(",");
 | |
| 
 | |
|     data.append("photo_ids", photo_ids);
 | |
|     common.post(url, data, set_unset_searchhidden_callback);
 | |
| }
 | |
| function unset_searchhidden_form()
 | |
| {
 | |
|     if (photo_clipboard.clipboard.size == 0)
 | |
|         {return;}
 | |
| 
 | |
|     var url = "/batch/photos/unset_searchhidden";
 | |
|     var data = new FormData();
 | |
|     var photo_ids = Array.from(photo_clipboard.clipboard).join(",");
 | |
| 
 | |
|     data.append("photo_ids", photo_ids);
 | |
|     common.post(url, data, set_unset_searchhidden_callback);
 | |
| }
 | |
| </script>
 | |
| </html>
 |