Add "Save Defaults" button so user can save personal defaults for any new grid.
This commit is contained in:
		
							parent
							
								
									d57f5169b0
								
							
						
					
					
						commit
						2b1bdec2f8
					
				
					 3 changed files with 88 additions and 24 deletions
				
			
		|  | @ -26,10 +26,13 @@ Core Grid Classes | ||||||
| 
 | 
 | ||||||
| from __future__ import unicode_literals | from __future__ import unicode_literals | ||||||
| 
 | 
 | ||||||
|  | from rattail.db.api import get_setting, save_setting | ||||||
|  | 
 | ||||||
| from pyramid.renderers import render | from pyramid.renderers import render | ||||||
| from webhelpers.html import HTML, tags | from webhelpers.html import HTML, tags | ||||||
| from webhelpers.html.builder import format_attrs | from webhelpers.html.builder import format_attrs | ||||||
| 
 | 
 | ||||||
|  | from tailbone.db import Session | ||||||
| from tailbone.newgrids import filters | from tailbone.newgrids import filters | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -155,6 +158,10 @@ class Grid(object): | ||||||
|             settings['filter.{0}.verb'.format(filtr.key)] = filtr.default_verb |             settings['filter.{0}.verb'.format(filtr.key)] = filtr.default_verb | ||||||
|             settings['filter.{0}.value'.format(filtr.key)] = filtr.default_value |             settings['filter.{0}.value'.format(filtr.key)] = filtr.default_value | ||||||
| 
 | 
 | ||||||
|  |         # If user has default settings on file, apply those first. | ||||||
|  |         if self.user_has_defaults(): | ||||||
|  |             self.apply_user_defaults(settings) | ||||||
|  | 
 | ||||||
|         # If request contains instruction to reset to default filters, then we |         # If request contains instruction to reset to default filters, then we | ||||||
|         # can skip the rest of the request/session checks. |         # can skip the rest of the request/session checks. | ||||||
|         if self.request.GET.get('reset-to-default-filters') == 'true': |         if self.request.GET.get('reset-to-default-filters') == 'true': | ||||||
|  | @ -200,7 +207,12 @@ class Grid(object): | ||||||
|              |              | ||||||
|         # Maybe store settings for next time. |         # Maybe store settings for next time. | ||||||
|         if store: |         if store: | ||||||
|             self.store_settings(settings) |             self.persist_settings(settings, 'session') | ||||||
|  | 
 | ||||||
|  |         # If request contained instruction to save current settings as defaults | ||||||
|  |         # for the current user, then do that. | ||||||
|  |         if self.request.GET.get('save-current-filters-as-defaults') == 'true': | ||||||
|  |             self.persist_settings(settings, 'defaults') | ||||||
| 
 | 
 | ||||||
|         # Update ourself and our filters, to reflect settings. |         # Update ourself and our filters, to reflect settings. | ||||||
|         if self.filterable: |         if self.filterable: | ||||||
|  | @ -215,6 +227,37 @@ class Grid(object): | ||||||
|             self.pagesize = settings['pagesize'] |             self.pagesize = settings['pagesize'] | ||||||
|             self.page = settings['page'] |             self.page = settings['page'] | ||||||
| 
 | 
 | ||||||
|  |     def user_has_defaults(self): | ||||||
|  |         """ | ||||||
|  |         Check to see if the current user has default settings on file for this grid. | ||||||
|  |         """ | ||||||
|  |         # User defaults should have all or nothing, so just check one key. | ||||||
|  |         key = 'tailbone.{0}.grid.{1}.sortkey'.format(self.request.user.uuid, self.key) | ||||||
|  |         return get_setting(Session(), key) is not None | ||||||
|  | 
 | ||||||
|  |     def apply_user_defaults(self, settings): | ||||||
|  |         """ | ||||||
|  |         Update the given settings dict with user defaults, if any exist. | ||||||
|  |         """ | ||||||
|  |         def merge(key, coerce=lambda v: v): | ||||||
|  |             skey = 'tailbone.{0}.grid.{1}.{2}'.format(self.request.user.uuid, self.key, key) | ||||||
|  |             value = get_setting(Session(), skey) | ||||||
|  |             settings[key] = coerce(value) | ||||||
|  | 
 | ||||||
