Refactor several "field grids" per Buefy theme
e.g. the Users field when viewing a Role, and Vendor Sources panel when viewing a Product
This commit is contained in:
		
							parent
							
								
									9fe1d4c596
								
							
						
					
					
						commit
						3ece3303db
					
				
					 9 changed files with 299 additions and 17 deletions
				
			
		|  | @ -615,6 +615,9 @@ class Form(object): | ||||||
|         elif type_ == 'text': |         elif type_ == 'text': | ||||||
|             self.set_renderer(key, self.render_pre_sans_serif) |             self.set_renderer(key, self.render_pre_sans_serif) | ||||||
|             self.set_widget(key, dfwidget.TextAreaWidget(cols=80, rows=8)) |             self.set_widget(key, dfwidget.TextAreaWidget(cols=80, rows=8)) | ||||||
|  |         elif type_ == 'text_wrapped': | ||||||
|  |             self.set_renderer(key, self.render_pre_sans_serif_wrapped) | ||||||
|  |             self.set_widget(key, dfwidget.TextAreaWidget(cols=80, rows=8)) | ||||||
|         elif type_ == 'file': |         elif type_ == 'file': | ||||||
|             tmpstore = SessionFileUploadTempStore(self.request) |             tmpstore = SessionFileUploadTempStore(self.request) | ||||||
|             kw = {'widget': dfwidget.FileUploadWidget(tmpstore), |             kw = {'widget': dfwidget.FileUploadWidget(tmpstore), | ||||||
|  | @ -914,14 +917,26 @@ class Form(object): | ||||||
|             return "" |             return "" | ||||||
|         return HTML.tag('pre', value) |         return HTML.tag('pre', value) | ||||||
| 
 | 
 | ||||||
|     def render_pre_sans_serif(self, record, field_name): |     def render_pre_sans_serif(self, record, field_name, wrapped=False): | ||||||
|         value = self.obtain_value(record, field_name) |         value = self.obtain_value(record, field_name) | ||||||
|         if value is None: |         if value is None: | ||||||
|             return "" |             return "" | ||||||
|         # this uses a Bulma helper class, for which we also add custom styles | 
 | ||||||
|         # to our "default" base.css (for jquery theme) |         kwargs = { | ||||||
|         return HTML.tag('pre', class_='is-family-sans-serif', |             'c': value, | ||||||
|                         c=value) |             # this uses a Bulma helper class, for which we also add | ||||||
|  |             # custom styles to our "default" base.css (for jquery | ||||||
|  |             # theme) | ||||||
|  |             'class_': 'is-family-sans-serif', | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if wrapped: | ||||||
|  |             kwargs['style'] = 'white-space: pre-wrap;' | ||||||
|  | 
 | ||||||
|  |         return HTML.tag('pre', **kwargs) | ||||||
|  | 
 | ||||||
|  |     def render_pre_sans_serif_wrapped(self, record, field_name): | ||||||
|  |         return self.render_pre_sans_serif(record, field_name, wrapped=True) | ||||||
| 
 | 
 | ||||||
|     def obtain_value(self, record, field_name): |     def obtain_value(self, record, field_name): | ||||||
|         if record: |         if record: | ||||||
|  |  | ||||||
|  | @ -1418,12 +1418,13 @@ class GridAction(object): | ||||||
|     """ |     """ | ||||||
| 
 | 
 | ||||||
|     def __init__(self, key, label=None, url='#', icon=None, target=None, |     def __init__(self, key, label=None, url='#', icon=None, target=None, | ||||||
|                  click_handler=None): |                  link_class=None, click_handler=None): | ||||||
|         self.key = key |         self.key = key | ||||||
|         self.label = label or prettify(key) |         self.label = label or prettify(key) | ||||||
|         self.icon = icon |         self.icon = icon | ||||||
|         self.url = url |         self.url = url | ||||||
|         self.target = target |         self.target = target | ||||||
|  |         self.link_class = link_class | ||||||
|         self.click_handler = click_handler |         self.click_handler = click_handler | ||||||
| 
 | 
 | ||||||
|     def get_url(self, row, i): |     def get_url(self, row, i): | ||||||
|  |  | ||||||
|  | @ -26,4 +26,29 @@ | ||||||
|   % endif |   % endif | ||||||
| </%def> | </%def> | ||||||
| 
 | 
 | ||||||
|  | <%def name="render_buefy_form()"> | ||||||
|  |   <div class="form"> | ||||||
|  |     <tailbone-form @detach-person="detachPerson"> | ||||||
|  |     </tailbone-form> | ||||||
|  |   </div> | ||||||
|  | </%def> | ||||||
|  | 
 | ||||||
|  | <%def name="modify_this_page_vars()"> | ||||||
|  |   ${parent.modify_this_page_vars()} | ||||||
|  |   <script type="text/javascript"> | ||||||
|  | 
 | ||||||
|  |     ${form.component_studly}Data.peopleData = ${json.dumps(people_data)|n} | ||||||
|  | 
 | ||||||
|  |     ThisPage.methods.detachPerson = function(url) { | ||||||
|  |         ## TODO: this should require POST, but we will add that once | ||||||
|  |         ## we can assume a Buefy theme is present, to avoid having to | ||||||
|  |         ## implement the logic in old jquery... | ||||||
|  |         if (confirm("Are you sure you want to detach this person from this customer account?")) { | ||||||
|  |             location.href = url | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |   </script> | ||||||
|  | </%def> | ||||||
|  | 
 | ||||||
| ${parent.body()} | ${parent.body()} | ||||||
|  |  | ||||||
|  | @ -15,6 +15,9 @@ | ||||||
|    % if loading is not Undefined and loading: |    % if loading is not Undefined and loading: | ||||||
|    :loading="${loading}" |    :loading="${loading}" | ||||||
|    % endif |    % endif | ||||||
|  |    % if grid.default_sortkey: | ||||||
|  |    :default-sort="['${grid.default_sortkey}', '${grid.default_sortdir}']" | ||||||
|  |    % endif | ||||||
|    > |    > | ||||||
| 
 | 
 | ||||||
|   <template slot-scope="props"> |   <template slot-scope="props"> | ||||||
|  | @ -47,7 +50,11 @@ | ||||||
|         <b-table-column field="actions" label="Actions"> |         <b-table-column field="actions" label="Actions"> | ||||||
|           % for action in grid.main_actions: |           % for action in grid.main_actions: | ||||||
|               <a :href="props.row._action_url_${action.key}" |               <a :href="props.row._action_url_${action.key}" | ||||||
|  |                  % if action.link_class: | ||||||
|  |                  class="${action.link_class}" | ||||||
|  |                  % else: | ||||||
|                  class="grid-action${' has-text-danger' if action.key == 'delete' else ''}" |                  class="grid-action${' has-text-danger' if action.key == 'delete' else ''}" | ||||||
|  |                  % endif | ||||||
|                  % if action.click_handler: |                  % if action.click_handler: | ||||||
|                  @click.prevent="${action.click_handler}" |                  @click.prevent="${action.click_handler}" | ||||||
|                  % endif |                  % endif | ||||||
|  |  | ||||||
|  | @ -231,6 +231,9 @@ | ||||||
| </%def> | </%def> | ||||||
| 
 | 
 | ||||||
| <%def name="lookup_codes_grid()"> | <%def name="lookup_codes_grid()"> | ||||||
|  |   % if use_buefy: | ||||||
|  |       ${lookup_codes['grid'].render_buefy_table_element(data_prop='lookupCodesData')|n} | ||||||
|  |   % else: | ||||||
|   <div class="grid full no-border"> |   <div class="grid full no-border"> | ||||||
|     <table> |     <table> | ||||||
|       <thead> |       <thead> | ||||||
|  | @ -247,6 +250,7 @@ | ||||||
|       </tbody> |       </tbody> | ||||||
|     </table> |     </table> | ||||||
|   </div> |   </div> | ||||||
|  |   % endif | ||||||
| </%def> | </%def> | ||||||
| 
 | 
 | ||||||
| <%def name="lookup_codes_panel()"> | <%def name="lookup_codes_panel()"> | ||||||
|  | @ -266,6 +270,9 @@ | ||||||
| </%def> | </%def> | ||||||
| 
 | 
 | ||||||
| <%def name="sources_grid()"> | <%def name="sources_grid()"> | ||||||
|  |   % if use_buefy: | ||||||
|  |       ${vendor_sources['grid'].render_buefy_table_element(data_prop='vendorSourcesData')|n} | ||||||
|  |   % else: | ||||||
|   <div class="grid full no-border"> |   <div class="grid full no-border"> | ||||||
|     <table> |     <table> | ||||||
|       <thead> |       <thead> | ||||||
|  | @ -298,6 +305,7 @@ | ||||||
|       </tbody> |       </tbody> | ||||||
|     </table> |     </table> | ||||||
|   </div> |   </div> | ||||||
|  |   % endif | ||||||
| </%def> | </%def> | ||||||
| 
 | 
 | ||||||
| <%def name="sources_panel()"> | <%def name="sources_panel()"> | ||||||
|  | @ -627,6 +635,9 @@ | ||||||
|             }) |             }) | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         ThisPageData.vendorSourcesData = ${json.dumps(vendor_sources['data'])|n} | ||||||
|  |         ThisPageData.lookupCodesData = ${json.dumps(lookup_codes['data'])|n} | ||||||
|  | 
 | ||||||
