home · contact · privacy
In /file view, for tag addition propose tags used elsewhere.
authorChristian Heller <c.heller@plomlompom.de>
Tue, 3 Dec 2024 05:01:11 +0000 (06:01 +0100)
committerChristian Heller <c.heller@plomlompom.de>
Tue, 3 Dec 2024 05:01:11 +0000 (06:01 +0100)
src/templates/file_data.tmpl
src/ytplom/http.py
src/ytplom/misc.py

index e0d415d97e238e51f1ba62358ef243b6ae4f4d3d..b5a45b9d8fefabdf29043e525e336385a71cff3f 100644 (file)
@@ -28,7 +28,12 @@ td.flags { text-align: right; }
 {% for tag in file.tags %}
 <input type="checkbox" name="tags" value="{{tag}}" checked /> {{tag}}<br />
 {% endfor %}
-<input name="tags" />
+<input name="tags" list="unused_tags" autocomplete="off" />
+<datalist id="unused_tags" />
+{% for tag in unused_tags %}
+<option value="{{tag}}">{{tag}}</option>
+{% endfor %}
+</datalist>
 </td>
 </tr>
 </table>
index 08ca629e57833ec3f5ff67a15163581db08cf3d2..006d96458b1a99a3bb1c41b2d527f463474d49e9 100644 (file)
@@ -12,7 +12,7 @@ from jinja2 import (  # type: ignore
 from ytplom.db import Hash, DbConn
 from ytplom.misc import (
         FilesWithIndex, FlagName, PlayerUpdateId, QueryId, QueryText,
-        QuotaCost, UrlStr, YoutubeId,
+        QuotaCost, Tag, UrlStr, YoutubeId,
         FILE_FLAGS, PATH_THUMBNAILS, YOUTUBE_URL_PREFIX,
         ensure_expected_dirs,
         Config, DownloadsManager, Player, QuotaLog, VideoFile, YoutubeQuery,
@@ -28,7 +28,7 @@ _TemplateContext: TypeAlias = dict[
         None | bool
         | FilesWithIndex | _PageNames | _ParamsStr | Path | PlayerUpdateId
         | QueryText | QuotaCost | UrlStr | 'VideoFile' | YoutubeId
-        | 'YoutubeVideo' | list[FlagName] | list['VideoFile']
+        | 'YoutubeVideo' | list[FlagName] | list['Tag'] | list['VideoFile']
         | list['YoutubeVideo'] | list['YoutubeQuery']
 ]
 
@@ -147,7 +147,7 @@ class _TaskHandler(BaseHTTPRequestHandler):
         with DbConn() as conn:
             file = VideoFile.get_one(conn, digest)
             file.set_flags([FILE_FLAGS[name] for name in flag_names])
-            file.tags = postvars.get('tags', [])
+            file.tags = [Tag(t) for t in postvars.get('tags', [])]
             file.save(conn)
             conn.commit()
         file.ensure_absence_if_deleted()
@@ -276,9 +276,11 @@ class _TaskHandler(BaseHTTPRequestHandler):
     def _send_file_data(self, digest: Hash) -> None:
         with DbConn() as conn:
             file = VideoFile.get_one(conn, digest)
+            all_tags = VideoFile.get_all_tags(conn)
         self._send_rendered_template(
                 _NAME_TEMPLATE_FILE_DATA,
-                {'file': file, 'flag_names': list(FILE_FLAGS)})
+                {'file': file, 'flag_names': list(FILE_FLAGS),
+                 'unused_tags': [t for t in all_tags if t not in file.tags]})
 
     def _send_files_index(self,
                           filter_: _ParamsStr,
index b8605d33bc98c72c6ca03e7fcb13ae62ceca8c6f..4b36b5a7bad2768ab3b8aac490625e15d7dceef4 100644 (file)
@@ -37,6 +37,7 @@ QueryText = NewType('QueryText', str)
 ProseText = NewType('ProseText', str)
 FlagName = NewType('FlagName', str)
 FlagsInt = NewType('FlagsInt', int)
+Tag = NewType('Tag', str)
 AmountDownloads = NewType('AmountDownloads', int)
 PlayerUpdateId = NewType('PlayerUpdateId', str)
 UrlStr = NewType('UrlStr', str)
@@ -250,6 +251,7 @@ class VideoFile(DbData):
     last_update: DatetimeStr
     rel_path: Path
     digest: Hash
+    tags: list[Tag]
 
     def __init__(self,
                  digest: Optional[Hash],
@@ -262,7 +264,7 @@ class VideoFile(DbData):
         self.rel_path = rel_path
         self.digest = digest if digest else Hash.from_file(self.full_path)
         self.flags = flags
-        self.tags = tags_str.split(',') if tags_str else []
+        self.tags = [Tag(t) for t in tags_str.split(',')] if tags_str else []
         self.yt_id = yt_id
         if last_update is None:
             self._renew_last_update()
@@ -281,6 +283,15 @@ class VideoFile(DbData):
             raise NotFoundException(f'no entry for file to Youtube ID {yt_id}')
         return cls._from_table_row(row)
 
+    @classmethod
+    def get_all_tags(cls, conn: BaseDbConn) -> set[Tag]:
+        """Return all tags used among VideoFiles."""
+        tags = set()
+        for file in cls.get_all(conn):
+            for tag in file.tags:
+                tags.add(tag)
+        return tags
+
     @property
     def tags_str(self):
         """Return self.tags joined by ','."""