Feature: give diagrams a title
This commit is contained in:
parent
adce8d067c
commit
89253454f9
5 changed files with 169 additions and 91 deletions
|
@ -266,15 +266,19 @@ class AnimationHandler(tornado.web.RequestHandler):
|
||||||
if first_line.endswith(","):
|
if first_line.endswith(","):
|
||||||
first_line = first_line[:-1]
|
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(
|
files.append(
|
||||||
{
|
{
|
||||||
"name": f"/files/{name[:-16]}",
|
"name": f"/files/{drawing_id}",
|
||||||
"id": name[:-16],
|
"id": drawing_id,
|
||||||
"ctime": metadata[0],
|
"title": title,
|
||||||
|
"ctime": drawing_specs[0],
|
||||||
"mtime": datetime.datetime.fromtimestamp(stat.st_mtime).strftime("%Y-%m-%d %T"),
|
"mtime": datetime.datetime.fromtimestamp(stat.st_mtime).strftime("%Y-%m-%d %T"),
|
||||||
"dimensions": [metadata[1], metadata[2]],
|
"dimensions": [drawing_specs[1], drawing_specs[2]],
|
||||||
"svg": f"/drawing/{name[:-16]}.svg",
|
"svg": f"/drawing/{drawing_id}.svg",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -63,12 +63,16 @@
|
||||||
background: white;
|
background: white;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
.playlist .title{
|
||||||
|
display: block;
|
||||||
|
font-weight: bold;;
|
||||||
|
}
|
||||||
|
|
||||||
.help {
|
.help {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
right: 0;
|
||||||
top: 10px;
|
top: 10px;
|
||||||
left: 70px;
|
left: 220px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
@ -306,7 +306,7 @@ class Annotator extends EventTarget {
|
||||||
|
|
||||||
getColorForTag(tag_id) {
|
getColorForTag(tag_id) {
|
||||||
const tag = this.tagMap[tag_id];
|
const tag = this.tagMap[tag_id];
|
||||||
console.log(tag_id, tag);
|
// console.log(tag_id, tag);
|
||||||
if (tag && tag.hasOwnProperty('color')) {
|
if (tag && tag.hasOwnProperty('color')) {
|
||||||
return tag.color;
|
return tag.color;
|
||||||
}
|
}
|
||||||
|
@ -497,6 +497,7 @@ class Annotator extends EventTarget {
|
||||||
|
|
||||||
updateState() {
|
updateState() {
|
||||||
const state = {
|
const state = {
|
||||||
|
'title': this.title,
|
||||||
'file': this.filename,
|
'file': this.filename,
|
||||||
'annotations': this.annotations,
|
'annotations': this.annotations,
|
||||||
'audio': {
|
'audio': {
|
||||||
|
@ -700,6 +701,15 @@ class Annotator extends EventTarget {
|
||||||
this._updatePlayhead();
|
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.filename = drawing.file;
|
||||||
this.strokes = drawing.shape.map(s => new Stroke(s['color'], s['points']));
|
this.strokes = drawing.shape.map(s => new Stroke(s['color'], s['points']));
|
||||||
this.viewboxes = drawing.viewboxes;
|
this.viewboxes = drawing.viewboxes;
|
||||||
|
@ -827,11 +837,29 @@ class Annotator extends EventTarget {
|
||||||
}
|
}
|
||||||
else {
|
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');
|
let audioConfigEl = document.createElement('div');
|
||||||
audioConfigEl.classList.add('audioconfig')
|
audioConfigEl.classList.add('audioconfig')
|
||||||
this.wrapperEl.appendChild(audioConfigEl);
|
mdConfigEl.appendChild(audioConfigEl);
|
||||||
|
|
||||||
audioConfigEl.prepend(this.audioEl);
|
|
||||||
|
audioConfigEl.appendChild(this.audioEl);
|
||||||
|
|
||||||
let audioSelectEl = document.createElement('select');
|
let audioSelectEl = document.createElement('select');
|
||||||
audioSelectEl.classList.add('audioselect');
|
audioSelectEl.classList.add('audioselect');
|
||||||
|
|
|
@ -2,6 +2,8 @@ class Playlist {
|
||||||
constructor(wrapperEl, url) {
|
constructor(wrapperEl, url) {
|
||||||
this.wrapperEl = wrapperEl;
|
this.wrapperEl = wrapperEl;
|
||||||
|
|
||||||
|
this.onlyWithTitle = true;
|
||||||
|
|
||||||
const request = new Request(url, {
|
const request = new Request(url, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
});
|
});
|
||||||
|
@ -9,80 +11,109 @@ class Playlist {
|
||||||
fetch(request)
|
fetch(request)
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
let playlist = this.wrapperEl.querySelector('.playlist');
|
this.files = data;
|
||||||
if (!playlist) {
|
this.buildList()
|
||||||
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
|
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -249,24 +249,35 @@ path.before_in {
|
||||||
right: 110%;
|
right: 110%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.audioconfig {
|
.metadataconfig {
|
||||||
z-index: 9;
|
z-index: 9;
|
||||||
background: black;
|
background: black;
|
||||||
color: white;
|
color: white;
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100px;
|
/* width: 100px; */
|
||||||
/* as wide as audio controls only */
|
/* as wide as audio controls only */
|
||||||
overflow: hidden;
|
overflow:visible;
|
||||||
/* white-space: nowrap; */
|
/* white-space: nowrap; */
|
||||||
left: -50px;
|
/* left: -50px; */
|
||||||
}
|
}
|
||||||
|
|
||||||
.audioconfig:hover {
|
.metadataconfig .drawing-title{
|
||||||
width: auto;
|
font-weight: bold;
|
||||||
|
padding: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metadataconfig .audioconfig{
|
||||||
|
display: none;;
|
||||||
|
background-color: black;;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metadataconfig:hover .audioconfig{
|
||||||
|
/* width: auto;
|
||||||
left: 0px;
|
left: 0px;
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
height: 200px;
|
height: 200px; */
|
||||||
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.audioconfig select,
|
.audioconfig select,
|
||||||
|
|
Loading…
Reference in a new issue