|  |         if self.filterable: | ||||||
|  |             for filtr in self.iter_filters(): | ||||||
|  |                 merge('filter.{0}.active'.format(filtr.key), lambda v: v == 'true') | ||||||
|  |                 merge('filter.{0}.verb'.format(filtr.key)) | ||||||
|  |                 merge('filter.{0}.value'.format(filtr.key)) | ||||||
|  | 
 | ||||||
|  |         if self.sortable: | ||||||
|  |             merge('sortkey') | ||||||
|  |             merge('sortdir') | ||||||
|  | 
 | ||||||
|  |         if self.pageable: | ||||||
|  |             merge('pagesize', int) | ||||||
|  |             merge('page', int) | ||||||
|  | 
 | ||||||
|     def request_has_settings(self, type_): |     def request_has_settings(self, type_): | ||||||
|         """ |         """ | ||||||
|         Determine if the current request (GET query string) contains any |         Determine if the current request (GET query string) contains any | ||||||
|  | @ -266,7 +309,7 @@ class Grid(object): | ||||||
|         else: |         else: | ||||||
|             value = self.request.session.get('grid.{0}.{1}'.format(self.key, key)) |             value = self.request.session.get('grid.{0}.{1}'.format(self.key, key)) | ||||||
|             if value is not None: |             if value is not None: | ||||||
|                 return value |                 return coerce(value) | ||||||
| 
 | 
 | ||||||
|         # If source had nothing, try default/existing settings. |         # If source had nothing, try default/existing settings. | ||||||
|         value = settings.get(key) |         value = settings.get(key) | ||||||
|  | @ -307,7 +350,8 @@ class Grid(object): | ||||||
| 
 | 
 | ||||||
