Add new page /clipboard, with full photo cards.
This commit is contained in:
parent
ef5bbf5fc3
commit
91d445a877
7 changed files with 154 additions and 1 deletions
|
@ -79,7 +79,6 @@ If you are interested in helping, please raise an issue before making any pull r
|
|||
- Currently, the Jinja templates are having a tangling influence on the backend objects, because Jinja cannot import my other modules like bytestring, but it can access the methods of the objects I pass into the template. As a result, the objects have excess helper methods. Consider making them into Jinja filters instead. Which is also kind of ugly but will move that pollution out of the backend at least.
|
||||
- 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?
|
||||
- Improve transaction rollbacking. I'm not satisfied with the @transaction decorator because sometimes I want to use exceptions as control flow without them rolling things back. Context managers are good but it's a matter of how abstracted they should be.
|
||||
|
||||
### To do list: User permissions
|
||||
|
|
|
@ -115,6 +115,40 @@ def post_photo_refresh_metadata(photo_id):
|
|||
|
||||
return jsonify.make_json_response({})
|
||||
|
||||
# Clipboard ########################################################################################
|
||||
|
||||
@site.route('/clipboard')
|
||||
@session_manager.give_token
|
||||
def get_clipboard_page():
|
||||
return flask.render_template('clipboard.html')
|
||||
|
||||
@site.route('/photo_cards', methods=['POST'])
|
||||
def get_photo_cards():
|
||||
photo_ids = request.form.get('photo_ids', None)
|
||||
if photo_ids is None:
|
||||
return jsonify.make_json_response({})
|
||||
|
||||
photo_ids = etiquette.helpers.comma_space_split(photo_ids)
|
||||
photos = [common.P_photo(photo_id, response_type='html') for photo_id in photo_ids]
|
||||
|
||||
# Photo filenames are prevented from having colons, so using it as a split
|
||||
# delimiter should be safe.
|
||||
template = '''
|
||||
{% import "photo_card.html" as photo_card %}
|
||||
{% for photo in photos %}
|
||||
{{photo.id}}:
|
||||
{{photo_card.create_photo_card(photo)}}
|
||||
:SPLITME:
|
||||
{% endfor %}
|
||||
'''
|
||||
html = flask.render_template_string(template, photos=photos)
|
||||
divs = [div.strip() for div in html.split(':SPLITME:')]
|
||||
divs = [div for div in divs if div]
|
||||
divs = [div.split(':', 1) for div in divs]
|
||||
divs = {photo_id.strip(): photo_card.strip() for (photo_id, photo_card) in divs}
|
||||
response = jsonify.make_json_response(divs)
|
||||
return response
|
||||
|
||||
# Search ###########################################################################################
|
||||
|
||||
def get_search_core():
|
||||
|
|
|
@ -305,3 +305,8 @@ is hovered over.
|
|||
width: 300px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
#clipboard_tray_toolbox
|
||||
{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
|
|
@ -356,3 +356,10 @@ function entry_with_history_hook(box, button)
|
|||
box.entry_history_pos = -1;
|
||||
}
|
||||
}
|
||||
|
||||
function html_to_element(html)
|
||||
{
|
||||
var template = document.createElement("template");
|
||||
template.innerHTML = html;
|
||||
return template.content.firstChild;
|
||||
}
|
||||
|
|
|
@ -173,6 +173,12 @@ function update_clipboard_tray()
|
|||
Update the clipboard's title bar to the correct number of items and rebuild
|
||||
the rows if the tray is open.
|
||||
*/
|
||||
var clipboard_tray = document.getElementById("clipboard_tray");
|
||||
if (clipboard_tray === null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var tray_button = document.getElementById("clipboard_tray_expandbutton");
|
||||
if (tray_button !== null)
|
||||
{
|
||||
|
|
101
frontends/etiquette_flask/templates/clipboard.html
Normal file
101
frontends/etiquette_flask/templates/clipboard.html
Normal file
|
@ -0,0 +1,101 @@
|
|||
<!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/common.css">
|
||||
<script src="/static/common.js"></script>
|
||||
<script src="/static/photoclipboard.js"></script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
</head>
|
||||
|
||||
|
||||
<body>
|
||||
{{header.make_header(session=session)}}
|
||||
<div id="content_body">
|
||||
<div id="photo_card_holder">
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
|
||||
<script type="text/javascript">
|
||||
var divs = {};
|
||||
var needed = new Set();
|
||||
var holder = document.getElementById("photo_card_holder");
|
||||
|
||||
function recalculate_needed()
|
||||
{
|
||||
needed = new Set();
|
||||
photo_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.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 = "/photo_cards";
|
||||
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 = html_to_element(response[photo_id]);
|
||||
divs[photo_id] = photo_div;
|
||||
needed.delete(photo_id)
|
||||
holder.appendChild(photo_div);
|
||||
}
|
||||
apply_check_all();
|
||||
}
|
||||
post(url, data, callback);
|
||||
}
|
||||
|
||||
function myhook()
|
||||
{
|
||||
recalculate_needed();
|
||||
request_more_divs();
|
||||
refresh_divs();
|
||||
}
|
||||
|
||||
on_clipboard_load_hooks.push(myhook);
|
||||
</script>
|
||||
</html>
|
|
@ -7,6 +7,7 @@
|
|||
>Clipboard: 0 items</button>
|
||||
<div id="clipboard_tray_body" class="hidden">
|
||||
<div id="clipboard_tray_toolbox">
|
||||
<a target="_blank" href="/clipboard">Full clipboard</a>
|
||||
</div>
|
||||
<div id="clipboard_tray_lines">
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue