Give Tags a description field.

This commit is contained in:
voussoir 2017-05-12 17:31:17 -07:00
parent a485be3c64
commit a4a278c173
8 changed files with 60 additions and 16 deletions

View file

@ -65,6 +65,7 @@ SQL_PHOTO_COLUMNS = [
SQL_TAG_COLUMNS = [ SQL_TAG_COLUMNS = [
'id', 'id',
'name', 'name',
'description',
] ]
SQL_SYN_COLUMNS = [ SQL_SYN_COLUMNS = [
'name', 'name',
@ -161,8 +162,9 @@ DEFAULT_CONFIGURATION = {
'enable_new_tag': True, 'enable_new_tag': True,
'enable_new_user': True, 'enable_new_user': True,
'enable_photo_add_remove_tag': True, 'enable_photo_add_remove_tag': True,
'enable_photo_reload_metadata': True,
'enable_photo_generate_thumbnail': True, 'enable_photo_generate_thumbnail': True,
'enable_photo_reload_metadata': True,
'enable_tag_edit': True,
'min_tag_name_length': 1, 'min_tag_name_length': 1,
'max_tag_name_length': 32, 'max_tag_name_length': 32,

View file

@ -52,6 +52,7 @@ def tag(t, include_synonyms=False):
j = { j = {
'id': t.id, 'id': t.id,
'name': t.name, 'name': t.name,
'description': t.description,
'qualified_name': t.qualified_name(), 'qualified_name': t.qualified_name(),
} }
if include_synonyms: if include_synonyms:

View file

@ -223,8 +223,8 @@ class Album(ObjectBase, GroupableMixin):
if isinstance(db_row, (list, tuple)): if isinstance(db_row, (list, tuple)):
db_row = dict(zip(constants.SQL_ALBUM_COLUMNS, db_row)) db_row = dict(zip(constants.SQL_ALBUM_COLUMNS, db_row))
self.id = db_row['id'] self.id = db_row['id']
self.title = db_row['title'] self.title = db_row['title'] or ''
self.description = db_row['description'] self.description = db_row['description'] or ''
self.name = 'Album %s' % self.id self.name = 'Album %s' % self.id
self.group_getter = self.photodb.get_album self.group_getter = self.photodb.get_album
self._sum_bytes_photos = None self._sum_bytes_photos = None
@ -501,6 +501,7 @@ class Photo(ObjectBase):
if self.duration: if self.duration:
self.bitrate = (self.bytes / 128) / self.duration self.bitrate = (self.bytes / 128) / self.duration
self.mimetype = helpers.get_mimetype(self.real_filepath) self.mimetype = helpers.get_mimetype(self.real_filepath)
if self.mimetype is None: if self.mimetype is None:
self.simple_mimetype = None self.simple_mimetype = None
@ -954,6 +955,7 @@ class Tag(ObjectBase, GroupableMixin):
db_row = dict(zip(constants.SQL_TAG_COLUMNS, db_row)) db_row = dict(zip(constants.SQL_TAG_COLUMNS, db_row))
self.id = db_row['id'] self.id = db_row['id']
self.name = db_row['name'] self.name = db_row['name']
self.description = db_row['description'] or ''
self.group_getter = self.photodb.get_tag self.group_getter = self.photodb.get_tag
self._cached_qualified_name = None self._cached_qualified_name = None
@ -1063,6 +1065,25 @@ class Tag(ObjectBase, GroupableMixin):
self.photodb.log.debug('Committing - delete tag') self.photodb.log.debug('Committing - delete tag')
self.photodb.commit() self.photodb.commit()
@decorators.required_feature('enable_tag_edit')
@decorators.transaction
def edit(self, description=None, *, commit=True):
'''
Change the description. Leave None to keep current value.
'''
if description is None:
description = self.description
cur = self.photodb.sql.cursor()
cur.execute(
'UPDATE tags SET description = ? WHERE id == ?',
[description, self.id]
)
self.description = description
self._uncache()
if commit:
self.photodb.log.debug('Committing - edit tag')
self.photodb.commit()
def qualified_name(self): def qualified_name(self):
''' '''
Return the 'group1.group2.tag' string for this tag. Return the 'group1.group2.tag' string for this tag.
@ -1107,7 +1128,8 @@ class Tag(ObjectBase, GroupableMixin):
Rename the tag. Does not affect its relation to Photos or tag groups. Rename the tag. Does not affect its relation to Photos or tag groups.
''' '''
new_name = self.photodb.normalize_tagname(new_name) new_name = self.photodb.normalize_tagname(new_name)
if new_name == self.name: old_name = self.name
if new_name == old_name:
return return
try: try:
@ -1124,7 +1146,7 @@ class Tag(ObjectBase, GroupableMixin):
if apply_to_synonyms: if apply_to_synonyms:
cur.execute( cur.execute(
'UPDATE tag_synonyms SET mastername = ? WHERE mastername = ?', 'UPDATE tag_synonyms SET mastername = ? WHERE mastername = ?',
[new_name, self.name] [new_name, old_name]
) )
self.name = new_name self.name = new_name

View file

@ -28,7 +28,7 @@ logging.getLogger('PIL.PngImagePlugin').setLevel(logging.WARNING)
# Note: Setting user_version pragma in init sequence is safe because it only # Note: Setting user_version pragma in init sequence is safe because it only
# happens after the out-of-date check occurs, so no chance of accidentally # happens after the out-of-date check occurs, so no chance of accidentally
# overwriting it. # overwriting it.
DATABASE_VERSION = 7 DATABASE_VERSION = 8
DB_INIT = ''' DB_INIT = '''
PRAGMA count_changes = OFF; PRAGMA count_changes = OFF;
PRAGMA cache_size = 10000; PRAGMA cache_size = 10000;
@ -125,7 +125,8 @@ CREATE INDEX IF NOT EXISTS index_tag_synonyms_name on tag_synonyms(name);
---------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS tags( CREATE TABLE IF NOT EXISTS tags(
id TEXT, id TEXT,
name TEXT name TEXT,
description TEXT
); );
CREATE INDEX IF NOT EXISTS index_tags_id on tags(id); CREATE INDEX IF NOT EXISTS index_tags_id on tags(id);
CREATE INDEX IF NOT EXISTS index_tags_name on tags(name); CREATE INDEX IF NOT EXISTS index_tags_name on tags(name);
@ -961,7 +962,7 @@ class PDBTagMixin:
@decorators.required_feature('enable_new_tag') @decorators.required_feature('enable_new_tag')
@decorators.transaction @decorators.transaction
def new_tag(self, tagname, *, commit=True): def new_tag(self, tagname, description=None, *, commit=True):
''' '''
Register a new tag and return the Tag object. Register a new tag and return the Tag object.
''' '''
@ -976,11 +977,18 @@ class PDBTagMixin:
tagid = self.generate_id('tags') tagid = self.generate_id('tags')
self._cached_frozen_children = None self._cached_frozen_children = None
cur = self.sql.cursor() cur = self.sql.cursor()
cur.execute('INSERT INTO tags VALUES(?, ?)', [tagid, tagname]) data = {
'id': tagid,
'name': tagname,
'description': description,
}
(qmarks, bindings) = helpers.binding_filler(constants.SQL_TAG_COLUMNS, data)
query = 'INSERT INTO tags VALUES(%s)' % qmarks
cur.execute(query, bindings)
if commit: if commit:
self.log.debug('Committing - new_tag') self.log.debug('Committing - new_tag')
self.commit() self.commit()
tag = objects.Tag(self, [tagid, tagname]) tag = objects.Tag(self, data)
return tag return tag
def normalize_tagname(self, tagname): def normalize_tagname(self, tagname):

View file

@ -524,8 +524,8 @@ def get_search_core():
total_tags = set() total_tags = set()
for photo in photos: for photo in photos:
for tag in photo.tags(): for tag in photo.tags():
total_tags.add(tag.qualified_name()) total_tags.add(tag)
total_tags = sorted(total_tags) total_tags = sorted(total_tags, key=lambda t: t.qualified_name())
# PREV-NEXT PAGE URLS # PREV-NEXT PAGE URLS
offset = search_kwargs['offset'] or 0 offset = search_kwargs['offset'] or 0
@ -613,6 +613,7 @@ def get_tags_html(specific_tag=None):
'tags.html', 'tags.html',
include_synonyms=include_synonyms, include_synonyms=include_synonyms,
session=session, session=session,
specific_tag=specific_tag,
tags=tags, tags=tags,
) )
return response return response

View file

@ -270,7 +270,7 @@ form
<span>Tags on this page (click to join query):</span> <span>Tags on this page (click to join query):</span>
<ul> <ul>
{% for tag in total_tags %} {% for tag in total_tags %}
<li><a href="" class="tag_object">{{tag}}</a></li> <li><a href="javascript:void(0)" title="{{tag.description}}" class="tag_object tags_on_this_page">{{tag.name}}</a></li>
{% endfor %} {% endfor %}
</ul> </ul>
{% endif %} {% endif %}
@ -560,7 +560,7 @@ var inputted_forbids = [];
{% endfor %} {% endfor %}
/* Assign the click handler to "Tags on this page" results. */ /* Assign the click handler to "Tags on this page" results. */
var found_on_page = document.getElementsByClassName("tag_object"); var found_on_page = document.getElementsByClassName("tags_on_this_page");
for (var index = 0; index < found_on_page.length; index += 1) for (var index = 0; index < found_on_page.length; index += 1)
{ {
var tag_object = found_on_page[index]; var tag_object = found_on_page[index];

View file

@ -67,11 +67,15 @@ body
{{header.make_header(session=session)}} {{header.make_header(session=session)}}
<div id="content_body"> <div id="content_body">
<div id="left"> <div id="left">
{% if specific_tag is not none %}
<h1>{{specific_tag.name}}</h1>
<p>{{specific_tag.description}}</p>
{% endif %}
<ul> <ul>
{% for tag in tags %} {% for tag in tags %}
{% set qualified_name = tag.qualified_name() %} {% set qualified_name = tag.qualified_name() %}
<li> <li>
<a target="_blank" class="tag_object" href="/search?tag_musts={{tag.name}}">{{qualified_name}}</a><!-- <a target="_blank" class="tag_object" title="{{tag.description}}" href="/search?tag_musts={{tag.name}}">{{qualified_name}}</a><!--
--><button class="remove_tag_button" onclick="delete_tag('{{tag.name}}', receive_callback);"></button> --><button class="remove_tag_button" onclick="delete_tag('{{tag.name}}', receive_callback);"></button>
</li> </li>
{% if include_synonyms %} {% if include_synonyms %}

View file

@ -118,7 +118,6 @@ def upgrade_6_to_7(sql):
for index in indices: for index in indices:
cur.execute('DROP INDEX %s' % index) cur.execute('DROP INDEX %s' % index)
cur.execute(''' cur.execute('''
CREATE TABLE album_associated_directories( CREATE TABLE album_associated_directories(
albumid TEXT, albumid TEXT,
@ -140,6 +139,13 @@ def upgrade_6_to_7(sql):
''') ''')
cur.execute('DROP TABLE deleting_albums') cur.execute('DROP TABLE deleting_albums')
def upgrade_7_to_8(sql):
'''
Give the Tags table a description field.
'''
cur = sql.cursor()
cur.execute('ALTER TABLE tags ADD COLUMN description TEXT')
def upgrade_all(database_filename): def upgrade_all(database_filename):
''' '''