server/tags: add description field

This commit is contained in:
rr- 2016-06-21 18:06:35 +02:00
parent a6d6aa2f4d
commit 7eec347bca
10 changed files with 48 additions and 2 deletions

5
API.md
View file

@ -379,6 +379,7 @@ data.
{
"names": [<name1>, <name2>, ...],
"category": <category>,
"description": <description>, // optional
"implications": [<name1>, <name2>, ...], // optional
"suggestions": [<name1>, <name2>, ...] // optional
}
@ -421,6 +422,7 @@ data.
{
"names": [<name1>, <name2>, ...], // optional
"category": <category>, // optional
"description": <description>, // optional
"implications": [<name1>, <name2>, ...], // optional
"suggestions": [<name1>, <name2>, ...] // optional
}
@ -1514,6 +1516,7 @@ A single tag. Tags are used to let users search for posts.
"creationTime": <creation-time>,
"lastEditTime": <last-edit-time>,
"usages": <usage-count>,
"description": <description>,
"snapshots": [
<snapshot>,
<snapshot>,
@ -1534,6 +1537,8 @@ A single tag. Tags are used to let users search for posts.
- `<creation-time>`: time the tag was created, formatted as per RFC 3339.
- `<last-edit-time>`: time the tag was edited, formatted as per RFC 3339.
- `<usage-count>`: the number of posts the tag was used in.
- `<description>`: the tag description (instructions how to use, history etc.)
The client should render is as Markdown.
- `<snapshot>`: a [snapshot resource](#snapshot) that contains the tag's
earlier versions.

View file

@ -84,6 +84,7 @@ privileges:
'tags:create': regular
'tags:edit:names': power
'tags:edit:category': power
'tags:edit:description': power
'tags:edit:implications': power
'tags:edit:suggestions': power
'tags:list': regular # note: will be available as data_url/tags.json anyway

View file

@ -32,6 +32,8 @@ class TagListApi(BaseApi):
names = ctx.get_param_as_list('names', required=True)
category = ctx.get_param_as_string('category', required=True)
description = ctx.get_param_as_string(
'description', required=False, default=None)
suggestions = ctx.get_param_as_list(
'suggestions', required=False, default=[])
implications = ctx.get_param_as_list(
@ -41,6 +43,7 @@ class TagListApi(BaseApi):
_create_if_needed(implications, ctx.user)
tag = tags.create_tag(names, category, suggestions, implications)
tags.update_tag_description(tag, description)
ctx.session.add(tag)
ctx.session.flush()
snapshots.save_entity_creation(tag, ctx.user)
@ -63,6 +66,10 @@ class TagDetailApi(BaseApi):
auth.verify_privilege(ctx.user, 'tags:edit:category')
tags.update_tag_category_name(
tag, ctx.get_param_as_string('category'))
if ctx.has_param('description'):
auth.verify_privilege(ctx.user, 'tags:edit:description')
tags.update_tag_description(
tag, ctx.get_param_as_string('description', default=None))
if ctx.has_param('suggestions'):
auth.verify_privilege(ctx.user, 'tags:edit:suggestions')
suggestions = ctx.get_param_as_list('suggestions')

View file

@ -1,4 +1,4 @@
from sqlalchemy import Column, Integer, DateTime, Unicode, ForeignKey
from sqlalchemy import Column, Integer, DateTime, Unicode, UnicodeText, ForeignKey
from sqlalchemy.orm import relationship, column_property
from sqlalchemy.sql.expression import func, select
from szurubooru.db.base import Base
@ -46,6 +46,7 @@ class Tag(Base):
'category_id', Integer, ForeignKey('tag_category.id'), nullable=False, index=True)
creation_time = Column('creation_time', DateTime, nullable=False)
last_edit_time = Column('last_edit_time', DateTime)
description = Column('description', UnicodeText, default=None)
category = relationship('TagCategory', lazy='joined')
names = relationship(

View file

@ -42,6 +42,7 @@ def serialize_tag(tag, options=None):
{
'names': lambda: [tag_name.name for tag_name in tag.names],
'category': lambda: tag.category.name,
'description': lambda: tag.description,
'creationTime': lambda: tag.creation_time,
'lastEditTime': lambda: tag.last_edit_time,
'usages': lambda: tag.post_count,
@ -218,3 +219,6 @@ def update_tag_suggestions(tag, relations):
if _check_name_intersection(_get_plain_names(tag), relations):
raise InvalidTagRelationError('Tag cannot suggest itself.')
tag.suggestions = get_tags_by_names(relations)
def update_tag_description(tag, description):
tag.description = description

View file

@ -0,0 +1,20 @@
'''
Add description to tags
Revision ID: 4c526f869323
Created at: 2016-06-21 17:56:34.979741
'''
import sqlalchemy as sa
from alembic import op
revision = '4c526f869323'
down_revision = '055d0e048fb3'
branch_labels = None
depends_on = None
def upgrade():
op.add_column('tag', sa.Column('description', sa.UnicodeText(), nullable=True))
def downgrade():
op.drop_column('tag', 'description')

View file

@ -34,6 +34,7 @@ def test_creating_simple_tags(test_ctx, fake_datetime):
input={
'names': ['tag1', 'tag2'],
'category': 'meta',
'description': 'desc',
'suggestions': [],
'implications': [],
},
@ -43,6 +44,7 @@ def test_creating_simple_tags(test_ctx, fake_datetime):
assert result == {
'names': ['tag1', 'tag2'],
'category': 'meta',
'description': 'desc',
'suggestions': [],
'implications': [],
'creationTime': datetime.datetime(1997, 12, 1),

View file

@ -38,6 +38,7 @@ def test_merging_without_usages(test_ctx, fake_datetime):
assert result == {
'names': ['target'],
'category': 'meta',
'description': None,
'suggestions': [],
'implications': [],
'creationTime': datetime.datetime(1996, 1, 1),

View file

@ -50,6 +50,7 @@ def test_retrieving_single(test_ctx):
assert result == {
'names': ['tag'],
'category': 'dummy',
'description': None,
'creationTime': datetime.datetime(1996, 1, 1),
'lastEditTime': None,
'suggestions': [],

View file

@ -19,6 +19,7 @@ def test_ctx(
'tags:create': db.User.RANK_REGULAR,
'tags:edit:names': db.User.RANK_REGULAR,
'tags:edit:category': db.User.RANK_REGULAR,
'tags:edit:description': db.User.RANK_REGULAR,
'tags:edit:suggestions': db.User.RANK_REGULAR,
'tags:edit:implications': db.User.RANK_REGULAR,
},
@ -43,6 +44,7 @@ def test_simple_updating(test_ctx, fake_datetime):
input={
'names': ['tag3'],
'category': 'character',
'description': 'desc',
},
user=test_ctx.user_factory(rank=db.User.RANK_REGULAR)),
'tag1')
@ -51,6 +53,7 @@ def test_simple_updating(test_ctx, fake_datetime):
assert result == {
'names': ['tag3'],
'category': 'character',
'description': 'desc',
'suggestions': [],
'implications': [],
'creationTime': datetime.datetime(1996, 1, 1),
@ -91,13 +94,14 @@ def test_trying_to_pass_invalid_input(test_ctx, input, expected_exception):
'tag1')
@pytest.mark.parametrize(
'field', ['names', 'category', 'implications', 'suggestions'])
'field', ['names', 'category', 'description', 'implications', 'suggestions'])
def test_omitting_optional_field(test_ctx, field):
db.session.add(test_ctx.tag_factory(names=['tag'], category_name='meta'))
db.session.commit()
input = {
'names': ['tag1', 'tag2'],
'category': 'meta',
'description': 'desc',
'suggestions': [],
'implications': [],
}