diff --git a/crudkit/ui/templates/field.html b/crudkit/ui/templates/field.html index aecb234..9a9174a 100644 --- a/crudkit/ui/templates/field.html +++ b/crudkit/ui/templates/field.html @@ -1,4 +1,4 @@ -{# show label unless hidden/custom #} + {% if field_type != 'hidden' and field_label %} {% macro render_row(row) %} + {% if row.fields or row.children or row.legend %} {% if row.legend %}{{ row.legend }}{% endif %} Flask: _models.Inventory, _models.RoomFunction, _models.Room, + _models.Status, _models.User, _models.WorkLog, _models.WorkNote, diff --git a/inventory/models/__init__.py b/inventory/models/__init__.py index 4f197bd..9b62bb4 100644 --- a/inventory/models/__init__.py +++ b/inventory/models/__init__.py @@ -12,11 +12,12 @@ from .image import Image from .inventory import Inventory from .room_function import RoomFunction from .room import Room +from .status import Status from .user import User from .work_log import WorkLog from .work_note import WorkNote __all__ = [ "Area", "Brand", "DeviceType", "Image", "Inventory", - "RoomFunction", "Room", "User", "WorkLog", "WorkNote", + "RoomFunction", "Room", "Status", "User", "WorkLog", "WorkNote", ] diff --git a/inventory/models/inventory.py b/inventory/models/inventory.py index 1425a0e..78617be 100644 --- a/inventory/models/inventory.py +++ b/inventory/models/inventory.py @@ -17,7 +17,10 @@ class Inventory(Base, CRUDMixin): name: Mapped[Optional[str]] = mapped_column(Unicode(255), index=True) serial: Mapped[Optional[str]] = mapped_column(Unicode(255), index=True) - condition: Mapped[str] = mapped_column(Unicode(255)) + # condition: Mapped[str] = mapped_column(Unicode(255)) + condition: Mapped[Optional['Status']] = relationship('Status', back_populates='inventory') + condition_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey('status.id'), nullable=True, index=True) + model: Mapped[Optional[str]] = mapped_column(Unicode(255)) notes: Mapped[Optional[str]] = mapped_column(Unicode(255)) shared: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False, server_default=sql.false()) diff --git a/inventory/models/status.py b/inventory/models/status.py new file mode 100644 index 0000000..98bb2c4 --- /dev/null +++ b/inventory/models/status.py @@ -0,0 +1,33 @@ +import enum + +from typing import List +from sqlalchemy import Boolean, Enum as SAEnum, Unicode +from sqlalchemy.orm import Mapped, mapped_column, relationship +from sqlalchemy.sql import expression as sql + +from crudkit.core.base import Base, CRUDMixin + +class StatusCategory(str, enum.Enum): + ACTIVE = "Active" + AVAILABLE = "Available" + PENDING = "Pending" + FAULTED = "Faulted" + DECOMMISSIONED = "Decommissioned" + DISPOSED = "Disposed" + ADMINISTRATIVE = "Administrative" + +status_type = SAEnum( + StatusCategory, + name="status_category_enum", + validate_strings=True, +) + +class Status(Base, CRUDMixin): + __tablename__ = "status" + + description: Mapped[str] = mapped_column(Unicode(255), nullable=False, index=True, unique=True) + category: Mapped[StatusCategory] = mapped_column(status_type, nullable=False) + + is_deleted: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False, server_default=sql.false()) + + inventory: Mapped[List['Inventory']] = relationship('Inventory', back_populates='condition') diff --git a/inventory/routes/entry.py b/inventory/routes/entry.py index 895a5e1..6f303d8 100644 --- a/inventory/routes/entry.py +++ b/inventory/routes/entry.py @@ -9,7 +9,7 @@ from crudkit.core import normalize_payload bp_entry = Blueprint("entry", __name__) -ENTRY_WHITELIST = ["inventory", "user", "worklog", "room"] +ENTRY_WHITELIST = ["inventory", "user", "worklog", "room", "status"] def _fields_for_model(model: str): fields: list[str] = [] @@ -53,16 +53,18 @@ def _fields_for_model(model: str): "attrs": {"class": "form-control"}, "label_attrs": {"class": "form-label"}, "label_spec": "{name} - {room_function.description}"}, {"name": "condition", "label": "Condition", "row": "status", "wrap": {"class": "col"}, - "type": "select", "options": [ - {"label": "Deployed", "value": "Deployed"}, - {"label": "Working", "value": "Working"}, - {"label": "Unverified", "value": "Unverified"}, - {"label": "Partially Inoperable", "value": "Partially Inoperable"}, - {"label": "Inoperable", "value": "Inoperable"}, - {"label": "Removed", "value": "Removed"}, - {"label": "Disposed", "value": "Disposed"}, - ], - "label_attrs": {"class": "form-label"}, "attrs": {"class": "form-control"}}, + "label_attrs": {"class": "form-label"}}, + # {"name": "condition", "label": "Condition", "row": "status", "wrap": {"class": "col"}, + # "type": "select", "options": [ + # {"label": "Deployed", "value": "Deployed"}, + # {"label": "Working", "value": "Working"}, + # {"label": "Unverified", "value": "Unverified"}, + # {"label": "Partially Inoperable", "value": "Partially Inoperable"}, + # {"label": "Inoperable", "value": "Inoperable"}, + # {"label": "Removed", "value": "Removed"}, + # {"label": "Disposed", "value": "Disposed"}, + # ], + # "label_attrs": {"class": "form-label"}, "attrs": {"class": "form-control"}}, {"name": "image", "label": "", "row": "image", "type": "template", "label_spec": "{filename}", "template": "image_display.html", "attrs": {"class": "img-fluid img-thumbnail h-auto"}, "wrap": {"class": "h-100 w-100"}}, @@ -189,6 +191,31 @@ def _fields_for_model(model: str): {"name": "name", "order": 10, "attrs": {"class": "row"}}, {"name": "details", "order": 20, "attrs": {"class": "row"}}, ] + elif model == "status": + fields_spec = [ + {"name": "label", "label": "", "type": "display", "attrs": {"class": "display-6 mb-3"}, + "row": "label", "wrap": {"class": "col"}, "label_spec": "{description} ({category})"}, + {"name": "buttons", "label": "", "row": "label", "type": "template", "template": "entry_buttons.html", + "wrap": {"class": "col-auto text-end me-2"}, "attrs": {"data-model": model}}, + {"name": "description", "row": "details", "label": "Description", "attrs": {"class": "form-control"}, + "label_attrs": {"class": "form-label"}, "wrap": {"class": "col"}}, + {"name": "category", "row": "details", "label": "Category", "attrs": {"class": "form-control"}, + "type": "select", "wrap": {"class": "col"}, "label_attrs": {"class": "form-label"}, "options": [ + {"label": "Active", "value": "Active"}, + {"label": "Available", "value": "Available"}, + {"label": "Pending", "value": "Pending"}, + {"label": "Faulted", "value": "Faulted"}, + {"label": "Decommissioned", "value": "Decommissioned"}, + {"label": "Disposed", "value": "Disposed"}, + {"label": "Administrative", "value": "Administrative"}, + ]}, + ] + layout = [ + {"name": "label", "order": 0, "attrs": {"class": "row align-items-center"}}, + {"name": "details", "order": 10, "attrs": {"class": "row"}}, + ] + + return (fields, fields_spec, layout) diff --git a/inventory/routes/settings.py b/inventory/routes/settings.py index e4c8560..ccd2044 100644 --- a/inventory/routes/settings.py +++ b/inventory/routes/settings.py @@ -19,6 +19,8 @@ def init_settings_routes(app): function_service = crudkit.crud.get_service(function_model) room_model = crudkit.crud.get_model('room') room_service = crudkit.crud.get_service(room_model) + status_model = crudkit.crud.get_model('status') + status_service = crudkit.crud.get_service(status_model) brands = brand_service.list({"sort": "name", "limit": 0}) device_types = device_type_service.list({"sort": "description", "limit": 0}) @@ -42,6 +44,16 @@ def init_settings_routes(app): ], opts={"object_class": 'room'}) - return render_template("settings.html", brands=brands, device_types=device_types, areas=areas, functions=functions, rooms=rooms) + statuses = status_service.list({ + "sort": "category", + "limit": 0, + "fields": [ + "description", + "category", + ], + }) + statuses = render_table(statuses, opts={"object_class": 'status'}) + + return render_template("settings.html", brands=brands, device_types=device_types, areas=areas, functions=functions, rooms=rooms, statuses=statuses) app.register_blueprint(bp_settings) diff --git a/inventory/templates/crudkit/table.html b/inventory/templates/crudkit/table.html index 2fb4ef1..25cf8b2 100644 --- a/inventory/templates/crudkit/table.html +++ b/inventory/templates/crudkit/table.html @@ -1,3 +1,4 @@ + diff --git a/inventory/templates/settings.html b/inventory/templates/settings.html index 2473272..e1a6227 100644 --- a/inventory/templates/settings.html +++ b/inventory/templates/settings.html @@ -24,24 +24,33 @@ - Brand + Brands {{ combobox('brand', 'brand', 'Enter the name of a brand.', brands, 'id', 'name') }} - Device Type + Device Types {{ combobox('devicetype', 'devicetype', 'Enter the description of a device type.', device_types, 'id', 'description') }} + + + + Conditions + [+] + + {{ statuses | safe }} + + - Area + Areas {{ combobox('area', 'area', 'Enter the name of an area.', areas, 'id', 'name') }} - Description + Descriptions {{ combobox('roomfunction', 'roomfunction', 'Enter a room description.', functions, 'id', 'description') }}