|             else: # source = session |             else: # source = session | ||||||
|                 settings['{0}.active'.format(prefix)] = self.get_setting( |                 settings['{0}.active'.format(prefix)] = self.get_setting( | ||||||
|                     source, settings, '{0}.active'.format(prefix), default=False) |                     source, settings, '{0}.active'.format(prefix), | ||||||
|  |                     coerce=lambda v: unicode(v).lower() == 'true', default=False) | ||||||
|                 settings['{0}.verb'.format(prefix)] = self.get_setting( |                 settings['{0}.verb'.format(prefix)] = self.get_setting( | ||||||
|                     source, settings, '{0}.verb'.format(prefix), default='') |                     source, settings, '{0}.verb'.format(prefix), default='') | ||||||
|                 settings['{0}.value'.format(prefix)] = self.get_setting( |                 settings['{0}.value'.format(prefix)] = self.get_setting( | ||||||
|  | @ -361,26 +405,31 @@ class Grid(object): | ||||||
|             if page is not None: |             if page is not None: | ||||||
|                 settings['page'] = page |                 settings['page'] = page | ||||||
| 
 | 
 | ||||||
|     def store_settings(self, settings): |     def persist_settings(self, settings, to='session'): | ||||||
|         """ |         """ | ||||||
|         Store settings in current session, for next time. |         Persist the given settings in some way, as defined by ``func``. | ||||||
|         """ |         """ | ||||||
|         def store(key): |         def persist(key, value=lambda k: settings[k]): | ||||||
|             self.request.session['grid.{0}.{1}'.format(self.key, key)] = settings[key] |             if to == 'defaults': | ||||||
|  |                 skey = 'tailbone.{0}.grid.{1}.{2}'.format(self.request.user.uuid, self.key, key) | ||||||
|  |                 save_setting(Session(), skey, value(key)) | ||||||
|  |             else: # to == session | ||||||
|  |                 skey = 'grid.{0}.{1}'.format(self.key, key) | ||||||
|  |                 self.request.session[skey] = value(key) | ||||||
| 
 | 
 | ||||||
|         if self.filterable: |         if self.filterable: | ||||||
|             for filtr in self.iter_filters(): |             for filtr in self.iter_filters(): | ||||||
|                 store('filter.{0}.active'.format(filtr.key)) |                 persist('filter.{0}.active'.format(filtr.key), value=lambda k: unicode(settings[k]).lower()) | ||||||
|                 store('filter.{0}.verb'.format(filtr.key)) |                 persist('filter.{0}.verb'.format(filtr.key)) | ||||||
|                 store('filter.{0}.value'.format(filtr.key)) |                 persist('filter.{0}.value'.format(filtr.key)) | ||||||
| 
 | 
 | ||||||
|         if self.sortable: |         if self.sortable: | ||||||
|             store('sortkey') |             persist('sortkey') | ||||||
|             store('sortdir') |             persist('sortdir') | ||||||
| 
 | 
 | ||||||
|         if self.pageable: |         if self.pageable: | ||||||
|             store('pagesize') |             persist('pagesize') | ||||||
|             store('page') |             persist('page') | ||||||
| 
 | 
 | ||||||
|     def filter_data(self, data): |     def filter_data(self, data): | ||||||
|         """ |         """ | ||||||
|  |  | ||||||
							
								
								
									
										32
									
								
								tailbone/static/js/jquery.ui.tailbone.js
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										32
									
								
								tailbone/static/js/jquery.ui.tailbone.js
									
										
									
									
										vendored
									
									
								
							|  | @ -17,10 +17,12 @@ | ||||||
| 
 | 
 | ||||||
|             // Snag some element references.
 |             // Snag some element references.
 | ||||||
|             this.filters = this.element.find('.newfilters'); |             this.filters = this.element.find('.newfilters'); | ||||||
|  |             this.filters_form = this.filters.find('form'); | ||||||
|             this.add_filter = this.filters.find('#add-filter'); |             this.add_filter = this.filters.find('#add-filter'); | ||||||
|             this.apply_filters = this.filters.find('#apply-filters'); |             this.apply_filters = this.filters.find('#apply-filters'); | ||||||
|             this.default_filters = this.filters.find('#default-filters'); |             this.default_filters = this.filters.find('#default-filters'); | ||||||
|             this.clear_filters = this.filters.find('#clear-filters'); |             this.clear_filters = this.filters.find('#clear-filters'); | ||||||
|  |             this.save_defaults = this.filters.find('#save-defaults'); | ||||||
|             this.grid = this.element.find('.newgrid'); |             this.grid = this.element.find('.newgrid'); | ||||||
| 
 | 
 | ||||||
|             // Enhance filters etc.
 |             // Enhance filters etc.
 | ||||||
|  | @ -28,6 +30,7 @@ | ||||||
|             this.apply_filters.button('option', 'icons', {primary: 'ui-icon-search'}); |             this.apply_filters.button('option', 'icons', {primary: 'ui-icon-search'}); | ||||||
|             this.default_filters.button('option', 'icons', {primary: 'ui-icon-home'}); |             this.default_filters.button('option', 'icons', {primary: 'ui-icon-home'}); | ||||||
|             this.clear_filters.button('option', 'icons', {primary: 'ui-icon-trash'}); |             this.clear_filters.button('option', 'icons', {primary: 'ui-icon-trash'}); | ||||||
|  |             this.save_defaults.button('option', 'icons', {primary: 'ui-icon-disk'}); | ||||||
|             if (! this.filters.find('.active:checked').length) { |             if (! this.filters.find('.active:checked').length) { | ||||||
|                 this.apply_filters.button('disable'); |                 this.apply_filters.button('disable'); | ||||||
|             } |             } | ||||||
|  | @ -56,11 +59,12 @@ | ||||||
|             }); |             }); | ||||||
| 
 | 
 | ||||||
|             // Intercept filters form submittal, and submit via AJAX instead.
 |             // Intercept filters form submittal, and submit via AJAX instead.
 | ||||||