|         ThisPageData.showingCostHistory = false |         ThisPageData.showingCostHistory = false | ||||||
|         ThisPageData.costHistoryDataRaw = ${json.dumps(cost_history_grid.get_buefy_data()['data'])|n} |         ThisPageData.costHistoryDataRaw = ${json.dumps(cost_history_grid.get_buefy_data()['data'])|n} | ||||||
|         ThisPageData.costHistoryLoading = false |         ThisPageData.costHistoryLoading = false | ||||||
|  |  | ||||||
|  | @ -8,7 +8,7 @@ | ||||||
| 
 | 
 | ||||||
| <%def name="page_content()"> | <%def name="page_content()"> | ||||||
|   ${parent.page_content()} |   ${parent.page_content()} | ||||||
| 
 |   % if not use_buefy: | ||||||
|   <h2>Users</h2> |   <h2>Users</h2> | ||||||
| 
 | 
 | ||||||
|   % if instance is guest_role: |   % if instance is guest_role: | ||||||
|  | @ -21,7 +21,27 @@ | ||||||
|   % else: |   % else: | ||||||
|       <p>There are no users assigned to this role.</p> |       <p>There are no users assigned to this role.</p> | ||||||
|   % endif |   % endif | ||||||
|  |   % endif | ||||||
| </%def> | </%def> | ||||||
| 
 | 
 | ||||||
