Rewrote tags code in annotate (with help from OpenCode)
This commit is contained in:
parent
fefa0a28b6
commit
4a22264d3f
@ -366,8 +366,8 @@ class Work(models.Model):
|
||||
|
||||
def music_tags(self):
|
||||
tags = dict(self.orchestration.as_list())
|
||||
for section in Section.objects.filter(doc__work_id=self.pk):
|
||||
tags.setdefault(section.tag, section.name)
|
||||
# for section in Section.objects.filter(doc__work_id=self.pk):
|
||||
# tags.setdefault(section.tag, section.name)
|
||||
|
||||
return tags.items()
|
||||
|
||||
|
||||
@ -4,9 +4,10 @@ import re
|
||||
GENERAL = """
|
||||
mvmt Movement
|
||||
ex Excerpt
|
||||
sec Section
|
||||
sect Section
|
||||
pce Piece
|
||||
no Number
|
||||
no No.
|
||||
page Page
|
||||
"""
|
||||
|
||||
# taken from https://imslp.org/wiki/IMSLP:Abbreviations_for_MusicTags
|
||||
|
||||
@ -14,42 +14,97 @@
|
||||
|
||||
{% block media %}
|
||||
<style>
|
||||
#unassigned-area {
|
||||
max-width: 200px;
|
||||
}
|
||||
#unassigned-area .tag {
|
||||
cursor: pointer;
|
||||
}
|
||||
#area-left h3 {
|
||||
margin-top: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
.tag-grid {
|
||||
display: flex;
|
||||
margin-bottom: 5px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.grid-column {
|
||||
margin-left: 1em;
|
||||
margin-right: 1em;
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
.grid-page {
|
||||
height: 25px;
|
||||
margin-bottom: 5px;
|
||||
border: 1px solid #999;
|
||||
border-radius: 5px;
|
||||
border: none;
|
||||
border-top: 1px solid #DDD;
|
||||
text-align: center;
|
||||
width: 50px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.grid-page:last-child {
|
||||
border-bottom: 1px solid #DDD;
|
||||
height: 26px;
|
||||
}
|
||||
.grid-page.is-active {
|
||||
background-color: var(--primary);
|
||||
color: white;
|
||||
/*background-color: var(--bulma-link-light);*/
|
||||
color: var(--bulma-link);
|
||||
background-color: #EEE;
|
||||
border-radius: 0px 6px 6px 0px;
|
||||
}
|
||||
.grid-tag {
|
||||
border: 2px solid var(--primary);
|
||||
background-color: rgba(240, 240, 240, 0.5);
|
||||
border-radius: 5px;
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
margin-bottom: 5px;
|
||||
min-width: 200px;
|
||||
background: #fff;
|
||||
border: 1px solid #DDD;
|
||||
border-radius: 0px 4px 4px 0px;
|
||||
border-left: none;
|
||||
padding-left: 0.5em;
|
||||
min-width: 100px;
|
||||
position: absolute;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: start;
|
||||
align-items: top;
|
||||
z-index: 1;
|
||||
margin: 0;
|
||||
box-shadow: 4px 0 6px -4px rgba(0,0,0,0.12);
|
||||
}
|
||||
.grid-tag:hover {
|
||||
z-index: 100 !important;
|
||||
}
|
||||
.tag-handle {
|
||||
position: relative;
|
||||
width: 20px;
|
||||
background-color: var(--bulma-warning-light);
|
||||
margin-left: 10px;
|
||||
cursor: move;
|
||||
}
|
||||
.tag-name {
|
||||
flex: 1;
|
||||
text-align: right;
|
||||
}
|
||||
.tag-handle-resize {
|
||||
position: absolute;
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
bottom: 0px;
|
||||
right: 0px;
|
||||
border-radius: 3px 0px 0px 0px;
|
||||
background-color: var(--bulma-warning);
|
||||
cursor: ns-resize;
|
||||
}
|
||||
|
||||
{% for tag, colour in tag_colours %}
|
||||
.tag-type-{{ tag }} .tag-handle {
|
||||
background-color: var(--bulma-{{ colour }}-light);
|
||||
}
|
||||
.tag-type-{{ tag }} .tag-handle-resize {
|
||||
background-color: var(--bulma-{{ colour }});
|
||||
}
|
||||
{% endfor %}
|
||||
|
||||
#tag-area {
|
||||
min-width: 220px;
|
||||
position: relative;
|
||||
font-size: 9pt;
|
||||
}
|
||||
.instrument {
|
||||
display: list-item !important;
|
||||
@ -64,32 +119,34 @@
|
||||
{% block page %}
|
||||
<h3 class="subtitle"><a href="{% url 'work_detail' collection.pk document.work_id %}">{{ document.work.name }}</a></h3>
|
||||
<div id="annotation-area" class="columns is-centered">
|
||||
<div class="column is-narrow">
|
||||
<div class="column is-narrow" id="area-left">
|
||||
<h3>Page control</h3>
|
||||
<div class="columns">
|
||||
<div class="column is-narrow">
|
||||
<button class="button is-small is-primary" id="prev"><</button>
|
||||
</div>
|
||||
<div class="column">
|
||||
<div class="column has-text-centered">
|
||||
<span id="page-num">-</span> / <span id="page-count">-</span>
|
||||
</div>
|
||||
<div class="column is-narrow">
|
||||
<button class="button is-small is-primary" id="next">></button>
|
||||
</div>
|
||||
</div>
|
||||
<h3>Quick Tags</h3>
|
||||
<ul id="unassigned-area">
|
||||
{% for tag, inst in document.work.music_tags %}
|
||||
<li>
|
||||
<span class="is-clickable" onclick="assignInstrument('{{tag}}', this)")>{{ inst }}</span>
|
||||
|
||||
<span class="is-clickable" onclick="addNumberedInstrument('{{tag}}', this)">...</span>
|
||||
</li>
|
||||
<li class="tag is-warning" onclick="assignTag('{{tag}}', this)">{{ inst }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<a onclick="document.getElementById('add-modal').classList.add('is-active')">Add Tag</a>
|
||||
<h3>Actions</h3>
|
||||
<div>
|
||||
<a class="button is-small is-primary" onclick="showAddModal()">New Tag</a>
|
||||
<button class="button is-small is-primary" onclick="expandEntries()">Expand Tags</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-narrow">
|
||||
<div class="has-text-centered">
|
||||
<div class="box" style="display: inline-block;">
|
||||
<div class="box" style="display: inline-block; padding: 0px;">
|
||||
<canvas id="inline-viewer" style="width: 500px;"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
@ -102,7 +159,6 @@
|
||||
<div class="grid-column" id="tag-area">
|
||||
</div>
|
||||
</div>
|
||||
<button class="button is-primary" style="width: 100%" onclick="expandEntries()">Expand</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@ -111,24 +167,46 @@
|
||||
<div class="modal-background" onclick="closeAddModal()"></div>
|
||||
<div class="modal-card">
|
||||
<header class="modal-card-head">
|
||||
<p class="modal-card-title">Add Instrument</p>
|
||||
<p class="modal-card-title">Add Tag</p>
|
||||
<button class="delete" aria-label="close" onclick="closeAddModal()"></button>
|
||||
</header>
|
||||
<section class="modal-card-body">
|
||||
<div class="field has-addons">
|
||||
<div class="field has-addons is-justify-content-center">
|
||||
<span class="control">
|
||||
<input type="text" class="input" list="instrument-list" id="add-instrument-name"/>
|
||||
<span class="select">
|
||||
<select onChange="changeTagType()" id="tag-type-selection">
|
||||
<option value="inst">Instrument</option>
|
||||
<option value="mvmt">Movement</option>
|
||||
<option value="sect">Section</option>
|
||||
<option value="no">Number</option>
|
||||
<option value="page">Page</option>
|
||||
</select>
|
||||
</span>
|
||||
</span>
|
||||
<span class="control add-tag-option enable-page">
|
||||
<span class="select">
|
||||
<select id="add-tag-page">
|
||||
<option>Left</option>
|
||||
<option>Right</option>
|
||||
</select>
|
||||
</span>
|
||||
</span>
|
||||
<span class="control add-tag-option enable-sect">
|
||||
<input type="text" class="input" id="add-tag-name"/>
|
||||
</span>
|
||||
<span class="control add-tag-option enable-inst">
|
||||
<input type="text" class="input" list="instrument-list" id="add-tag-inst"/>
|
||||
<datalist id="instrument-list">
|
||||
{% for inst in json_data.instruments.values %}
|
||||
<option value="{{inst}}"/>
|
||||
{% endfor %}
|
||||
</datalist>
|
||||
</span>
|
||||
<span class="control">
|
||||
<input type="number" class="input" max="4" min="1" size="3" id="add-instrument-variant"/>
|
||||
<span class="control add-tag-option enable-inst enable-mvmt enable-no">
|
||||
<input type="number" class="input" min="1" size="3" id="add-tag-ordinal"/>
|
||||
</span>
|
||||
<span class="control">
|
||||
<button class="button is-primary" onclick="addInstrument();">Add</button>
|
||||
<button class="button is-primary" onclick="createNewTag();">Add</button>
|
||||
</span>
|
||||
</div>
|
||||
</section>
|
||||
@ -137,6 +215,15 @@
|
||||
|
||||
<p>{{ document.upload.name }}</p>
|
||||
|
||||
<template id="blank-tag">
|
||||
<div class="grid-tag">
|
||||
<span class="tag-name"></span>
|
||||
<div class="tag-handle">
|
||||
<div class="tag-handle-resize"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
@ -166,7 +253,11 @@
|
||||
pageNumPending = null,
|
||||
scale = 1,
|
||||
canvas = document.getElementById('inline-viewer'),
|
||||
ctx = canvas.getContext('2d');
|
||||
ctx = canvas.getContext('2d'),
|
||||
draggedTag = null,
|
||||
dragMode = null,
|
||||
dragOrigStart = null,
|
||||
dragOrigEnd = null;
|
||||
|
||||
/**
|
||||
* Get page info from document, resize canvas accordingly, and render page.
|
||||
@ -251,6 +342,7 @@
|
||||
pdfDoc = pdfDoc_;
|
||||
|
||||
const pageList = document.getElementById('page-list');
|
||||
const tagGrid = document.querySelector('.tag-grid');
|
||||
pageList.innerHTML = '';
|
||||
for (var i=0; i<pdfDoc.numPages; i++) {
|
||||
let page = i+1;
|
||||
@ -264,10 +356,47 @@
|
||||
pageList.appendChild(el);
|
||||
}
|
||||
|
||||
tagGrid.addEventListener('dragover', (e) => {
|
||||
e.preventDefault();
|
||||
e.dataTransfer.dropEffect = 'move';
|
||||
if (draggedTag) {
|
||||
const rect = pageList.getBoundingClientRect();
|
||||
const y = e.clientY - rect.top;
|
||||
const page = Math.min(Math.max(Math.floor(y / 25) + 1, 1), pdfDoc.numPages);
|
||||
if (dragMode === 'resize') {
|
||||
if (page >= parseInt(draggedTag.dataset.start) && page !== parseInt(draggedTag.dataset.end)) {
|
||||
draggedTag.dataset.end = page;
|
||||
updateTag(draggedTag);
|
||||
resolveOverlaps();
|
||||
}
|
||||
} else {
|
||||
const length = dragOrigEnd - dragOrigStart;
|
||||
if (page !== parseInt(draggedTag.dataset.start)) {
|
||||
draggedTag.dataset.start = page;
|
||||
draggedTag.dataset.end = Math.min(page + length, pdfDoc.numPages);
|
||||
updateTag(draggedTag);
|
||||
resolveOverlaps();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
tagGrid.addEventListener('drop', (e) => {
|
||||
e.preventDefault();
|
||||
if (draggedTag) {
|
||||
draggedTag = null;
|
||||
dragMode = null;
|
||||
}
|
||||
resolveOverlaps();
|
||||
});
|
||||
|
||||
document.getElementById('page-count').textContent = pdfDoc.numPages;
|
||||
|
||||
// Initial/first page rendering
|
||||
renderPage(pageNum);
|
||||
setTimeout(() => {
|
||||
const previewBox = document.querySelector('.box');
|
||||
tagGrid.style.maxHeight = previewBox.offsetHeight + 'px';
|
||||
}, 100);
|
||||
|
||||
tagArea.innerHTML = '';
|
||||
for (let pageTag of data.pageTags) {
|
||||
@ -276,10 +405,13 @@
|
||||
dirty = false;
|
||||
});
|
||||
|
||||
function showAddModal() {
|
||||
document.getElementById("add-modal").classList.add("is-active");
|
||||
changeTagType();
|
||||
}
|
||||
|
||||
function closeAddModal() {
|
||||
document.getElementById('add-modal').classList.remove('is-active');
|
||||
document.getElementById('add-instrument-name').value = "";
|
||||
document.getElementById('add-instrument-variant').value = "";
|
||||
}
|
||||
|
||||
function addNumberedInstrument(tag, e) {
|
||||
@ -292,11 +424,27 @@
|
||||
modal.classList.add('is-active');
|
||||
}
|
||||
|
||||
function addInstrument() {
|
||||
let name = document.getElementById('add-instrument-name');
|
||||
let variant = document.getElementById('add-instrument-variant');
|
||||
function changeTagType() {
|
||||
const tag_select = document.querySelector("#tag-type-selection");
|
||||
const selected = tag_select.value;
|
||||
document.querySelectorAll(".add-tag-option").forEach((x) => {x.classList.add("is-hidden")});
|
||||
document.querySelectorAll(".add-tag-option input").forEach((x) => {x.value=""});
|
||||
document.querySelectorAll(".enable-" + selected).forEach((x) => {x.classList.remove("is-hidden")});
|
||||
tag_select.focus();
|
||||
|
||||
let inst_name = name.value;
|
||||
}
|
||||
|
||||
function generateNewTag() {
|
||||
const selected = document.querySelector("#tag-type-selection").value;
|
||||
const n = document.querySelector("#add-tag-ordinal").value;
|
||||
switch (selected) {
|
||||
case "mvmt":
|
||||
case "no":
|
||||
return selected + "-" + n;
|
||||
case "sect":
|
||||
return "sect-" + document.querySelector("#add-tag-name").value;
|
||||
case "inst":
|
||||
const inst_name = document.querySelector("#add-tag-inst").value;
|
||||
var tag = null;
|
||||
for (let key in data.instruments) {
|
||||
if (data.instruments[key] == inst_name) {
|
||||
@ -306,83 +454,172 @@
|
||||
}
|
||||
|
||||
if (!tag) {
|
||||
alert("Unknown tag: " + name);
|
||||
return;
|
||||
tag = inst_name;
|
||||
}
|
||||
|
||||
if (variant.value) {
|
||||
tag += "-" + variant.value;
|
||||
if (n) {
|
||||
tag += "-" + n;
|
||||
}
|
||||
return tag;
|
||||
case "page":
|
||||
return "page-" + document.querySelector("#add-tag-page").value;
|
||||
}
|
||||
}
|
||||
|
||||
variant.value = '';
|
||||
name.value = '';
|
||||
|
||||
let li = document.createElement('li');
|
||||
li.classList.add("is-clickable");
|
||||
li.addEventListener('click', () => assignInstrument(tag, li));
|
||||
li.innerHTML = get_instrument(tag);
|
||||
document.getElementById('unassigned-area').appendChild(li);
|
||||
function createNewTag() {
|
||||
|
||||
const tag = generateNewTag()
|
||||
|
||||
addTag(tag, pageNum, pageNum);
|
||||
closeAddModal();
|
||||
}
|
||||
|
||||
function assignInstrument(tag, el) {
|
||||
function assignTag(tag, el) {
|
||||
addTag(tag, pageNum, pageNum);
|
||||
//el.remove();
|
||||
}
|
||||
|
||||
function addTag(tag, start, end) {
|
||||
console.log("addTag", tag, start, end);
|
||||
const el = document.createElement('div');
|
||||
el.className = 'grid-tag';
|
||||
el.dataset.tag = tag;
|
||||
|
||||
|
||||
//console.log("addTag", tag, start, end);
|
||||
const fragment = document.importNode(document.querySelector("#blank-tag").content, true);
|
||||
const el = fragment.querySelector("div");
|
||||
const tagName = el.querySelector(".tag-name");
|
||||
tagName.innerHTML=get_tag_name(tag);
|
||||
|
||||
//el.className = 'grid-tag';
|
||||
el.dataset.start = start;
|
||||
el.dataset.end = end;
|
||||
el.dataset.tag = tag;
|
||||
|
||||
let setStart = document.createElement('span');
|
||||
setStart.className = "icon is-action";
|
||||
setStart.innerHTML = '<span class="material-symbols-outlined" title="Set start page">vertical_align_top</span>';
|
||||
setStart.addEventListener('click', () => setTagStart(el));
|
||||
el.appendChild(setStart);
|
||||
const parts = tag.split("-")
|
||||
el.classList.add("tag-type-" + parts[0]);
|
||||
|
||||
|
||||
let label = document.createElement('span');
|
||||
|
||||
let name = document.createElement('b');
|
||||
name.innerHTML = get_instrument(tag);
|
||||
label.appendChild(name);
|
||||
el.appendChild(label);
|
||||
|
||||
let del = document.createElement('span');
|
||||
del.className = "icon is-action";
|
||||
del.innerHTML = '<span class="material-symbols-outlined" title="Remove this tag">delete</span>';
|
||||
del.addEventListener('click', () => {
|
||||
const handle = el.querySelector('.tag-handle');
|
||||
handle.draggable = true;
|
||||
handle.addEventListener('dragstart', (e) => {
|
||||
draggedTag = el;
|
||||
dragMode = 'move';
|
||||
dragOrigStart = parseInt(el.dataset.start);
|
||||
dragOrigEnd = parseInt(el.dataset.end);
|
||||
el.style.zIndex = 1000;
|
||||
e.dataTransfer.effectAllowed = 'move';
|
||||
const blankImg = new Image();
|
||||
blankImg.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';
|
||||
e.dataTransfer.setDragImage(blankImg, 0, 0);
|
||||
});
|
||||
handle.addEventListener('dragend', () => {
|
||||
if (draggedTag === el && dragMode === 'move') {
|
||||
el.dataset.start = dragOrigStart;
|
||||
el.dataset.end = dragOrigEnd;
|
||||
updateTag(el);
|
||||
el.remove();
|
||||
dirty = true;
|
||||
} else if (draggedTag === el) {
|
||||
el.dataset.start = dragOrigStart;
|
||||
el.dataset.end = dragOrigEnd;
|
||||
updateTag(el);
|
||||
el.style.zIndex = '';
|
||||
}
|
||||
resolveOverlaps();
|
||||
draggedTag = null;
|
||||
dragMode = null;
|
||||
});
|
||||
el.appendChild(del)
|
||||
|
||||
let setEnd = document.createElement('span');
|
||||
setEnd.className = "icon is-action";
|
||||
setEnd.innerHTML = '<span class="material-symbols-outlined" title="Set end page">vertical_align_bottom</span>';
|
||||
setEnd.addEventListener('click', () => setTagEnd(el));
|
||||
el.appendChild(setEnd);
|
||||
const resize = el.querySelector('.tag-handle-resize');
|
||||
resize.draggable = true;
|
||||
resize.addEventListener('dragstart', (e) => {
|
||||
draggedTag = el;
|
||||
dragMode = 'resize';
|
||||
dragOrigEnd = parseInt(el.dataset.end);
|
||||
el.style.zIndex = 1000;
|
||||
e.dataTransfer.effectAllowed = 'move';
|
||||
const blankImg2 = new Image();
|
||||
blankImg2.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';
|
||||
e.dataTransfer.setDragImage(blankImg2, 0, 0);
|
||||
e.stopPropagation();
|
||||
});
|
||||
resize.addEventListener('dragend', () => {
|
||||
if (draggedTag === el) {
|
||||
el.dataset.end = dragOrigEnd;
|
||||
updateTag(el);
|
||||
el.style.zIndex = '';
|
||||
}
|
||||
resolveOverlaps();
|
||||
draggedTag = null;
|
||||
dragMode = null;
|
||||
});
|
||||
|
||||
updateTag(el);
|
||||
tagArea.appendChild(el);
|
||||
resolveOverlaps();
|
||||
}
|
||||
|
||||
function updateTag(tag) {
|
||||
let start = tag.dataset.start;
|
||||
let end = tag.dataset.end;
|
||||
let span = end-start+1;
|
||||
let height = span * 25 + (span-1) * 5;
|
||||
let top = (start-1) * 30;
|
||||
let height = span * 25 + 1;
|
||||
let top = (start-1) * 25;
|
||||
|
||||
tag.style.height = height + 'px';
|
||||
tag.style.marginTop = top + 'px';
|
||||
dirty = true;
|
||||
|
||||
const name = tag.querySelector('.tag-name');
|
||||
const handle = tag.querySelector('.tag-handle');
|
||||
if (name) {
|
||||
if (span >= 3) {
|
||||
name.style.position = 'absolute';
|
||||
name.style.top = '4px';
|
||||
name.style.right = '20px';
|
||||
name.style.writingMode = 'vertical-rl';
|
||||
tag.style.justifyContent = 'flex-end';
|
||||
if (handle) handle.style.marginLeft = 'auto';
|
||||
} else {
|
||||
name.style.position = '';
|
||||
name.style.top = '';
|
||||
name.style.right = '';
|
||||
name.style.writingMode = '';
|
||||
tag.style.justifyContent = '';
|
||||
if (handle) handle.style.marginLeft = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function resolveOverlaps() {
|
||||
const tags = Array.from(tagArea.children);
|
||||
tags.sort((a, b) => parseInt(a.dataset.start) - parseInt(b.dataset.start));
|
||||
|
||||
const groups = [];
|
||||
let current = [tags[0]];
|
||||
for (let i = 1; i < tags.length; i++) {
|
||||
const prevEnd = parseInt(tags[i-1].dataset.end);
|
||||
const currStart = parseInt(tags[i].dataset.start);
|
||||
if (currStart <= prevEnd) {
|
||||
current.push(tags[i]);
|
||||
} else {
|
||||
groups.push(current);
|
||||
current = [tags[i]];
|
||||
}
|
||||
}
|
||||
if (current.length) groups.push(current);
|
||||
|
||||
for (let group of groups) {
|
||||
group.sort((a, b) => {
|
||||
const spanA = parseInt(a.dataset.end) - parseInt(a.dataset.start);
|
||||
const spanB = parseInt(b.dataset.end) - parseInt(b.dataset.start);
|
||||
return spanB - spanA;
|
||||
});
|
||||
const n = group.length;
|
||||
group.forEach((tag, i) => {
|
||||
tag.style.minWidth = (120 + (n - 1 - i) * 70) + 'px';
|
||||
tag.style.zIndex = i;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function setTagStart(el) {
|
||||
@ -404,6 +641,10 @@
|
||||
}
|
||||
|
||||
function expandEntries() {
|
||||
const answer = confirm("This will expand all tags to fill up available pages");
|
||||
if (!answer) return;
|
||||
|
||||
|
||||
const entries = Array.from(tagArea.children);
|
||||
entries.sort((a, b) => a.dataset.start-b.dataset.start);
|
||||
const c = entries.length;
|
||||
@ -416,6 +657,33 @@
|
||||
updateTag(entries[c-1]);
|
||||
}
|
||||
|
||||
const body = document.querySelector("body");
|
||||
function keymap(e) {
|
||||
if (e.target != body) return;
|
||||
switch(e.key) {
|
||||
case "ArrowRight":
|
||||
case "l":
|
||||
case "ArrowDown":
|
||||
case "j":
|
||||
onNextPage();
|
||||
break;
|
||||
case "ArrowLeft":
|
||||
case "h":
|
||||
case "ArrowUp":
|
||||
case "k":
|
||||
onPrevPage();
|
||||
break;
|
||||
case "n":
|
||||
showAddModal();
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
|
||||
}
|
||||
body.addEventListener("keydown", keymap)
|
||||
|
||||
function saveTags() {
|
||||
const pageTags = [];
|
||||
for (let pageTag of tagArea.children ) {
|
||||
@ -444,9 +712,9 @@
|
||||
dirty = false;
|
||||
}
|
||||
|
||||
function get_instrument(s) {
|
||||
function get_tag_name(s) {
|
||||
let parts = s.split('-');
|
||||
let instrument = data.instruments[parts[0]];
|
||||
let instrument = data.instruments[parts[0]] || parts[0];
|
||||
if (parts.length == 2) {
|
||||
return instrument + " " + parts[1];
|
||||
}
|
||||
|
||||
@ -35,7 +35,6 @@ class ProjectItemListView(ProjectMixin, ListView):
|
||||
model = models.ProjectItem
|
||||
|
||||
def post(self, request: HttpRequest, **kwargs):
|
||||
|
||||
project_works = self.project.works.all()
|
||||
|
||||
print(request.POST)
|
||||
@ -597,6 +596,12 @@ class DocumentAnnotateView(DocumentMixin, DetailView):
|
||||
collection=data["collection"].pk,
|
||||
pk=data["document"].pk,
|
||||
)
|
||||
data["tag_colours"] = [
|
||||
("page", "danger"),
|
||||
("no", "link"),
|
||||
("mvmt", "link"),
|
||||
("sect", "success"),
|
||||
]
|
||||
|
||||
data["json_data"] = {"pageTags": pages, "instruments": dict(MUSIC_TAGS)}
|
||||
return data
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user