Add /clipboard UI for mass-tagging.
This commit is contained in:
		
							parent
							
								
									4b79308119
								
							
						
					
					
						commit
						5a1d259780
					
				
					 4 changed files with 132 additions and 10 deletions
				
			
		|  | @ -84,6 +84,7 @@ If you are interested in helping, please raise an issue before making any pull r | ||||||
| - Fix album size cache when photo reload metadata and generally improve that validation. | - Fix album size cache when photo reload metadata and generally improve that validation. | ||||||
| - Better bookmark url validation. | - Better bookmark url validation. | ||||||
| - Create a textbox which gives autocomplete tag names. | - Create a textbox which gives autocomplete tag names. | ||||||
|  | - Clean up the textbox hooks & handlers and make them more like stackable decorators (entry with history + bind box to button). | ||||||
| 
 | 
 | ||||||
| ### To do list: User permissions | ### To do list: User permissions | ||||||
| Here are some thoughts about the kinds of features that need to exist within the permission system. I don't know how I'll actually manage it just yet. Possibly a `permissions` table in the database with `user_id | permission` where `permission` is some reliably-formatted string. | Here are some thoughts about the kinds of features that need to exist within the permission system. I don't know how I'll actually manage it just yet. Possibly a `permissions` table in the database with `user_id | permission` where `permission` is some reliably-formatted string. | ||||||
|  |  | ||||||
|  | @ -82,7 +82,7 @@ def post_photo_add_remove_tag_core(photo_ids, tagname, add_or_remove): | ||||||
|             photo.remove_tag(tag, commit=False) |             photo.remove_tag(tag, commit=False) | ||||||
|     common.P.commit() |     common.P.commit() | ||||||
| 
 | 
 | ||||||
|     response = {'tagname': tag.name} |     response = {'action': add_or_remove, 'tagname': tag.name} | ||||||
|     return jsonify.make_json_response(response) |     return jsonify.make_json_response(response) | ||||||
| 
 | 
 | ||||||
| @site.route('/photo/<photo_id>/add_tag', methods=['POST']) | @site.route('/photo/<photo_id>/add_tag', methods=['POST']) | ||||||
|  |  | ||||||
|  | @ -11,21 +11,80 @@ | ||||||
|     <script src="/static/photoclipboard.js"></script> |     <script src="/static/photoclipboard.js"></script> | ||||||
| 
 | 
 | ||||||
| <style> | <style> | ||||||
| #content_body | body | ||||||
| { | { | ||||||
|     flex-direction: column; |     display: grid; | ||||||
|  |     grid-template-rows: auto 1fr; | ||||||
|  |     grid-template-columns: 1fr 300px; | ||||||
|  |     grid-template-areas: | ||||||
|  |         "header header" | ||||||
|  |         "left right"; | ||||||
|  | } | ||||||
|  | #header | ||||||
|  | { | ||||||
|  |     grid-area: header; | ||||||
|  | } | ||||||
|  | #left | ||||||
|  | { | ||||||
|  |     word-break: break-word; | ||||||
|  |     grid-area: left; | ||||||
|  | } | ||||||
|  | #right | ||||||
|  | { | ||||||
|  |     position: fixed; | ||||||
|  |     right: 8px; | ||||||
|  |     bottom: 8px; | ||||||
|  |     top: 30px; | ||||||
|  |     width: 300px; | ||||||
|  |     grid-area: right; | ||||||
|  | 
 | ||||||
|  |     display: grid; | ||||||
|  |     grid-template-rows: 1fr 1fr 1fr; | ||||||
|  |     grid-template-areas: | ||||||
|  |         "add_tag_area" | ||||||
|  |         "remove_tag_area" | ||||||
|  |         "message_area"; | ||||||
|  | 
 | ||||||
|  |     background-color: rgba(0, 0, 0, 0.1); | ||||||
|  | } | ||||||
|  | #add_tag_area | ||||||
|  | { | ||||||
|  |     grid-area: add_tag_area; | ||||||
|  |     margin: auto; | ||||||
|  | } | ||||||
|  | #remove_tag_area | ||||||
|  | { | ||||||
|  |     grid-area: remove_tag_area; | ||||||
|  |     margin: auto; | ||||||
|  | } | ||||||
|  | #message_area | ||||||
|  | { | ||||||
|  |     grid-area: message_area; | ||||||
|  |     margin: 8px; | ||||||
| } | } | ||||||
| </style> | </style> | ||||||
| </head> | </head> | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| <body> | <body> | ||||||
|     {{header.make_header(session=session)}} | {{header.make_header(session=session)}} | ||||||
|     <div id="content_body"> | <div id="left"> | ||||||
|         <span>The clipboard contains <span class="clipboard_count">0</span> items</span> |     <span>The clipboard contains <span class="clipboard_count">0</span> items</span> | ||||||
|         <div id="photo_card_holder"> |     <div id="photo_card_holder"> | ||||||
|         </div> |  | ||||||
|     </div> |     </div> | ||||||
|  | </div> | ||||||
|  | <div id="right"> | ||||||
|  |     <div id="add_tag_area"> | ||||||
|  |         <input type="text" id="add_tag_textbox"> | ||||||
|  |         <button class="add_tag_button green_button" id="add_tag_button" onclick="submit_add_tag(add_remove_callback);">add</button> | ||||||
|  |     </div> | ||||||
|  |     <div id="remove_tag_area"> | ||||||
|  |         <input type="text" id="remove_tag_textbox"> | ||||||
|  |         <button class="red_button" id="remove_tag_button" onclick="submit_remove_tag(add_remove_callback);">Remove</button> | ||||||
|  |     </div> | ||||||
|  |     <div id="message_area"> | ||||||
|  |     </div> | ||||||
|  | </div> | ||||||
| </body> | </body> | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -34,6 +93,13 @@ var divs = {}; | ||||||
| var needed = new Set(); | var needed = new Set(); | ||||||
| var holder = document.getElementById("photo_card_holder"); | 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.onkeydown = function(){entry_with_history_hook(add_box, add_button)}; | ||||||
|  | var remove_box = document.getElementById("remove_tag_textbox"); | ||||||
|  | var remove_button = document.getElementById("remove_tag_button"); | ||||||
|  | remove_box.onkeydown = function(){entry_with_history_hook(remove_box, remove_button)}; | ||||||
|  | 
 | ||||||
