Enhance inventory management by updating timestamp type to DateTime, adding stale worklog display on the index page, and improving template styles and scripts for better user experience.
This commit is contained in:
parent
0835248f34
commit
58754c71bd
7 changed files with 73 additions and 16 deletions
Binary file not shown.
|
@ -6,7 +6,7 @@ if TYPE_CHECKING:
|
|||
from .work_log import WorkLog
|
||||
from .rooms import Room
|
||||
|
||||
from sqlalchemy import Boolean, ForeignKeyConstraint, ForeignKey, Identity, Index, Integer, PrimaryKeyConstraint, String, Unicode, text
|
||||
from sqlalchemy import Boolean, ForeignKeyConstraint, ForeignKey, Identity, Index, Integer, PrimaryKeyConstraint, String, Unicode, DateTime, text
|
||||
from sqlalchemy.dialects.mssql import DATETIME2, MONEY
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
import datetime
|
||||
|
@ -20,7 +20,7 @@ class Inventory(db.Model):
|
|||
)
|
||||
|
||||
id: Mapped[int] = mapped_column("ID", Integer, Identity(start=1, increment=1), primary_key=True)
|
||||
timestamp: Mapped[datetime.datetime] = mapped_column('Date Entered', DATETIME2)
|
||||
timestamp: Mapped[datetime.datetime] = mapped_column('Date Entered', DateTime)
|
||||
condition: Mapped[str] = mapped_column('Working Condition', Unicode(255))
|
||||
needed: Mapped[str] = mapped_column("Needed", Unicode(255))
|
||||
type_id: Mapped[int] = mapped_column('Item Type', Integer, ForeignKey("Items.ID"))
|
||||
|
|
32
routes.py
32
routes.py
|
@ -1,11 +1,11 @@
|
|||
from flask import Blueprint, render_template, url_for, request, redirect
|
||||
from .models import Area, Brand, Item, Inventory, RoomFunction, User, WorkLog, Room
|
||||
import html
|
||||
from .models import Brand, Item, Inventory, RoomFunction, User, WorkLog, Room
|
||||
from sqlalchemy import or_
|
||||
from sqlalchemy.orm import aliased
|
||||
from typing import Callable, Any, List
|
||||
from . import db
|
||||
from .utils import eager_load_user_relationships, eager_load_inventory_relationships, eager_load_room_relationships, eager_load_worklog_relationships, chunk_list
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
main = Blueprint('main', __name__)
|
||||
|
||||
|
@ -130,7 +130,27 @@ def render_paginated_table(
|
|||
|
||||
@main.route("/")
|
||||
def index():
|
||||
return render_template("index.html", title="Inventory Manager")
|
||||
stale_worklog_page = request.args.get('stale_worklog_page', 1, int)
|
||||
cutoff = datetime.utcnow() - timedelta(days=14)
|
||||
|
||||
worklog_query = eager_load_worklog_relationships(
|
||||
db.session.query(WorkLog)
|
||||
).filter(
|
||||
(WorkLog.start_time < cutoff) & (WorkLog.complete == False)
|
||||
)
|
||||
|
||||
stale_pagination = make_paginated_data(worklog_query, stale_worklog_page, 3)
|
||||
stale_count = len(worklog_query.all())
|
||||
stale_worklog_headers = {k: v for k, v in worklog_headers.items() if k not in ['End Time', 'Quick Analysis?', 'Complete?', 'Follow Up?']}
|
||||
|
||||
return render_template(
|
||||
"index.html",
|
||||
title="Inventory Manager",
|
||||
stale_pagination=stale_pagination,
|
||||
stale_count=stale_count,
|
||||
stale_worklog_headers=stale_worklog_headers,
|
||||
stale_worklog_rows=[{"id": log.id, "cells": [fn(log) for fn in stale_worklog_headers.values()]} for log in stale_pagination['items']],
|
||||
)
|
||||
|
||||
def link(text, endpoint, **values):
|
||||
return {"text": text, "url": url_for(endpoint, **values)}
|
||||
|
@ -338,10 +358,12 @@ def search():
|
|||
UserAlias.last_name.ilike(f"%{query}%")
|
||||
))
|
||||
inventory_pagination = make_paginated_data(inventory_query, inventory_page)
|
||||
user_query = eager_load_user_relationships(db.session.query(User)).filter(
|
||||
user_query = eager_load_user_relationships(db.session.query(User).join(UserAlias, User.supervisor)).filter(
|
||||
or_(
|
||||
User.first_name.ilike(f"%{query}%"),
|
||||
User.last_name.ilike(f"%{query}%")
|
||||
User.last_name.ilike(f"%{query}%"),
|
||||
UserAlias.first_name.ilike(f"%{query}%"),
|
||||
UserAlias.last_name.ilike(f"%{query}%")
|
||||
))
|
||||
user_pagination = make_paginated_data(user_query, user_page)
|
||||
worklog_query = eager_load_worklog_relationships(db.session.query(WorkLog).join(UserAlias, WorkLog.contact).join(InventoryAlias, WorkLog.work_item)).filter(
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
{% if cell.type == 'bool' %}
|
||||
{{ cell.html | safe }}
|
||||
{% elif cell.url %}
|
||||
<a href="{{ cell.url }}">{{ cell.text }}</a>
|
||||
<a class="link-success link-underline-opacity-0" href="{{ cell.url }}">{{ cell.text }}</a>
|
||||
{% else %}
|
||||
{{ cell.text or '-' }}
|
||||
{% endif %}
|
||||
|
|
|
@ -7,5 +7,31 @@
|
|||
<div class="container text-center">
|
||||
<h1 class="display-4">Welcome to Inventory Manager</h1>
|
||||
<p class="lead">Find out about all of your assets.</p>
|
||||
<div class="row">
|
||||
{% if stale_pagination['items'] %}
|
||||
<div class="col">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Stale Worklogs</h5>
|
||||
<h6 class="card-subtitle mb-2 text-body-secondary">You have {{ stale_count }} worklogs
|
||||
that need attention!</h6>
|
||||
{{ tables.render_table(
|
||||
stale_worklog_headers,
|
||||
stale_worklog_rows,
|
||||
'index'
|
||||
)}}
|
||||
{{ tables.render_pagination(
|
||||
'index',
|
||||
stale_pagination['page'],
|
||||
stale_pagination['has_prev'],
|
||||
stale_pagination['has_next'],
|
||||
stale_pagination['total_pages'],
|
||||
page_variable='stale_worklog_page'
|
||||
)}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -14,9 +14,7 @@
|
|||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.6/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||
integrity="sha384-4Q6Gf2aSP4eDXB8Miphtr37CMZZQ5oXLH2yaXMJ2w8e2ZtHTl7GptT4jmndRuHDT" crossorigin="anonymous">
|
||||
<style>
|
||||
{
|
||||
% block style %
|
||||
}
|
||||
{% block style %}
|
||||
|
||||
.sticky-top {
|
||||
position: sticky;
|
||||
|
@ -43,18 +41,16 @@
|
|||
background-color: white;
|
||||
}
|
||||
|
||||
{
|
||||
% endblock %
|
||||
}
|
||||
{% endblock %}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body class="bg-tertiary text-primary-emphasis">
|
||||
<nav class="navbar navbar-expand bg-body-tertiary border-bottom">
|
||||
<div class="container-fluid">
|
||||
<span class="navbar-brand">
|
||||
<a class="navbar-brand" href="{{ url_for('index') }}">
|
||||
Inventory Manager
|
||||
</span>
|
||||
</a>
|
||||
<button class="navbar-toggler">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
@ -76,6 +72,9 @@
|
|||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.6/dist/js/bootstrap.bundle.min.js"
|
||||
integrity="sha384-j1CDi7MgGQ12Z7Qab0qlWQ/Qqz24Gc6BM0thvEMVjHnfYGF0rmFCozFSxQBxwHKO"
|
||||
crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/mark.js/8.11.1/mark.min.js"
|
||||
integrity="sha512-5CYOlHXGh6QpOFA/TeTylKLWfB3ftPsde7AnmhuitiTX4K5SqCLBeKro6sPS8ilsz1Q4NRx3v8Ko2IBiszzdww=="
|
||||
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||
<script src="{{ url_for('static', filename='js/datalist.js') }}"></script>
|
||||
<script>
|
||||
const searchInput = document.querySelector('#search');
|
||||
|
|
|
@ -77,3 +77,13 @@ title=title,
|
|||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block script %}
|
||||
{% if query %}
|
||||
const query = "{{ query|e }}";
|
||||
if (query) {
|
||||
const instance = new Mark(document.querySelector("main"));
|
||||
instance.mark(query);
|
||||
}
|
||||
{% endif %}
|
||||
{% endblock %}
|
Loading…
Add table
Add a link
Reference in a new issue