From fdd0b6ec3b00a2b90c034072bdf633067fe42cfe Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 21 Nov 2016 17:47:24 -0600 Subject: [PATCH] Add some links between employees / people / customers views --- tailbone/forms/renderers/__init__.py | 1 + tailbone/forms/renderers/people.py | 39 ++++++++--------------- tailbone/views/employees.py | 46 ++++++++++++++++------------ tailbone/views/people.py | 36 +++++++++++++++++++--- 4 files changed, 72 insertions(+), 50 deletions(-) diff --git a/tailbone/forms/renderers/__init__.py b/tailbone/forms/renderers/__init__.py index c238f537..2c6cd0f4 100644 --- a/tailbone/forms/renderers/__init__.py +++ b/tailbone/forms/renderers/__init__.py @@ -35,6 +35,7 @@ from .common import (StrippedTextFieldRenderer, CodeTextAreaFieldRenderer, Autoc from .files import FileFieldRenderer +# TODO: deprecate / remove Link renderers from .people import (PersonFieldRenderer, PersonFieldLinkRenderer, CustomerFieldRenderer, CustomerFieldLinkRenderer) diff --git a/tailbone/forms/renderers/people.py b/tailbone/forms/renderers/people.py index d1a1ee93..e103b7f5 100644 --- a/tailbone/forms/renderers/people.py +++ b/tailbone/forms/renderers/people.py @@ -26,12 +26,9 @@ People Field Renderers from __future__ import unicode_literals, absolute_import -from .common import AutocompleteFieldRenderer from webhelpers.html import tags - -__all__ = ['PersonFieldRenderer', 'PersonFieldLinkRenderer', - 'CustomerFieldRenderer', 'CustomerFieldLinkRenderer'] +from tailbone.forms.renderers.common import AutocompleteFieldRenderer class PersonFieldRenderer(AutocompleteFieldRenderer): @@ -41,19 +38,14 @@ class PersonFieldRenderer(AutocompleteFieldRenderer): service_route = 'people.autocomplete' - -class PersonFieldLinkRenderer(PersonFieldRenderer): - """ - Renderer for :class:`rattail.db.model.Person` instance fields (with hyperlink). - """ - def render_readonly(self, **kwargs): person = self.raw_value - if person: - return tags.link_to( - unicode(person), - self.request.route_url('people.view', uuid=person.uuid)) - return u'' + if not person: + return '' + return tags.link_to(person, self.request.route_url('people.view', uuid=person.uuid)) + +# TODO: deprecate / remove this +PersonFieldLinkRenderer = PersonFieldRenderer class CustomerFieldRenderer(AutocompleteFieldRenderer): @@ -63,16 +55,11 @@ class CustomerFieldRenderer(AutocompleteFieldRenderer): service_route = 'customers.autocomplete' - -class CustomerFieldLinkRenderer(CustomerFieldRenderer): - """ - Renderer for :class:`rattail.db.model.Customer` instance fields (with hyperlink). - """ - def render_readonly(self, **kwargs): customer = self.raw_value - if customer: - return tags.link_to( - unicode(customer), - self.request.route_url('customers.view', uuid=customer.uuid)) - return u'' + if not customer: + return '' + return tags.link_to(customer, self.request.route_url('customers.view', uuid=customer.uuid)) + +# TODO: deprecate / remove this +CustomerFieldLinkRenderer = CustomerFieldRenderer diff --git a/tailbone/views/employees.py b/tailbone/views/employees.py index 69bef032..6a697234 100644 --- a/tailbone/views/employees.py +++ b/tailbone/views/employees.py @@ -28,10 +28,9 @@ from __future__ import unicode_literals, absolute_import import sqlalchemy as sa -from rattail import enum from rattail.db import model -import formalchemy +import formalchemy as fa from tailbone import forms from tailbone.db import Session @@ -67,8 +66,8 @@ class EmployeesView(MasterView): g.filters['id'].label = "ID" g.filters['status'].default_active = True g.filters['status'].default_verb = 'equal' - g.filters['status'].default_value = enum.EMPLOYEE_STATUS_CURRENT - g.filters['status'].set_value_renderer(EnumValueRenderer(enum.EMPLOYEE_STATUS)) + g.filters['status'].default_value = self.enum.EMPLOYEE_STATUS_CURRENT + g.filters['status'].set_value_renderer(EnumValueRenderer(self.enum.EMPLOYEE_STATUS)) else: del g.filters['id'] del g.filters['status'] @@ -97,7 +96,7 @@ class EmployeesView(MasterView): g.last_name, g.phone.label("Phone Number"), g.email.label("Email Address"), - g.status.with_renderer(forms.EnumFieldRenderer(enum.EMPLOYEE_STATUS)), + g.status.with_renderer(forms.renderers.EnumFieldRenderer(self.enum.EMPLOYEE_STATUS)), ], readonly=True) @@ -108,38 +107,47 @@ class EmployeesView(MasterView): def query(self, session): q = session.query(model.Employee).join(model.Person) if not self.request.has_perm('employees.edit'): - q = q.filter(model.Employee.status == enum.EMPLOYEE_STATUS_CURRENT) + q = q.filter(model.Employee.status == self.enum.EMPLOYEE_STATUS_CURRENT) return q - def configure_fieldset(self, fs): + def _preconfigure_fieldset(self, fs): fs.append(forms.AssociationProxyField('first_name')) fs.append(forms.AssociationProxyField('last_name')) - fs.append(forms.AssociationProxyField('display_name')) fs.append(StoresField('stores')) fs.append(DepartmentsField('departments')) + + fs.person.set(renderer=forms.renderers.PersonFieldRenderer) + fs.display_name.set(label="Short Name") + fs.phone.set(label="Phone Number", readonly=True) + fs.email.set(label="Email Address", readonly=True) + fs.status.set(renderer=forms.renderers.EnumFieldRenderer(self.enum.EMPLOYEE_STATUS)) + fs.id.set(label="ID") + + def configure_fieldset(self, fs): fs.configure( include=[ - fs.id.label("ID"), + fs.person, fs.first_name, fs.last_name, fs.display_name, - fs.phone.label("Phone Number").readonly(), - fs.email.label("Email Address").readonly(), - fs.status.with_renderer(forms.EnumFieldRenderer(enum.EMPLOYEE_STATUS)), + fs.phone, + fs.email, + fs.status, + fs.id, fs.stores, fs.departments, ]) -class StoresField(formalchemy.Field): +class StoresField(fa.Field): def __init__(self, name, **kwargs): - kwargs.setdefault('type', formalchemy.types.Set) + kwargs.setdefault('type', fa.types.Set) kwargs.setdefault('options', Session.query(model.Store).order_by(model.Store.name)) kwargs.setdefault('value', self.get_value) kwargs.setdefault('multiple', True) kwargs.setdefault('size', 3) - formalchemy.Field.__init__(self, name=name, **kwargs) + fa.Field.__init__(self, name=name, **kwargs) def get_value(self, employee): return [s.uuid for s in employee.stores] @@ -159,15 +167,15 @@ class StoresField(formalchemy.Field): employee.stores.remove(store) -class DepartmentsField(formalchemy.Field): +class DepartmentsField(fa.Field): def __init__(self, name, **kwargs): - kwargs.setdefault('type', formalchemy.types.Set) + kwargs.setdefault('type', fa.types.Set) kwargs.setdefault('options', Session.query(model.Department).order_by(model.Department.name)) kwargs.setdefault('value', self.get_value) kwargs.setdefault('multiple', True) kwargs.setdefault('size', 10) - formalchemy.Field.__init__(self, name=name, **kwargs) + fa.Field.__init__(self, name=name, **kwargs) def get_value(self, employee): return [d.uuid for d in employee.departments] @@ -197,7 +205,7 @@ class EmployeesAutocomplete(AutocompleteView): def filter_query(self, q): return q.join(model.Employee)\ - .filter(model.Employee.status == enum.EMPLOYEE_STATUS_CURRENT) + .filter(model.Employee.status == self.enum.EMPLOYEE_STATUS_CURRENT) def value(self, person): return person.employee.uuid diff --git a/tailbone/views/people.py b/tailbone/views/people.py index 18957915..4ef4f999 100644 --- a/tailbone/views/people.py +++ b/tailbone/views/people.py @@ -2,7 +2,7 @@ ################################################################################ # # Rattail -- Retail Software Framework -# Copyright © 2010-2015 Lance Edgar +# Copyright © 2010-2016 Lance Edgar # # This file is part of Rattail. # @@ -28,13 +28,31 @@ from __future__ import unicode_literals, absolute_import import sqlalchemy as sa +import formalchemy as fa from pyramid.httpexceptions import HTTPFound, HTTPNotFound +from webhelpers.html import HTML, tags from tailbone.views import MasterView, AutocompleteView from rattail.db import model +class CustomersFieldRenderer(fa.FieldRenderer): + + def render_readonly(self, **kwargs): + customers = self.raw_value + if not customers: + return '' + + items = [] + for customer in customers: + customer = customer.customer + items.append(HTML.tag('li', c=tags.link_to('{} {}'.format(customer.id, customer), + self.request.route_url('customers.view', uuid=customer.uuid)))) + + return HTML.tag('ul', c=items) + + class PeopleView(MasterView): """ Master view for the Person class. @@ -89,16 +107,24 @@ class PeopleView(MasterView): return instance.person raise HTTPNotFound + def _preconfigure_fieldset(self, fs): + fs.display_name.set(label="Full Name") + fs.phone.set(label="Phone Number", readonly=True) + fs.email.set(label="Email Address", readonly=True) + fs.address.set(label="Mailing Address", readonly=True) + fs._customers.set(renderer=CustomersFieldRenderer, readonly=True) + def configure_fieldset(self, fs): fs.configure( include=[ - fs.display_name.label("Full Name"), + fs.display_name, fs.first_name, fs.middle_name, fs.last_name, - fs.phone.label("Phone Number").readonly(), - fs.email.label("Email Address").readonly(), - fs.address.label("Mailing Address").readonly(), + fs.phone, + fs.email, + fs.address, + fs._customers, ])