2025-01-17 11:03:00 +01:00
|
|
|
import logging
|
|
|
|
|
|
|
|
from flask import (
|
|
|
|
Blueprint,
|
2025-01-28 23:07:12 +01:00
|
|
|
current_app,
|
2025-01-17 11:03:00 +01:00
|
|
|
jsonify,
|
|
|
|
render_template,
|
|
|
|
redirect,
|
|
|
|
request,
|
|
|
|
url_for,
|
|
|
|
)
|
|
|
|
from flask_login import login_required
|
|
|
|
from werkzeug.wrappers.response import Response
|
|
|
|
|
|
|
|
from .exceptions import exception_handler
|
|
|
|
from ..minifigure import BrickMinifigure
|
|
|
|
from ..part import BrickPart
|
|
|
|
from ..set import BrickSet
|
2025-02-04 10:08:25 +01:00
|
|
|
from ..set_list import BrickSetList, set_metadata_lists
|
2025-01-31 16:34:52 +01:00
|
|
|
from ..set_owner_list import BrickSetOwnerList
|
2025-02-04 12:52:18 +01:00
|
|
|
from ..set_purchase_location_list import BrickSetPurchaseLocationList
|
2025-01-30 15:03:16 +01:00
|
|
|
from ..set_status_list import BrickSetStatusList
|
2025-02-03 16:46:45 +01:00
|
|
|
from ..set_storage_list import BrickSetStorageList
|
2025-01-31 18:08:53 +01:00
|
|
|
from ..set_tag_list import BrickSetTagList
|
2025-01-28 23:07:12 +01:00
|
|
|
from ..socket import MESSAGES
|
2025-01-17 11:03:00 +01:00
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
set_page = Blueprint('set', __name__, url_prefix='/sets')
|
|
|
|
|
|
|
|
|
|
|
|
# List of all sets
|
|
|
|
@set_page.route('/', methods=['GET'])
|
|
|
|
@exception_handler(__file__)
|
|
|
|
def list() -> str:
|
2025-01-24 10:36:24 +01:00
|
|
|
return render_template(
|
|
|
|
'sets.html',
|
|
|
|
collection=BrickSetList().all(),
|
2025-02-03 16:46:45 +01:00
|
|
|
brickset_statuses=BrickSetStatusList.list(),
|
2025-02-04 10:08:25 +01:00
|
|
|
**set_metadata_lists(as_class=True)
|
2025-01-24 10:36:24 +01:00
|
|
|
)
|
2025-01-17 11:03:00 +01:00
|
|
|
|
|
|
|
|
2025-02-04 12:52:18 +01:00
|
|
|
# Change the value of purchase location
|
|
|
|
@set_page.route('/<id>/purchase_location', methods=['POST'])
|
|
|
|
@login_required
|
|
|
|
@exception_handler(__file__, json=True)
|
|
|
|
def update_purchase_location(*, id: str) -> Response:
|
|
|
|
brickset = BrickSet().select_light(id)
|
|
|
|
purchase_location = BrickSetPurchaseLocationList.get(
|
|
|
|
request.json.get('value', ''), # type: ignore
|
|
|
|
allow_none=True
|
|
|
|
)
|
|
|
|
|
|
|
|
value = purchase_location.update_set_value(
|
|
|
|
brickset,
|
|
|
|
value=purchase_location.fields.id
|
|
|
|
)
|
|
|
|
|
|
|
|
return jsonify({'value': value})
|
|
|
|
|
|
|
|
|
2025-01-31 16:34:52 +01:00
|
|
|
# Change the state of a owner
|
|
|
|
@set_page.route('/<id>/owner/<metadata_id>', methods=['POST'])
|
|
|
|
@login_required
|
|
|
|
@exception_handler(__file__, json=True)
|
|
|
|
def update_owner(*, id: str, metadata_id: str) -> Response:
|
|
|
|
brickset = BrickSet().select_light(id)
|
2025-02-03 16:46:45 +01:00
|
|
|
owner = BrickSetOwnerList.get(metadata_id)
|
2025-01-31 16:34:52 +01:00
|
|
|
|
|
|
|
state = owner.update_set_state(brickset, json=request.json)
|
|
|
|
|
|
|
|
return jsonify({'value': state})
|
|
|
|
|
|
|
|
|
|
|
|
# Change the state of a status
|
2025-01-30 12:17:25 +01:00
|
|
|
@set_page.route('/<id>/status/<metadata_id>', methods=['POST'])
|
2025-01-17 11:03:00 +01:00
|
|
|
@login_required
|
|
|
|
@exception_handler(__file__, json=True)
|
2025-01-30 12:17:25 +01:00
|
|
|
def update_status(*, id: str, metadata_id: str) -> Response:
|
2025-01-24 10:36:24 +01:00
|
|
|
brickset = BrickSet().select_light(id)
|
2025-02-03 16:46:45 +01:00
|
|
|
status = BrickSetStatusList.get(metadata_id)
|
2025-01-17 11:03:00 +01:00
|
|
|
|
2025-01-31 18:37:44 +01:00
|
|
|
state = status.update_set_state(brickset, json=request.json)
|
2025-01-17 11:03:00 +01:00
|
|
|
|
2025-01-30 12:17:25 +01:00
|
|
|
return jsonify({'value': state})
|
2025-01-17 11:03:00 +01:00
|
|
|
|
|
|
|
|
2025-02-04 12:34:19 +01:00
|
|
|
# Change the value of storage
|
2025-02-03 16:46:45 +01:00
|
|
|
@set_page.route('/<id>/storage', methods=['POST'])
|
|
|
|
@login_required
|
|
|
|
@exception_handler(__file__, json=True)
|
|
|
|
def update_storage(*, id: str) -> Response:
|
|
|
|
brickset = BrickSet().select_light(id)
|
|
|
|
storage = BrickSetStorageList.get(
|
|
|
|
request.json.get('value', ''), # type: ignore
|
|
|
|
allow_none=True
|
|
|
|
)
|
|
|
|
|
2025-02-04 10:37:43 +01:00
|
|
|
value = storage.update_set_value(brickset, value=storage.fields.id)
|
2025-02-03 16:46:45 +01:00
|
|
|
|
2025-02-04 10:37:43 +01:00
|
|
|
return jsonify({'value': value})
|
2025-02-03 16:46:45 +01:00
|
|
|
|
|
|
|
|
2025-01-31 18:08:53 +01:00
|
|
|
# Change the state of a tag
|
|
|
|
@set_page.route('/<id>/tag/<metadata_id>', methods=['POST'])
|
|
|
|
@login_required
|
|
|
|
@exception_handler(__file__, json=True)
|
|
|
|
def update_tag(*, id: str, metadata_id: str) -> Response:
|
|
|
|
brickset = BrickSet().select_light(id)
|
2025-02-03 16:46:45 +01:00
|
|
|
tag = BrickSetTagList.get(metadata_id)
|
2025-01-31 18:08:53 +01:00
|
|
|
|
|
|
|
state = tag.update_set_state(brickset, json=request.json)
|
|
|
|
|
|
|
|
return jsonify({'value': state})
|
|
|
|
|
|
|
|
|
2025-01-17 11:03:00 +01:00
|
|
|
# Ask for deletion of a set
|
|
|
|
@set_page.route('/<id>/delete', methods=['GET'])
|
|
|
|
@login_required
|
|
|
|
@exception_handler(__file__)
|
|
|
|
def delete(*, id: str) -> str:
|
|
|
|
return render_template(
|
|
|
|
'delete.html',
|
|
|
|
item=BrickSet().select_specific(id),
|
|
|
|
error=request.args.get('error'),
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# Actually delete of a set
|
|
|
|
@set_page.route('/<id>/delete', methods=['POST'])
|
2025-01-29 17:41:34 +01:00
|
|
|
@login_required
|
2025-01-17 11:03:00 +01:00
|
|
|
@exception_handler(__file__, post_redirect='set.delete')
|
|
|
|
def do_delete(*, id: str) -> Response:
|
2025-01-24 10:36:24 +01:00
|
|
|
brickset = BrickSet().select_light(id)
|
2025-01-17 11:03:00 +01:00
|
|
|
brickset.delete()
|
|
|
|
|
|
|
|
# Info
|
2025-01-27 18:40:51 +01:00
|
|
|
logger.info('Set {set} ({id}): deleted'.format(
|
|
|
|
set=brickset.fields.set,
|
2025-01-24 10:36:24 +01:00
|
|
|
id=brickset.fields.id,
|
2025-01-17 11:03:00 +01:00
|
|
|
))
|
|
|
|
|
|
|
|
return redirect(url_for('set.deleted', id=id))
|
|
|
|
|
|
|
|
|
|
|
|
# Set is deleted
|
|
|
|
@set_page.route('/<id>/deleted', methods=['GET'])
|
2025-01-29 17:41:34 +01:00
|
|
|
@login_required
|
2025-01-17 11:03:00 +01:00
|
|
|
@exception_handler(__file__)
|
|
|
|
def deleted(*, id: str) -> str:
|
|
|
|
return render_template(
|
|
|
|
'success.html',
|
|
|
|
message='Set "{id}" has been successfuly deleted.'.format(id=id),
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# Details of one set
|
|
|
|
@set_page.route('/<id>/details', methods=['GET'])
|
|
|
|
@exception_handler(__file__)
|
|
|
|
def details(*, id: str) -> str:
|
|
|
|
return render_template(
|
|
|
|
'set.html',
|
|
|
|
item=BrickSet().select_specific(id),
|
|
|
|
open_instructions=request.args.get('open_instructions'),
|
2025-02-03 16:46:45 +01:00
|
|
|
brickset_statuses=BrickSetStatusList.list(all=True),
|
2025-02-04 10:08:25 +01:00
|
|
|
**set_metadata_lists(as_class=True)
|
2025-01-17 11:03:00 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
|
2025-01-31 20:46:36 +01:00
|
|
|
# Update problematic pieces of a set
|
|
|
|
@set_page.route('/<id>/parts/<part>/<int:color>/<int:spare>/<problem>', defaults={'figure': None}, methods=['POST']) # noqa: E501
|
|
|
|
@set_page.route('/<id>/minifigures/<figure>/parts/<part>/<int:color>/<int:spare>/<problem>', methods=['POST']) # noqa: E501
|
2025-01-17 11:03:00 +01:00
|
|
|
@login_required
|
|
|
|
@exception_handler(__file__, json=True)
|
2025-01-31 20:46:36 +01:00
|
|
|
def problem_part(
|
2025-01-28 19:18:51 +01:00
|
|
|
*,
|
|
|
|
id: str,
|
|
|
|
figure: str | None,
|
|
|
|
part: str,
|
|
|
|
color: int,
|
|
|
|
spare: int,
|
2025-01-31 20:46:36 +01:00
|
|
|
problem: str,
|
2025-01-28 19:18:51 +01:00
|
|
|
) -> Response:
|
2025-01-17 11:03:00 +01:00
|
|
|
brickset = BrickSet().select_specific(id)
|
2025-01-28 19:18:51 +01:00
|
|
|
|
|
|
|
if figure is not None:
|
|
|
|
brickminifigure = BrickMinifigure().select_specific(brickset, figure)
|
|
|
|
else:
|
|
|
|
brickminifigure = None
|
|
|
|
|
2025-01-27 11:21:15 +01:00
|
|
|
brickpart = BrickPart().select_specific(
|
2025-01-17 11:03:00 +01:00
|
|
|
brickset,
|
2025-01-27 11:21:15 +01:00
|
|
|
part,
|
2025-01-28 19:18:51 +01:00
|
|
|
color,
|
|
|
|
spare,
|
2025-01-27 11:21:15 +01:00
|
|
|
minifigure=brickminifigure,
|
2025-01-17 11:03:00 +01:00
|
|
|
)
|
|
|
|
|
2025-01-31 20:46:36 +01:00
|
|
|
amount = brickpart.update_problem(problem, request.json)
|
2025-01-17 11:03:00 +01:00
|
|
|
|
|
|
|
# Info
|
2025-01-31 20:46:36 +01:00
|
|
|
logger.info('Set {set} ({id}): updated part ({part} color: {color}, spare: {spare}, minifigure: {figure}) {problem} count to {amount}'.format( # noqa: E501
|
2025-01-27 18:40:51 +01:00
|
|
|
set=brickset.fields.set,
|
2025-01-24 10:36:24 +01:00
|
|
|
id=brickset.fields.id,
|
2025-01-28 19:18:51 +01:00
|
|
|
figure=figure,
|
|
|
|
part=brickpart.fields.part,
|
|
|
|
color=brickpart.fields.color,
|
|
|
|
spare=brickpart.fields.spare,
|
2025-01-31 20:46:36 +01:00
|
|
|
problem=problem,
|
|
|
|
amount=amount
|
2025-01-17 11:03:00 +01:00
|
|
|
))
|
|
|
|
|
2025-01-31 20:46:36 +01:00
|
|
|
return jsonify({problem: amount})
|
2025-01-28 23:07:12 +01:00
|
|
|
|
|
|
|
|
|
|
|
# Refresh a set
|
|
|
|
@set_page.route('/<id>/refresh', methods=['GET'])
|
2025-01-29 17:41:34 +01:00
|
|
|
@login_required
|
2025-01-28 23:07:12 +01:00
|
|
|
@exception_handler(__file__)
|
|
|
|
def refresh(*, id: str) -> str:
|
|
|
|
return render_template(
|
|
|
|
'refresh.html',
|
|
|
|
item=BrickSet().select_specific(id),
|
|
|
|
path=current_app.config['SOCKET_PATH'],
|
|
|
|
namespace=current_app.config['SOCKET_NAMESPACE'],
|
|
|
|
messages=MESSAGES
|
|
|
|
)
|