Set purchase location
This commit is contained in:
parent
e7bfa66512
commit
195f18f141
@ -168,6 +168,12 @@
|
|||||||
# Default: 3333
|
# Default: 3333
|
||||||
# BK_PORT=3333
|
# BK_PORT=3333
|
||||||
|
|
||||||
|
# Optional: Change the default order of purchase locations. By default ordered by insertion order.
|
||||||
|
# Useful column names for this option are:
|
||||||
|
# - "bricktracker_metadata_purchase_locations"."name" ASC: storage name
|
||||||
|
# Default: "bricktracker_metadata_purchase_locations"."name" ASC
|
||||||
|
# BK_PURCHASE_LOCATION_DEFAULT_ORDER="bricktracker_metadata_purchase_locations"."name" ASC
|
||||||
|
|
||||||
# Optional: Shuffle the lists on the front page.
|
# Optional: Shuffle the lists on the front page.
|
||||||
# Default: false
|
# Default: false
|
||||||
# Legacy name: RANDOM
|
# Legacy name: RANDOM
|
||||||
|
@ -14,7 +14,8 @@
|
|||||||
- Added: `BK_SHOW_GRID_SORT`, show the sort options on the grid by default
|
- Added: `BK_SHOW_GRID_SORT`, show the sort options on the grid by default
|
||||||
- Added: `BK_SHOW_GRID_FILTERS`, show the filter options on the grid by default
|
- Added: `BK_SHOW_GRID_FILTERS`, show the filter options on the grid by default
|
||||||
- Added: `BK_HIDE_ALL_STORAGES`, hide the "Storages" menu entry
|
- Added: `BK_HIDE_ALL_STORAGES`, hide the "Storages" menu entry
|
||||||
- Added: `BK_MINIFIGURES_DEFAULT_ORDER`, ordering of storages
|
- Added: `BK_STORAGE_DEFAULT_ORDER`, ordering of storages
|
||||||
|
- Added: `BK_PURCHASE_LOCATION_DEFAULT_ORDER`, ordering of purchase locations
|
||||||
|
|
||||||
### Code
|
### Code
|
||||||
|
|
||||||
@ -39,6 +40,7 @@
|
|||||||
- Ownership
|
- Ownership
|
||||||
- Tags
|
- Tags
|
||||||
- Storage
|
- Storage
|
||||||
|
- Purchase location
|
||||||
|
|
||||||
- Storage
|
- Storage
|
||||||
- Storage content and list
|
- Storage content and list
|
||||||
@ -85,6 +87,7 @@
|
|||||||
- Tags
|
- Tags
|
||||||
- Refresh
|
- Refresh
|
||||||
- Storage
|
- Storage
|
||||||
|
- Purchase location
|
||||||
|
|
||||||
- Sets grid
|
- Sets grid
|
||||||
- Collapsible controls depending on screen size
|
- Collapsible controls depending on screen size
|
||||||
|
@ -17,6 +17,7 @@ from bricktracker.views.admin.database import admin_database_page
|
|||||||
from bricktracker.views.admin.image import admin_image_page
|
from bricktracker.views.admin.image import admin_image_page
|
||||||
from bricktracker.views.admin.instructions import admin_instructions_page
|
from bricktracker.views.admin.instructions import admin_instructions_page
|
||||||
from bricktracker.views.admin.owner import admin_owner_page
|
from bricktracker.views.admin.owner import admin_owner_page
|
||||||
|
from bricktracker.views.admin.purchase_location import admin_purchase_location_page # noqa: E501
|
||||||
from bricktracker.views.admin.retired import admin_retired_page
|
from bricktracker.views.admin.retired import admin_retired_page
|
||||||
from bricktracker.views.admin.status import admin_status_page
|
from bricktracker.views.admin.status import admin_status_page
|
||||||
from bricktracker.views.admin.storage import admin_storage_page
|
from bricktracker.views.admin.storage import admin_storage_page
|
||||||
@ -88,6 +89,7 @@ def setup_app(app: Flask) -> None:
|
|||||||
app.register_blueprint(admin_instructions_page)
|
app.register_blueprint(admin_instructions_page)
|
||||||
app.register_blueprint(admin_retired_page)
|
app.register_blueprint(admin_retired_page)
|
||||||
app.register_blueprint(admin_owner_page)
|
app.register_blueprint(admin_owner_page)
|
||||||
|
app.register_blueprint(admin_purchase_location_page)
|
||||||
app.register_blueprint(admin_status_page)
|
app.register_blueprint(admin_status_page)
|
||||||
app.register_blueprint(admin_storage_page)
|
app.register_blueprint(admin_storage_page)
|
||||||
app.register_blueprint(admin_tag_page)
|
app.register_blueprint(admin_tag_page)
|
||||||
|
@ -41,6 +41,7 @@ CONFIG: Final[list[dict[str, Any]]] = [
|
|||||||
{'n': 'PARTS_DEFAULT_ORDER', 'd': '"rebrickable_parts"."name" ASC, "rebrickable_parts"."color_name" ASC, "bricktracker_parts"."spare" ASC'}, # noqa: E501
|
{'n': 'PARTS_DEFAULT_ORDER', 'd': '"rebrickable_parts"."name" ASC, "rebrickable_parts"."color_name" ASC, "bricktracker_parts"."spare" ASC'}, # noqa: E501
|
||||||
{'n': 'PARTS_FOLDER', 'd': 'parts', 's': True},
|
{'n': 'PARTS_FOLDER', 'd': 'parts', 's': True},
|
||||||
{'n': 'PORT', 'd': 3333, 'c': int},
|
{'n': 'PORT', 'd': 3333, 'c': int},
|
||||||
|
{'n': 'PURCHASE_LOCATION_DEFAULT_ORDER', 'd': '"bricktracker_metadata_purchase_locations"."name" ASC'}, # noqa: E501
|
||||||
{'n': 'RANDOM', 'e': 'RANDOM', 'c': bool},
|
{'n': 'RANDOM', 'e': 'RANDOM', 'c': bool},
|
||||||
{'n': 'REBRICKABLE_API_KEY', 'e': 'REBRICKABLE_API_KEY', 'd': ''},
|
{'n': 'REBRICKABLE_API_KEY', 'e': 'REBRICKABLE_API_KEY', 'd': ''},
|
||||||
{'n': 'REBRICKABLE_IMAGE_NIL', 'd': 'https://rebrickable.com/static/img/nil.png'}, # noqa: E501
|
{'n': 'REBRICKABLE_IMAGE_NIL', 'd': 'https://rebrickable.com/static/img/nil.png'}, # noqa: E501
|
||||||
|
@ -48,7 +48,7 @@ class BrickMetadata(BrickRecord):
|
|||||||
def as_column(self, /) -> str:
|
def as_column(self, /) -> str:
|
||||||
return '{kind}_{id}'.format(
|
return '{kind}_{id}'.format(
|
||||||
id=self.fields.id,
|
id=self.fields.id,
|
||||||
kind=self.kind.lower()
|
kind=self.kind.lower().replace(' ', '-')
|
||||||
)
|
)
|
||||||
|
|
||||||
# HTML dataset name
|
# HTML dataset name
|
||||||
@ -90,8 +90,6 @@ class BrickMetadata(BrickRecord):
|
|||||||
|
|
||||||
# Rename the entry
|
# Rename the entry
|
||||||
def rename(self, /) -> None:
|
def rename(self, /) -> None:
|
||||||
self.safe()
|
|
||||||
|
|
||||||
self.update_field('name', value=self.fields.name)
|
self.update_field('name', value=self.fields.name)
|
||||||
|
|
||||||
# Make the name "safe"
|
# Make the name "safe"
|
||||||
@ -159,7 +157,7 @@ class BrickMetadata(BrickRecord):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if rows != 1:
|
if rows != 1:
|
||||||
raise DatabaseException('Could not update the field "{field}" for {kind} {name} ({id})'.format( # noqa: E501
|
raise DatabaseException('Could not update the field "{field}" for {kind} "{name}" ({id})'.format( # noqa: E501
|
||||||
field=field,
|
field=field,
|
||||||
kind=self.kind,
|
kind=self.kind,
|
||||||
name=self.fields.name,
|
name=self.fields.name,
|
||||||
|
@ -7,13 +7,21 @@ from .exceptions import NotFoundException
|
|||||||
from .fields import BrickRecordFields
|
from .fields import BrickRecordFields
|
||||||
from .record_list import BrickRecordList
|
from .record_list import BrickRecordList
|
||||||
from .set_owner import BrickSetOwner
|
from .set_owner import BrickSetOwner
|
||||||
|
from .set_purchase_location import BrickSetPurchaseLocation
|
||||||
from .set_status import BrickSetStatus
|
from .set_status import BrickSetStatus
|
||||||
from .set_storage import BrickSetStorage
|
from .set_storage import BrickSetStorage
|
||||||
from .set_tag import BrickSetTag
|
from .set_tag import BrickSetTag
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
T = TypeVar('T', BrickSetOwner, BrickSetStatus, BrickSetStorage, BrickSetTag)
|
T = TypeVar(
|
||||||
|
'T',
|
||||||
|
BrickSetOwner,
|
||||||
|
BrickSetPurchaseLocation,
|
||||||
|
BrickSetStatus,
|
||||||
|
BrickSetStorage,
|
||||||
|
BrickSetTag
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# Lego sets metadata list
|
# Lego sets metadata list
|
||||||
|
@ -9,6 +9,7 @@ if TYPE_CHECKING:
|
|||||||
from .rebrickable_set import RebrickableSet
|
from .rebrickable_set import RebrickableSet
|
||||||
from .set import BrickSet
|
from .set import BrickSet
|
||||||
from .set_owner import BrickSetOwner
|
from .set_owner import BrickSetOwner
|
||||||
|
from .set_purchase_location import BrickSetPurchaseLocation
|
||||||
from .set_status import BrickSetStatus
|
from .set_status import BrickSetStatus
|
||||||
from .set_storage import BrickSetStorage
|
from .set_storage import BrickSetStorage
|
||||||
from .set_tag import BrickSetTag
|
from .set_tag import BrickSetTag
|
||||||
@ -20,6 +21,7 @@ T = TypeVar(
|
|||||||
'BrickPart',
|
'BrickPart',
|
||||||
'BrickSet',
|
'BrickSet',
|
||||||
'BrickSetOwner',
|
'BrickSetOwner',
|
||||||
|
'BrickSetPurchaseLocation',
|
||||||
'BrickSetStatus',
|
'BrickSetStatus',
|
||||||
'BrickSetStorage',
|
'BrickSetStorage',
|
||||||
'BrickSetTag',
|
'BrickSetTag',
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
from .instructions_list import BrickInstructionsList
|
from .instructions_list import BrickInstructionsList
|
||||||
from .retired_list import BrickRetiredList
|
from .retired_list import BrickRetiredList
|
||||||
from .set_owner_list import BrickSetOwnerList
|
from .set_owner_list import BrickSetOwnerList
|
||||||
|
from .set_purchase_location_list import BrickSetPurchaseLocationList
|
||||||
from .set_status_list import BrickSetStatusList
|
from .set_status_list import BrickSetStatusList
|
||||||
from .set_storage_list import BrickSetStorageList
|
from .set_storage_list import BrickSetStorageList
|
||||||
from .set_tag_list import BrickSetTagList
|
from .set_tag_list import BrickSetTagList
|
||||||
@ -17,6 +18,9 @@ def reload() -> None:
|
|||||||
# Reload the set owners
|
# Reload the set owners
|
||||||
BrickSetOwnerList.new(force=True)
|
BrickSetOwnerList.new(force=True)
|
||||||
|
|
||||||
|
# Reload the set purchase locations
|
||||||
|
BrickSetPurchaseLocationList.new(force=True)
|
||||||
|
|
||||||
# Reload the set statuses
|
# Reload the set statuses
|
||||||
BrickSetStatusList.new(force=True)
|
BrickSetStatusList.new(force=True)
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ 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
|
||||||
from .set_owner_list import BrickSetOwnerList
|
from .set_owner_list import BrickSetOwnerList
|
||||||
|
from .set_purchase_location_list import BrickSetPurchaseLocationList
|
||||||
from .set_status_list import BrickSetStatusList
|
from .set_status_list import BrickSetStatusList
|
||||||
from .set_storage_list import BrickSetStorageList
|
from .set_storage_list import BrickSetStorageList
|
||||||
from .set_tag_list import BrickSetTagList
|
from .set_tag_list import BrickSetTagList
|
||||||
@ -63,6 +64,13 @@ class BrickSet(RebrickableSet):
|
|||||||
)
|
)
|
||||||
self.fields.storage = storage.fields.id
|
self.fields.storage = storage.fields.id
|
||||||
|
|
||||||
|
# Save the purchase location
|
||||||
|
purchase_location = BrickSetPurchaseLocationList.get(
|
||||||
|
data.get('purchase_location', ''),
|
||||||
|
allow_none=True
|
||||||
|
)
|
||||||
|
self.fields.purchase_location = purchase_location.fields.id
|
||||||
|
|
||||||
# Insert into database
|
# Insert into database
|
||||||
self.insert(commit=False)
|
self.insert(commit=False)
|
||||||
|
|
||||||
|
@ -5,6 +5,8 @@ from flask import current_app
|
|||||||
from .record_list import BrickRecordList
|
from .record_list import BrickRecordList
|
||||||
from .set_owner import BrickSetOwner
|
from .set_owner import BrickSetOwner
|
||||||
from .set_owner_list import BrickSetOwnerList
|
from .set_owner_list import BrickSetOwnerList
|
||||||
|
from .set_purchase_location import BrickSetPurchaseLocation
|
||||||
|
from .set_purchase_location_list import BrickSetPurchaseLocationList
|
||||||
from .set_status_list import BrickSetStatusList
|
from .set_status_list import BrickSetStatusList
|
||||||
from .set_storage import BrickSetStorage
|
from .set_storage import BrickSetStorage
|
||||||
from .set_storage_list import BrickSetStorageList
|
from .set_storage_list import BrickSetStorageList
|
||||||
@ -175,6 +177,8 @@ def set_metadata_lists(
|
|||||||
str,
|
str,
|
||||||
Union[
|
Union[
|
||||||
list[BrickSetOwner],
|
list[BrickSetOwner],
|
||||||
|
list[BrickSetPurchaseLocation],
|
||||||
|
BrickSetPurchaseLocation,
|
||||||
list[BrickSetStorage],
|
list[BrickSetStorage],
|
||||||
BrickSetStorageList,
|
BrickSetStorageList,
|
||||||
list[BrickSetTag]
|
list[BrickSetTag]
|
||||||
@ -182,6 +186,7 @@ def set_metadata_lists(
|
|||||||
]:
|
]:
|
||||||
return {
|
return {
|
||||||
'brickset_owners': BrickSetOwnerList.list(),
|
'brickset_owners': BrickSetOwnerList.list(),
|
||||||
|
'brickset_purchase_locations': BrickSetPurchaseLocationList.list(as_class=as_class), # noqa: E501
|
||||||
'brickset_storages': BrickSetStorageList.list(as_class=as_class),
|
'brickset_storages': BrickSetStorageList.list(as_class=as_class),
|
||||||
'brickset_tags': BrickSetTagList.list(),
|
'brickset_tags': BrickSetTagList.list(),
|
||||||
}
|
}
|
||||||
|
13
bricktracker/set_purchase_location.py
Normal file
13
bricktracker/set_purchase_location.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
from .metadata import BrickMetadata
|
||||||
|
|
||||||
|
|
||||||
|
# Lego set purchase location metadata
|
||||||
|
class BrickSetPurchaseLocation(BrickMetadata):
|
||||||
|
kind: str = 'purchase location'
|
||||||
|
|
||||||
|
# Queries
|
||||||
|
delete_query: str = 'set/metadata/purchase_location/delete'
|
||||||
|
insert_query: str = 'set/metadata/purchase_location/insert'
|
||||||
|
select_query: str = 'set/metadata/purchase_location/select'
|
||||||
|
update_field_query: str = 'set/metadata/purchase_location/update/field'
|
||||||
|
update_set_value_query: str = 'set/metadata/purchase_location/update/value'
|
42
bricktracker/set_purchase_location_list.py
Normal file
42
bricktracker/set_purchase_location_list.py
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import logging
|
||||||
|
from typing import Self
|
||||||
|
|
||||||
|
from flask import current_app
|
||||||
|
|
||||||
|
from .metadata_list import BrickMetadataList
|
||||||
|
from .set_purchase_location import BrickSetPurchaseLocation
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
# Lego sets purchase location list
|
||||||
|
class BrickSetPurchaseLocationList(
|
||||||
|
BrickMetadataList[BrickSetPurchaseLocation]
|
||||||
|
):
|
||||||
|
kind: str = 'set purchase locations'
|
||||||
|
|
||||||
|
# Queries
|
||||||
|
select_query = 'set/metadata/purchase_location/list'
|
||||||
|
all_query = 'set/metadata/purchase_location/all'
|
||||||
|
|
||||||
|
# Set value endpoint
|
||||||
|
set_value_endpoint: str = 'set.update_purchase_location'
|
||||||
|
|
||||||
|
# Load all purchase locations
|
||||||
|
@classmethod
|
||||||
|
def all(cls, /) -> Self:
|
||||||
|
new = cls.new()
|
||||||
|
new.override()
|
||||||
|
|
||||||
|
for record in new.select(
|
||||||
|
override_query=cls.all_query,
|
||||||
|
order=current_app.config['PURCHASE_LOCATION_DEFAULT_ORDER']
|
||||||
|
):
|
||||||
|
new.records.append(new.model(record=record))
|
||||||
|
|
||||||
|
return new
|
||||||
|
|
||||||
|
# Instantiate the list with the proper class
|
||||||
|
@classmethod
|
||||||
|
def new(cls, /, *, force: bool = False) -> Self:
|
||||||
|
return cls(BrickSetPurchaseLocation, force=force)
|
@ -1,6 +1,7 @@
|
|||||||
SELECT
|
SELECT
|
||||||
{% block id %}{% endblock %}
|
{% block id %}{% endblock %}
|
||||||
"bricktracker_sets"."storage",
|
"bricktracker_sets"."storage",
|
||||||
|
"bricktracker_sets"."purchase_location",
|
||||||
"rebrickable_sets"."set",
|
"rebrickable_sets"."set",
|
||||||
"rebrickable_sets"."number",
|
"rebrickable_sets"."number",
|
||||||
"rebrickable_sets"."version",
|
"rebrickable_sets"."version",
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
INSERT OR IGNORE INTO "bricktracker_sets" (
|
INSERT OR IGNORE INTO "bricktracker_sets" (
|
||||||
"id",
|
"id",
|
||||||
"set",
|
"set",
|
||||||
"storage"
|
"storage",
|
||||||
|
"purchase_location"
|
||||||
) VALUES (
|
) VALUES (
|
||||||
:id,
|
:id,
|
||||||
:set,
|
:set,
|
||||||
:storage
|
:storage,
|
||||||
|
:purchase_location
|
||||||
)
|
)
|
||||||
|
6
bricktracker/sql/set/metadata/purchase_location/base.sql
Normal file
6
bricktracker/sql/set/metadata/purchase_location/base.sql
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
SELECT
|
||||||
|
"bricktracker_metadata_purchase_locations"."id",
|
||||||
|
"bricktracker_metadata_purchase_locations"."name"
|
||||||
|
FROM "bricktracker_metadata_purchase_locations"
|
||||||
|
|
||||||
|
{% block where %}{% endblock %}
|
10
bricktracker/sql/set/metadata/purchase_location/delete.sql
Normal file
10
bricktracker/sql/set/metadata/purchase_location/delete.sql
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
BEGIN TRANSACTION;
|
||||||
|
|
||||||
|
DELETE FROM "bricktracker_metadata_purchase_locations"
|
||||||
|
WHERE "bricktracker_metadata_purchase_locations"."id" IS NOT DISTINCT FROM '{{ id }}';
|
||||||
|
|
||||||
|
UPDATE "bricktracker_sets"
|
||||||
|
SET "purchase_location" = NULL
|
||||||
|
WHERE "bricktracker_sets"."purchase_location" IS NOT DISTINCT FROM '{{ id }}';
|
||||||
|
|
||||||
|
COMMIT;
|
11
bricktracker/sql/set/metadata/purchase_location/insert.sql
Normal file
11
bricktracker/sql/set/metadata/purchase_location/insert.sql
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
BEGIN TRANSACTION;
|
||||||
|
|
||||||
|
INSERT INTO "bricktracker_metadata_purchase_locations" (
|
||||||
|
"id",
|
||||||
|
"name"
|
||||||
|
) VALUES (
|
||||||
|
'{{ id }}',
|
||||||
|
'{{ name }}'
|
||||||
|
);
|
||||||
|
|
||||||
|
COMMIT;
|
1
bricktracker/sql/set/metadata/purchase_location/list.sql
Normal file
1
bricktracker/sql/set/metadata/purchase_location/list.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
{% extends 'set/metadata/purchase_location/base.sql' %}
|
@ -0,0 +1,5 @@
|
|||||||
|
{% extends 'set/metadata/purchase_location/base.sql' %}
|
||||||
|
|
||||||
|
{% block where %}
|
||||||
|
WHERE "bricktracker_metadata_purchase_locations"."id" IS NOT DISTINCT FROM :id
|
||||||
|
{% endblock %}
|
@ -0,0 +1,3 @@
|
|||||||
|
UPDATE "bricktracker_metadata_purchase_locations"
|
||||||
|
SET "{{field}}" = :value
|
||||||
|
WHERE "bricktracker_metadata_purchase_locations"."id" IS NOT DISTINCT FROM :id
|
@ -0,0 +1,3 @@
|
|||||||
|
UPDATE "bricktracker_sets"
|
||||||
|
SET "purchase_location" = :value
|
||||||
|
WHERE "bricktracker_sets"."id" IS NOT DISTINCT FROM :set_id
|
@ -10,6 +10,8 @@ from ...rebrickable_image import RebrickableImage
|
|||||||
from ...retired_list import BrickRetiredList
|
from ...retired_list import BrickRetiredList
|
||||||
from ...set_owner import BrickSetOwner
|
from ...set_owner import BrickSetOwner
|
||||||
from ...set_owner_list import BrickSetOwnerList
|
from ...set_owner_list import BrickSetOwnerList
|
||||||
|
from ...set_purchase_location import BrickSetPurchaseLocation
|
||||||
|
from ...set_purchase_location_list import BrickSetPurchaseLocationList
|
||||||
from ...set_storage import BrickSetStorage
|
from ...set_storage import BrickSetStorage
|
||||||
from ...set_storage_list import BrickSetStorageList
|
from ...set_storage_list import BrickSetStorageList
|
||||||
from ...set_status import BrickSetStatus
|
from ...set_status import BrickSetStatus
|
||||||
@ -36,6 +38,7 @@ def admin() -> str:
|
|||||||
database_version: int = -1
|
database_version: int = -1
|
||||||
instructions: BrickInstructionsList | None = None
|
instructions: BrickInstructionsList | None = None
|
||||||
metadata_owners: list[BrickSetOwner] = []
|
metadata_owners: list[BrickSetOwner] = []
|
||||||
|
metadata_purchase_locations: list[BrickSetPurchaseLocation] = []
|
||||||
metadata_statuses: list[BrickSetStatus] = []
|
metadata_statuses: list[BrickSetStatus] = []
|
||||||
metadata_storages: list[BrickSetStorage] = []
|
metadata_storages: list[BrickSetStorage] = []
|
||||||
metadata_tags: list[BrickSetTag] = []
|
metadata_tags: list[BrickSetTag] = []
|
||||||
@ -54,6 +57,7 @@ def admin() -> str:
|
|||||||
instructions = BrickInstructionsList()
|
instructions = BrickInstructionsList()
|
||||||
|
|
||||||
metadata_owners = BrickSetOwnerList.list()
|
metadata_owners = BrickSetOwnerList.list()
|
||||||
|
metadata_purchase_locations = BrickSetPurchaseLocationList.list()
|
||||||
metadata_statuses = BrickSetStatusList.list(all=True)
|
metadata_statuses = BrickSetStatusList.list(all=True)
|
||||||
metadata_storages = BrickSetStorageList.list()
|
metadata_storages = BrickSetStorageList.list()
|
||||||
metadata_tags = BrickSetTagList.list()
|
metadata_tags = BrickSetTagList.list()
|
||||||
@ -81,6 +85,7 @@ def admin() -> str:
|
|||||||
open_instructions = request.args.get('open_instructions', None)
|
open_instructions = request.args.get('open_instructions', None)
|
||||||
open_logout = request.args.get('open_logout', None)
|
open_logout = request.args.get('open_logout', None)
|
||||||
open_owner = request.args.get('open_owner', None)
|
open_owner = request.args.get('open_owner', None)
|
||||||
|
open_purchase_location = request.args.get('open_purchase_location', None)
|
||||||
open_retired = request.args.get('open_retired', None)
|
open_retired = request.args.get('open_retired', None)
|
||||||
open_status = request.args.get('open_status', None)
|
open_status = request.args.get('open_status', None)
|
||||||
open_storage = request.args.get('open_storage', None)
|
open_storage = request.args.get('open_storage', None)
|
||||||
@ -89,6 +94,7 @@ def admin() -> str:
|
|||||||
|
|
||||||
open_metadata = (
|
open_metadata = (
|
||||||
open_owner or
|
open_owner or
|
||||||
|
open_purchase_location or
|
||||||
open_status or
|
open_status or
|
||||||
open_storage or
|
open_storage or
|
||||||
open_tag
|
open_tag
|
||||||
@ -113,6 +119,7 @@ def admin() -> str:
|
|||||||
database_version=database_version,
|
database_version=database_version,
|
||||||
instructions=instructions,
|
instructions=instructions,
|
||||||
metadata_owners=metadata_owners,
|
metadata_owners=metadata_owners,
|
||||||
|
metadata_purchase_locations=metadata_purchase_locations,
|
||||||
metadata_statuses=metadata_statuses,
|
metadata_statuses=metadata_statuses,
|
||||||
metadata_storages=metadata_storages,
|
metadata_storages=metadata_storages,
|
||||||
metadata_tags=metadata_tags,
|
metadata_tags=metadata_tags,
|
||||||
@ -126,12 +133,14 @@ def admin() -> str:
|
|||||||
open_logout=open_logout,
|
open_logout=open_logout,
|
||||||
open_metadata=open_metadata,
|
open_metadata=open_metadata,
|
||||||
open_owner=open_owner,
|
open_owner=open_owner,
|
||||||
|
open_purchase_location=open_purchase_location,
|
||||||
open_retired=open_retired,
|
open_retired=open_retired,
|
||||||
open_status=open_status,
|
open_status=open_status,
|
||||||
open_storage=open_storage,
|
open_storage=open_storage,
|
||||||
open_tag=open_tag,
|
open_tag=open_tag,
|
||||||
open_theme=open_theme,
|
open_theme=open_theme,
|
||||||
owner_error=request.args.get('owner_error'),
|
owner_error=request.args.get('owner_error'),
|
||||||
|
purchase_location_error=request.args.get('purchase_location_error'),
|
||||||
retired=BrickRetiredList(),
|
retired=BrickRetiredList(),
|
||||||
status_error=request.args.get('status_error'),
|
status_error=request.args.get('status_error'),
|
||||||
storage_error=request.args.get('storage_error'),
|
storage_error=request.args.get('storage_error'),
|
||||||
|
84
bricktracker/views/admin/purchase_location.py
Normal file
84
bricktracker/views/admin/purchase_location.py
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
from flask import (
|
||||||
|
Blueprint,
|
||||||
|
redirect,
|
||||||
|
request,
|
||||||
|
render_template,
|
||||||
|
url_for,
|
||||||
|
)
|
||||||
|
from flask_login import login_required
|
||||||
|
from werkzeug.wrappers.response import Response
|
||||||
|
|
||||||
|
from ..exceptions import exception_handler
|
||||||
|
from ...reload import reload
|
||||||
|
from ...set_purchase_location import BrickSetPurchaseLocation
|
||||||
|
|
||||||
|
admin_purchase_location_page = Blueprint(
|
||||||
|
'admin_purchase_location',
|
||||||
|
__name__,
|
||||||
|
url_prefix='/admin/purchase_location'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Add a metadata purchase location
|
||||||
|
@admin_purchase_location_page.route('/add', methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
@exception_handler(
|
||||||
|
__file__,
|
||||||
|
post_redirect='admin.admin',
|
||||||
|
error_name='purchase_location_error',
|
||||||
|
open_purchase_location=True
|
||||||
|
)
|
||||||
|
def add() -> Response:
|
||||||
|
BrickSetPurchaseLocation().from_form(request.form).insert()
|
||||||
|
|
||||||
|
reload()
|
||||||
|
|
||||||
|
return redirect(url_for('admin.admin', open_purchase_location=True))
|
||||||
|
|
||||||
|
|
||||||
|
# Delete the metadata purchase location
|
||||||
|
@admin_purchase_location_page.route('<id>/delete', methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@exception_handler(__file__)
|
||||||
|
def delete(*, id: str) -> str:
|
||||||
|
return render_template(
|
||||||
|
'admin.html',
|
||||||
|
delete_purchase_location=True,
|
||||||
|
purchase_location=BrickSetPurchaseLocation().select_specific(id),
|
||||||
|
error=request.args.get('purchase_location_error')
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Actually delete the metadata purchase location
|
||||||
|
@admin_purchase_location_page.route('<id>/delete', methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
@exception_handler(
|
||||||
|
__file__,
|
||||||
|
post_redirect='admin_purchase_location.delete',
|
||||||
|
error_name='purchase_location_error'
|
||||||
|
)
|
||||||
|
def do_delete(*, id: str) -> Response:
|
||||||
|
purchase_location = BrickSetPurchaseLocation().select_specific(id)
|
||||||
|
purchase_location.delete()
|
||||||
|
|
||||||
|
reload()
|
||||||
|
|
||||||
|
return redirect(url_for('admin.admin', open_purchase_location=True))
|
||||||
|
|
||||||
|
|
||||||
|
# Rename the metadata purchase location
|
||||||
|
@admin_purchase_location_page.route('<id>/rename', methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
@exception_handler(
|
||||||
|
__file__,
|
||||||
|
post_redirect='admin.admin',
|
||||||
|
error_name='purchase_location_error',
|
||||||
|
open_purchase_location=True
|
||||||
|
)
|
||||||
|
def rename(*, id: str) -> Response:
|
||||||
|
purchase_location = BrickSetPurchaseLocation().select_specific(id)
|
||||||
|
purchase_location.from_form(request.form).rename()
|
||||||
|
|
||||||
|
reload()
|
||||||
|
|
||||||
|
return redirect(url_for('admin.admin', open_purchase_location=True))
|
@ -18,6 +18,7 @@ from ..part import BrickPart
|
|||||||
from ..set import BrickSet
|
from ..set import BrickSet
|
||||||
from ..set_list import BrickSetList, set_metadata_lists
|
from ..set_list import BrickSetList, set_metadata_lists
|
||||||
from ..set_owner_list import BrickSetOwnerList
|
from ..set_owner_list import BrickSetOwnerList
|
||||||
|
from ..set_purchase_location_list import BrickSetPurchaseLocationList
|
||||||
from ..set_status_list import BrickSetStatusList
|
from ..set_status_list import BrickSetStatusList
|
||||||
from ..set_storage_list import BrickSetStorageList
|
from ..set_storage_list import BrickSetStorageList
|
||||||
from ..set_tag_list import BrickSetTagList
|
from ..set_tag_list import BrickSetTagList
|
||||||
@ -40,6 +41,25 @@ def list() -> str:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# 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})
|
||||||
|
|
||||||
|
|
||||||
# Change the state of a owner
|
# Change the state of a owner
|
||||||
@set_page.route('/<id>/owner/<metadata_id>', methods=['POST'])
|
@set_page.route('/<id>/owner/<metadata_id>', methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
|
@ -16,6 +16,7 @@ class BrickSetSocket extends BrickSocket {
|
|||||||
this.html_input = document.getElementById(`${id}-set`);
|
this.html_input = document.getElementById(`${id}-set`);
|
||||||
this.html_no_confim = document.getElementById(`${id}-no-confirm`);
|
this.html_no_confim = document.getElementById(`${id}-no-confirm`);
|
||||||
this.html_owners = document.getElementById(`${id}-owners`);
|
this.html_owners = document.getElementById(`${id}-owners`);
|
||||||
|
this.html_purchase_location = document.getElementById(`${id}-purchase-location`);
|
||||||
this.html_storage = document.getElementById(`${id}-storage`);
|
this.html_storage = document.getElementById(`${id}-storage`);
|
||||||
this.html_tags = document.getElementById(`${id}-tags`);
|
this.html_tags = document.getElementById(`${id}-tags`);
|
||||||
|
|
||||||
@ -152,6 +153,12 @@ class BrickSetSocket extends BrickSocket {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Grab the purchase location
|
||||||
|
let purchase_location = null;
|
||||||
|
if (this.html_purchase_location) {
|
||||||
|
purchase_location = this.html_purchase_location.value;
|
||||||
|
}
|
||||||
|
|
||||||
// Grab the storage
|
// Grab the storage
|
||||||
let storage = null;
|
let storage = null;
|
||||||
if (this.html_storage) {
|
if (this.html_storage) {
|
||||||
@ -177,6 +184,7 @@ class BrickSetSocket extends BrickSocket {
|
|||||||
this.socket.emit(this.messages.IMPORT_SET, {
|
this.socket.emit(this.messages.IMPORT_SET, {
|
||||||
set: (set !== undefined) ? set : this.html_input.value,
|
set: (set !== undefined) ? set : this.html_input.value,
|
||||||
owners: owners,
|
owners: owners,
|
||||||
|
purchase_location: purchase_location,
|
||||||
storage: storage,
|
storage: storage,
|
||||||
tags: tags,
|
tags: tags,
|
||||||
refresh: this.refresh
|
refresh: this.refresh
|
||||||
@ -293,6 +301,10 @@ class BrickSetSocket extends BrickSocket {
|
|||||||
this.html_owners.querySelectorAll('input').forEach(input => input.disabled = !enabled);
|
this.html_owners.querySelectorAll('input').forEach(input => input.disabled = !enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.html_purchase_location) {
|
||||||
|
this.html_purchase_location.disabled = !enabled;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.html_storage) {
|
if (this.html_storage) {
|
||||||
this.html_storage.disabled = !enabled;
|
this.html_storage.disabled = !enabled;
|
||||||
}
|
}
|
||||||
|
@ -51,9 +51,22 @@
|
|||||||
</div>
|
</div>
|
||||||
{{ accordion.footer() }}
|
{{ accordion.footer() }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if brickset_purchase_locations | length %}
|
||||||
|
{{ accordion.header('Purchase location', 'purchase-location', 'metadata', icon='building-line') }}
|
||||||
|
<label class="visually-hidden" for="add-purchase-location">{{ name }}</label>
|
||||||
|
<div class="input-group">
|
||||||
|
<select id="add-purchase-location" class="form-select" autocomplete="off">
|
||||||
|
<option value="" selected><i>None</i></option>
|
||||||
|
{% for purchase_location in brickset_purchase_locations %}
|
||||||
|
<option value="{{ purchase_location.fields.id }}">{{ purchase_location.fields.name }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
{{ accordion.footer() }}
|
||||||
|
{% endif %}
|
||||||
{% if brickset_storages | length %}
|
{% if brickset_storages | length %}
|
||||||
{{ accordion.header('Storage', 'storage', 'metadata', icon='archive-2-line') }}
|
{{ accordion.header('Storage', 'storage', 'metadata', icon='archive-2-line') }}
|
||||||
<label class="visually-hidden" for="storage">{{ name }}</label>
|
<label class="visually-hidden" for="add-storage">{{ name }}</label>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<select id="add-storage" class="form-select" autocomplete="off">
|
<select id="add-storage" class="form-select" autocomplete="off">
|
||||||
<option value="" selected><i>None</i></option>
|
<option value="" selected><i>None</i></option>
|
||||||
|
@ -18,6 +18,8 @@
|
|||||||
{% include 'admin/database/delete.html' %}
|
{% include 'admin/database/delete.html' %}
|
||||||
{% elif delete_owner %}
|
{% elif delete_owner %}
|
||||||
{% include 'admin/owner/delete.html' %}
|
{% include 'admin/owner/delete.html' %}
|
||||||
|
{% elif delete_purchase_location %}
|
||||||
|
{% include 'admin/purchase_location/delete.html' %}
|
||||||
{% elif delete_status %}
|
{% elif delete_status %}
|
||||||
{% include 'admin/status/delete.html' %}
|
{% include 'admin/status/delete.html' %}
|
||||||
{% elif delete_storage %}
|
{% elif delete_storage %}
|
||||||
@ -39,10 +41,11 @@
|
|||||||
{% include 'admin/theme.html' %}
|
{% include 'admin/theme.html' %}
|
||||||
{% include 'admin/retired.html' %}
|
{% include 'admin/retired.html' %}
|
||||||
{{ accordion.header('Set metadata', 'metadata', 'admin', expanded=open_metadata, icon='profile-line', class='p-0') }}
|
{{ accordion.header('Set metadata', 'metadata', 'admin', expanded=open_metadata, icon='profile-line', class='p-0') }}
|
||||||
{% include 'admin/owner.html' %}
|
{% include 'admin/owner.html' %}
|
||||||
{% include 'admin/status.html' %}
|
{% include 'admin/purchase_location.html' %}
|
||||||
{% include 'admin/storage.html' %}
|
{% include 'admin/status.html' %}
|
||||||
{% include 'admin/tag.html' %}
|
{% include 'admin/storage.html' %}
|
||||||
|
{% include 'admin/tag.html' %}
|
||||||
{{ accordion.footer() }}
|
{{ accordion.footer() }}
|
||||||
{% include 'admin/database.html' %}
|
{% include 'admin/database.html' %}
|
||||||
{% include 'admin/configuration.html' %}
|
{% include 'admin/configuration.html' %}
|
||||||
|
42
templates/admin/purchase_location.html
Normal file
42
templates/admin/purchase_location.html
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
{% import 'macro/accordion.html' as accordion %}
|
||||||
|
|
||||||
|
{{ accordion.header('Set purchase locations', 'purchase-location', 'metadata', expanded=open_purchase_location, icon='building-line', class='p-0') }}
|
||||||
|
{% if purchase_location_error %}<div class="alert alert-danger m-2" role="alert"><strong>Error:</strong> {{ purchase_location_error }}.</div>{% endif %}
|
||||||
|
<ul class="list-group list-group-flush">
|
||||||
|
{% if metadata_purchase_locations | length %}
|
||||||
|
{% for purchase_location in metadata_purchase_locations %}
|
||||||
|
<li class="list-group-item">
|
||||||
|
<form action="{{ url_for('admin_purchase_location.rename', id=purchase_location.fields.id) }}" method="post" class="row row-cols-lg-auto g-3 align-items-center">
|
||||||
|
<div class="col-12 flex-grow-1">
|
||||||
|
<label class="visually-hidden" for="name-{{ purchase_location.fields.id }}">Name</label>
|
||||||
|
<div class="input-group">
|
||||||
|
<div class="input-group-text">Name</div>
|
||||||
|
<input type="text" class="form-control" id="name-{{ purchase_location.fields.id }}" name="name" value="{{ purchase_location.fields.name }}">
|
||||||
|
<button type="submit" class="btn btn-primary"><i class="ri-edit-line"></i> Rename</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-12">
|
||||||
|
<a href="{{ url_for('admin_purchase_location.delete', id=purchase_location.fields.id) }}" class="btn btn-danger" role="button"><i class="ri-delete-bin-2-line"></i> Delete</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
{% else %}
|
||||||
|
<li class="list-group-item text-center"><i class="ri-error-warning-line"></i> No purchase location found.</li>
|
||||||
|
{% endif %}
|
||||||
|
<li class="list-group-item">
|
||||||
|
<form action="{{ url_for('admin_purchase_location.add') }}" method="post" class="row row-cols-lg-auto g-3 align-items-center">
|
||||||
|
<div class="col-12 flex-grow-1">
|
||||||
|
<label class="visually-hidden" for="name">Name</label>
|
||||||
|
<div class="input-group">
|
||||||
|
<div class="input-group-text">Name</div>
|
||||||
|
<input type="text" class="form-control" id="name" name="name" value="">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-12">
|
||||||
|
<button type="submit" class="btn btn-primary"><i class="ri-add-circle-line"></i> Add</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
{{ accordion.footer() }}
|
19
templates/admin/purchase_location/delete.html
Normal file
19
templates/admin/purchase_location/delete.html
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{% import 'macro/accordion.html' as accordion %}
|
||||||
|
|
||||||
|
{{ accordion.header('Set purchase locations danger zone', 'purchase-location-danger', 'admin', expanded=true, danger=true, class='text-end') }}
|
||||||
|
<form action="{{ url_for('admin_purchase_location.do_delete', id=purchase_location.fields.id) }}" method="post">
|
||||||
|
{% if purchase_location_error %}<div class="alert alert-danger text-start" role="alert"><strong>Error:</strong> {{ purchase_location_error }}.</div>{% endif %}
|
||||||
|
<div class="alert alert-danger text-center" role="alert">You are about to <strong>delete a set purchase location</strong>. This action is irreversible.</div>
|
||||||
|
<div class="row row-cols-lg-auto g-3 align-items-center">
|
||||||
|
<div class="col-12 flex-grow-1">
|
||||||
|
<div class="input-group">
|
||||||
|
<div class="input-group-text">Name</div>
|
||||||
|
<input type="text" class="form-control" value="{{ purchase_location.fields.name }}" disabled>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr class="border-bottom">
|
||||||
|
<a class="btn btn-danger" href="{{ url_for('admin.admin', open_purchase_location=true) }}" role="button"><i class="ri-arrow-left-long-line"></i> Back to the admin</a>
|
||||||
|
<button type="submit" class="btn btn-danger"><i class="ri-delete-bin-2-line"></i> Delete <strong>the set purchase location</strong></button>
|
||||||
|
</form>
|
||||||
|
{{ accordion.footer() }}
|
@ -65,6 +65,18 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro purchase_location(item, purchase_locations, solo=false, last=false) %}
|
||||||
|
{% if purchase_locations and item.fields.purchase_location in purchase_locations.mapping %}
|
||||||
|
{% set purchase_location = purchase_locations.mapping[item.fields.purchase_location] %}
|
||||||
|
{% if last %}
|
||||||
|
{% set tooltip=purchase_location.fields.name %}
|
||||||
|
{% else %}
|
||||||
|
{% set text=purchase_location.fields.name %}
|
||||||
|
{% endif %}
|
||||||
|
{{ badge(check=purchase_location, solo=solo, last=last, color='light border', icon='building-line', text=text, tooltip=tooltip) }}
|
||||||
|
{% endif %}
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
{% macro set(set, solo=false, last=false, url=None, id=None) %}
|
{% macro set(set, solo=false, last=false, url=None, id=None) %}
|
||||||
{% if id %}
|
{% if id %}
|
||||||
{% set url=url_for('set.details', id=id) %}
|
{% set url=url_for('set.details', id=id) %}
|
||||||
|
@ -17,6 +17,11 @@
|
|||||||
{% if not config['HIDE_TABLE_DAMAGED_PARTS'] %}
|
{% if not config['HIDE_TABLE_DAMAGED_PARTS'] %}
|
||||||
data-has-damaged="{{ (item.fields.total_damaged > 0) | int }}" data-damaged="{{ item.fields.total_damaged }}"
|
data-has-damaged="{{ (item.fields.total_damaged > 0) | int }}" data-damaged="{{ item.fields.total_damaged }}"
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
data-has-purchase-location="{{ item.fields.purchase_location is not none | int }}"
|
||||||
|
{% if item.fields.purchase_location is not none %}
|
||||||
|
data-purchase-location="{{ item.fields.purchase_location }}"
|
||||||
|
{% if item.fields.purchase_location in brickset_purchase_locations.mapping %}data-search-purchase-location="{{ brickset_purchase_locations.mapping[item.fields.purchase_location].fields.name | lower }}"{% endif %}
|
||||||
|
{% endif %}
|
||||||
data-has-storage="{{ item.fields.storage is not none | int }}"
|
data-has-storage="{{ item.fields.storage is not none | int }}"
|
||||||
{% if item.fields.storage is not none %}
|
{% if item.fields.storage is not none %}
|
||||||
data-storage="{{ item.fields.storage }}"
|
data-storage="{{ item.fields.storage }}"
|
||||||
@ -63,6 +68,7 @@
|
|||||||
{{ badge.owner(item, owner, solo=solo, last=last) }}
|
{{ badge.owner(item, owner, solo=solo, last=last) }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{{ badge.storage(item, brickset_storages, solo=solo, last=last) }}
|
{{ badge.storage(item, brickset_storages, solo=solo, last=last) }}
|
||||||
|
{{ badge.purchase_location(item, brickset_purchase_locations, solo=solo, last=last) }}
|
||||||
{% if not last %}
|
{% if not last %}
|
||||||
{% if not solo %}
|
{% if not solo %}
|
||||||
{{ badge.instructions(item, solo=solo, last=last) }}
|
{{ badge.instructions(item, solo=solo, last=last) }}
|
||||||
|
@ -60,6 +60,22 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if brickset_purchase_locations | length %}
|
||||||
|
<div class="col-12 flex-grow-1">
|
||||||
|
<label class="visually-hidden" for="grid-owner">Purchase location</label>
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-text"><i class="ri-building-line"></i><span class="ms-1 d-none d-md-inline"> Purchase location</span></span>
|
||||||
|
<select id="grid-purchase-location" class="form-select"
|
||||||
|
data-filter="value" data-filter-attribute="purchase-location"
|
||||||
|
autocomplete="off">
|
||||||
|
<option value="" selected>All</option>
|
||||||
|
{% for purchase_location in brickset_purchase_locations %}
|
||||||
|
<option value="{{ purchase_location.fields.id }}">{{ purchase_location.fields.name }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
{% if brickset_storages | length %}
|
{% if brickset_storages | length %}
|
||||||
<div class="col-12 flex-grow-1">
|
<div class="col-12 flex-grow-1">
|
||||||
<label class="visually-hidden" for="grid-owner">Storage</label>
|
<label class="visually-hidden" for="grid-owner">Storage</label>
|
||||||
|
@ -1,44 +1,53 @@
|
|||||||
{% if g.login.is_authenticated() %}
|
{% if g.login.is_authenticated() %}
|
||||||
{{ accordion.header('Management', 'set-management', 'set-details', icon='settings-4-line', class='p-0') }}
|
{{ accordion.header('Management', 'set-management', 'set-details', icon='settings-4-line', class='p-0') }}
|
||||||
{{ accordion.header('Owners', 'owner', 'set-management', icon='group-line', class='p-0') }}
|
{{ accordion.header('Owners', 'owner', 'set-management', icon='group-line', class='p-0') }}
|
||||||
<ul class="list-group list-group-flush">
|
<ul class="list-group list-group-flush">
|
||||||
{% if brickset_owners | length %}
|
{% if brickset_owners | length %}
|
||||||
{% for owner in brickset_owners %}
|
{% for owner in brickset_owners %}
|
||||||
<li class="d-flex list-group-item list-group-item-action text-nowrap">{{ form.checkbox(item, owner, delete=delete) }}</li>
|
<li class="d-flex list-group-item list-group-item-action text-nowrap">{{ form.checkbox(item, owner, delete=delete) }}</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<li class="list-group-item list-group-item-action text-center"><i class="ri-error-warning-line"></i> No owner found.</li>
|
<li class="list-group-item list-group-item-action text-center"><i class="ri-error-warning-line"></i> No owner found.</li>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
<div class="list-group list-group-flush border-top">
|
||||||
|
<a class="list-group-item list-group-item-action" href="{{ url_for('admin.admin', open_owner=true) }}"><i class="ri-settings-4-line"></i> Manage the set owners</a>
|
||||||
|
</div>
|
||||||
|
{{ accordion.footer() }}
|
||||||
|
{{ accordion.header('Purchase location', 'purchase-location', 'set-management', icon='building-line') }}
|
||||||
|
{% if brickset_purchase_locations | length %}
|
||||||
|
{{ form.select('Purchase location', item, 'purchase_location', brickset_purchase_locations, delete=delete) }}
|
||||||
|
{% else %}
|
||||||
|
<p class="text-center"><i class="ri-error-warning-line"></i> No purchase location found.</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</ul>
|
<hr>
|
||||||
<div class="list-group list-group-flush border-top">
|
<a href="{{ url_for('admin.admin', open_purchase_location=true) }}" class="btn btn-primary" role="button"><i class="ri-settings-4-line"></i> Manage the set purchase locations</a>
|
||||||
<a class="list-group-item list-group-item-action" href="{{ url_for('admin.admin', open_owner=true) }}"><i class="ri-settings-4-line"></i> Manage the set owners</a>
|
{{ accordion.footer() }}
|
||||||
</div>
|
|
||||||
{{ accordion.footer() }}
|
|
||||||
{{ accordion.header('Storage', 'storage', 'set-management', icon='archive-2-line') }}
|
{{ accordion.header('Storage', 'storage', 'set-management', icon='archive-2-line') }}
|
||||||
{% if brickset_storages | length %}
|
{% if brickset_storages | length %}
|
||||||
{{ form.select('Storage', item, 'storage', brickset_storages, delete=delete) }}
|
{{ form.select('Storage', item, 'storage', brickset_storages, delete=delete) }}
|
||||||
{% else %}
|
{% else %}
|
||||||
<p class="text-center"><i class="ri-error-warning-line"></i> No storage found.</p>
|
<p class="text-center"><i class="ri-error-warning-line"></i> No storage found.</p>
|
||||||
{% endif %}
|
|
||||||
<hr>
|
|
||||||
<a href="{{ url_for('admin.admin', open_storage=true) }}" class="btn btn-primary" role="button"><i class="ri-settings-4-line"></i> Manage the set storages</a>
|
|
||||||
{{ accordion.footer() }}
|
|
||||||
{{ accordion.header('Tags', 'tag', 'set-management', icon='price-tag-2-line', class='p-0') }}
|
|
||||||
<ul class="list-group list-group-flush">
|
|
||||||
{% if brickset_tags | length %}
|
|
||||||
{% for tag in brickset_tags %}
|
|
||||||
<li class="d-flex list-group-item list-group-item-action text-nowrap">{{ form.checkbox(item, tag, delete=delete) }}</li>
|
|
||||||
{% endfor %}
|
|
||||||
{% else %}
|
|
||||||
<li class="list-group-item list-group-item-action text-center"><i class="ri-error-warning-line"></i> No tag found.</li>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</ul>
|
<hr>
|
||||||
<div class="list-group list-group-flush border-top">
|
<a href="{{ url_for('admin.admin', open_storage=true) }}" class="btn btn-primary" role="button"><i class="ri-settings-4-line"></i> Manage the set storages</a>
|
||||||
<a class="list-group-item list-group-item-action" href="{{ url_for('admin.admin', open_tag=true) }}"><i class="ri-settings-4-line"></i> Manage the set tags</a>
|
{{ accordion.footer() }}
|
||||||
</div>
|
{{ accordion.header('Tags', 'tag', 'set-management', icon='price-tag-2-line', class='p-0') }}
|
||||||
{{ accordion.footer() }}
|
<ul class="list-group list-group-flush">
|
||||||
|
{% if brickset_tags | length %}
|
||||||
|
{% for tag in brickset_tags %}
|
||||||
|
<li class="d-flex list-group-item list-group-item-action text-nowrap">{{ form.checkbox(item, tag, delete=delete) }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
{% else %}
|
||||||
|
<li class="list-group-item list-group-item-action text-center"><i class="ri-error-warning-line"></i> No tag found.</li>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
<div class="list-group list-group-flush border-top">
|
||||||
|
<a class="list-group-item list-group-item-action" href="{{ url_for('admin.admin', open_tag=true) }}"><i class="ri-settings-4-line"></i> Manage the set tags</a>
|
||||||
|
</div>
|
||||||
|
{{ accordion.footer() }}
|
||||||
{{ accordion.header('Data', 'data', 'set-management', icon='database-2-line') }}
|
{{ accordion.header('Data', 'data', 'set-management', icon='database-2-line') }}
|
||||||
<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() }}
|
||||||
{{ accordion.footer() }}
|
{{ accordion.footer() }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
<label class="visually-hidden" for="grid-search">Search</label>
|
<label class="visually-hidden" for="grid-search">Search</label>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<span class="input-group-text"><i class="ri-search-line"></i><span class="ms-1 d-none d-md-inline"> Search</span></span>
|
<span class="input-group-text"><i class="ri-search-line"></i><span class="ms-1 d-none d-md-inline"> Search</span></span>
|
||||||
<input id="grid-search" data-search-exact="name,number,parts,searchStorage,theme,year" data-search-list="searchOwner,searchTag" class="form-control form-control-sm" type="text" placeholder="Set, name, number of parts, theme, year, owner, storage, tag" value="">
|
<input id="grid-search" data-search-exact="name,number,parts,searchPurchaseLocation,searchStorage,theme,year" data-search-list="searchOwner,searchTag" class="form-control form-control-sm" type="text" placeholder="Set, name, number of parts, theme, year, owner, purchase location, storage, tag" value="">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
|
Loading…
Reference in New Issue
Block a user