From 89253454f95820037a877dd89d99f623c6e6949e Mon Sep 17 00:00:00 2001 From: Ruben van de Ven Date: Fri, 10 Jun 2022 13:10:19 +0200 Subject: [PATCH] Feature: give diagrams a title --- app/webserver.py | 16 ++-- app/www/annotate.html | 6 +- app/www/annotate.js | 34 +++++++- app/www/playlist.js | 177 +++++++++++++++++++++++++----------------- app/www/svganim.css | 27 +++++-- 5 files changed, 169 insertions(+), 91 deletions(-) diff --git a/app/webserver.py b/app/webserver.py index 99ca601..ce1aa04 100644 --- a/app/webserver.py +++ b/app/webserver.py @@ -266,15 +266,19 @@ class AnimationHandler(tornado.web.RequestHandler): if first_line.endswith(","): first_line = first_line[:-1] - metadata = json.loads(first_line) + drawing_specs = json.loads(first_line) + drawing_id = name[:-16] + md = self.index.drawings[drawing_id].get_metadata() if drawing_id in self.index.drawings else {} + title = md['title'] if 'title' in md else None files.append( { - "name": f"/files/{name[:-16]}", - "id": name[:-16], - "ctime": metadata[0], + "name": f"/files/{drawing_id}", + "id": drawing_id, + "title": title, + "ctime": drawing_specs[0], "mtime": datetime.datetime.fromtimestamp(stat.st_mtime).strftime("%Y-%m-%d %T"), - "dimensions": [metadata[1], metadata[2]], - "svg": f"/drawing/{name[:-16]}.svg", + "dimensions": [drawing_specs[1], drawing_specs[2]], + "svg": f"/drawing/{drawing_id}.svg", } ) diff --git a/app/www/annotate.html b/app/www/annotate.html index 5beb82c..712ddc5 100644 --- a/app/www/annotate.html +++ b/app/www/annotate.html @@ -63,12 +63,16 @@ background: white; display: block; } + .playlist .title{ + display: block; + font-weight: bold;; + } .help { position: absolute; right: 0; top: 10px; - left: 70px; + left: 220px; margin: 0; padding: 0; display: flex; diff --git a/app/www/annotate.js b/app/www/annotate.js index 07b924e..54163ce 100644 --- a/app/www/annotate.js +++ b/app/www/annotate.js @@ -306,7 +306,7 @@ class Annotator extends EventTarget { getColorForTag(tag_id) { const tag = this.tagMap[tag_id]; - console.log(tag_id, tag); + // console.log(tag_id, tag); if (tag && tag.hasOwnProperty('color')) { return tag.color; } @@ -497,6 +497,7 @@ class Annotator extends EventTarget { updateState() { const state = { + 'title': this.title, 'file': this.filename, 'annotations': this.annotations, 'audio': { @@ -700,6 +701,15 @@ class Annotator extends EventTarget { this._updatePlayhead(); } + this.title = null; + console.log(metadata); + if (metadata && metadata.hasOwnProperty('title')) { + this.title = metadata.title; + } + else if (drawing.hasOwnProperty('title')) { + this.title = drawing.title; + } + this.filename = drawing.file; this.strokes = drawing.shape.map(s => new Stroke(s['color'], s['points'])); this.viewboxes = drawing.viewboxes; @@ -827,11 +837,29 @@ class Annotator extends EventTarget { } else { + let mdConfigEl = document.createElement('div'); + mdConfigEl.classList.add('metadataconfig') + this.wrapperEl.appendChild(mdConfigEl); + + + let titleEl = document.createElement('div'); + titleEl.classList.add('drawing-title'); + titleEl.innerText = this.title ?? "[add title]" + titleEl.addEventListener('click', (ev) => { + const title = prompt("Change the title for the drawing", this.title ?? ""); + if(title === null) return; //cancel + titleEl.innerText = title.length ? title : "[add title]"; + this.title = title.length ? title : null; + this.updateState(); + }) + mdConfigEl.appendChild(titleEl); + let audioConfigEl = document.createElement('div'); audioConfigEl.classList.add('audioconfig') - this.wrapperEl.appendChild(audioConfigEl); + mdConfigEl.appendChild(audioConfigEl); - audioConfigEl.prepend(this.audioEl); + + audioConfigEl.appendChild(this.audioEl); let audioSelectEl = document.createElement('select'); audioSelectEl.classList.add('audioselect'); diff --git a/app/www/playlist.js b/app/www/playlist.js index 249eacf..1f2bc46 100644 --- a/app/www/playlist.js +++ b/app/www/playlist.js @@ -2,6 +2,8 @@ class Playlist { constructor(wrapperEl, url) { this.wrapperEl = wrapperEl; + this.onlyWithTitle = true; + const request = new Request(url, { method: 'GET', }); @@ -9,80 +11,109 @@ class Playlist { fetch(request) .then(response => response.json()) .then(data => { - let playlist = this.wrapperEl.querySelector('.playlist'); - if (!playlist) { - playlist = document.createElement('nav'); - playlist.classList.add('playlist'); - this.wrapperEl.appendChild(playlist) - } - else { - playlist.innerHTML = ""; - } - - const listEl = document.createElement("ul"); - for (let file of data) { - const liEl = document.createElement("li"); - - - const imgEl = document.createElement("img"); - imgEl.classList.add('img'); - imgEl.title = file.id; - imgEl.src = file.svg; - liEl.append(imgEl); - - - let time = file.mtime; - if (file.ctime != file.mtime){ - time += ` (orig: ${file.ctime})`; - } - const dateEl = document.createElement("span"); - dateEl.classList.add('date'); - dateEl.innerText = time; - liEl.append(dateEl); - - - const nameEl = document.createElement("span"); - nameEl.classList.add('name'); - nameEl.innerText = file.name; - liEl.append(nameEl); - - const linksEl = document.createElement("span"); - linksEl.classList.add('links'); - liEl.append(linksEl); - - const playEl = document.createElement("a"); - playEl.classList.add('play'); - playEl.innerText = "Play"; - playEl.href = location; - playEl.pathname = "annotate.html"; - playEl.search = "?file="+file.name+"&player=1"; - linksEl.append(playEl); - - const annotateEl = document.createElement("a"); - annotateEl.classList.add('annotate'); - annotateEl.innerText = "Annotate"; - annotateEl.href = location; - annotateEl.pathname = "annotate.html"; - annotateEl.search = "?file="+file.name; - linksEl.append(annotateEl); - - const drawEl = document.createElement("a"); - drawEl.classList.add('draw'); - drawEl.innerText = "Draw"; - drawEl.href = location; - drawEl.pathname = "draw.html"; - drawEl.hash = file.id; - linksEl.append(drawEl); - - // liEl.addEventListener('click', (e) => { - // this.play(fileUrl); - // playlist.style.display = "none"; - // }); - listEl.appendChild(liEl); - } - playlist.appendChild(listEl); - // do something with the data sent in the request + this.files = data; + this.buildList() }); } + + buildList() { + let playlist = this.wrapperEl.querySelector('.playlist'); + if (!playlist) { + playlist = document.createElement('nav'); + playlist.classList.add('playlist'); + this.wrapperEl.appendChild(playlist) + } + else { + playlist.innerHTML = ""; + } + + const filterEl = document.createElement('label'); + filterEl.classList.add('filter'); + filterEl.innerText = "Show only diagrams with title" + const filterCheckEl = document.createElement('input'); + filterCheckEl.type = "checkbox"; + filterCheckEl.checked = this.onlyWithTitle; + filterCheckEl.addEventListener('click', (ev) => { + this.onlyWithTitle = ev.target.checked; + this.buildList() + }) + filterEl.appendChild(filterCheckEl) + + playlist.appendChild(filterEl) + + const listEl = document.createElement("ul"); + for (let file of this.files) { + + if(this.onlyWithTitle && file.title === null) { + continue; + } + const liEl = document.createElement("li"); + + const imgEl = document.createElement("img"); + imgEl.classList.add('img'); + imgEl.title = file.id; + imgEl.src = file.svg; + liEl.append(imgEl); + + if (file.title) { + const titleEl = document.createElement("span"); + titleEl.classList.add('title'); + titleEl.innerText = file.title; + liEl.append(titleEl); + } + + + let time = file.mtime; + if (file.ctime != file.mtime) { + time += ` (orig: ${file.ctime})`; + } + const dateEl = document.createElement("span"); + dateEl.classList.add('date'); + dateEl.innerText = time; + liEl.append(dateEl); + + + const nameEl = document.createElement("span"); + nameEl.classList.add('name'); + nameEl.innerText = file.name; + liEl.append(nameEl); + + const linksEl = document.createElement("span"); + linksEl.classList.add('links'); + liEl.append(linksEl); + + const playEl = document.createElement("a"); + playEl.classList.add('play'); + playEl.innerText = "Play"; + playEl.href = location; + playEl.pathname = "annotate.html"; + playEl.search = "?file=" + file.name + "&player=1"; + linksEl.append(playEl); + + const annotateEl = document.createElement("a"); + annotateEl.classList.add('annotate'); + annotateEl.innerText = "Annotate"; + annotateEl.href = location; + annotateEl.pathname = "annotate.html"; + annotateEl.search = "?file=" + file.name; + linksEl.append(annotateEl); + + const drawEl = document.createElement("a"); + drawEl.classList.add('draw'); + drawEl.innerText = "Draw"; + drawEl.href = location; + drawEl.pathname = "draw.html"; + drawEl.hash = file.id; + linksEl.append(drawEl); + + // liEl.addEventListener('click', (e) => { + // this.play(fileUrl); + // playlist.style.display = "none"; + // }); + listEl.appendChild(liEl); + } + playlist.appendChild(listEl); + // do something with the data sent in the request + } } \ No newline at end of file diff --git a/app/www/svganim.css b/app/www/svganim.css index 0d78041..3fd516b 100644 --- a/app/www/svganim.css +++ b/app/www/svganim.css @@ -249,24 +249,35 @@ path.before_in { right: 110%; } -.audioconfig { +.metadataconfig { z-index: 9; background: black; color: white; position: relative; - width: 100px; + /* width: 100px; */ /* as wide as audio controls only */ - overflow: hidden; + overflow:visible; /* white-space: nowrap; */ - left: -50px; + /* left: -50px; */ } -.audioconfig:hover { - width: auto; +.metadataconfig .drawing-title{ + font-weight: bold; + padding: 10px; + cursor: pointer; +} + +.metadataconfig .audioconfig{ + display: none;; + background-color: black;; +} + +.metadataconfig:hover .audioconfig{ + /* width: auto; left: 0px; overflow: visible; - height: 200px; - + height: 200px; */ + display: block; } .audioconfig select,