Ethan Dalool
da5c1ee008
Tags on photos can now have timestamps, so that if you are tagging a video or audio you can reference a specific moment with your tag. In the interface, this means the tag is clickable and seeks to that point in the media. For the user interface, I am finding I need to move away from jinja for the object cards because it is too much hassle to keep the code for jinja-based cards for static rendering and the js-based cards for dynamic rendering in sync. Rather than write the same cards in two languages I can dump the JSON into the script and render the cards on load. Which makes the static HTML worse but that's what the JSON API is for anyway.
203 lines
5.7 KiB
HTML
203 lines
5.7 KiB
HTML
<!DOCTYPE html>
|
|
<html class="theme_{{theme}}">
|
|
<head>
|
|
{% import "header.html" as header %}
|
|
{% import "cards.html" as cards %}
|
|
<title>Bookmarks</title>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
|
<link rel="icon" href="/favicon.png" type="image/png"/>
|
|
<link rel="stylesheet" href="/static/css/common.css">
|
|
<link rel="stylesheet" href="/static/css/etiquette.css">
|
|
<link rel="stylesheet" href="/static/css/cards.css">
|
|
<script src="/static/js/common.js"></script>
|
|
<script src="/static/js/api.js"></script>
|
|
<script src="/static/js/cards.js"></script>
|
|
<script src="/static/js/http.js"></script>
|
|
<script src="/static/js/spinners.js"></script>
|
|
<script src="/static/js/editor.js"></script>
|
|
|
|
<style>
|
|
#bookmark_panel,
|
|
#bookmark_list
|
|
{
|
|
display: flex;
|
|
flex: 0 0 auto;
|
|
flex-direction: column;
|
|
}
|
|
.bookmark_card h2 .editor_input
|
|
{
|
|
font-size: inherit;
|
|
font-weight: inherit;
|
|
}
|
|
</style>
|
|
</head>
|
|
|
|
<body>
|
|
{{header.make_header(session=request.session)}}
|
|
<div id="content_body">
|
|
<div id="bookmark_panel" class="panel">
|
|
<h1><span class="dynamic_bookmark_count">{{bookmarks|length}}</span> Bookmarks</h1>
|
|
<div id="bookmark_list">
|
|
</div>
|
|
|
|
<div id="new_bookmark_card" class="bookmark_card">
|
|
<input id="new_bookmark_title" type="text" placeholder="title (optional)">
|
|
<input id="new_bookmark_url" type="text" placeholder="url">
|
|
<div class="bookmark_toolbox">
|
|
<button id="new_bookmark_button" class="green_button" onclick="return create_bookmark_form();">Create</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
|
|
<script type="text/javascript">
|
|
const BOOKMARKS = [
|
|
{% for bookmark in bookmarks %}
|
|
{{bookmark.jsonify()|tojson|safe}},
|
|
{% endfor %}
|
|
];
|
|
|
|
function create_bookmark_form()
|
|
{
|
|
const url = document.getElementById("new_bookmark_url").value.trim();
|
|
const title = document.getElementById("new_bookmark_title").value.trim();
|
|
if (!url)
|
|
{
|
|
return;
|
|
}
|
|
return api.bookmarks.create(url, title, create_bookmark_callback);
|
|
}
|
|
|
|
function create_bookmark_callback(response)
|
|
{
|
|
if (! (response.meta.status === 200 && response.meta.json_ok))
|
|
{
|
|
alert(JSON.stringify(response));
|
|
return;
|
|
}
|
|
const bookmark = response.data;
|
|
const bookmark_card = cards.bookmarks.create({
|
|
bookmark: bookmark,
|
|
add_author: true,
|
|
add_delete_button: true,
|
|
add_url_element: true,
|
|
});
|
|
create_editor(bookmark_card);
|
|
|
|
const bookmark_panel = document.getElementById("bookmark_panel");
|
|
const new_bookmark_card = document.getElementById("new_bookmark_card");
|
|
bookmark_panel.insertBefore(bookmark_card, new_bookmark_card);
|
|
|
|
document.getElementById("new_bookmark_url").value = "";
|
|
document.getElementById("new_bookmark_title").value = "";
|
|
}
|
|
|
|
function delete_bookmark_form(event)
|
|
{
|
|
const card = event.target.closest(".bookmark_card");
|
|
const id = card.dataset.id;
|
|
function callback(response)
|
|
{
|
|
if (response.meta.status !== 200)
|
|
{
|
|
alert(JSON.stringify(response));
|
|
return;
|
|
}
|
|
card.parentElement.removeChild(card);
|
|
}
|
|
api.bookmarks.delete(id, callback);
|
|
}
|
|
|
|
ed_on_open = undefined;
|
|
|
|
function ed_on_save(ed)
|
|
{
|
|
function callback(response)
|
|
{
|
|
ed.hide_spinner();
|
|
|
|
if (response.meta.status != 200)
|
|
{
|
|
ed.show_error("Status: " + response.meta.status);
|
|
return;
|
|
}
|
|
|
|
// The data coming back from the server will have been normalized.
|
|
ed.elements["title"].edit.value = response.data.title;
|
|
|
|
ed.save();
|
|
|
|
ed.elements["title"].display.href = response.data.url;
|
|
ed.elements["title"].display.title = response.data.url;
|
|
ed.elements["url"].display.href = response.data.url;
|
|
}
|
|
|
|
ed.elements["url"].edit.value = ed.elements["url"].edit.value.trim();
|
|
if (! ed.elements["url"].edit.value)
|
|
{
|
|
return;
|
|
}
|
|
|
|
const bookmark_id = ed.misc_data["bookmark_id"];
|
|
const title = ed.elements["title"].edit.value;
|
|
const url = ed.elements["url"].edit.value;
|
|
|
|
ed.show_spinner();
|
|
api.bookmarks.edit(bookmark_id, title, url, callback);
|
|
}
|
|
|
|
ed_on_cancel = undefined;
|
|
|
|
function create_editor(bookmark_card)
|
|
{
|
|
const ed_elements = [
|
|
{
|
|
"id": "title",
|
|
"element": bookmark_card.getElementsByClassName("bookmark_title")[0],
|
|
"placeholder": "title (optional)",
|
|
"empty_text": bookmark_card.dataset.id,
|
|
"autofocus": true,
|
|
},
|
|
{
|
|
"id": "url",
|
|
"element": bookmark_card.getElementsByClassName("bookmark_url")[0],
|
|
"placeholder": "url",
|
|
},
|
|
];
|
|
ed = new editor.Editor(ed_elements, ed_on_open, ed_on_save, ed_on_cancel);
|
|
ed.misc_data["bookmark_id"] = bookmark_card.dataset.id;
|
|
}
|
|
|
|
function create_editors()
|
|
{
|
|
const cards = document.getElementsByClassName("bookmark_card");
|
|
for (const card of cards)
|
|
{
|
|
if (card.id == "new_bookmark_card")
|
|
{
|
|
continue;
|
|
}
|
|
create_editor(card);
|
|
}
|
|
}
|
|
|
|
function on_pageload()
|
|
{
|
|
common.update_dynamic_elements("dynamic_bookmark_count", BOOKMARKS.length);
|
|
for (const bookmark of BOOKMARKS)
|
|
{
|
|
const bookmark_card = cards.bookmarks.create({
|
|
bookmark: bookmark,
|
|
add_author: true,
|
|
add_delete_button: true,
|
|
add_url_element: true,
|
|
});
|
|
document.getElementById("bookmark_list").append(bookmark_card);
|
|
}
|
|
create_editors();
|
|
}
|
|
document.addEventListener("DOMContentLoaded", on_pageload);
|
|
</script>
|
|
</html>
|