Counts for tags in index

This commit is contained in:
Ruben van de Ven 2022-06-08 18:51:22 +02:00
parent 4b0b5c2c16
commit adce8d067c
4 changed files with 51 additions and 31 deletions

View file

@ -14,7 +14,7 @@ import tempfile
import io import io
import logging import logging
from anytree import NodeMixin, RenderTree, iterators from anytree import NodeMixin, RenderTree, iterators
from anytree.exporter import JsonExporter from anytree.exporter import JsonExporter, DictExporter
from anytree.importer import JsonImporter, DictImporter from anytree.importer import JsonImporter, DictImporter
logger = logging.getLogger('svganim.strokes') logger = logging.getLogger('svganim.strokes')
@ -538,10 +538,15 @@ class AnnotationIndex:
self.shelve['_annotations'][annotation.id] = annotation self.shelve['_annotations'][annotation.id] = annotation
if annotation.tag not in self.shelve['_tags']: if annotation.tag not in self.shelve['_tags']:
self.shelve['_tags'][annotation.tag] = [annotation] self.shelve['_tags'][annotation.tag] = [annotation]
logger.error(f"Use of non-existing tag {annotation.tag}")
else: else:
self.shelve['_tags'][annotation.tag].append( self.shelve['_tags'][annotation.tag].append(
annotation annotation
) )
tag = self.root_tag.find_by_id(annotation.tag)
if tag is not None:
tag.annotation_count += 1
@property @property
def drawings(self) -> dict[str, Drawing]: def drawings(self) -> dict[str, Drawing]:
@ -715,7 +720,7 @@ def strokes2D(strokes):
return d return d
class Tag(NodeMixin): class Tag(NodeMixin):
def __init__(self, id, name = None, description = "", color = None, parent=None, children=None): def __init__(self, id, name = None, description = "", color = None, parent=None, children=None, annotation_count=None):
self.id = id self.id = id
self.name = self.id if name is None else name self.name = self.id if name is None else name
self.color = color self.color = color
@ -724,6 +729,8 @@ class Tag(NodeMixin):
if children: if children:
self.children = children self.children = children
self.annotation_count = 0 #always zero!
if self.id == 'root' and not self.is_root: if self.id == 'root' and not self.is_root:
logger.error("Root node shouldn't have a parent assigned") logger.error("Root node shouldn't have a parent assigned")
@ -747,8 +754,11 @@ class Tag(NodeMixin):
return t return t
return None return None
def toJson(self) -> str: def toJson(self, with_counts=False) -> str:
return JsonExporter(indent=2).export(self) ignore_counts=lambda attrs: [(k, v) for k, v in attrs if k != "annotation_count"]
attrFilter = None if with_counts else ignore_counts
return JsonExporter(DictExporter(attriter=attrFilter), indent=2).export(self)
def loadTagFromJson(string) -> Tag: def loadTagFromJson(string) -> Tag:
tree: Tag = JsonImporter(DictImporter(Tag)).import_(string) tree: Tag = JsonImporter(DictImporter(Tag)).import_(string)

View file

@ -53,6 +53,12 @@
; ;
} }
#annotations .annotations-actions {
margin-bottom: 10px;
color: darkgray;
font-size: 80%;
border-bottom: solid 3px #444;
}
@ -73,16 +79,20 @@
vertical-align: middle; vertical-align: middle;
margin-right: 10px; margin-right: 10px;
} }
#tags li:hover>div>input.rm-tag { #tags li:hover>div>input.rm-tag {
display: inline-block; display: inline-block;
} }
#tags li div { #tags li div {
position: relative position: relative
} }
#tags input.rm-tag:hover { #tags input.rm-tag:hover {
color: red; color: red;
transform: rotate(20deg); transform: rotate(20deg);
} }
#tags input.rm-tag { #tags input.rm-tag {
/* display: none; */ /* display: none; */
position: absolute; position: absolute;
@ -143,9 +153,7 @@
} }
#annotations li { #annotations li {}
}
#annotations img { #annotations img {
/* width: 400px; */ /* width: 400px; */
@ -179,7 +187,6 @@
#annotations .svganim_player:hover .controls { #annotations .svganim_player:hover .controls {
visibility: visible !important; visibility: visible !important;
} }
</style> </style>
<script src="assets/nouislider-15.5.0.js"></script> <script src="assets/nouislider-15.5.0.js"></script>
<script src="assets/wNumb-1.2.0.min.js"></script> <script src="assets/wNumb-1.2.0.min.js"></script>

View file

@ -558,9 +558,10 @@ class TagsHandler(tornado.web.RequestHandler):
def get(self): def get(self):
self.set_header("Content-Type", "application/json") self.set_header("Content-Type", "application/json")
with open('www/tags.json', 'r') as fp: self.write(self.index.root_tag.toJson(with_counts=True))
# TODO: enrich with counts # with open('www/tags.json', 'r') as fp:
self.write(fp.read()) # # TODO: enrich with counts
# self.write(fp.read())
def put(self): def put(self):
# data = json.loads(self.request.body) # data = json.loads(self.request.body)

View file

@ -8,12 +8,13 @@ class AnnotationManager {
this.selectedAnnotations = []; this.selectedAnnotations = [];
this.selectedTag = null; this.selectedTag = null;
this.loadTags(tagsUrl); this.tagsUrl = tagsUrl;
this.loadTags();
} }
loadTags(tagFile) { loadTags() {
// tags config // tags config
const request = new Request(tagFile); const request = new Request(this.tagsUrl);
return fetch(request) return fetch(request)
.then(response => response.json()) .then(response => response.json())
.then(rootTag => { .then(rootTag => {
@ -31,7 +32,7 @@ class AnnotationManager {
const tagSubEl = document.createElement('ul'); const tagSubEl = document.createElement('ul');
const tagEl = document.createElement('div'); const tagEl = document.createElement('div');
tagEl.innerText = tag.get_name(); tagEl.innerText = `${tag.get_name()} (${tag.annotation_count ?? 0})`;
tagEl.addEventListener('click', (ev) => { tagEl.addEventListener('click', (ev) => {
this.selectTag(tag); this.selectTag(tag);
}) })
@ -318,6 +319,7 @@ class AnnotationManager {
})); }));
this.loadAnnotationsForTag(this.selectedTag) this.loadAnnotationsForTag(this.selectedTag)
this.loadTags() //updates the counts
} }
async saveTags() { async saveTags() {