Rework admin form/list view

master
informatic 2020-04-28 19:58:31 +02:00
parent 39745971ff
commit 7ad9fa4335
4 changed files with 157 additions and 31 deletions

View File

@ -4,10 +4,11 @@ import datetime
import csv
from flask import redirect, flash, request, url_for, make_response, current_app, session, has_request_context
import flask_admin
from flask_admin.model.template import macro
import pdfplumber
from flask_admin.form import rules
from formity.extensions import admin, db, ModelView, ModelViewHighSecurity, AdminSecurityMixin
from wtforms import TextAreaField, validators
from wtforms import TextAreaField, RadioField, validators
from formity.models import FaceshieldRequest, RequestChange, Status, PostalCode, ExternalUser, Orga
from spaceauth import current_user
from flask_weasyprint import HTML, render_pdf
@ -50,6 +51,7 @@ class IndexView(AdminSecurityMixin, flask_admin.AdminIndexView):
class FaceshieldRequestAdmin(ModelView):
column_default_sort = 'created'
details_modal_template = 'changelog_details_modal.html'
create_template = 'changelog_edit.html'
edit_template = 'changelog_edit.html'
list_template = 'faceshieldrequest_list.html'
@ -75,25 +77,88 @@ class FaceshieldRequestAdmin(ModelView):
'postalcode_info',
)
form_create_rules = (
'entity_info', 'full_name', 'phone_number',
rules.FieldSet((
rules.Field('shipping_name'),
rules.Field('shipping_street'),
rules.Field('shipping_postalcode'),
rules.Field('shipping_city'),
rules.Field('shipping_latitude'),
rules.Field('shipping_longitude'),
), 'Shipping information')
form_create_rules = form_edit_rules = (
rules.Macro('render_submit'),
rules.Container('row', rules.NestedRule([
rules.Container('split', rules.FieldSet((
'status',
'handling_orga',
'entity_info',
'full_name',
'phone_number',
'email',
rules.Macro('render_readonly', name='Extra', field='extra'),
'remarks',
rules.Macro('render_readonly', name='Created', field='created'),
rules.Macro('render_readonly', name='Updated', field='updated'),
rules.Macro('render_readonly', name='IP', field='ip'),
rules.Macro('render_readonly', name='UA', field='ua'),
), 'Request')),
rules.Container('split', rules.FieldSet((
'delivery_method',
'shipping_name',
'shipping_street',
'shipping_postalcode',
'shipping_city',
'shipping_latitude',
'shipping_longitude',
'parent_shipment',
'children',
'shipping_provider',
'shipping_id',
), 'Shipping information')),
])),
rules.Container('split', rules.FieldSet((
'faceshield_full_required',
'faceshield_front_required',
'adapter_3m_dar_required',
'adapter_easybreath_dar_required',
'adapter_rd40_dar_required',
'adapter_secura_dar_required',
'faceshield_model',
), 'Order')),
rules.Container('split', rules.FieldSet((
'faceshield_full_delivered',
'faceshield_front_delivered',
'adapter_3m_dar_delivered',
'adapter_easybreath_dar_delivered',
'adapter_rd40_dar_delivered',
'adapter_secura_dar_delivered',
), 'Delivered')),
)
form_overrides = {'entity_info': TextAreaField, 'extra': TextAreaField, 'remarks': TextAreaField}
form_choices = {
'handling_orga': [
('hswaw', 'hswaw'),
('hskrk', 'hskrk'),
],
'delivery_method': [
('shipping', 'Shipping'),
('pickup', 'Pickup'),
],
'shipping_provider': [
('kurjerzy', 'Kurjerzy'),
('xbs', 'XBS Group'),
],
}
form_overrides = {'entity_info': TextAreaField, 'extra': TextAreaField, 'remarks': TextAreaField, 'delivery_method': RadioField}
form_args = {
'shipping_name': {'validators': [validators.Length(max=35)]},
'delivery_method': {'choices': form_choices['delivery_method']},
}
form_widget_args = {
'delivery_method': { 'class': 'radio' },
}
form_excluded_columns = ('handling_orga_info', 'changelog', 'postalcode_info')
column_list = ('id', 'entity_info', 'full_name', 'items_total_delivered', 'handling_orga', 'created', 'status')
column_sortable_list = column_list
column_editable_list = ('status', 'remarks', 'handling_orga')
column_formatters = {'items_total_delivered': macro('render_items')}
column_labels = {'items_total_delivered': 'Items'}
column_export_list = column_filters
column_labels = {
'faceshield_front_required': 'Front required',
@ -102,7 +167,6 @@ class FaceshieldRequestAdmin(ModelView):
'faceshield_full_delivered': 'Full delivered',
}
column_list = ('id', 'entity_info', 'full_name', 'faceshield_full_required', 'faceshield_full_delivered', 'faceshield_front_required', 'faceshield_front_delivered', 'handling_orga', 'created', 'status')
allowed_columns = None
extra_allowed_columns = ('id',)
@property
@ -121,22 +185,6 @@ class FaceshieldRequestAdmin(ModelView):
def _list_columns(self, value):
return None
column_editable_list = ('status', 'remarks', 'handling_orga')
form_choices = {
'handling_orga': [
('hswaw', 'hswaw'),
('hskrk', 'hskrk'),
],
'delivery_method': [
('shipping', 'Shipping'),
('pickup', 'Pickup'),
],
'shipping_provider': [
('kurjerzy', 'Kurjerzy'),
('xbs', 'XBS Group'),
],
}
can_delete = False
can_view_details = True
details_modal = True

View File

@ -146,6 +146,37 @@ class FaceshieldRequest(db.Model):
return self.faceshield_full_delivered // 150
return 1
@property
def items(self):
item_types = ('faceshield_full', 'faceshield_front', 'adapter_3m_dar', 'adapter_easybreath_dar', 'adapter_rd40_dar', 'adapter_secura_dar')
return [
{
'type': item,
'required': getattr(self, '{}_required'.format(item)),
'delivered': getattr(self, '{}_delivered'.format(item)),
}
for item in item_types
if getattr(self, '{}_required'.format(item)) or getattr(self, '{}_delivered'.format(item))
]
@hybrid_property
def items_total_delivered(self):
return self.faceshield_full_delivered + \
self.faceshield_front_delivered + \
self.adapter_3m_dar_delivered + \
self.adapter_easybreath_dar_delivered + \
self.adapter_rd40_dar_delivered + \
self.adapter_secura_dar_delivered
@hybrid_property
def items_total_required(self):
return self.faceshield_full_required + \
self.faceshield_front_required + \
self.adapter_3m_dar_required + \
self.adapter_easybreath_dar_required + \
self.adapter_rd40_dar_required + \
self.adapter_secura_dar_required
def fetch_shipping_info(self):
if self.shipping_provider == 'kurjerzy':
from shipping.kurjerzy import Kurjerzy

View File

@ -2,8 +2,10 @@
{% from "_changelog.html" import render_changelog %}
{% block body %}
{{ super() }}
{{ render_changelog(model) }}
{{ super() }}
{% if model is defined %}
{{ render_changelog(model) }}
{% endif %}
{% endblock %}
{% block navlinks %}
@ -19,6 +21,7 @@
<li class="active">
<a href="javascript:void(0)">{{ _gettext('Edit') }}</a>
</li>
{% if model is defined %}
{%- if admin_view.can_view_details -%}
<li>
<a href="{{ get_url('.details_view', id=request.args.get('id'), url=return_url) }}">{{ _gettext('Details') }}</a>
@ -30,5 +33,33 @@
<li>
<a href="{{ url_for('map.index_view', id=model.id) }}" title="Show on map"><span class="glyphicon glyphicon-map-marker"></span> Show on map</a>
</li>
{% endif %}
</ul>
{% endblock %}
{% macro row(form, form_opts={}) %}
<div class="row">
{{ caller() }}
</div>
{% endmacro %}
{% macro split(form, form_opts={}) %}
<div class="col-md-6">
{{ caller() }}
</div>
{% endmacro %}
{% macro render_submit() %}
<div class="row">
<div class="pull-right">
<input type="submit" class="btn btn-primary btn-lg" value="{{ _gettext('Save') }}" />
</div>
</div>
{% endmacro %}
{% macro render_readonly(form, name, field) %}
<div class="form-group">
<label for="" class="col-md-2 control-label">{{ name }}</label>
<div class="col-md-10" style="white-space: pre-line;"><div class="checkbox">{% if model is defined %}{{ model[field] }}{% endif %}</div></div>
</div>
{% endmacro %}

View File

@ -34,3 +34,19 @@ $(function () {
})
</script>
{% endblock %}
{% macro render_items(model, column) %}
<table class="table" style="margin: 0">
{% for item in model.items %}
{% set color = {
'faceshield_full': 'primary',
'faceshield_front': 'info',
}.get(item.type, 'warning') %}
<tr>
<td><span class="label label-{{ color }}">{{ item.type }}</span></td>
<td class="text-primary">{{ item.required }}</td>
<td class="text-success">{{ item.delivered }}</td>
</tr>
{% endfor %}
</table>
{% endmacro %}