Add the clipboard tray where users manage their photo clipboard.
Appearing on search and album pages, the tray is where you can remove items from your clipboard without having to click on its checkbox -- that photo card may not even be on the current page.
This commit is contained in:
parent
0b5f736574
commit
443d93ce18
7 changed files with 143 additions and 15 deletions
|
@ -54,6 +54,7 @@ If you are interested in helping, please raise an issue before making any pull r
|
|||
- Use browser localstorage to act as a clipboard for holding photos, so that you can select them on one tab and move them into an album on another, etc.
|
||||
- Perhaps instead of actually deleting objects, they should just have a `deleted` flag, to make easy restoration possible. Also consider regrouping the children of restored Groupables if those children haven't already been reassigned somewhere else.
|
||||
- Add a new table to store permanent history of add/remove of tags on photos, so that accidents or trolling can be reversed.
|
||||
- Currently, the photo clipboard only stores IDs and therefore when we construct the clipboard tray elements we cannot provide more rich information like filename, the user is only presented with a list of IDs which they probably don't care about. Should the localstorage cache some other more user-friendly information?
|
||||
|
||||
### 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.
|
||||
|
|
|
@ -284,3 +284,30 @@ is hovered over.
|
|||
{
|
||||
background-color: #faa;
|
||||
}
|
||||
|
||||
#clipboard_tray
|
||||
{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
position: fixed;
|
||||
right: 8px;
|
||||
bottom: 8px;
|
||||
z-index: 10;
|
||||
|
||||
max-height: 80%;
|
||||
min-width: 150px;
|
||||
padding: 2px;
|
||||
|
||||
background-color: #ffffd4;
|
||||
}
|
||||
#clipboard_tray_expandbutton
|
||||
{
|
||||
flex: 1 0 auto;
|
||||
width: 100%;
|
||||
}
|
||||
#clipboard_tray_body
|
||||
{
|
||||
width: 300px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
|
|
@ -292,6 +292,14 @@ function create_album_and_follow(parent)
|
|||
post(url, data, receive_callback);
|
||||
}
|
||||
|
||||
function delete_all_children(element)
|
||||
{
|
||||
while (element.firstChild)
|
||||
{
|
||||
element.removeChild(element.firstChild);
|
||||
}
|
||||
}
|
||||
|
||||
function entry_with_history_hook(box, button)
|
||||
{
|
||||
//console.log(event.keyCode);
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
var photo_clipboard = new Set();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//--LOAD-SAVE-----------------------------------------------------------------//
|
||||
function load_photo_clipboard(event)
|
||||
{
|
||||
console.log("Loading photo clipboard");
|
||||
|
@ -15,9 +17,6 @@ function load_photo_clipboard(event)
|
|||
{
|
||||
photo_clipboard = new Set(JSON.parse(stored));
|
||||
}
|
||||
|
||||
var photo_divs = Array.from(document.getElementsByClassName("photo_card"));
|
||||
photo_divs.forEach(apply_check);
|
||||
return photo_clipboard;
|
||||
}
|
||||
|
||||
|
@ -26,12 +25,16 @@ function save_photo_clipboard()
|
|||
console.log("Saving photo clipboard");
|
||||
var serialized = JSON.stringify(Array.from(photo_clipboard));
|
||||
localStorage.setItem("photo_clipboard", serialized);
|
||||
on_storage();
|
||||
}
|
||||
|
||||
function apply_check(photo_div)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//*-CARD MANAGEMENT-----------------------------------------------------------//
|
||||
function apply_check(photo_card)
|
||||
{
|
||||
var checkbox = photo_div.getElementsByClassName("photo_card_selector_checkbox")[0];
|
||||
if (photo_clipboard.has(photo_div.dataset.id))
|
||||
var checkbox = photo_card.getElementsByClassName("photo_card_selector_checkbox")[0];
|
||||
if (photo_clipboard.has(photo_card.dataset.id))
|
||||
{
|
||||
checkbox.checked = true;
|
||||
}
|
||||
|
@ -41,6 +44,12 @@ function apply_check(photo_div)
|
|||
}
|
||||
}
|
||||
|
||||
function update_checked_cards()
|
||||
{
|
||||
var photo_divs = Array.from(document.getElementsByClassName("photo_card"));
|
||||
photo_divs.forEach(apply_check);
|
||||
}
|
||||
|
||||
var previous_photo_select;
|
||||
function on_photo_select(event)
|
||||
{
|
||||
|
@ -95,9 +104,80 @@ function on_photo_select(event)
|
|||
save_photo_clipboard();
|
||||
}
|
||||
|
||||
function onpageload()
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//--TRAY MANAGEMENT-----------------------------------------------------------//
|
||||
function toggle_clipboard_tray_collapsed()
|
||||
{
|
||||
window.addEventListener("storage", load_photo_clipboard, false);
|
||||
load_photo_clipboard();
|
||||
var tray_body = document.getElementById("clipboard_tray_body");
|
||||
if (tray_body.classList.contains("hidden") && photo_clipboard.size > 0)
|
||||
{
|
||||
tray_body.classList.remove("hidden");
|
||||
update_clipboard_tray();
|
||||
}
|
||||
else
|
||||
{
|
||||
tray_body.classList.add("hidden");
|
||||
}
|
||||
}
|
||||
document.addEventListener("DOMContentLoaded", onpageload);
|
||||
|
||||
function on_tray_delete_button(event)
|
||||
{
|
||||
var clipboard_line = event.target.parentElement;
|
||||
var photo_id = clipboard_line.dataset.id;
|
||||
photo_clipboard.delete(photo_id);
|
||||
if (photo_clipboard.size == 0)
|
||||
{
|
||||
toggle_clipboard_tray_collapsed();
|
||||
}
|
||||
save_photo_clipboard();
|
||||
}
|
||||
|
||||
function update_clipboard_tray()
|
||||
{
|
||||
var tray_button = document.getElementById("clipboard_tray_expandbutton");
|
||||
if (tray_button !== null)
|
||||
{
|
||||
tray_button.innerText = "Clipboard: " + photo_clipboard.size + " items";
|
||||
}
|
||||
|
||||
var tray_body = document.getElementById("clipboard_tray_body");
|
||||
if (!clipboard_tray.classList.contains("hidden"))
|
||||
{
|
||||
delete_all_children(tray_body);
|
||||
var photo_ids = Array.from(photo_clipboard);
|
||||
photo_ids.sort();
|
||||
for (var i = 0; i < photo_ids.length; i += 1)
|
||||
{
|
||||
var clipboard_line = document.createElement("div");
|
||||
clipboard_line.classList.add("clipboard_tray_line");
|
||||
clipboard_line.dataset.id = photo_ids[i];
|
||||
|
||||
var clipboard_line_delete_button = document.createElement("button");
|
||||
clipboard_line_delete_button.classList.add("remove_tag_button_perm");
|
||||
clipboard_line_delete_button.onclick = on_tray_delete_button;
|
||||
|
||||
var clipboard_line_link = document.createElement("a");
|
||||
clipboard_line_link.target = "_blank";
|
||||
clipboard_line_link.href = "/photo/" + photo_ids[i];
|
||||
clipboard_line_link.innerText = photo_ids[i];
|
||||
|
||||
clipboard_line.appendChild(clipboard_line_delete_button);
|
||||
clipboard_line.appendChild(clipboard_line_link);
|
||||
tray_body.appendChild(clipboard_line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function on_storage()
|
||||
{
|
||||
load_photo_clipboard();
|
||||
update_checked_cards();
|
||||
update_clipboard_tray();
|
||||
}
|
||||
function on_pageload()
|
||||
{
|
||||
window.addEventListener("storage", on_storage, false);
|
||||
on_storage();
|
||||
}
|
||||
document.addEventListener("DOMContentLoaded", on_pageload);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
<head>
|
||||
{% import "photo_card.html" as photo_card %}
|
||||
{% import "header.html" as header %}
|
||||
{% import "clipboard_tray.html" as clipboard_tray %}
|
||||
<title>Album {{album.display_name}}</title>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
|
@ -115,6 +116,7 @@ p
|
|||
{% endif %}
|
||||
{% endif %}
|
||||
</p>
|
||||
{{clipboard_tray.clipboard_tray()}}
|
||||
</div>
|
||||
</body>
|
||||
|
||||
|
|
11
frontends/etiquette_flask/templates/clipboard_tray.html
Normal file
11
frontends/etiquette_flask/templates/clipboard_tray.html
Normal file
|
@ -0,0 +1,11 @@
|
|||
{% macro clipboard_tray() %}
|
||||
<div id="clipboard_tray">
|
||||
<button
|
||||
id="clipboard_tray_expandbutton"
|
||||
class="green_button"
|
||||
onclick="toggle_clipboard_tray_collapsed()"
|
||||
>Clipboard: 0 items</button>
|
||||
<div id="clipboard_tray_body" class="hidden">
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
|
@ -4,6 +4,7 @@
|
|||
{% import "photo_card.html" as photo_card %}
|
||||
{% import "header.html" as header %}
|
||||
{% import "tag_object.html" as tag_object %}
|
||||
{% import "clipboard_tray.html" as clipboard_tray %}
|
||||
<title>Search</title>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
|
@ -37,11 +38,6 @@ form
|
|||
|
||||
color: #fff;
|
||||
}
|
||||
#left, #right
|
||||
{
|
||||
/* Keep the prev-next buttons from scraping the floor */
|
||||
/*padding-bottom: 30px;*/
|
||||
}
|
||||
#left
|
||||
{
|
||||
flex: 1;
|
||||
|
@ -60,6 +56,8 @@ form
|
|||
flex: 1;
|
||||
|
||||
padding: 8px;
|
||||
/* Keep the prev-next buttons from scraping the floor */
|
||||
padding-bottom: 30px;
|
||||
|
||||
width: auto;
|
||||
}
|
||||
|
@ -296,6 +294,7 @@ form
|
|||
|
||||
{{prev_next_buttons()}}
|
||||
</div>
|
||||
{{clipboard_tray.clipboard_tray()}}
|
||||
</div>
|
||||
</body>
|
||||
|
||||
|
|
Loading…
Reference in a new issue