server/tags: let mods set default category
This commit is contained in:
parent
4b3640bf2e
commit
77998f1660
13 changed files with 100 additions and 7 deletions
34
API.md
34
API.md
|
@ -19,6 +19,7 @@
|
|||
- [Updating tag category](#updating-tag-category)
|
||||
- [Getting tag category](#getting-tag-category)
|
||||
- [Deleting tag category](#deleting-tag-category)
|
||||
- [Setting default tag category](#setting-default-tag-category)
|
||||
- Tags
|
||||
- [Listing tags](#listing-tags)
|
||||
- [Creating tag](#creating-tag)
|
||||
|
@ -185,7 +186,8 @@ data.
|
|||
- **Description**
|
||||
|
||||
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
|
||||
- **Request**
|
||||
|
@ -260,6 +262,31 @@ data.
|
|||
Deletes existing tag category. The tag category to be deleted must have no
|
||||
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
|
||||
- **Request**
|
||||
|
||||
|
@ -1405,6 +1432,7 @@ experience.
|
|||
"name": <name>,
|
||||
"color": <color>,
|
||||
"usages": <usages>
|
||||
"default": <is_default>
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -1413,6 +1441,7 @@ experience.
|
|||
- `<name>`: the category name.
|
||||
- `<color>`: the category color.
|
||||
- `<usages>`: how many tags is the given category used with.
|
||||
- `<is_default>`: whether the tag category is the default one.
|
||||
|
||||
## Detailed tag category
|
||||
**Description**
|
||||
|
@ -1723,7 +1752,8 @@ A snapshot is a version of a database resource.
|
|||
```json5
|
||||
{
|
||||
"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:view': anonymous
|
||||
'tag_categories:delete': moderator
|
||||
'tag_categories:set_default': moderator
|
||||
|
||||
'comments:create': regular
|
||||
'comments:delete:any': moderator
|
||||
|
|
|
@ -9,7 +9,8 @@ from szurubooru.api.tag_api import (
|
|||
TagSiblingsApi)
|
||||
from szurubooru.api.tag_category_api import (
|
||||
TagCategoryListApi,
|
||||
TagCategoryDetailApi)
|
||||
TagCategoryDetailApi,
|
||||
DefaultTagCategoryApi)
|
||||
from szurubooru.api.comment_api import (
|
||||
CommentListApi,
|
||||
CommentDetailApi,
|
||||
|
|
|
@ -60,3 +60,13 @@ class TagCategoryDetailApi(BaseApi):
|
|||
ctx.session.commit()
|
||||
tags.export_to_json()
|
||||
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-category/{category_name}', api.TagCategoryDetailApi())
|
||||
app.add_route('/tag-category/{category_name}/default', api.DefaultTagCategoryApi())
|
||||
app.add_route('/tags/', api.TagListApi())
|
||||
app.add_route('/tag/{tag_name}', api.TagDetailApi())
|
||||
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.sql.expression import func, select
|
||||
from szurubooru.db.base import Base
|
||||
|
@ -10,6 +10,7 @@ class TagCategory(Base):
|
|||
tag_category_id = Column('id', Integer, primary_key=True)
|
||||
name = Column('name', Unicode(32), nullable=False)
|
||||
color = Column('color', Unicode(32), nullable=False, default='#000000')
|
||||
default = Column('default', Boolean, nullable=False, default=False)
|
||||
|
||||
def __init__(self, name=None):
|
||||
self.name = name
|
||||
|
|
|
@ -28,6 +28,7 @@ def get_tag_category_snapshot(category):
|
|||
return {
|
||||
'name': category.name,
|
||||
'color': category.color,
|
||||
'default': True if category.default else False,
|
||||
}
|
||||
|
||||
# pylint: disable=invalid-name
|
||||
|
|
|
@ -19,6 +19,7 @@ def serialize_category(category):
|
|||
'name': category.name,
|
||||
'color': category.color,
|
||||
'usages': category.tag_count,
|
||||
'default': category.default,
|
||||
}
|
||||
|
||||
def serialize_category_with_details(category):
|
||||
|
@ -31,6 +32,8 @@ def create_category(name, color):
|
|||
category = db.TagCategory()
|
||||
update_category_name(category, name)
|
||||
update_category_color(category, color)
|
||||
if not get_all_categories():
|
||||
category.default = True
|
||||
return category
|
||||
|
||||
def update_category_name(category, name):
|
||||
|
@ -76,14 +79,27 @@ def get_all_categories():
|
|||
return db.session.query(db.TagCategory).all()
|
||||
|
||||
def try_get_default_category():
|
||||
return db.session \
|
||||
category = db.session \
|
||||
.query(db.TagCategory) \
|
||||
.order_by(db.TagCategory.tag_category_id.asc()) \
|
||||
.limit(1) \
|
||||
.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) \
|
||||
.order_by(db.TagCategory.tag_category_id.asc()) \
|
||||
.first()
|
||||
return category
|
||||
|
||||
def get_default_category():
|
||||
category = try_get_default_category()
|
||||
if not category:
|
||||
raise TagCategoryNotFoundError('No tag category created yet.')
|
||||
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',
|
||||
'color': 'black',
|
||||
'usages': 0,
|
||||
'default': True,
|
||||
}
|
||||
assert len(result['snapshots']) == 1
|
||||
category = db.session.query(db.TagCategory).one()
|
||||
|
|
|
@ -42,6 +42,7 @@ def test_retrieving_single(test_ctx):
|
|||
'name': 'cat',
|
||||
'color': 'dummy',
|
||||
'usages': 0,
|
||||
'default': False,
|
||||
},
|
||||
'snapshots': [],
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ def test_simple_updating(test_ctx):
|
|||
'name': 'changed',
|
||||
'color': 'white',
|
||||
'usages': 0,
|
||||
'default': False,
|
||||
}
|
||||
assert len(result['snapshots']) == 1
|
||||
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) == {
|
||||
'name': 'name',
|
||||
'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):
|
||||
|
|
Loading…
Reference in a new issue