server/tags: let mods set default category
This commit is contained in:
parent
4b3640bf2e
commit
77998f1660
34
API.md
34
API.md
|
@ -19,6 +19,7 @@
|
||||||
- [Updating tag category](#updating-tag-category)
|
- [Updating tag category](#updating-tag-category)
|
||||||
- [Getting tag category](#getting-tag-category)
|
- [Getting tag category](#getting-tag-category)
|
||||||
- [Deleting tag category](#deleting-tag-category)
|
- [Deleting tag category](#deleting-tag-category)
|
||||||
|
- [Setting default tag category](#setting-default-tag-category)
|
||||||
- Tags
|
- Tags
|
||||||
- [Listing tags](#listing-tags)
|
- [Listing tags](#listing-tags)
|
||||||
- [Creating tag](#creating-tag)
|
- [Creating tag](#creating-tag)
|
||||||
|
@ -185,7 +186,8 @@ data.
|
||||||
- **Description**
|
- **Description**
|
||||||
|
|
||||||
Creates a new tag category using specified parameters. Name must match
|
Creates a new tag category using specified parameters. Name must match
|
||||||
`tag_category_name_regex` from server's configuration.
|
`tag_category_name_regex` from server's configuration. First category
|
||||||
|
created becomes the default category.
|
||||||
|
|
||||||
## Updating tag category
|
## Updating tag category
|
||||||
- **Request**
|
- **Request**
|
||||||
|
@ -260,6 +262,31 @@ data.
|
||||||
Deletes existing tag category. The tag category to be deleted must have no
|
Deletes existing tag category. The tag category to be deleted must have no
|
||||||
usages.
|
usages.
|
||||||
|
|
||||||
|
## Setting default tag category
|
||||||
|
- **Request**
|
||||||
|
|
||||||
|
`PUT /tag-category/<name>/default`
|
||||||
|
|
||||||
|
- **Input**
|
||||||
|
|
||||||
|
```json5
|
||||||
|
{}
|
||||||
|
```
|
||||||
|
|
||||||
|
- **Output**
|
||||||
|
|
||||||
|
A [detailed tag category resource](#detailed-tag-category).
|
||||||
|
|
||||||
|
- **Errors**
|
||||||
|
|
||||||
|
- the tag category does not exist
|
||||||
|
- privileges are too low
|
||||||
|
|
||||||
|
- **Description**
|
||||||
|
|
||||||
|
Sets given tag category as default. All new tags created manually or
|
||||||
|
automatically will have this category.
|
||||||
|
|
||||||
## Listing tags
|
## Listing tags
|
||||||
- **Request**
|
- **Request**
|
||||||
|
|
||||||
|
@ -1405,6 +1432,7 @@ experience.
|
||||||
"name": <name>,
|
"name": <name>,
|
||||||
"color": <color>,
|
"color": <color>,
|
||||||
"usages": <usages>
|
"usages": <usages>
|
||||||
|
"default": <is_default>
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1413,6 +1441,7 @@ experience.
|
||||||
- `<name>`: the category name.
|
- `<name>`: the category name.
|
||||||
- `<color>`: the category color.
|
- `<color>`: the category color.
|
||||||
- `<usages>`: how many tags is the given category used with.
|
- `<usages>`: how many tags is the given category used with.
|
||||||
|
- `<is_default>`: whether the tag category is the default one.
|
||||||
|
|
||||||
## Detailed tag category
|
## Detailed tag category
|
||||||
**Description**
|
**Description**
|
||||||
|
@ -1723,7 +1752,8 @@ A snapshot is a version of a database resource.
|
||||||
```json5
|
```json5
|
||||||
{
|
{
|
||||||
"name": "character",
|
"name": "character",
|
||||||
"color": "#FF0000"
|
"color": "#FF0000",
|
||||||
|
"default": false
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -98,6 +98,7 @@ privileges:
|
||||||
'tag_categories:list': anonymous # note: will be available as data_url/tags.json anyway
|
'tag_categories:list': anonymous # note: will be available as data_url/tags.json anyway
|
||||||
'tag_categories:view': anonymous
|
'tag_categories:view': anonymous
|
||||||
'tag_categories:delete': moderator
|
'tag_categories:delete': moderator
|
||||||
|
'tag_categories:set_default': moderator
|
||||||
|
|
||||||
'comments:create': regular
|
'comments:create': regular
|
||||||
'comments:delete:any': moderator
|
'comments:delete:any': moderator
|
||||||
|
|
|
@ -9,7 +9,8 @@ from szurubooru.api.tag_api import (
|
||||||
TagSiblingsApi)
|
TagSiblingsApi)
|
||||||
from szurubooru.api.tag_category_api import (
|
from szurubooru.api.tag_category_api import (
|
||||||
TagCategoryListApi,
|
TagCategoryListApi,
|
||||||
TagCategoryDetailApi)
|
TagCategoryDetailApi,
|
||||||
|
DefaultTagCategoryApi)
|
||||||
from szurubooru.api.comment_api import (
|
from szurubooru.api.comment_api import (
|
||||||
CommentListApi,
|
CommentListApi,
|
||||||
CommentDetailApi,
|
CommentDetailApi,
|
||||||
|
|
|
@ -60,3 +60,13 @@ class TagCategoryDetailApi(BaseApi):
|
||||||
ctx.session.commit()
|
ctx.session.commit()
|
||||||
tags.export_to_json()
|
tags.export_to_json()
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
class DefaultTagCategoryApi(BaseApi):
|
||||||
|
def put(self, ctx, category_name):
|
||||||
|
auth.verify_privilege(ctx.user, 'tag_categories:set_default')
|
||||||
|
category = tag_categories.get_category_by_name(category_name)
|
||||||
|
tag_categories.set_default_category(category)
|
||||||
|
snapshots.save_entity_modification(category, ctx.user)
|
||||||
|
ctx.session.commit()
|
||||||
|
tags.export_to_json()
|
||||||
|
return tag_categories.serialize_category_with_details(category)
|
||||||
|
|
|
@ -98,6 +98,7 @@ def create_app():
|
||||||
|
|
||||||
app.add_route('/tag-categories/', api.TagCategoryListApi())
|
app.add_route('/tag-categories/', api.TagCategoryListApi())
|
||||||
app.add_route('/tag-category/{category_name}', api.TagCategoryDetailApi())
|
app.add_route('/tag-category/{category_name}', api.TagCategoryDetailApi())
|
||||||
|
app.add_route('/tag-category/{category_name}/default', api.DefaultTagCategoryApi())
|
||||||
app.add_route('/tags/', api.TagListApi())
|
app.add_route('/tags/', api.TagListApi())
|
||||||
app.add_route('/tag/{tag_name}', api.TagDetailApi())
|
app.add_route('/tag/{tag_name}', api.TagDetailApi())
|
||||||
app.add_route('/tag-merge/', api.TagMergeApi())
|
app.add_route('/tag-merge/', api.TagMergeApi())
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from sqlalchemy import Column, Integer, Unicode, table
|
from sqlalchemy import Column, Integer, Unicode, Boolean, table
|
||||||
from sqlalchemy.orm import column_property
|
from sqlalchemy.orm import column_property
|
||||||
from sqlalchemy.sql.expression import func, select
|
from sqlalchemy.sql.expression import func, select
|
||||||
from szurubooru.db.base import Base
|
from szurubooru.db.base import Base
|
||||||
|
@ -10,6 +10,7 @@ class TagCategory(Base):
|
||||||
tag_category_id = Column('id', Integer, primary_key=True)
|
tag_category_id = Column('id', Integer, primary_key=True)
|
||||||
name = Column('name', Unicode(32), nullable=False)
|
name = Column('name', Unicode(32), nullable=False)
|
||||||
color = Column('color', Unicode(32), nullable=False, default='#000000')
|
color = Column('color', Unicode(32), nullable=False, default='#000000')
|
||||||
|
default = Column('default', Boolean, nullable=False, default=False)
|
||||||
|
|
||||||
def __init__(self, name=None):
|
def __init__(self, name=None):
|
||||||
self.name = name
|
self.name = name
|
||||||
|
|
|
@ -28,6 +28,7 @@ def get_tag_category_snapshot(category):
|
||||||
return {
|
return {
|
||||||
'name': category.name,
|
'name': category.name,
|
||||||
'color': category.color,
|
'color': category.color,
|
||||||
|
'default': True if category.default else False,
|
||||||
}
|
}
|
||||||
|
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
|
|
|
@ -19,6 +19,7 @@ def serialize_category(category):
|
||||||
'name': category.name,
|
'name': category.name,
|
||||||
'color': category.color,
|
'color': category.color,
|
||||||
'usages': category.tag_count,
|
'usages': category.tag_count,
|
||||||
|
'default': category.default,
|
||||||
}
|
}
|
||||||
|
|
||||||
def serialize_category_with_details(category):
|
def serialize_category_with_details(category):
|
||||||
|
@ -31,6 +32,8 @@ def create_category(name, color):
|
||||||
category = db.TagCategory()
|
category = db.TagCategory()
|
||||||
update_category_name(category, name)
|
update_category_name(category, name)
|
||||||
update_category_color(category, color)
|
update_category_color(category, color)
|
||||||
|
if not get_all_categories():
|
||||||
|
category.default = True
|
||||||
return category
|
return category
|
||||||
|
|
||||||
def update_category_name(category, name):
|
def update_category_name(category, name):
|
||||||
|
@ -76,14 +79,27 @@ def get_all_categories():
|
||||||
return db.session.query(db.TagCategory).all()
|
return db.session.query(db.TagCategory).all()
|
||||||
|
|
||||||
def try_get_default_category():
|
def try_get_default_category():
|
||||||
return db.session \
|
category = db.session \
|
||||||
|
.query(db.TagCategory) \
|
||||||
|
.filter(db.TagCategory.default) \
|
||||||
|
.first()
|
||||||
|
# if for some reason (e.g. as a result of migration) there's no default
|
||||||
|
# category, get the first record available.
|
||||||
|
if not category:
|
||||||
|
category = db.session \
|
||||||
.query(db.TagCategory) \
|
.query(db.TagCategory) \
|
||||||
.order_by(db.TagCategory.tag_category_id.asc()) \
|
.order_by(db.TagCategory.tag_category_id.asc()) \
|
||||||
.limit(1) \
|
|
||||||
.first()
|
.first()
|
||||||
|
return category
|
||||||
|
|
||||||
def get_default_category():
|
def get_default_category():
|
||||||
category = try_get_default_category()
|
category = try_get_default_category()
|
||||||
if not category:
|
if not category:
|
||||||
raise TagCategoryNotFoundError('No tag category created yet.')
|
raise TagCategoryNotFoundError('No tag category created yet.')
|
||||||
return category
|
return category
|
||||||
|
|
||||||
|
def set_default_category(category):
|
||||||
|
old_category = try_get_default_category()
|
||||||
|
if old_category:
|
||||||
|
old_category.default = False
|
||||||
|
category.default = True
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
'''
|
||||||
|
Add default column to tag categories
|
||||||
|
|
||||||
|
Revision ID: 055d0e048fb3
|
||||||
|
Created at: 2016-05-22 18:12:58.149678
|
||||||
|
'''
|
||||||
|
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from alembic import op
|
||||||
|
|
||||||
|
revision = '055d0e048fb3'
|
||||||
|
down_revision = '49ab4e1139ef'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
op.add_column('tag_category', sa.Column('default', sa.Boolean(), nullable=True))
|
||||||
|
op.execute(sa.table('tag_category', sa.column('default')).update().values(default=False))
|
||||||
|
op.alter_column('tag_category', 'default', nullable=False)
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
op.drop_column('tag_category', 'default')
|
|
@ -25,6 +25,7 @@ def test_creating_category(test_ctx):
|
||||||
'name': 'meta',
|
'name': 'meta',
|
||||||
'color': 'black',
|
'color': 'black',
|
||||||
'usages': 0,
|
'usages': 0,
|
||||||
|
'default': True,
|
||||||
}
|
}
|
||||||
assert len(result['snapshots']) == 1
|
assert len(result['snapshots']) == 1
|
||||||
category = db.session.query(db.TagCategory).one()
|
category = db.session.query(db.TagCategory).one()
|
||||||
|
|
|
@ -42,6 +42,7 @@ def test_retrieving_single(test_ctx):
|
||||||
'name': 'cat',
|
'name': 'cat',
|
||||||
'color': 'dummy',
|
'color': 'dummy',
|
||||||
'usages': 0,
|
'usages': 0,
|
||||||
|
'default': False,
|
||||||
},
|
},
|
||||||
'snapshots': [],
|
'snapshots': [],
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@ def test_simple_updating(test_ctx):
|
||||||
'name': 'changed',
|
'name': 'changed',
|
||||||
'color': 'white',
|
'color': 'white',
|
||||||
'usages': 0,
|
'usages': 0,
|
||||||
|
'default': False,
|
||||||
}
|
}
|
||||||
assert len(result['snapshots']) == 1
|
assert len(result['snapshots']) == 1
|
||||||
assert tag_categories.try_get_category_by_name('name') is None
|
assert tag_categories.try_get_category_by_name('name') is None
|
||||||
|
|
|
@ -92,6 +92,13 @@ def test_serializing_tag_category(tag_category_factory):
|
||||||
assert snapshots.get_tag_category_snapshot(category) == {
|
assert snapshots.get_tag_category_snapshot(category) == {
|
||||||
'name': 'name',
|
'name': 'name',
|
||||||
'color': 'color',
|
'color': 'color',
|
||||||
|
'default': False,
|
||||||
|
}
|
||||||
|
category.default = True
|
||||||
|
assert snapshots.get_tag_category_snapshot(category) == {
|
||||||
|
'name': 'name',
|
||||||
|
'color': 'color',
|
||||||
|
'default': True,
|
||||||
}
|
}
|
||||||
|
|
||||||
def test_merging_modification_to_creation(tag_factory, user_factory):
|
def test_merging_modification_to_creation(tag_factory, user_factory):
|
||||||
|
|
Loading…
Reference in New Issue