|  | <%def name="modify_this_page_vars()"> | ||||||
|  |   ${parent.modify_this_page_vars()} | ||||||
|  |   <script type="text/javascript"> | ||||||
|  | 
 | ||||||
|  |     % if users_data is not Undefined: | ||||||
|  |         ${form.component_studly}Data.usersData = ${json.dumps(users_data)|n} | ||||||
|  |     % endif | ||||||
|  | 
 | ||||||
|  |     ThisPage.methods.detachPerson = function(url) { | ||||||
|  |         ## TODO: this should require POST, but we will add that once | ||||||
|  |         ## we can assume a Buefy theme is present, to avoid having to | ||||||
|  |         ## implement the logic in old jquery... | ||||||
|  |         if (confirm("Are you sure you want to detach this person from this customer account?")) { | ||||||
|  |             location.href = url | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |   </script> | ||||||
|  | </%def> | ||||||
| 
 | 
 | ||||||
| ${parent.body()} | ${parent.body()} | ||||||
|  |  | ||||||
|  | @ -173,6 +173,7 @@ class CustomerView(MasterView): | ||||||
|         super(CustomerView, self).configure_common_form(f) |         super(CustomerView, self).configure_common_form(f) | ||||||
|         customer = f.model_instance |         customer = f.model_instance | ||||||
|         permission_prefix = self.get_permission_prefix() |         permission_prefix = self.get_permission_prefix() | ||||||
|  |         use_buefy = self.get_use_buefy() | ||||||
| 
 | 
 | ||||||
|         f.set_renderer('default_email', self.render_default_email) |         f.set_renderer('default_email', self.render_default_email) | ||||||
|         if not self.creating and customer.emails: |         if not self.creating and customer.emails: | ||||||
|  | @ -217,13 +218,15 @@ class CustomerView(MasterView): | ||||||
|             f.set_renderer('person', self.form_render_person) |             f.set_renderer('person', self.form_render_person) | ||||||
| 
 | 
 | ||||||
|         # people |         # people | ||||||
|         if self.creating: |         if self.viewing: | ||||||
|             f.remove_field('people') |             if use_buefy: | ||||||
|         elif self.viewing and self.request.has_perm('{}.detach_person'.format(permission_prefix)): |                 f.set_renderer('people', self.render_people_buefy) | ||||||
|             f.set_renderer('people', self.render_people_removable) |             elif self.has_perm('detach_person'): | ||||||
|  |                 f.set_renderer('people', self.render_people_removable) | ||||||
|  |             else: | ||||||
|  |                 f.set_renderer('people', self.render_people) | ||||||
|         else: |         else: | ||||||
|             f.set_renderer('people', self.render_people) |             f.remove('people') | ||||||
|             f.set_readonly('people') |  | ||||||
| 
 | 
 | ||||||
|         # groups |         # groups | ||||||
|         if self.creating: |         if self.creating: | ||||||
|  | @ -245,7 +248,30 @@ class CustomerView(MasterView): | ||||||
|             f.set_readonly('members') |             f.set_readonly('members') | ||||||
| 
 | 
 | ||||||
|     def template_kwargs_view(self, **kwargs): |     def template_kwargs_view(self, **kwargs): | ||||||
|  |         kwargs = super(CustomerView, self).template_kwargs_view(**kwargs) | ||||||
|  | 
 | ||||||
|         kwargs['show_profiles_helper'] = self.show_profiles_helper |         kwargs['show_profiles_helper'] = self.show_profiles_helper | ||||||
|  | 
 | ||||||
|  |         use_buefy = self.get_use_buefy() | ||||||
|  |         if use_buefy: | ||||||
|  |             customer = kwargs['instance'] | ||||||
|  |             people = [] | ||||||
|  |             for person in customer.people: | ||||||
|  |                 people.append({ | ||||||
|  |                     'uuid': person.uuid, | ||||||
|  |                     'full_name': person.display_name, | ||||||
|  |                     'first_name': person.first_name, | ||||||
|  |                     'last_name': person.last_name, | ||||||
|  |                     '_action_url_view': self.request.route_url('people.view', | ||||||
|  |                                                                uuid=person.uuid), | ||||||
|  |                     '_action_url_edit': self.request.route_url('people.edit', | ||||||
|  |                                                                uuid=person.uuid), | ||||||
|  |                     '_action_url_detach': self.request.route_url('customers.detach_person', | ||||||
|  |                                                                  uuid=customer.uuid, | ||||||
|  |                                                                  person_uuid=person.uuid), | ||||||
|  |                 }) | ||||||
|  |             kwargs['people_data'] = people | ||||||
|  | 
 | ||||||
|         return kwargs |         return kwargs | ||||||
| 
 | 
 | ||||||
|     def unique_id(self, node, value): |     def unique_id(self, node, value): | ||||||
|  | @ -318,6 +344,35 @@ class CustomerView(MasterView): | ||||||
|             main_actions=actions) |             main_actions=actions) | ||||||
|         return HTML.literal(g.render_grid()) |         return HTML.literal(g.render_grid()) | ||||||
| 
 | 
 | ||||||
