Set theme override
This commit is contained in:
parent
a79f0ffd6a
commit
0ad9cff7a0
@ -11,10 +11,10 @@ from .parser import parse_set
|
|||||||
from .rebrickable import Rebrickable
|
from .rebrickable import Rebrickable
|
||||||
from .rebrickable_image import RebrickableImage
|
from .rebrickable_image import RebrickableImage
|
||||||
from .record import BrickRecord
|
from .record import BrickRecord
|
||||||
|
from .theme import BrickTheme
|
||||||
from .theme_list import BrickThemeList
|
from .theme_list import BrickThemeList
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from .socket import BrickSocket
|
from .socket import BrickSocket
|
||||||
from .theme import BrickTheme
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -66,7 +66,13 @@ class RebrickableSet(BrickRecord):
|
|||||||
if not hasattr(self.fields, 'theme_id'):
|
if not hasattr(self.fields, 'theme_id'):
|
||||||
self.fields.theme_id = 0
|
self.fields.theme_id = 0
|
||||||
|
|
||||||
self.theme = BrickThemeList().get(self.fields.theme_id)
|
if not hasattr(self.fields, 'theme_name'):
|
||||||
|
self.fields.theme_name = None
|
||||||
|
|
||||||
|
self.theme = BrickThemeList().get(
|
||||||
|
str(self.fields.theme_id),
|
||||||
|
name=self.fields.theme_name
|
||||||
|
)
|
||||||
|
|
||||||
# Resolve instructions
|
# Resolve instructions
|
||||||
if self.resolve_instructions:
|
if self.resolve_instructions:
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import logging
|
import logging
|
||||||
|
from sqlite3 import Row
|
||||||
import traceback
|
import traceback
|
||||||
from typing import Any, Self, TYPE_CHECKING
|
from typing import Any, Self, TYPE_CHECKING
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
|
||||||
from flask import current_app, url_for
|
from flask import current_app, url_for
|
||||||
|
|
||||||
from .exceptions import DatabaseException, NotFoundException
|
from .exceptions import DatabaseException, ErrorException, NotFoundException
|
||||||
from .minifigure_list import BrickMinifigureList
|
from .minifigure_list import BrickMinifigureList
|
||||||
from .part_list import BrickPartList
|
from .part_list import BrickPartList
|
||||||
from .rebrickable_set import RebrickableSet
|
from .rebrickable_set import RebrickableSet
|
||||||
@ -121,6 +122,29 @@ class BrickSet(RebrickableSet):
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
# Ingest a set
|
||||||
|
def ingest(self, record: Row | dict[str, Any], /):
|
||||||
|
# Super charge the record with theme override
|
||||||
|
if 'theme' in record.keys() and record['theme'] is not None:
|
||||||
|
if isinstance(record, Row):
|
||||||
|
record = dict(record)
|
||||||
|
|
||||||
|
record['theme_id'] = record['theme']
|
||||||
|
record['theme_name'] = record['theme']
|
||||||
|
|
||||||
|
super().ingest(record)
|
||||||
|
|
||||||
|
# A identifier for HTML component
|
||||||
|
def html_id(self, prefix: str | None = None, /) -> str:
|
||||||
|
components: list[str] = []
|
||||||
|
|
||||||
|
if prefix is not None:
|
||||||
|
components.append(prefix)
|
||||||
|
|
||||||
|
components.append(self.fields.id)
|
||||||
|
|
||||||
|
return '-'.join(components)
|
||||||
|
|
||||||
# Minifigures
|
# Minifigures
|
||||||
def minifigures(self, /) -> BrickMinifigureList:
|
def minifigures(self, /) -> BrickMinifigureList:
|
||||||
return BrickMinifigureList().from_set(self)
|
return BrickMinifigureList().from_set(self)
|
||||||
@ -185,6 +209,36 @@ class BrickSet(RebrickableSet):
|
|||||||
id=self.fields.id,
|
id=self.fields.id,
|
||||||
))
|
))
|
||||||
|
|
||||||
|
# Update theme
|
||||||
|
def update_theme(self, json: Any | None, /) -> None:
|
||||||
|
theme: str | None = json.get('value', '') # type: ignore
|
||||||
|
|
||||||
|
# We need a string
|
||||||
|
try:
|
||||||
|
theme = str(theme)
|
||||||
|
theme = theme.strip()
|
||||||
|
except Exception:
|
||||||
|
raise ErrorException('"{theme}" is not a valid string'.format(
|
||||||
|
theme=theme
|
||||||
|
))
|
||||||
|
|
||||||
|
if theme == '':
|
||||||
|
theme = None
|
||||||
|
|
||||||
|
self.fields.theme = theme
|
||||||
|
|
||||||
|
# Update the status
|
||||||
|
rows, _ = BrickSQL().execute_and_commit(
|
||||||
|
'set/update/theme',
|
||||||
|
parameters=self.sql_parameters()
|
||||||
|
)
|
||||||
|
|
||||||
|
if rows != 1:
|
||||||
|
raise DatabaseException('Could not update the theme override for set {set} ({id})'.format( # noqa: E501
|
||||||
|
set=self.fields.set,
|
||||||
|
id=self.fields.id,
|
||||||
|
))
|
||||||
|
|
||||||
# Self url
|
# Self url
|
||||||
def url(self, /) -> str:
|
def url(self, /) -> str:
|
||||||
return url_for('set.details', id=self.fields.id)
|
return url_for('set.details', id=self.fields.id)
|
||||||
@ -217,3 +271,10 @@ class BrickSet(RebrickableSet):
|
|||||||
'set.refresh',
|
'set.refresh',
|
||||||
id=self.fields.id,
|
id=self.fields.id,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Compute the url for the theme override
|
||||||
|
def url_for_theme(self, /) -> str:
|
||||||
|
return url_for(
|
||||||
|
'set.update_theme',
|
||||||
|
id=self.fields.id,
|
||||||
|
)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
SELECT
|
SELECT
|
||||||
{% block id %}{% endblock %}
|
{% block id %}{% endblock %}
|
||||||
|
"bricktracker_sets"."theme",
|
||||||
"rebrickable_sets"."set",
|
"rebrickable_sets"."set",
|
||||||
"rebrickable_sets"."number",
|
"rebrickable_sets"."number",
|
||||||
"rebrickable_sets"."version",
|
"rebrickable_sets"."version",
|
||||||
|
3
bricktracker/sql/set/update/theme.sql
Normal file
3
bricktracker/sql/set/update/theme.sql
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
UPDATE "bricktracker_sets"
|
||||||
|
SET "theme" = :theme
|
||||||
|
WHERE "bricktracker_sets"."id" IS NOT DISTINCT FROM :id
|
@ -1,14 +1,14 @@
|
|||||||
# Lego set theme
|
# Lego set theme
|
||||||
class BrickTheme(object):
|
class BrickTheme(object):
|
||||||
id: int
|
id: str
|
||||||
name: str
|
name: str
|
||||||
parent: int | None
|
parent: str | None
|
||||||
|
|
||||||
def __init__(self, id: str | int, name: str, parent: str | None = None, /):
|
def __init__(self, id: str, name: str, parent: str | None = None, /):
|
||||||
self.id = int(id)
|
self.id = id
|
||||||
self.name = name
|
self.name = name
|
||||||
|
|
||||||
if parent is not None and parent != '':
|
if parent is not None and parent != '':
|
||||||
self.parent = int(parent)
|
self.parent = parent
|
||||||
else:
|
else:
|
||||||
self.parent = None
|
self.parent = None
|
||||||
|
@ -17,7 +17,7 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
# Lego sets themes
|
# Lego sets themes
|
||||||
class BrickThemeList(object):
|
class BrickThemeList(object):
|
||||||
themes: dict[int, BrickTheme]
|
themes: dict[str, BrickTheme]
|
||||||
mtime: datetime | None
|
mtime: datetime | None
|
||||||
size: int | None
|
size: int | None
|
||||||
exception: Exception | None
|
exception: Exception | None
|
||||||
@ -57,12 +57,15 @@ class BrickThemeList(object):
|
|||||||
BrickThemeList.mtime = None
|
BrickThemeList.mtime = None
|
||||||
|
|
||||||
# Get a theme
|
# Get a theme
|
||||||
def get(self, id: int, /) -> BrickTheme:
|
def get(self, id: str, /, *, name: str | None = None) -> BrickTheme:
|
||||||
# Seed a fake entry if missing
|
# Seed a fake entry if missing
|
||||||
if id not in self.themes:
|
if id not in self.themes:
|
||||||
|
if name is None:
|
||||||
|
name = 'Unknown ({id})'.format(id=id)
|
||||||
|
|
||||||
BrickThemeList.themes[id] = BrickTheme(
|
BrickThemeList.themes[id] = BrickTheme(
|
||||||
id,
|
id,
|
||||||
'Unknown ({id})'.format(id=id)
|
name,
|
||||||
)
|
)
|
||||||
|
|
||||||
return self.themes[id]
|
return self.themes[id]
|
||||||
|
@ -167,3 +167,22 @@ def refresh(*, id: str) -> str:
|
|||||||
namespace=current_app.config['SOCKET_NAMESPACE'],
|
namespace=current_app.config['SOCKET_NAMESPACE'],
|
||||||
messages=MESSAGES
|
messages=MESSAGES
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Change the theme override
|
||||||
|
@set_page.route('/<id>/theme', methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
@exception_handler(__file__, json=True)
|
||||||
|
def update_theme(*, id: str) -> Response:
|
||||||
|
brickset = BrickSet().select_light(id)
|
||||||
|
|
||||||
|
brickset.update_theme(request.json)
|
||||||
|
|
||||||
|
# Info
|
||||||
|
logger.info('Set {set} ({id}): theme override changed to "{theme}"'.format( # noqa: E501
|
||||||
|
set=brickset.fields.set,
|
||||||
|
id=brickset.fields.id,
|
||||||
|
theme=brickset.fields.theme,
|
||||||
|
))
|
||||||
|
|
||||||
|
return jsonify({'value': brickset.fields.theme})
|
||||||
|
@ -1,5 +1,11 @@
|
|||||||
{% if g.login.is_authenticated() %}
|
{% if g.login.is_authenticated() %}
|
||||||
{{ accordion.header('Management', 'management', 'set-details', icon='settings-4-line', class='text-end') }}
|
{{ accordion.header('Management', 'management', 'set-details', expanded=true, icon='settings-4-line') }}
|
||||||
|
<h5>Theme override</h5>
|
||||||
|
<p>
|
||||||
|
You can override the current theme ({{ badge.theme(item.theme.name, solo=solo, last=last) }}) with any string you want.
|
||||||
|
{{ form.input('Theme', item.fields.id, item.html_id('theme'), item.url_for_theme(), item.fields.theme, all=all, read_only=read_only) }}
|
||||||
|
</p>
|
||||||
|
<h5 class="border-bottom">Data</h5>
|
||||||
<a href="{{ item.url_for_refresh() }}" class="btn btn-primary" role="button"><i class="ri-refresh-line"></i> Refresh the set data</a>
|
<a href="{{ item.url_for_refresh() }}" class="btn btn-primary" role="button"><i class="ri-refresh-line"></i> Refresh the set data</a>
|
||||||
{{ accordion.footer() }}
|
{{ accordion.footer() }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
Loading…
Reference in New Issue
Block a user