Add basic Buefy support for App Settings page
also various buttons have been tweaked on some other "master view" pages
This commit is contained in:
		
							parent
							
								
									e1ff4578e9
								
							
						
					
					
						commit
						fcfc8b56bb
					
				
					 13 changed files with 245 additions and 52 deletions
				
			
		|  | @ -67,7 +67,8 @@ class Grid(object): | ||||||
|     Core grid class.  In sore need of documentation. |     Core grid class.  In sore need of documentation. | ||||||
|     """ |     """ | ||||||
| 
 | 
 | ||||||
|     def __init__(self, key, data, columns=None, width='auto', request=None, mobile=False, model_class=None, |     def __init__(self, key, data, columns=None, width='auto', request=None, mobile=False, | ||||||
|  |                  model_class=None, model_title=None, model_title_plural=None, | ||||||
|                  enums={}, labels={}, renderers={}, extra_row_class=None, linked_columns=[], url='#', |                  enums={}, labels={}, renderers={}, extra_row_class=None, linked_columns=[], url='#', | ||||||
|                  joiners={}, filterable=False, filters={}, use_byte_string_filters=False, |                  joiners={}, filterable=False, filters={}, use_byte_string_filters=False, | ||||||
|                  sortable=False, sorters={}, default_sortkey=None, default_sortdir='asc', |                  sortable=False, sorters={}, default_sortkey=None, default_sortdir='asc', | ||||||
|  | @ -84,6 +85,18 @@ class Grid(object): | ||||||
|         self.model_class = model_class |         self.model_class = model_class | ||||||
|         if self.model_class and self.columns is None: |         if self.model_class and self.columns is None: | ||||||
|             self.columns = self.make_columns() |             self.columns = self.make_columns() | ||||||
|  | 
 | ||||||
|  |         self.model_title = model_title | ||||||
|  |         if not self.model_title and self.model_class: | ||||||
|  |             self.model_title = self.model_class.get_model_title() | ||||||
|  | 
 | ||||||
|  |         self.model_title_plural = model_title_plural | ||||||
|  |         if not self.model_title_plural: | ||||||
|  |             if self.model_class: | ||||||
|  |                 self.model_title_plural = self.model_class.get_model_title_plural() | ||||||
|  |             if not self.model_title_plural: | ||||||
|  |                 self.model_title_plural = '{}s'.format(self.model_title) | ||||||
|  | 
 | ||||||
|         self.enums = enums or {} |         self.enums = enums or {} | ||||||
| 
 | 
 | ||||||
|         self.labels = labels or {} |         self.labels = labels or {} | ||||||
|  |  | ||||||
|  | @ -7,11 +7,14 @@ | ||||||
| 
 | 
 | ||||||
| <%def name="extra_javascript()"> | <%def name="extra_javascript()"> | ||||||
|   ${parent.extra_javascript()} |   ${parent.extra_javascript()} | ||||||
|  |   % if not use_buefy: | ||||||
|   ${h.javascript_link(request.static_url('tailbone:static/js/tailbone.appsettings.js') + '?ver={}'.format(tailbone.__version__))} |   ${h.javascript_link(request.static_url('tailbone:static/js/tailbone.appsettings.js') + '?ver={}'.format(tailbone.__version__))} | ||||||
|  |   % endif | ||||||
| </%def> | </%def> | ||||||
| 
 | 
 | ||||||
| <%def name="extra_styles()"> | <%def name="extra_styles()"> | ||||||
|   ${parent.extra_styles()} |   ${parent.extra_styles()} | ||||||
|  |   % if not use_buefy: | ||||||
|   <style type="text/css"> |   <style type="text/css"> | ||||||
|     div.form { |     div.form { | ||||||
|         float: none; |         float: none; | ||||||
|  | @ -27,6 +30,7 @@ | ||||||
|         width: 50em; |         width: 50em; | ||||||
|     } |     } | ||||||
|   </style> |   </style> | ||||||
|  |   % endif | ||||||
| </%def> | </%def> | ||||||
| 
 | 
 | ||||||
| <div class="form"> | <div class="form"> | ||||||
|  | @ -46,10 +50,17 @@ | ||||||
|       </div> |       </div> | ||||||
|   % endif |   % endif | ||||||
| 
 | 
 | ||||||
|  |   % if use_buefy: | ||||||
|  |   <div id="app-settings-app"> | ||||||
|  |     <app-settings :groups="groups" :showing-group="showingGroup"></app-settings> | ||||||
|  |   </div> | ||||||
|  | 
 | ||||||
|  |   % else: | ||||||
|  |   ## not buefy | ||||||
|   <div class="group-picker"> |   <div class="group-picker"> | ||||||
|     <div class="field-wrapper"> |     <div class="field-wrapper"> | ||||||
|       <label for="settings-group">Showing Group</label> |       <label for="settings-group">Showing Group</label> | ||||||
|       <div class="field"> |       <div class="field select"> | ||||||
|         ${h.select('settings-group', current_group, group_options, **{'auto-enhance': 'true'})} |         ${h.select('settings-group', current_group, group_options, **{'auto-enhance': 'true'})} | ||||||
|       </div> |       </div> | ||||||
|     </div> |     </div> | ||||||
|  | @ -88,11 +99,116 @@ | ||||||
|         </div><!-- panel-body --> |         </div><!-- panel-body --> | ||||||
|       </div><! -- panel --> |       </div><! -- panel --> | ||||||
|   % endfor |   % endfor | ||||||
|  |   % endif | ||||||
| 
 | 
 | ||||||
|   <div class="buttons"> |   <div class="buttons"> | ||||||
|     ${h.submit('save', getattr(form, 'submit_label', getattr(form, 'save_label', "Submit")))} |     ${h.submit('save', getattr(form, 'submit_label', getattr(form, 'save_label', "Submit")), class_='button is-primary')} | ||||||
|     ${h.link_to("Cancel", form.cancel_url, class_='cancel button{}'.format(' autodisable' if form.auto_disable_cancel else ''))} |     ${h.link_to("Cancel", form.cancel_url, class_='cancel button{}'.format(' autodisable' if form.auto_disable_cancel else ''))} | ||||||
|   </div> |   </div> | ||||||
| 
 | 
 | ||||||
|   ${h.end_form()} |   ${h.end_form()} | ||||||
| </div> | </div> | ||||||
|  | 
 | ||||||
|  | % if use_buefy: | ||||||
|  |     <script type="text/x-template" id="app-settings-template"> | ||||||
|  |       <div class="app-wrapper"> | ||||||
|  | 
 | ||||||
|  |         <div class="field-wrapper"> | ||||||
|  |           <label for="settings-group">Showing Group</label> | ||||||
|  |           <b-select @input="showGroup" | ||||||
|  |                     name="settings-group" | ||||||
|  |                     v-model="showingGroup"> | ||||||
|  |             <option value="">(All)</option> | ||||||
|  |             <option v-for="group in groups" | ||||||
|  |                     :key="group.label" | ||||||
|  |                     :value="group.label"> | ||||||
|  |               {{ group.label }} | ||||||
|  |             </option> | ||||||
|  |           </b-select> | ||||||
|  |         </div> | ||||||
|  | 
 | ||||||
|  |         <div v-for="group in groups" | ||||||
|  |              class="card" | ||||||
|  |              v-show="!showingGroup || showingGroup == group.label" | ||||||
|  |              style="margin-bottom: 1rem;"> | ||||||
|  |           <header class="card-header"> | ||||||
|  |             <p class="card-header-title">{{ group.label }}</p> | ||||||
|  |           </header> | ||||||
|  |           <div class="card-content"> | ||||||
|  |             <div v-for="setting in group.settings" | ||||||
|  |                 :class="'field-wrapper' + (setting.error ? ' with-error' : '')"> | ||||||
|  | 
 | ||||||
|  |               <div v-if="setting.error" class="field-error"> | ||||||
|  |                 <span v-for="msg in setting.error_messages" | ||||||
|  |                       class="error-msg"> | ||||||
|  |                   {{ msg }} | ||||||
|  |                 </span> | ||||||
|  |               </div> | ||||||
|  | 
 | ||||||
|  |               <div class="field-row"> | ||||||
|  |                 <label :for="setting.field_name">{{ setting.label }}</label> | ||||||
|  |                 <div class="field"> | ||||||
|  | 
 | ||||||
|  |                   <input v-if="setting.data_type == 'bool'" | ||||||
|  |                          type="checkbox" | ||||||
|  |                          :name="setting.field_name" | ||||||
|  |                          :id="setting.field_name" | ||||||
|  |                          v-model="setting.value" | ||||||
|  |                          value="true" /> | ||||||
|  | 
 | ||||||
|  |                   <b-select v-else-if="setting.choices" | ||||||
|  |                             :name="setting.field_name" | ||||||
|  |                             :id="setting.field_name" | ||||||
|  |                             v-model="setting.value"> | ||||||
|  |                     <option v-for="choice in setting.choices" | ||||||
|  |                             :value="choice"> | ||||||
|  |                       {{ choice }} | ||||||
|  |                     </option> | ||||||
|  |                   </b-select> | ||||||
|  | 
 | ||||||
|  |                   <b-input v-else | ||||||
|  |                            :name="setting.field_name" | ||||||
|  |                            :id="setting.field_name" | ||||||
|  |                            v-model="setting.value" /> | ||||||
|  |                 </div> | ||||||
|  |               </div> | ||||||
|  | 
 | ||||||
|  |               <span v-if="setting.helptext" class="instructions"> | ||||||
|  |                 {{ setting.helptext }} | ||||||
|  |               </span> | ||||||
|  | 
 | ||||||
|  |             </div><!-- field-wrapper --> | ||||||
|  |           </div><!-- card-content --> | ||||||
|  |         </div><!-- card --> | ||||||
|  | 
 | ||||||
|  |       </div><!-- app-wrapper --> | ||||||
|  |     </script> | ||||||
|  | 
 | ||||||
|  |     <script type="text/javascript"> | ||||||
|  | 
 | ||||||
|  |       Vue.component('app-settings', { | ||||||
|  |           template: '#app-settings-template', | ||||||
|  |           props: { | ||||||
|  |               groups: Array, | ||||||
|  |               showingGroup: String | ||||||
|  |           }, | ||||||
|  |           methods: { | ||||||
|  |               showGroup(group) { | ||||||
|  |                   console.log("SHOWING GROUP") | ||||||
|  |                   console.log(group) | ||||||
|  |               } | ||||||
|  |           } | ||||||
|  |       }) | ||||||
|  | 
 | ||||||
|  |       new Vue({ | ||||||
|  |           el: '#app-settings-app', | ||||||
|  |           data() { | ||||||
|  |               return { | ||||||
|  |                   groups: ${json.dumps(buefy_data)|n}, | ||||||
|  |                   showingGroup: ${json.dumps(current_group or '')|n} | ||||||
|  |               } | ||||||
|  |           } | ||||||
|  |       }) | ||||||
|  | 
 | ||||||
|  |     </script> | ||||||
|  | % endif | ||||||
|  |  | ||||||
|  | @ -21,7 +21,9 @@ | ||||||
| 
 | 
 | ||||||
| <%def name="object_helpers()"> | <%def name="object_helpers()"> | ||||||
|   ${parent.object_helpers()} |   ${parent.object_helpers()} | ||||||
|  |   % if instance.people: | ||||||
|       ${view_profiles_helper(instance.people)} |       ${view_profiles_helper(instance.people)} | ||||||
|  |   % endif | ||||||
| </%def> | </%def> | ||||||
| 
 | 
 | ||||||
| ${parent.body()} | ${parent.body()} | ||||||
|  |  | ||||||
|  | @ -5,16 +5,16 @@ | ||||||
|   ${parent.grid_tools()} |   ${parent.grid_tools()} | ||||||
| 
 | 
 | ||||||
|   % if request.has_perm('datasync.restart'): |   % if request.has_perm('datasync.restart'): | ||||||
|       ${h.form(url('datasync.restart'), name='restart-datasync', class_='autodisable')} |       ${h.form(url('datasync.restart'), name='restart-datasync', class_='autodisable control')} | ||||||
|       ${h.csrf_token(request)} |       ${h.csrf_token(request)} | ||||||
|       ${h.submit('submit', "Restart DataSync", data_working_label="Restarting DataSync")} |       ${h.submit('submit', "Restart DataSync", data_working_label="Restarting DataSync", class_='button')} | ||||||
|       ${h.end_form()} |       ${h.end_form()} | ||||||
|   % endif |   % endif | ||||||
| 
 | 
 | ||||||
|   % if allow_filemon_restart and request.has_perm('filemon.restart'): |   % if allow_filemon_restart and request.has_perm('filemon.restart'): | ||||||
|       ${h.form(url('filemon.restart'), name='restart-filemon', class_='autodisable')} |       ${h.form(url('filemon.restart'), name='restart-filemon', class_='autodisable control')} | ||||||
|       ${h.csrf_token(request)} |       ${h.csrf_token(request)} | ||||||
|       ${h.submit('submit', "Restart FileMon", data_working_label="Restarting FileMon")} |       ${h.submit('submit', "Restart FileMon", data_working_label="Restarting FileMon", class_='button')} | ||||||
|       ${h.end_form()} |       ${h.end_form()} | ||||||
|   % endif |   % endif | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -11,6 +11,7 @@ | ||||||
| 
 | 
 | ||||||
|   <input type="hidden" name="__start__" value="${name}:sequence" |   <input type="hidden" name="__start__" value="${name}:sequence" | ||||||
|          tal:condition="multiple" /> |          tal:condition="multiple" /> | ||||||
|  |   <div class="select"> | ||||||
|   <select tal:attributes=" |   <select tal:attributes=" | ||||||
|           name name; |           name name; | ||||||
|           id oid; |           id oid; | ||||||
|  | @ -36,6 +37,7 @@ | ||||||
|               value item[0]">${item[1]}</option> |               value item[0]">${item[1]}</option> | ||||||
|     </tal:loop> |     </tal:loop> | ||||||
|   </select> |   </select> | ||||||
|  |   </div> | ||||||
|   <input type="hidden" name="__end__" value="${name}:sequence" |   <input type="hidden" name="__end__" value="${name}:sequence" | ||||||
|          tal:condition="multiple" /> |          tal:condition="multiple" /> | ||||||
|   <script tal:condition="not multiple" type="text/javascript"> |   <script tal:condition="not multiple" type="text/javascript"> | ||||||
|  |  | ||||||
|  | @ -67,7 +67,7 @@ | ||||||
| 
 | 
 | ||||||
|       <div class="grid-tools-wrapper"> |       <div class="grid-tools-wrapper"> | ||||||
|         % if tools: |         % if tools: | ||||||
|             <div class="grid-tools"> |             <div class="grid-tools field is-grouped"> | ||||||
|               ## TODO: stop using |n filter |               ## TODO: stop using |n filter | ||||||
|               ${tools|n} |               ${tools|n} | ||||||
|             </div> |             </div> | ||||||
|  | @ -299,6 +299,14 @@ | ||||||
|               // apply current filters as normal, but add special directive |               // apply current filters as normal, but add special directive | ||||||
|               const params = ['save-current-filters-as-defaults=true'] |               const params = ['save-current-filters-as-defaults=true'] | ||||||
|               this.applyFilters(params) |               this.applyFilters(params) | ||||||
|  |           }, | ||||||
|  | 
 | ||||||
|  |           deleteResults(event) { | ||||||
|  | 
 | ||||||
|  |               // submit form if user confirms | ||||||
|  |               if (confirm("You are about to delete " + this.total + " ${grid.model_title_plural}.\n\nAre you sure?")) { | ||||||
|  |                   event.target.form.submit() | ||||||
|  |               } | ||||||
|           } |           } | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -25,7 +25,7 @@ | ||||||
|   ${h.csrf_token(request)} |   ${h.csrf_token(request)} | ||||||
|     <div class="buttons"> |     <div class="buttons"> | ||||||
|       <a class="button" href="${form.cancel_url}">Whoops, nevermind...</a> |       <a class="button" href="${form.cancel_url}">Whoops, nevermind...</a> | ||||||
|       ${h.submit('submit', "Yes, please DELETE this data forever!")} |       ${h.submit('submit', "Yes, please DELETE this data forever!", class_='button is-primary')} | ||||||
|     </div> |     </div> | ||||||
|   ${h.end_form()} |   ${h.end_form()} | ||||||
| </%def> | </%def> | ||||||
|  |  | ||||||
|  | @ -45,7 +45,7 @@ | ||||||
| 
 | 
 | ||||||