|  |     def render_people_buefy(self, customer, field): | ||||||
|  |         route_prefix = self.get_route_prefix() | ||||||
|  |         permission_prefix = self.get_permission_prefix() | ||||||
|  | 
 | ||||||
|  |         factory = self.get_grid_factory() | ||||||
|  |         g = factory( | ||||||
|  |             key='{}.people'.format(route_prefix), | ||||||
|  |             data=[], | ||||||
|  |             columns=[ | ||||||
|  |                 'full_name', | ||||||
|  |                 'first_name', | ||||||
|  |                 'last_name', | ||||||
|  |             ], | ||||||
|  |             sortable=True, | ||||||
|  |             sorters={'full_name': True, 'first_name': True, 'last_name': True}, | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  |         if self.request.has_perm('people.view'): | ||||||
|  |             g.main_actions.append(self.make_action('view', icon='eye')) | ||||||
|  |         if self.request.has_perm('people.edit'): | ||||||
|  |             g.main_actions.append(self.make_action('edit', icon='edit')) | ||||||
|  |         if self.has_perm('detach_person'): | ||||||
|  |             g.main_actions.append(self.make_action('detach', icon='minus-circle', | ||||||
|  |                                                    link_class='has-text-warning', | ||||||
|  |                                                    click_handler="$emit('detach-person', props.row._action_url_detach)")) | ||||||
|  | 
 | ||||||
|  |         return HTML.literal( | ||||||
|  |             g.render_buefy_table_element(data_prop='peopleData')) | ||||||
|  | 
 | ||||||
|     def render_groups(self, customer, field): |     def render_groups(self, customer, field): | ||||||
|         groups = customer.groups |         groups = customer.groups | ||||||
|         if not groups: |         if not groups: | ||||||
|  | @ -372,18 +427,25 @@ class CustomerView(MasterView): | ||||||
|     def _customer_defaults(cls, config): |     def _customer_defaults(cls, config): | ||||||
|         route_prefix = cls.get_route_prefix() |         route_prefix = cls.get_route_prefix() | ||||||
|         url_prefix = cls.get_url_prefix() |         url_prefix = cls.get_url_prefix() | ||||||
|  |         instance_url_prefix = cls.get_instance_url_prefix() | ||||||
|         permission_prefix = cls.get_permission_prefix() |         permission_prefix = cls.get_permission_prefix() | ||||||
|         model_key = cls.get_model_key() |         model_key = cls.get_model_key() | ||||||
|         model_title = cls.get_model_title() |         model_title = cls.get_model_title() | ||||||
| 
 | 
 | ||||||
|         # detach person |         # detach person | ||||||
|         if cls.people_detachable: |         if cls.people_detachable: | ||||||
|             config.add_tailbone_permission(permission_prefix, '{}.detach_person'.format(permission_prefix), |             config.add_tailbone_permission(permission_prefix, | ||||||
|  |                                            '{}.detach_person'.format(permission_prefix), | ||||||
|                                            "Detach a Person from a {}".format(model_title)) |                                            "Detach a Person from a {}".format(model_title)) | ||||||
|             config.add_route('{}.detach_person'.format(route_prefix), '{}/{{{}}}/detach-person/{{person_uuid}}'.format(url_prefix, model_key), |             # TODO: this should require POST, but we'll add that once | ||||||
|  |             # we can assume a Buefy theme is present, to avoid having | ||||||
|  |             # to implement the logic in old jquery... | ||||||
|  |             config.add_route('{}.detach_person'.format(route_prefix), | ||||||
|  |                              '{}/detach-person/{{person_uuid}}'.format(instance_url_prefix), | ||||||
|                              # request_method='POST', |                              # request_method='POST', | ||||||
|             ) |             ) | ||||||
|             config.add_view(cls, attr='detach_person', route_name='{}.detach_person'.format(route_prefix), |             config.add_view(cls, attr='detach_person', | ||||||
|  |                             route_name='{}.detach_person'.format(route_prefix), | ||||||
|                             permission='{}.detach_person'.format(permission_prefix)) |                             permission='{}.detach_person'.format(permission_prefix)) | ||||||
| 
 | 
 | ||||||
| # TODO: deprecate / remove this | # TODO: deprecate / remove this | ||||||
|  |  | ||||||
|  | @ -1152,8 +1152,88 @@ class ProductView(MasterView): | ||||||
|         kwargs['costs_label_vendor'] = "Vendor" |         kwargs['costs_label_vendor'] = "Vendor" | ||||||
|         kwargs['costs_label_code'] = "Order Code" |         kwargs['costs_label_code'] = "Order Code" | ||||||
|         kwargs['costs_label_case_size'] = "Case Size" |         kwargs['costs_label_case_size'] = "Case Size" | ||||||
|  | 
 | ||||||
|  |         if use_buefy: | ||||||
|  |             kwargs['vendor_sources'] = self.get_context_vendor_sources(product) | ||||||
|  |             kwargs['lookup_codes'] = self.get_context_lookup_codes(product) | ||||||
|  | 
 | ||||||
|         return kwargs |         return kwargs | ||||||
| 
 | 
 | ||||||
|  |     def get_context_vendor_sources(self, product): | ||||||
|  |         app = self.get_rattail_app() | ||||||
|  |         route_prefix = self.get_route_prefix() | ||||||
|  | 
 | ||||||
|  |         factory = self.get_grid_factory() | ||||||
|  |         g = factory( | ||||||
|  |             key='{}.vendor_sources'.format(route_prefix), | ||||||
|  |             data=[], | ||||||
|  |             columns=[ | ||||||
|  |                 'preferred', | ||||||
|  |                 'vendor', | ||||||
|  |                 'vendor_item_code', | ||||||
|  |                 'case_size', | ||||||
|  |                 'case_cost', | ||||||
|  |                 'unit_cost', | ||||||
|  |                 'status', | ||||||
|  |             ], | ||||||
|  |             labels={ | ||||||
|  |                 'preferred': "Pref.", | ||||||
|  |                 'vendor_item_code': "Order Code", | ||||||
|  |             }, | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  |         sources = [] | ||||||
|  |         link_vendor = self.request.has_perm('vendors.view') | ||||||
|  |         for cost in product.costs: | ||||||
|  | 
 | ||||||
|  |             source = { | ||||||
|  |                 'uuid': cost.uuid, | ||||||
|  |                 'preferred': "X" if cost.preference == 1 else None, | ||||||
|  |                 'vendor_item_code': cost.code, | ||||||
|  |                 'case_size': app.render_quantity(cost.case_size), | ||||||
|  |                 'case_cost': app.render_currency(cost.case_cost), | ||||||
|  |                 'unit_cost': app.render_currency(cost.unit_cost, scale=4), | ||||||
|  |                 'status': "discontinued" if cost.discontinued else "available", | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             text = six.text_type(cost.vendor) | ||||||
|  |             if link_vendor: | ||||||
|  |                 url = self.request.route_url('vendors.view', uuid=cost.vendor.uuid) | ||||||
|  |                 source['vendor'] = tags.link_to(text, url) | ||||||
|  |             else: | ||||||
|  |                 source['vendor'] = text | ||||||
|  | 
 | ||||||
|  |             sources.append(source) | ||||||
|  | 
 | ||||||
|  |         return {'grid': g, 'data': sources} | ||||||
|  | 
 | ||||||
|  |     def get_context_lookup_codes(self, product): | ||||||
|  |         route_prefix = self.get_route_prefix() | ||||||
|  | 
 | ||||||
|  |         factory = self.get_grid_factory() | ||||||
|  |         g = factory( | ||||||
|  |             key='{}.lookup_codes'.format(route_prefix), | ||||||
|  |             data=[], | ||||||
|  |             columns=[ | ||||||
|  |                 'sequence', | ||||||
|  |                 'code', | ||||||
|  |             ], | ||||||
|  |             labels={ | ||||||
|  |                 'sequence': "Seq.", | ||||||
|  |             }, | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  |         lookup_codes = [] | ||||||
|  |         for code in product._codes: | ||||||
|  | 
 | ||||||
|  |             lookup_codes.append({ | ||||||
|  |                 'uuid': code.uuid, | ||||||
|  |                 'sequence': code.ordinal, | ||||||
|  |                 'code': code.code, | ||||||
|  |             }) | ||||||
|  | 
 | ||||||
|  |         return {'grid': g, 'data': lookup_codes} | ||||||
|  | 
 | ||||||
|     def get_regular_price_history(self, product): |     def get_regular_price_history(self, product): | ||||||
|         """ |         """ | ||||||
|         Returns a sequence of "records" which corresponds to the given |         Returns a sequence of "records" which corresponds to the given | ||||||
|  |  | ||||||
|  | @ -63,6 +63,7 @@ class RoleView(PrincipalMasterView): | ||||||
|         'name', |         'name', | ||||||
|         'session_timeout', |         'session_timeout', | ||||||
|         'notes', |         'notes', | ||||||
|  |         'users', | ||||||
|         'permissions', |         'permissions', | ||||||
|     ] |     ] | ||||||
| 
 | 
 | ||||||
|  | @ -147,7 +148,13 @@ class RoleView(PrincipalMasterView): | ||||||
|         f.set_validator('name', self.unique_name) |         f.set_validator('name', self.unique_name) | ||||||
| 
 | 
 | ||||||
|         # notes |         # notes | ||||||
|         f.set_type('notes', 'text') |         f.set_type('notes', 'text_wrapped') | ||||||
|  | 
 | ||||||
|  |         # users | ||||||
|  |         if use_buefy and self.viewing or self.deleting: | ||||||
|  |             f.set_renderer('users', self.render_users) | ||||||
|  |         else: | ||||||
|  |             f.remove('users') | ||||||
| 
 | 
 | ||||||
|         # permissions |         # permissions | ||||||
|         self.tailbone_permissions = self.get_available_permissions() |         self.tailbone_permissions = self.get_available_permissions() | ||||||
|  | @ -171,6 +178,40 @@ class RoleView(PrincipalMasterView): | ||||||
|         if self.editing and role is guest_role(self.Session()): |         if self.editing and role is guest_role(self.Session()): | ||||||
|             f.set_readonly('session_timeout') |             f.set_readonly('session_timeout') | ||||||
| 
 | 
 | ||||||
|  |     def render_users(self, role, field): | ||||||
|  | 
 | ||||||
|  |         if role is guest_role(self.Session()): | ||||||
|  |             return ("The guest role is implied for all anonymous users, " | ||||||
|  |                     "i.e. when not logged in.") | ||||||
|  | 
 | ||||||
|  |         if role is authenticated_role(self.Session()): | ||||||
|  |             return ("The authenticated role is implied for all users, " | ||||||
|  |                     "but only when logged in.") | ||||||
|  | 
 | ||||||
|  |         route_prefix = self.get_route_prefix() | ||||||
|  |         permission_prefix = self.get_permission_prefix() | ||||||
|  |         factory = self.get_grid_factory() | ||||||
|  |         g = factory( | ||||||
|  |             key='{}.users'.format(route_prefix), | ||||||
|  |             data=[], | ||||||
|  |             columns=[ | ||||||
|  |                 'full_name', | ||||||
|  |                 'username', | ||||||
|  |                 'active', | ||||||
|  |             ], | ||||||
|  |             sortable=True, | ||||||
|  |             sorters={'full_name': True, 'username': True, 'active': True}, | ||||||
|  |             default_sortkey='full_name', | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  |         if self.request.has_perm('users.view'): | ||||||
|  |             g.main_actions.append(self.make_action('view', icon='eye')) | ||||||
|  |         if self.request.has_perm('users.edit'): | ||||||
|  |             g.main_actions.append(self.make_action('edit', icon='edit')) | ||||||
|  | 
 | ||||||
|  |         return HTML.literal( | ||||||
|  |             g.render_buefy_table_element(data_prop='usersData')) | ||||||
|  | 
 | ||||||
|     def get_available_permissions(self): |     def get_available_permissions(self): | ||||||
|         """ |         """ | ||||||
|         Should return a dictionary with all "available" permissions.  The |         Should return a dictionary with all "available" permissions.  The | ||||||
|  | @ -259,8 +300,28 @@ class RoleView(PrincipalMasterView): | ||||||
|                                          main_actions=actions) |                                          main_actions=actions) | ||||||
|         else: |         else: | ||||||
|             kwargs['users'] = None |             kwargs['users'] = None | ||||||
|  | 
 | ||||||
|         kwargs['guest_role'] = guest_role(self.Session()) |         kwargs['guest_role'] = guest_role(self.Session()) | ||||||
|         kwargs['authenticated_role'] = authenticated_role(self.Session()) |         kwargs['authenticated_role'] = authenticated_role(self.Session()) | ||||||
|  | 
 | ||||||
|  |         use_buefy = self.get_use_buefy() | ||||||
|  |         if use_buefy: | ||||||
|  |             role = kwargs['instance'] | ||||||
|  |             if role not in (kwargs['guest_role'], kwargs['authenticated_role']): | ||||||
|  |                 users_data = [] | ||||||
|  |                 for user in role.users: | ||||||
|  |                     users_data.append({ | ||||||
|  |                         'uuid': user.uuid, | ||||||
|  |                         'full_name': user.display_name, | ||||||
|  |                         'username': user.username, | ||||||
|  |                         'active': "Yes" if user.active else "No", | ||||||
|  |                         '_action_url_view': self.request.route_url('users.view', | ||||||
|  |                                                                    uuid=user.uuid), | ||||||
|  |                         '_action_url_edit': self.request.route_url('users.edit', | ||||||
|  |                                                                    uuid=user.uuid), | ||||||
|  |                     }) | ||||||
|  |                 kwargs['users_data'] = users_data | ||||||
|  | 
 | ||||||
|         return kwargs |         return kwargs | ||||||
| 
 | 
 | ||||||
|     def before_delete(self, role): |     def before_delete(self, role): | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Lance Edgar
						Lance Edgar