Rework admin form/list view
parent
39745971ff
commit
7ad9fa4335
106
formity/admin.py
106
formity/admin.py
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -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 %}
|
||||
|
|
Loading…
Reference in New Issue