|             this.filters.find('form').on('submit', function() { |             this.filters_form.on('submit', function() { | ||||||
|                 var form = $(this); |  | ||||||
| 
 |  | ||||||
|                 var settings = {filter: true, partial: true}; |                 var settings = {filter: true, partial: true}; | ||||||
|                 form.find('.filter').each(function() { |                 if (that.filters_form.find('input[name="save-current-filters-as-defaults"]').val() == 'true') { | ||||||
|  |                     settings['save-current-filters-as-defaults'] = true; | ||||||
|  |                 } | ||||||
|  |                 that.filters.find('.filter').each(function() { | ||||||
| 
 | 
 | ||||||
|                     // currently active filters will be included in form data
 |                     // currently active filters will be included in form data
 | ||||||
|                     if ($(this).gridfilter('active')) { |                     if ($(this).gridfilter('active')) { | ||||||
|  | @ -74,7 +78,7 @@ | ||||||
|                 }); |                 }); | ||||||
| 
 | 
 | ||||||
|                 // if no filters are visible, disable submit button
 |                 // if no filters are visible, disable submit button
 | ||||||
|                 if (! form.find('.filter:visible').length) { |                 if (! that.filters.find('.filter:visible').length) { | ||||||
|                     that.apply_filters.button('disable'); |                     that.apply_filters.button('disable'); | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|  | @ -86,11 +90,19 @@ | ||||||
|             // When user clicks Default Filters button, refresh page with
 |             // When user clicks Default Filters button, refresh page with
 | ||||||
|             // instructions for the server to reset filters to default settings.
 |             // instructions for the server to reset filters to default settings.
 | ||||||
|             this.default_filters.click(function() { |             this.default_filters.click(function() { | ||||||
|                 var form = that.filters.find('form'); |                 that.filters_form.off('submit'); | ||||||
|                 form.off('submit'); |                 that.filters_form.find('input[name="reset-to-default-filters"]').val('true'); | ||||||
|                 form.append('<input type="hidden" name="reset-to-default-filters" value="true" />'); |  | ||||||
|                 that.element.mask("Refreshing data..."); |                 that.element.mask("Refreshing data..."); | ||||||
|                 form.submit(); |                 that.filters_form.submit(); | ||||||
|  |             }); | ||||||
|  | 
 | ||||||
|  |             // When user clicks Save Defaults button, refresh the grid as with
 | ||||||
|  |             // Apply Filters, but add an instruction for the server to save
 | ||||||
|  |             // current settings as defaults for the user.
 | ||||||
|  |             this.save_defaults.click(function() { | ||||||
|  |                 that.filters_form.find('input[name="save-current-filters-as-defaults"]').val('true'); | ||||||
|  |                 that.filters_form.submit(); | ||||||
|  |                 that.filters_form.find('input[name="save-current-filters-as-defaults"]').val('false'); | ||||||
|             }); |             }); | ||||||
| 
 | 
 | ||||||
|             // When user clicks Clear Filters button, deactivate all filters
 |             // When user clicks Clear Filters button, deactivate all filters
 | ||||||
|  | @ -101,7 +113,7 @@ | ||||||
|                         $(this).gridfilter('active', false); |                         $(this).gridfilter('active', false); | ||||||
|                     } |                     } | ||||||
|                 }); |                 }); | ||||||
|                 that.filters.find('form').submit(); |                 that.filters_form.submit(); | ||||||
|             }); |             }); | ||||||
| 
 | 
 | ||||||
|             // Refresh data when user clicks a sortable column header.
 |             // Refresh data when user clicks a sortable column header.
 | ||||||
|  |  | ||||||
|  | @ -2,6 +2,8 @@ | ||||||
| <div class="newfilters"> | <div class="newfilters"> | ||||||
| 
 | 
 | ||||||
|   ${form.begin(method='get')} |   ${form.begin(method='get')} | ||||||
|  |     <input type="hidden" name="reset-to-default-filters" value="false" /> | ||||||
|  |     <input type="hidden" name="save-current-filters-as-defaults" value="false" /> | ||||||
| 
 | 
 | ||||||
|     <fieldset> |     <fieldset> | ||||||
|       <legend>Filters</legend> |       <legend>Filters</legend> | ||||||
|  | @ -27,6 +29,7 @@ | ||||||
|       </select> |       </select> | ||||||
|       ${form.tag('button', type='button', id='default-filters', c="Default Filters")} |       ${form.tag('button', type='button', id='default-filters', c="Default Filters")} | ||||||
|       ${form.tag('button', type='button', id='clear-filters', c="Clear Filters")} |       ${form.tag('button', type='button', id='clear-filters', c="Clear Filters")} | ||||||
|  |       ${form.tag('button', type='button', id='save-defaults', c="Save Defaults")} | ||||||
|     </div> |     </div> | ||||||
| 
 | 
 | ||||||
|   ${form.end()} |   ${form.end()} | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Lance Edgar
						Lance Edgar