|         % endif |         % endif | ||||||
| 
 | 
 | ||||||
|         % if master.bulk_deletable and request.has_perm('{}.bulk_delete'.format(permission_prefix)): |         % if not use_buefy and master.bulk_deletable and request.has_perm('{}.bulk_delete'.format(permission_prefix)): | ||||||
| 
 | 
 | ||||||
|         $('form[name="bulk-delete"] button').click(function() { |         $('form[name="bulk-delete"] button').click(function() { | ||||||
|             var count = $('.grid-wrapper').gridwrapper('results_count', true); |             var count = $('.grid-wrapper').gridwrapper('results_count', true); | ||||||
|  | @ -134,42 +134,53 @@ | ||||||
| 
 | 
 | ||||||
|   ## merge 2 objects |   ## merge 2 objects | ||||||
|   % if master.mergeable and request.has_perm('{}.merge'.format(permission_prefix)): |   % if master.mergeable and request.has_perm('{}.merge'.format(permission_prefix)): | ||||||
|       ${h.form(url('{}.merge'.format(route_prefix)), name='merge-things')} |       ${h.form(url('{}.merge'.format(route_prefix)), name='merge-things', class_='control')} | ||||||
|       ${h.csrf_token(request)} |       ${h.csrf_token(request)} | ||||||
|       ${h.hidden('uuids')} |       ${h.hidden('uuids')} | ||||||
|       <button type="submit">Merge 2 ${model_title_plural}</button> |       <button type="submit" class="button">Merge 2 ${model_title_plural}</button> | ||||||
|       ${h.end_form()} |       ${h.end_form()} | ||||||
|   % endif |   % endif | ||||||
| 
 | 
 | ||||||
|   ## enable / disable selected objects |   ## enable / disable selected objects | ||||||
|   % if master.supports_set_enabled_toggle and request.has_perm('{}.enable_disable_set'.format(permission_prefix)): |   % if master.supports_set_enabled_toggle and request.has_perm('{}.enable_disable_set'.format(permission_prefix)): | ||||||
|       ${h.form(url('{}.enable_set'.format(route_prefix)), name='enable-set')} |       ${h.form(url('{}.enable_set'.format(route_prefix)), name='enable-set', class_='control')} | ||||||
|       ${h.csrf_token(request)} |       ${h.csrf_token(request)} | ||||||
|       ${h.hidden('uuids')} |       ${h.hidden('uuids')} | ||||||
|       <button type="button">Enable Selected</button> |       <button type="button" class="button">Enable Selected</button> | ||||||
|       ${h.end_form()} |       ${h.end_form()} | ||||||
| 
 | 
 | ||||||
|       ${h.form(url('{}.disable_set'.format(route_prefix)), name='disable-set')} |       ${h.form(url('{}.disable_set'.format(route_prefix)), name='disable-set', class_='control')} | ||||||
|       ${h.csrf_token(request)} |       ${h.csrf_token(request)} | ||||||
|       ${h.hidden('uuids')} |       ${h.hidden('uuids')} | ||||||
|       <button type="button">Disable Selected</button> |       <button type="button" class="button">Disable Selected</button> | ||||||
|       ${h.end_form()} |       ${h.end_form()} | ||||||
|   % endif |   % endif | ||||||
| 
 | 
 | ||||||
|   ## delete selected objects |   ## delete selected objects | ||||||
|   % if master.set_deletable and request.has_perm('{}.delete_set'.format(permission_prefix)): |   % if master.set_deletable and request.has_perm('{}.delete_set'.format(permission_prefix)): | ||||||
|       ${h.form(url('{}.delete_set'.format(route_prefix)), name='delete-set')} |       ${h.form(url('{}.delete_set'.format(route_prefix)), name='delete-set', class_='control')} | ||||||
|       ${h.csrf_token(request)} |       ${h.csrf_token(request)} | ||||||
|       ${h.hidden('uuids')} |       ${h.hidden('uuids')} | ||||||
|       <button type="button">Delete Selected</button> |       <button type="button" class="button">Delete Selected</button> | ||||||
|       ${h.end_form()} |       ${h.end_form()} | ||||||
|   % endif |   % endif | ||||||
| 
 | 
 | ||||||
|   ## delete search results |   ## delete search results | ||||||
|   % if master.bulk_deletable and request.has_perm('{}.bulk_delete'.format(permission_prefix)): |   % if master.bulk_deletable and request.has_perm('{}.bulk_delete'.format(permission_prefix)): | ||||||
|       ${h.form(url('{}.bulk_delete'.format(route_prefix)), name='bulk-delete')} |       ${h.form(url('{}.bulk_delete'.format(route_prefix)), name='bulk-delete', class_='control')} | ||||||
|       ${h.csrf_token(request)} |       ${h.csrf_token(request)} | ||||||
|  |       % if use_buefy: | ||||||
|  |           <b-button type="is-danger" | ||||||
|  |                     :disabled="! total" | ||||||
|  |                     :title="total ? null : 'There are no results to delete'" | ||||||
|  |                     @click="deleteResults" | ||||||
|  |                     icon-pack="fas" | ||||||
|  |                     icon-left="trash"> | ||||||
|  |             Delete Results | ||||||
|  |           </b-button> | ||||||
|  |       % else: | ||||||
|           <button type="button">Delete Results</button> |           <button type="button">Delete Results</button> | ||||||
|  |       % endif | ||||||
|       ${h.end_form()} |       ${h.end_form()} | ||||||
|   % endif |   % endif | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -43,12 +43,12 @@ ${parent.body()} | ||||||
|       % if instance.enabled and not instance.executing: |       % if instance.enabled and not instance.executing: | ||||||
|           ${h.form(url('{}.execute'.format(route_prefix), uuid=instance.uuid), class_='autodisable')} |           ${h.form(url('{}.execute'.format(route_prefix), uuid=instance.uuid), class_='autodisable')} | ||||||
|           ${h.csrf_token(request)} |           ${h.csrf_token(request)} | ||||||
|           ${h.submit('execute', "Execute this upgrade")} |           ${h.submit('execute', "Execute this upgrade", class_='button is-primary')} | ||||||
|           ${h.end_form()} |           ${h.end_form()} | ||||||
|       % elif instance.enabled: |       % elif instance.enabled: | ||||||
|           <button type="button" disabled="disabled" title="This upgrade is currently executing">Execute this upgrade</button> |           <button type="button" class="button is-primary" disabled="disabled" title="This upgrade is currently executing">Execute this upgrade</button> | ||||||
|       % else: |       % else: | ||||||
|           <button type="button" disabled="disabled" title="This upgrade is not enabled">Execute this upgrade</button> |           <button type="button" class="button is-primary" disabled="disabled" title="This upgrade is not enabled">Execute this upgrade</button> | ||||||
|       % endif |       % endif | ||||||
|     </div> |     </div> | ||||||
| % endif | % endif | ||||||
|  |  | ||||||
|  | @ -73,6 +73,25 @@ class View(object): | ||||||
|     def notfound(self): |     def notfound(self): | ||||||
|         return httpexceptions.HTTPNotFound() |         return httpexceptions.HTTPNotFound() | ||||||
|      |      | ||||||
|  |     def get_use_buefy(self): | ||||||
|  |         """ | ||||||
|  |         Returns a flag indicating whether or not the current theme supports | ||||||
|  |         (and therefore should use) the Buefy JS library. | ||||||
|  |         """ | ||||||
|  |         # first check theme-specific setting, if one has been defined | ||||||
|  |         theme = self.request.registry.settings['tailbone.theme'] | ||||||
|  |         buefy = self.rattail_config.getbool('tailbone', 'themes.{}.use_buefy'.format(theme)) | ||||||
|  |         if buefy is not None: | ||||||
|  |             return buefy | ||||||
|  | 
 | ||||||
|  |         # TODO: should not hard-code this surely, but works for now... | ||||||
|  |         if theme == 'falafel': | ||||||
|  |             return True | ||||||
|  | 
 | ||||||
|  |         # TODO: probably should not use this fallback? it was the first setting | ||||||
|  |         # i tested with, but is poorly named to say the least | ||||||
|  |         return self.rattail_config.getbool('tailbone', 'grids.use_buefy', default=False) | ||||||
|  | 
 | ||||||
|     def late_login_user(self): |     def late_login_user(self): | ||||||
|         """ |         """ | ||||||
|         Returns the :class:`rattail:rattail.db.model.User` instance |         Returns the :class:`rattail:rattail.db.model.User` instance | ||||||
|  |  | ||||||
|  | @ -33,7 +33,6 @@ import sqlalchemy as sa | ||||||
| from sqlalchemy import orm | from sqlalchemy import orm | ||||||
| 
 | 
 | ||||||
| import colander | import colander | ||||||
| from deform import widget as dfwidget |  | ||||||
| from pyramid.httpexceptions import HTTPNotFound | from pyramid.httpexceptions import HTTPNotFound | ||||||
| from webhelpers2.html import HTML, tags | from webhelpers2.html import HTML, tags | ||||||
| 
 | 
 | ||||||
|  | @ -220,7 +219,7 @@ class CustomersView(MasterView): | ||||||
|         f.set_enum('email_preference', self.enum.EMAIL_PREFERENCE) |         f.set_enum('email_preference', self.enum.EMAIL_PREFERENCE) | ||||||
|         preferences = list(self.enum.EMAIL_PREFERENCE.items()) |         preferences = list(self.enum.EMAIL_PREFERENCE.items()) | ||||||
|         preferences.insert(0, ('', "(no preference)")) |         preferences.insert(0, ('', "(no preference)")) | ||||||
|         f.set_widget('email_preference', dfwidget.SelectWidget(values=preferences)) |         f.widgets['email_preference'].values = preferences | ||||||
| 
 | 
 | ||||||
|         # person |         # person | ||||||
|         if self.creating: |         if self.creating: | ||||||
|  |  | ||||||
|  | @ -251,25 +251,6 @@ class MasterView(View): | ||||||
|                 labels.update(cls.row_labels) |                 labels.update(cls.row_labels) | ||||||
|         return labels |         return labels | ||||||
| 
 | 
 | ||||||
|     def get_use_buefy(self): |  | ||||||
|         """ |  | ||||||
|         Returns a flag indicating whether or not the current theme supports |  | ||||||
|         (and therefore should use) the Buefy JS library. |  | ||||||
|         """ |  | ||||||
|         # first check theme-specific setting, if one has been defined |  | ||||||
|         theme = self.request.registry.settings['tailbone.theme'] |  | ||||||
|         buefy = self.rattail_config.getbool('tailbone', 'themes.{}.use_buefy'.format(theme)) |  | ||||||
|         if buefy is not None: |  | ||||||
|             return buefy |  | ||||||
| 
 |  | ||||||
|         # TODO: should not hard-code this surely, but works for now... |  | ||||||
|         if theme == 'falafel': |  | ||||||
|             return True |  | ||||||
| 
 |  | ||||||
|         # TODO: probably should not use this fallback? it was the first setting |  | ||||||
|         # i tested with, but is poorly named to say the least |  | ||||||
|         return self.rattail_config.getbool('tailbone', 'grids.use_buefy', default=False) |  | ||||||
| 
 |  | ||||||
|     ############################## |     ############################## | ||||||
|     # Available Views |     # Available Views | ||||||
|     ############################## |     ############################## | ||||||
|  | @ -368,6 +349,8 @@ class MasterView(View): | ||||||
| 
 | 
 | ||||||
|         defaults = { |         defaults = { | ||||||
|             'model_class': getattr(self, 'model_class', None), |             'model_class': getattr(self, 'model_class', None), | ||||||
|  |             'model_title': self.get_model_title(), | ||||||
|  |             'model_title_plural': self.get_model_title_plural(), | ||||||
|             'width': 'full', |             'width': 'full', | ||||||
|             'filterable': self.filterable, |             'filterable': self.filterable, | ||||||
|             'use_byte_string_filters': self.use_byte_string_filters, |             'use_byte_string_filters': self.use_byte_string_filters, | ||||||
|  |  | ||||||
|  | @ -2,7 +2,7 @@ | ||||||
| ################################################################################ | ################################################################################ | ||||||
| # | # | ||||||
| #  Rattail -- Retail Software Framework | #  Rattail -- Retail Software Framework | ||||||
| #  Copyright © 2010-2018 Lance Edgar | #  Copyright © 2010-2019 Lance Edgar | ||||||
| # | # | ||||||
| #  This file is part of Rattail. | #  This file is part of Rattail. | ||||||
| # | # | ||||||
|  | @ -33,6 +33,7 @@ import six | ||||||
| from rattail.db import model, api | from rattail.db import model, api | ||||||
| from rattail.settings import Setting | from rattail.settings import Setting | ||||||
| from rattail.util import import_module_path | from rattail.util import import_module_path | ||||||
|  | from rattail.config import parse_bool | ||||||
| 
 | 
 | ||||||
| import colander | import colander | ||||||
| from webhelpers2.html import tags | from webhelpers2.html import tags | ||||||
|  | @ -109,7 +110,7 @@ class AppSettingsView(View): | ||||||
|         if form.validate(newstyle=True): |         if form.validate(newstyle=True): | ||||||
|             self.save_form(form) |             self.save_form(form) | ||||||
|             group = self.request.POST.get('settings-group') |             group = self.request.POST.get('settings-group') | ||||||
|             if group: |             if group is not None: | ||||||
|                 self.request.session['appsettings.current_group'] = group |                 self.request.session['appsettings.current_group'] = group | ||||||
|             self.request.session.flash("App Settings have been saved.") |             self.request.session.flash("App Settings have been saved.") | ||||||
|             return self.redirect(self.request.current_route_url()) |             return self.redirect(self.request.current_route_url()) | ||||||
|  | @ -120,17 +121,56 @@ class AppSettingsView(View): | ||||||
|         if not current_group: |         if not current_group: | ||||||
|             current_group = self.request.session.get('appsettings.current_group') |             current_group = self.request.session.get('appsettings.current_group') | ||||||
| 
 | 
 | ||||||
|         group_options = [tags.Option(group, group) for group in groups] |         use_buefy = self.get_use_buefy() | ||||||
|         group_options.insert(0, tags.Option("(All)", "(All)")) |         context = { | ||||||
|         return { |  | ||||||
|             'index_title': "App Settings", |             'index_title': "App Settings", | ||||||
|             'form': form, |             'form': form, | ||||||
|             'dform': form.make_deform_form(), |             'dform': form.make_deform_form(), | ||||||
|             'groups': groups, |             'groups': groups, | ||||||
|             'group_options': group_options, |  | ||||||
|             'current_group': current_group, |  | ||||||
|             'settings': settings, |             'settings': settings, | ||||||
|  |             'use_buefy': use_buefy, | ||||||
|         } |         } | ||||||
|  |         if use_buefy: | ||||||
|  |             context['buefy_data'] = self.get_buefy_data(form, groups, settings) | ||||||
|  |             # TODO: this seems hacky, and probably only needed if theme changes? | ||||||
|  |             if current_group == '(All)': | ||||||
|  |                 current_group = '' | ||||||
|  |         else: | ||||||
|  |             group_options = [tags.Option(group, group) for group in groups] | ||||||
|  |             group_options.insert(0, tags.Option("(All)", "(All)")) | ||||||
|  |             context['group_options'] = group_options | ||||||
|  |         context['current_group'] = current_group | ||||||
|  |         return context | ||||||
|  | 
 | ||||||
|  |     def get_buefy_data(self, form, groups, settings): | ||||||
|  |         dform = form.make_deform_form() | ||||||
|  |         grouped = dict([(label, []) | ||||||
|  |                         for label in groups]) | ||||||
|  | 
 | ||||||
|  |         for setting in settings: | ||||||
|  |             field = dform[setting.node_name] | ||||||
|  |             s = { | ||||||
|  |                 'field_name': field.name, | ||||||
|  |                 'label': form.get_label(field.name), | ||||||
|  |                 'data_type': setting.data_type.__name__, | ||||||
|  |                 'choices': setting.choices, | ||||||
|  |                 'helptext': form.render_helptext(field.name) if form.has_helptext(field.name) else None, | ||||||
|  |                 'error': field.error, | ||||||
|  |             } | ||||||
|  |             value = self.get_setting_value(setting) | ||||||
|  |             if setting.data_type is bool: | ||||||
|  |                 value = parse_bool(value) | ||||||
|  |             s['value'] = value | ||||||
|  |             if field.error: | ||||||
|  |                 s['error_messages'] = field.error_messages() | ||||||
|  |             grouped[setting.group].append(s) | ||||||
|  | 
 | ||||||
|  |         data = [] | ||||||
|  |         for label in groups: | ||||||
|  |             group = {'label': label, 'settings': grouped[label]} | ||||||
|  |             data.append(group) | ||||||
|  | 
 | ||||||
|  |         return data | ||||||
| 
 | 
 | ||||||
|     def make_form(self, known_settings): |     def make_form(self, known_settings): | ||||||
|         schema = colander.MappingSchema() |         schema = colander.MappingSchema() | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Lance Edgar
						Lance Edgar