From 464e63a0d1024d2ee58dd631ae837d88e5dbf8a7 Mon Sep 17 00:00:00 2001 From: Benjamin Bertrand <benjamin.bertrand@esss.se> Date: Thu, 21 Sep 2017 23:08:12 +0200 Subject: [PATCH] Display history in item view --- app/main/views.py | 2 +- app/models.py | 30 ++++++++++++++++++++--- app/templates/_helpers.html | 14 +++++------ app/templates/view_item.html | 47 +++++++++++++++++++++++++++--------- 4 files changed, 70 insertions(+), 23 deletions(-) diff --git a/app/main/views.py b/app/main/views.py index 479ba27..f85bb39 100644 --- a/app/main/views.py +++ b/app/main/views.py @@ -68,7 +68,7 @@ def index(): @login_required def view_item(ics_id): item = Item.query.filter_by(ics_id=ics_id).first_or_404() - return render_template('view_item.html', item=item) + return render_template('view_item.html', item=item.to_dict(extra=True)) @bp.route('/qrcodes') diff --git a/app/models.py b/app/models.py index 4f639c0..588c9dd 100644 --- a/app/models.py +++ b/app/models.py @@ -14,7 +14,7 @@ import qrcode import sqlalchemy as sa from sqlalchemy.orm import validates from sqlalchemy.ext.associationproxy import association_proxy -from sqlalchemy_continuum import make_versioned +from sqlalchemy_continuum import make_versioned, version_class from citext import CIText from flask import current_app from flask_login import UserMixin @@ -234,8 +234,8 @@ class Item(db.Model): raise utils.InventoryError('ICS id shall match [A-Z]{3}[0-9]{3}', status_code=422) return string - def to_dict(self): - return { + def to_dict(self, extra=False): + d = { 'id': self.id, 'ics_id': self.ics_id, 'serial_number': self.serial_number, @@ -247,8 +247,32 @@ class Item(db.Model): 'created': utils.format_field(self._created), 'parent': utils.format_field(self.parent), } + if extra: + d['children'] = [utils.format_field(child) for child in self.children] + d['history'] = self.history() + return d + + def history(self): + versions = [] + for version in self.versions: + # parent is an attribute used by SQLAlchemy-Continuum + # version.parent refers to an ItemVersion instance (and has no link with + # the item parent_id) + # We need to retrieve the parent "manually" + if version.parent_id is None: + parent = None + else: + parent = Item.query.get(version.parent_id) + versions.append({ + 'updated': utils.format_field(version._updated), + 'location': utils.format_field(version.location), + 'status': utils.format_field(version.status), + 'parent': utils.format_field(parent), + }) + return versions # call configure_mappers after defining all the models # required by sqlalchemy_continuum sa.orm.configure_mappers() +ItemVersion = version_class(Item) diff --git a/app/templates/_helpers.html b/app/templates/_helpers.html index ac555ca..8c761e0 100644 --- a/app/templates/_helpers.html +++ b/app/templates/_helpers.html @@ -2,16 +2,16 @@ {% if active %}active{% endif %} {%- endmacro %} -{% macro link_to_item(item) -%} - {% if item %} - <a href="{{ url_for('main.view_item', ics_id=item.ics_id) }}">{{ item.ics_id }}</a> +{% macro link_to_item(ics_id) -%} + {% if ics_id %} + <a href="{{ url_for('main.view_item', ics_id=ics_id) }}">{{ ics_id }}</a> {% else %} - {{ item }} + {{ ics_id }} {% endif %} {%- endmacro %} -{% macro link_to_children(item) -%} - {% for child in item.children %} - {{ link_to_item(child) }} +{% macro link_to_items(ics_ids) -%} + {% for ics_id in ics_ids %} + {{ link_to_item(ics_id) }} {% endfor %} {%- endmacro %} diff --git a/app/templates/view_item.html b/app/templates/view_item.html index 2155365..645c387 100644 --- a/app/templates/view_item.html +++ b/app/templates/view_item.html @@ -1,32 +1,55 @@ {%- extends "base.html" %} -{% from "_helpers.html" import link_to_item, link_to_children %} +{% from "_helpers.html" import link_to_item, link_to_items %} {% block title %}View Item - ICS Inventory{% endblock %} {% block main %} - <h2>Item {{ item.ics_id }}</h2> + <h2>Item {{ item['ics_id'] }}</h2> <dl class="row"> <dt class="col-sm-3">ICS id</dt> - <dd class="col-sm-9">{{ item.ics_id }}</dt> + <dd class="col-sm-9">{{ item['ics_id'] }}</dt> <dt class="col-sm-3">Created</dt> - <dd class="col-sm-9">{{ item._created.strftime("%Y-%m-%d %H:%M") }}</dt> + <dd class="col-sm-9">{{ item['created'] }}</dt> <dt class="col-sm-3">Updated</dt> - <dd class="col-sm-9">{{ item._updated.strftime("%Y-%m-%d %H:%M") }}</dt> + <dd class="col-sm-9">{{ item['updated'] }}</dt> <dt class="col-sm-3">Serial number</dt> - <dd class="col-sm-9">{{ item.serial_number }}</dt> + <dd class="col-sm-9">{{ item['serial_number'] }}</dt> <dt class="col-sm-3">Manufacturer</dt> - <dd class="col-sm-9">{{ item.manufacturer }}</dt> + <dd class="col-sm-9">{{ item['manufacturer'] }}</dt> <dt class="col-sm-3">Model</dt> - <dd class="col-sm-9">{{ item.model }}</dt> + <dd class="col-sm-9">{{ item['model'] }}</dt> <dt class="col-sm-3">Location</dt> - <dd class="col-sm-9">{{ item.location }}</dt> + <dd class="col-sm-9">{{ item['location'] }}</dt> <dt class="col-sm-3">Status</dt> - <dd class="col-sm-9">{{ item.status }}</dt> + <dd class="col-sm-9">{{ item['status'] }}</dt> <dt class="col-sm-3">Parent</dt> - <dd class="col-sm-9">{{ link_to_item(item.parent) }}</dt> + <dd class="col-sm-9">{{ link_to_item(item['parent']) }}</dt> <dt class="col-sm-3">Children</dt> - <dd class="col-sm-9">{{ link_to_children(item) }}</dt> + <dd class="col-sm-9">{{ link_to_items(item['children']) }}</dt> </dl> + <h4>History</h4> + + <table id="item_version_table" class="table table-bordered table-hover table-sm"> + <thead> + <tr> + <th>Updated</th> + <th>Location</th> + <th>Status</th> + <th>Parent</th> + </tr> + </thead> + <tbody> + {% for version in item['history'] %} + <tr> + <td>{{ version['updated'] }}</td> + <td>{{ version['location'] }}</td> + <td>{{ version['status'] }}</td> + <td>{{ link_to_item(version['parent']) }}</td> + </tr> + {% endfor %} + </tbody> + </table> + {%- endblock %} -- GitLab