| function recalculate_needed() | function recalculate_needed() | ||||||
| { | { | ||||||
|     needed = new Set(); |     needed = new Set(); | ||||||
|  | @ -103,5 +169,60 @@ function myhook() | ||||||
| 
 | 
 | ||||||
| on_clipboard_load_hooks.push(myhook); | on_clipboard_load_hooks.push(myhook); | ||||||
| on_clipboard_save_hooks.push(myhook); | on_clipboard_save_hooks.push(myhook); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | function submit_add_tag(callback) | ||||||
|  | { | ||||||
|  |     var box = document.getElementById("add_tag_textbox"); | ||||||
|  |     var tagname = box.value.trim(); | ||||||
|  |     if (! tagname) | ||||||
|  |         {return} | ||||||
|  | 
 | ||||||
|  |     box.value = ""; | ||||||
|  |     return submit_add_remove_tag("add", tagname, callback); | ||||||
|  | } | ||||||
|  | function submit_remove_tag(callback) | ||||||
|  | { | ||||||
|  |     var box = document.getElementById("remove_tag_textbox"); | ||||||
|  |     var tagname = box.value.trim(); | ||||||
|  |     if (! tagname) | ||||||
|  |         {return} | ||||||
|  | 
 | ||||||
|  |     box.value = ""; | ||||||
|  |     return submit_add_remove_tag("remove", tagname, callback); | ||||||
|  | } | ||||||
|  | function submit_add_remove_tag(action, tagname, callback) | ||||||
|  | { | ||||||
|  |     var url = "/batch/photos/" + action + "_tag"; | ||||||
|  |     var data = new FormData(); | ||||||
|  |     var photo_ids = Array.from(photo_clipboard).join(","); | ||||||
|  |     data.append("photo_ids", photo_ids); | ||||||
|  |     data.append("tagname", tagname); | ||||||
|  |     post(url, data, callback); | ||||||
|  | } | ||||||
|  | function add_remove_callback(response) | ||||||
|  | { | ||||||
|  |     response = response["data"]; | ||||||
|  |     var tagname = response["tagname"]; | ||||||
|  |     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;} | ||||||
|  |     } | ||||||
|  |     create_message_bubble(message_area, message_positivity, message_text, 8000); | ||||||
|  | } | ||||||
| </script> | </script> | ||||||
| </html> | </html> | ||||||
|  |  | ||||||
|  | @ -134,8 +134,8 @@ body | ||||||
| </div> | </div> | ||||||
| <div id="right"> | <div id="right"> | ||||||
|     <div id="editor_area"> |     <div id="editor_area"> | ||||||
|     <input type="text" id="add_tag_textbox" autofocus> |         <input type="text" id="add_tag_textbox" autofocus> | ||||||
|     <button class="add_tag_button green_button" id="add_tag_button" onclick="submit_tag(receive_callback);">add</button> |         <button class="add_tag_button green_button" id="add_tag_button" onclick="submit_tag(receive_callback);">add</button> | ||||||
|     </div> |     </div> | ||||||
|     <div id="message_area"> |     <div id="message_area"> | ||||||
|     </div> |     </div> | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue