Add/improve various display of Member data
This commit is contained in:
parent
8ac0bb2334
commit
970b5871e5
17
tailbone/templates/members/view.mako
Normal file
17
tailbone/templates/members/view.mako
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
## -*- coding: utf-8; -*-
|
||||||
|
<%inherit file="/master/view.mako" />
|
||||||
|
<%namespace file="/util.mako" import="view_profiles_helper" />
|
||||||
|
|
||||||
|
<%def name="object_helpers()">
|
||||||
|
${parent.object_helpers()}
|
||||||
|
<% people = [] %>
|
||||||
|
% if instance.person:
|
||||||
|
<% people.append(instance.person) %>
|
||||||
|
% endif
|
||||||
|
% if instance.customer:
|
||||||
|
<% people.extend(instance.customer.people) %>
|
||||||
|
% endif
|
||||||
|
${view_profiles_helper(people)}
|
||||||
|
</%def>
|
||||||
|
|
||||||
|
${parent.body()}
|
|
@ -9,6 +9,76 @@
|
||||||
${self.page_content()}
|
${self.page_content()}
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
<%def name="render_member_tab()">
|
||||||
|
<b-tab-item label="Member" icon-pack="fas" :icon="members.length ? 'check' : null">
|
||||||
|
|
||||||
|
<div v-if="members.length">
|
||||||
|
|
||||||
|
<div style="display: flex; justify-content: space-between;">
|
||||||
|
<p>{{ person.display_name }} is associated with <strong>{{ members.length }}</strong> member account(s)</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<b-collapse v-for="member in members"
|
||||||
|
:key="member.uuid"
|
||||||
|
class="panel"
|
||||||
|
:open="members.length == 1">
|
||||||
|
|
||||||
|
<div slot="trigger"
|
||||||
|
slot-scope="props"
|
||||||
|
class="panel-heading"
|
||||||
|
role="button">
|
||||||
|
<b-icon pack="fas"
|
||||||
|
icon="caret-right">
|
||||||
|
</b-icon>
|
||||||
|
<strong>#{{ member.id }} {{ member.display }}</strong>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="panel-block">
|
||||||
|
<div style="display: flex; justify-content: space-between; width: 100%;">
|
||||||
|
<div style="flex-grow: 1;">
|
||||||
|
|
||||||
|
<b-field horizontal label="ID">
|
||||||
|
{{ member.id }}
|
||||||
|
</b-field>
|
||||||
|
|
||||||
|
<b-field horizontal label="Active">
|
||||||
|
{{ member.active }}
|
||||||
|
</b-field>
|
||||||
|
|
||||||
|
<b-field horizontal label="Joined">
|
||||||
|
{{ member.joined }}
|
||||||
|
</b-field>
|
||||||
|
|
||||||
|
<b-field horizontal label="Withdrew"
|
||||||
|
v-if="member.withdrew">
|
||||||
|
{{ member.withdrew }}
|
||||||
|
</b-field>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="buttons" style="align-items: start;">
|
||||||
|
${self.render_member_panel_buttons(member)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</b-collapse>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="!members.length">
|
||||||
|
<p>{{ person.display_name }} has never had a member account.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</b-tab-item>
|
||||||
|
</%def>
|
||||||
|
|
||||||
|
<%def name="render_member_panel_buttons(member)">
|
||||||
|
% if request.has_perm('members.view'):
|
||||||
|
<b-button tag="a" :href="member.view_url">
|
||||||
|
View Member
|
||||||
|
</b-button>
|
||||||
|
% endif
|
||||||
|
</%def>
|
||||||
|
|
||||||
<%def name="render_customer_tab()">
|
<%def name="render_customer_tab()">
|
||||||
<b-tab-item label="Customer" icon-pack="fas" :icon="customers.length ? 'check' : null">
|
<b-tab-item label="Customer" icon-pack="fas" :icon="customers.length ? 'check' : null">
|
||||||
|
|
||||||
|
@ -236,6 +306,8 @@
|
||||||
|
|
||||||
${self.render_customer_tab()}
|
${self.render_customer_tab()}
|
||||||
|
|
||||||
|
${self.render_member_tab()}
|
||||||
|
|
||||||
<b-tab-item label="Employee" ${'icon="check" icon-pack="fas"' if employee else ''|n}>
|
<b-tab-item label="Employee" ${'icon="check" icon-pack="fas"' if employee else ''|n}>
|
||||||
|
|
||||||
% if employee:
|
% if employee:
|
||||||
|
@ -402,6 +474,7 @@
|
||||||
activeTab: 0,
|
activeTab: 0,
|
||||||
person: ${json.dumps(person_data)|n},
|
person: ${json.dumps(person_data)|n},
|
||||||
customers: ${json.dumps(customers_data)|n},
|
customers: ${json.dumps(customers_data)|n},
|
||||||
|
members: ${json.dumps(members_data)|n},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,6 +92,7 @@ class CustomersView(MasterView):
|
||||||
'active_in_pos_sticky',
|
'active_in_pos_sticky',
|
||||||
'people',
|
'people',
|
||||||
'groups',
|
'groups',
|
||||||
|
'members',
|
||||||
]
|
]
|
||||||
|
|
||||||
mobile_form_fields = [
|
mobile_form_fields = [
|
||||||
|
@ -250,6 +251,18 @@ class CustomersView(MasterView):
|
||||||
f.set_renderer('groups', self.render_groups)
|
f.set_renderer('groups', self.render_groups)
|
||||||
f.set_readonly('groups')
|
f.set_readonly('groups')
|
||||||
|
|
||||||
|
def configure_form(self, f):
|
||||||
|
super(CustomersView, self).configure_form(f)
|
||||||
|
customer = f.model_instance
|
||||||
|
permission_prefix = self.get_permission_prefix()
|
||||||
|
|
||||||
|
# members
|
||||||
|
if self.creating:
|
||||||
|
f.remove_field('members')
|
||||||
|
else:
|
||||||
|
f.set_renderer('members', self.render_members)
|
||||||
|
f.set_readonly('members')
|
||||||
|
|
||||||
def template_kwargs_view(self, **kwargs):
|
def template_kwargs_view(self, **kwargs):
|
||||||
kwargs['show_profiles_helper'] = self.show_profiles_helper
|
kwargs['show_profiles_helper'] = self.show_profiles_helper
|
||||||
return kwargs
|
return kwargs
|
||||||
|
@ -336,6 +349,17 @@ class CustomersView(MasterView):
|
||||||
items.append(HTML.tag('li', tags.link_to(text, url)))
|
items.append(HTML.tag('li', tags.link_to(text, url)))
|
||||||
return HTML.tag('ul', HTML.literal('').join(items))
|
return HTML.tag('ul', HTML.literal('').join(items))
|
||||||
|
|
||||||
|
def render_members(self, customer, field):
|
||||||
|
members = customer.members
|
||||||
|
if not members:
|
||||||
|
return ""
|
||||||
|
items = []
|
||||||
|
for member in members:
|
||||||
|
text = six.text_type(member)
|
||||||
|
url = self.request.route_url('members.view', uuid=member.uuid)
|
||||||
|
items.append(HTML.tag('li', tags.link_to(text, url)))
|
||||||
|
return HTML.tag('ul', HTML.literal('').join(items))
|
||||||
|
|
||||||
def get_version_child_classes(self):
|
def get_version_child_classes(self):
|
||||||
return [
|
return [
|
||||||
(model.CustomerPhoneNumber, 'parent_uuid'),
|
(model.CustomerPhoneNumber, 'parent_uuid'),
|
||||||
|
|
|
@ -113,7 +113,7 @@ class MemberView(MasterView):
|
||||||
def grid_extra_class(self, member, i):
|
def grid_extra_class(self, member, i):
|
||||||
if not member.active:
|
if not member.active:
|
||||||
return 'warning'
|
return 'warning'
|
||||||
if not member.equity_current:
|
if member.equity_current is False:
|
||||||
return 'notice'
|
return 'notice'
|
||||||
|
|
||||||
def configure_form(self, f):
|
def configure_form(self, f):
|
||||||
|
@ -158,7 +158,7 @@ class MemberView(MasterView):
|
||||||
f.set_label('customer_uuid', "Customer")
|
f.set_label('customer_uuid', "Customer")
|
||||||
else:
|
else:
|
||||||
f.set_readonly('customer')
|
f.set_readonly('customer')
|
||||||
# f.set_renderer('customer', self.render_customer)
|
f.set_renderer('customer', self.render_customer)
|
||||||
|
|
||||||
# default_email
|
# default_email
|
||||||
f.set_renderer('default_email', self.render_default_email)
|
f.set_renderer('default_email', self.render_default_email)
|
||||||
|
|
|
@ -32,6 +32,7 @@ from sqlalchemy import orm
|
||||||
|
|
||||||
from rattail.db import model, api
|
from rattail.db import model, api
|
||||||
from rattail.time import localtime
|
from rattail.time import localtime
|
||||||
|
from rattail.util import OrderedDict
|
||||||
|
|
||||||
import colander
|
import colander
|
||||||
from pyramid.httpexceptions import HTTPFound, HTTPNotFound
|
from pyramid.httpexceptions import HTTPFound, HTTPNotFound
|
||||||
|
@ -316,6 +317,7 @@ class PeopleView(MasterView):
|
||||||
'today': localtime(self.rattail_config).date(),
|
'today': localtime(self.rattail_config).date(),
|
||||||
'person_data': self.get_context_person(person),
|
'person_data': self.get_context_person(person),
|
||||||
'customers_data': self.get_context_customers(person),
|
'customers_data': self.get_context_customers(person),
|
||||||
|
'members_data': self.get_context_members(person),
|
||||||
'employee': employee,
|
'employee': employee,
|
||||||
'employee_view_url': self.request.route_url('employees.view', uuid=employee.uuid) if employee else None,
|
'employee_view_url': self.request.route_url('employees.view', uuid=employee.uuid) if employee else None,
|
||||||
'employee_history': employee.get_current_history() if employee else None,
|
'employee_history': employee.get_current_history() if employee else None,
|
||||||
|
@ -366,6 +368,30 @@ class PeopleView(MasterView):
|
||||||
})
|
})
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
def get_context_members(self, person):
|
||||||
|
data = OrderedDict()
|
||||||
|
|
||||||
|
for member in person.members:
|
||||||
|
data[member.uuid] = self.get_context_member(member)
|
||||||
|
|
||||||
|
for customer in person.customers:
|
||||||
|
for member in customer.members:
|
||||||
|
if member.uuid not in data:
|
||||||
|
data[member.uuid] = self.get_context_member(member)
|
||||||
|
|
||||||
|
return list(data.values())
|
||||||
|
|
||||||
|
def get_context_member(self, member):
|
||||||
|
return {
|
||||||
|
'uuid': member.uuid,
|
||||||
|
'id': member.id,
|
||||||
|
'active': member.active,
|
||||||
|
'joined': six.text_type(member.joined) if member.joined else None,
|
||||||
|
'withdrew': six.text_type(member.withdrew) if member.withdrew else None,
|
||||||
|
'display': six.text_type(member),
|
||||||
|
'view_url': self.request.route_url('members.view', uuid=member.uuid),
|
||||||
|
}
|
||||||
|
|
||||||
def get_context_employee_history(self, employee):
|
def get_context_employee_history(self, employee):
|
||||||
data = []
|
data = []
|
||||||
if employee:
|
if employee:
|
||||||
|
|
Loading…
Reference in a new issue