Added status table.
This commit is contained in:
parent
db287fb8ac
commit
f9d950c425
10 changed files with 108 additions and 19 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
{# show label unless hidden/custom #}
|
<!-- FIELD: {{ field_name }} ({{ field_type }}) -->
|
||||||
{% if field_type != 'hidden' and field_label %}
|
{% if field_type != 'hidden' and field_label %}
|
||||||
<label for="{{ field_name }}"
|
<label for="{{ field_name }}"
|
||||||
{% if label_attrs %}{% for k,v in label_attrs.items() %}
|
{% if label_attrs %}{% for k,v in label_attrs.items() %}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
|
<!-- FORM: {{ model_name|lower }} -->
|
||||||
<form method="POST" id="{{ model_name|lower }}_form">
|
<form method="POST" id="{{ model_name|lower }}_form">
|
||||||
{% macro render_row(row) %}
|
{% macro render_row(row) %}
|
||||||
|
<!-- ROW: {{ row['name'] }} -->
|
||||||
{% if row.fields or row.children or row.legend %}
|
{% if row.fields or row.children or row.legend %}
|
||||||
{% if row.legend %}<legend>{{ row.legend }}</legend>{% endif %}
|
{% if row.legend %}<legend>{{ row.legend }}</legend>{% endif %}
|
||||||
<fieldset
|
<fieldset
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,7 @@ def create_app(config_cls=crudkit.DevConfig) -> Flask:
|
||||||
_models.Inventory,
|
_models.Inventory,
|
||||||
_models.RoomFunction,
|
_models.RoomFunction,
|
||||||
_models.Room,
|
_models.Room,
|
||||||
|
_models.Status,
|
||||||
_models.User,
|
_models.User,
|
||||||
_models.WorkLog,
|
_models.WorkLog,
|
||||||
_models.WorkNote,
|
_models.WorkNote,
|
||||||
|
|
|
||||||
|
|
@ -12,11 +12,12 @@ from .image import Image
|
||||||
from .inventory import Inventory
|
from .inventory import Inventory
|
||||||
from .room_function import RoomFunction
|
from .room_function import RoomFunction
|
||||||
from .room import Room
|
from .room import Room
|
||||||
|
from .status import Status
|
||||||
from .user import User
|
from .user import User
|
||||||
from .work_log import WorkLog
|
from .work_log import WorkLog
|
||||||
from .work_note import WorkNote
|
from .work_note import WorkNote
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"Area", "Brand", "DeviceType", "Image", "Inventory",
|
"Area", "Brand", "DeviceType", "Image", "Inventory",
|
||||||
"RoomFunction", "Room", "User", "WorkLog", "WorkNote",
|
"RoomFunction", "Room", "Status", "User", "WorkLog", "WorkNote",
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,10 @@ class Inventory(Base, CRUDMixin):
|
||||||
name: Mapped[Optional[str]] = mapped_column(Unicode(255), index=True)
|
name: Mapped[Optional[str]] = mapped_column(Unicode(255), index=True)
|
||||||
serial: 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))
|
model: Mapped[Optional[str]] = mapped_column(Unicode(255))
|
||||||
notes: 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())
|
shared: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False, server_default=sql.false())
|
||||||
|
|
|
||||||
33
inventory/models/status.py
Normal file
33
inventory/models/status.py
Normal file
|
|
@ -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')
|
||||||
|
|
@ -9,7 +9,7 @@ from crudkit.core import normalize_payload
|
||||||
|
|
||||||
bp_entry = Blueprint("entry", __name__)
|
bp_entry = Blueprint("entry", __name__)
|
||||||
|
|
||||||
ENTRY_WHITELIST = ["inventory", "user", "worklog", "room"]
|
ENTRY_WHITELIST = ["inventory", "user", "worklog", "room", "status"]
|
||||||
|
|
||||||
def _fields_for_model(model: str):
|
def _fields_for_model(model: str):
|
||||||
fields: list[str] = []
|
fields: list[str] = []
|
||||||
|
|
@ -53,16 +53,18 @@ def _fields_for_model(model: str):
|
||||||
"attrs": {"class": "form-control"}, "label_attrs": {"class": "form-label"},
|
"attrs": {"class": "form-control"}, "label_attrs": {"class": "form-label"},
|
||||||
"label_spec": "{name} - {room_function.description}"},
|
"label_spec": "{name} - {room_function.description}"},
|
||||||
{"name": "condition", "label": "Condition", "row": "status", "wrap": {"class": "col"},
|
{"name": "condition", "label": "Condition", "row": "status", "wrap": {"class": "col"},
|
||||||
"type": "select", "options": [
|
"label_attrs": {"class": "form-label"}},
|
||||||
{"label": "Deployed", "value": "Deployed"},
|
# {"name": "condition", "label": "Condition", "row": "status", "wrap": {"class": "col"},
|
||||||
{"label": "Working", "value": "Working"},
|
# "type": "select", "options": [
|
||||||
{"label": "Unverified", "value": "Unverified"},
|
# {"label": "Deployed", "value": "Deployed"},
|
||||||
{"label": "Partially Inoperable", "value": "Partially Inoperable"},
|
# {"label": "Working", "value": "Working"},
|
||||||
{"label": "Inoperable", "value": "Inoperable"},
|
# {"label": "Unverified", "value": "Unverified"},
|
||||||
{"label": "Removed", "value": "Removed"},
|
# {"label": "Partially Inoperable", "value": "Partially Inoperable"},
|
||||||
{"label": "Disposed", "value": "Disposed"},
|
# {"label": "Inoperable", "value": "Inoperable"},
|
||||||
],
|
# {"label": "Removed", "value": "Removed"},
|
||||||
"label_attrs": {"class": "form-label"}, "attrs": {"class": "form-control"}},
|
# {"label": "Disposed", "value": "Disposed"},
|
||||||
|
# ],
|
||||||
|
# "label_attrs": {"class": "form-label"}, "attrs": {"class": "form-control"}},
|
||||||
{"name": "image", "label": "", "row": "image", "type": "template", "label_spec": "{filename}",
|
{"name": "image", "label": "", "row": "image", "type": "template", "label_spec": "{filename}",
|
||||||
"template": "image_display.html", "attrs": {"class": "img-fluid img-thumbnail h-auto"},
|
"template": "image_display.html", "attrs": {"class": "img-fluid img-thumbnail h-auto"},
|
||||||
"wrap": {"class": "h-100 w-100"}},
|
"wrap": {"class": "h-100 w-100"}},
|
||||||
|
|
@ -189,6 +191,31 @@ def _fields_for_model(model: str):
|
||||||
{"name": "name", "order": 10, "attrs": {"class": "row"}},
|
{"name": "name", "order": 10, "attrs": {"class": "row"}},
|
||||||
{"name": "details", "order": 20, "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)
|
return (fields, fields_spec, layout)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,8 @@ def init_settings_routes(app):
|
||||||
function_service = crudkit.crud.get_service(function_model)
|
function_service = crudkit.crud.get_service(function_model)
|
||||||
room_model = crudkit.crud.get_model('room')
|
room_model = crudkit.crud.get_model('room')
|
||||||
room_service = crudkit.crud.get_service(room_model)
|
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})
|
brands = brand_service.list({"sort": "name", "limit": 0})
|
||||||
device_types = device_type_service.list({"sort": "description", "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'})
|
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)
|
app.register_blueprint(bp_settings)
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
<!-- TABLE {{ kwargs['object_class'] if kwargs else '(NO MODEL ASSOCIATED)' }} -->
|
||||||
<div class="table-responsive" style="max-height: 80vh;">
|
<div class="table-responsive" style="max-height: 80vh;">
|
||||||
<table class="table table-sm table-info table-striped table-hover table-bordered border-tertiary text-nowrap overflow-x-auto mx-auto">
|
<table class="table table-sm table-info table-striped table-hover table-bordered border-tertiary text-nowrap overflow-x-auto mx-auto">
|
||||||
<thead>
|
<thead>
|
||||||
|
|
|
||||||
|
|
@ -24,24 +24,33 @@
|
||||||
<div class="tab-pane fade show active" id="device-tab-pane" tabindex="0">
|
<div class="tab-pane fade show active" id="device-tab-pane" tabindex="0">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<label for="brand" class="form-label">Brand</label>
|
<label for="brand" class="form-label">Brands</label>
|
||||||
{{ combobox('brand', 'brand', 'Enter the name of a brand.', brands, 'id', 'name') }}
|
{{ combobox('brand', 'brand', 'Enter the name of a brand.', brands, 'id', 'name') }}
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<label for="devicetype" class="form-label">Device Type</label>
|
<label for="devicetype" class="form-label">Device Types</label>
|
||||||
{{ combobox('devicetype', 'devicetype', 'Enter the description of a device type.', device_types, 'id', 'description') }}
|
{{ combobox('devicetype', 'devicetype', 'Enter the description of a device type.', device_types, 'id', 'description') }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row mt-3">
|
||||||
|
<div class="col">
|
||||||
|
<label for="status" class="form-label">
|
||||||
|
Conditions
|
||||||
|
<a href="{{ url_for('entry.entry_new', model='status') }}" class="link-success link-underline-opacity-0"><small>[+]</small></a>
|
||||||
|
</label>
|
||||||
|
{{ statuses | safe }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="tab-pane fade" id="location-tab-pane" tabindex="0">
|
<div class="tab-pane fade" id="location-tab-pane" tabindex="0">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<label for="area" class="form-label">Area</label>
|
<label for="area" class="form-label">Areas</label>
|
||||||
{{ combobox('area', 'area', 'Enter the name of an area.', areas, 'id', 'name') }}
|
{{ combobox('area', 'area', 'Enter the name of an area.', areas, 'id', 'name') }}
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<label for="roomfunction" class="form-label">Description</label>
|
<label for="roomfunction" class="form-label">Descriptions</label>
|
||||||
{{ combobox('roomfunction', 'roomfunction', 'Enter a room description.', functions, 'id', 'description') }}
|
{{ combobox('roomfunction', 'roomfunction', 'Enter a room description.', functions, 'id', 'description') }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue