From 2b1bdec2f886d6e611c60f9db61c519dcacadbdd Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Fri, 14 Aug 2015 19:59:26 -0500 Subject: [PATCH] Add "Save Defaults" button so user can save personal defaults for any new grid. --- tailbone/newgrids/core.py | 77 +++++++++++++++++++----- tailbone/static/js/jquery.ui.tailbone.js | 32 +++++++--- tailbone/templates/newgrids/filters.mako | 3 + 3 files changed, 88 insertions(+), 24 deletions(-) diff --git a/tailbone/newgrids/core.py b/tailbone/newgrids/core.py index 597b1ff6..2d74f9ae 100644 --- a/tailbone/newgrids/core.py +++ b/tailbone/newgrids/core.py @@ -26,10 +26,13 @@ Core Grid Classes from __future__ import unicode_literals +from rattail.db.api import get_setting, save_setting + from pyramid.renderers import render from webhelpers.html import HTML, tags from webhelpers.html.builder import format_attrs +from tailbone.db import Session 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}.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 # can skip the rest of the request/session checks. if self.request.GET.get('reset-to-default-filters') == 'true': @@ -200,7 +207,12 @@ class Grid(object): # Maybe store settings for next time. 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. if self.filterable: @@ -215,6 +227,37 @@ class Grid(object): self.pagesize = settings['pagesize'] 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_): """ Determine if the current request (GET query string) contains any @@ -266,7 +309,7 @@ class Grid(object): else: value = self.request.session.get('grid.{0}.{1}'.format(self.key, key)) if value is not None: - return value + return coerce(value) # If source had nothing, try default/existing settings. value = settings.get(key) @@ -307,7 +350,8 @@ class Grid(object): else: # source = session 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( source, settings, '{0}.verb'.format(prefix), default='') settings['{0}.value'.format(prefix)] = self.get_setting( @@ -361,26 +405,31 @@ class Grid(object): if page is not None: 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): - self.request.session['grid.{0}.{1}'.format(self.key, key)] = settings[key] + def persist(key, value=lambda k: settings[k]): + 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: for filtr in self.iter_filters(): - store('filter.{0}.active'.format(filtr.key)) - store('filter.{0}.verb'.format(filtr.key)) - store('filter.{0}.value'.format(filtr.key)) + persist('filter.{0}.active'.format(filtr.key), value=lambda k: unicode(settings[k]).lower()) + persist('filter.{0}.verb'.format(filtr.key)) + persist('filter.{0}.value'.format(filtr.key)) if self.sortable: - store('sortkey') - store('sortdir') + persist('sortkey') + persist('sortdir') if self.pageable: - store('pagesize') - store('page') + persist('pagesize') + persist('page') def filter_data(self, data): """ diff --git a/tailbone/static/js/jquery.ui.tailbone.js b/tailbone/static/js/jquery.ui.tailbone.js index fe2fe6ce..521920fa 100644 --- a/tailbone/static/js/jquery.ui.tailbone.js +++ b/tailbone/static/js/jquery.ui.tailbone.js @@ -17,10 +17,12 @@ // Snag some element references. this.filters = this.element.find('.newfilters'); + this.filters_form = this.filters.find('form'); this.add_filter = this.filters.find('#add-filter'); this.apply_filters = this.filters.find('#apply-filters'); this.default_filters = this.filters.find('#default-filters'); this.clear_filters = this.filters.find('#clear-filters'); + this.save_defaults = this.filters.find('#save-defaults'); this.grid = this.element.find('.newgrid'); // Enhance filters etc. @@ -28,6 +30,7 @@ this.apply_filters.button('option', 'icons', {primary: 'ui-icon-search'}); this.default_filters.button('option', 'icons', {primary: 'ui-icon-home'}); 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) { this.apply_filters.button('disable'); } @@ -56,11 +59,12 @@ }); // Intercept filters form submittal, and submit via AJAX instead. - this.filters.find('form').on('submit', function() { - var form = $(this); - + this.filters_form.on('submit', function() { 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 if ($(this).gridfilter('active')) { @@ -74,7 +78,7 @@ }); // 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'); } @@ -86,11 +90,19 @@ // When user clicks Default Filters button, refresh page with // instructions for the server to reset filters to default settings. this.default_filters.click(function() { - var form = that.filters.find('form'); - form.off('submit'); - form.append(''); + that.filters_form.off('submit'); + that.filters_form.find('input[name="reset-to-default-filters"]').val('true'); 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 @@ -101,7 +113,7 @@ $(this).gridfilter('active', false); } }); - that.filters.find('form').submit(); + that.filters_form.submit(); }); // Refresh data when user clicks a sortable column header. diff --git a/tailbone/templates/newgrids/filters.mako b/tailbone/templates/newgrids/filters.mako index e85d6484..10c77658 100644 --- a/tailbone/templates/newgrids/filters.mako +++ b/tailbone/templates/newgrids/filters.mako @@ -2,6 +2,8 @@
${form.begin(method='get')} + +
Filters @@ -27,6 +29,7 @@ ${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='save-defaults', c="Save Defaults")}
${form.end()}