From 6d283829c04098ddb7e0f4700c0078864831806e Mon Sep 17 00:00:00 2001 From: Ben Thomson Date: Sat, 8 Jun 2019 11:28:08 +0800 Subject: [PATCH] Store limited list widget configuration in user preferences (#4360) Provides a new method of storing the list page count and visible column configs that survives a user logging out then logging back in to October. In addition, the users are provided with a "Reset to Default" button in the config modal allowing them to use the default list config if preferred. --- modules/backend/traits/PreferenceMaker.php | 139 ++++++++++++++++++ modules/backend/widgets/Lists.php | 24 ++- .../widgets/lists/partials/_setup_form.htm | 8 + 3 files changed, 165 insertions(+), 6 deletions(-) create mode 100644 modules/backend/traits/PreferenceMaker.php diff --git a/modules/backend/traits/PreferenceMaker.php b/modules/backend/traits/PreferenceMaker.php new file mode 100644 index 000000000..d7afa3a04 --- /dev/null +++ b/modules/backend/traits/PreferenceMaker.php @@ -0,0 +1,139 @@ +getUserPreferences(); + $preferences[$key] = $value; + + $this->getPreferenceStorage()->set($this->getPreferenceKey(), $preferences); + + // Re-cache user preferences + self::$preferenceCache[$this->getPreferenceKey()] = $preferences; + } + + /** + * Retrieves a widget related key/value pair from the user preferences + * + * @param string $key Unique key for the data store. + * @param mixed $default A default value to use when value is not found. + * @return mixed + */ + public function getUserPreference(string $key = null, $default = null) + { + $preferences = $this->getUserPreferences(); + + return (isset($preferences[$key])) ? $preferences[$key] : $default; + } + + /** + * Retrieves and caches all user preferences for this particular controller/widget. + * + * @return array + */ + public function getUserPreferences(): array + { + if (isset(self::$preferenceCache[$this->getPreferenceKey()])) { + return self::$preferenceCache[$this->getPreferenceKey()]; + } + + $preferences = $this->getPreferenceStorage()->get($this->getPreferenceKey(), []); + + // Cache user preferences + self::$preferenceCache[$this->getPreferenceKey()] = $preferences; + + return $preferences; + } + + /** + * Clears a single preference key from the user preferences for this controller/widget. + * + * @param string $key Unique key for the data store. + * @return void + */ + public function clearUserPreference(string $key): void + { + $preferences = $this->getUserPreferences(); + + if (!isset($preferences[$key])) { + return; + } + + unset($preferences[$key]); + + if (count($preferences)) { + $this->getPreferenceStorage()->set($this->getPreferenceKey(), $preferences); + + // Re-cache user preferences + self::$preferenceCache[$this->getPreferenceKey()] = $preferences; + } else { + // Remove record from user preferences + $this->clearUserPreferences(); + } + } + + /** + * Clears all user preferences for this controller/widget. + * + * @return void + */ + public function clearUserPreferences(): void + { + $this->getPreferenceStorage()->reset($this->getPreferenceKey()); + + self::$preferenceCache[$this->getPreferenceKey()] = []; + } + + /** + * Returns a unique identifier for this widget and controller action for preference storage. + * + * @return string + */ + protected function getPreferenceKey(): string + { + $controller = (property_exists($this, 'controller') && $this->controller) + ? $this->controller + : $this; + + $uniqueId = (method_exists($this, 'getId')) ? $this->getId() : $controller->getId(); + + // Removes Class name and "Controllers" directory + $rootNamespace = Str::getClassId(Str::getClassNamespace(Str::getClassNamespace($controller))); + + // The controller action is intentionally omitted, preferences should be shared for all actions + return $rootNamespace . '::' . strtolower(class_basename($controller)) . '.' . strtolower($uniqueId); + } + + /** + * Specifies the model used for storing the user preferences. + * + * @return October\Rain\Database\Model + */ + protected function getPreferenceStorage() + { + return UserPreference::forUser(); + } +} diff --git a/modules/backend/widgets/Lists.php b/modules/backend/widgets/Lists.php index 67fa2f322..01bc5237a 100644 --- a/modules/backend/widgets/Lists.php +++ b/modules/backend/widgets/Lists.php @@ -24,6 +24,8 @@ use ApplicationException; */ class Lists extends WidgetBase { + use Backend\Traits\PreferenceMaker; + // // Configurable properties // @@ -207,7 +209,7 @@ class Lists extends WidgetBase /* * Configure the list widget */ - $this->recordsPerPage = $this->getSession('per_page', $this->recordsPerPage); + $this->recordsPerPage = $this->getUserPreference('per_page', $this->recordsPerPage); if ($this->showPagination == 'auto') { $this->showPagination = $this->recordsPerPage && $this->recordsPerPage > 0; @@ -502,7 +504,7 @@ class Lists extends WidgetBase $joinSql = $countQuery->select($joinSql)->toSql(); $selects[] = Db::raw("(".$joinSql.") as ".$alias); - + /* * If this is a polymorphic relation there will be bindings that need to be added to the query */ @@ -546,7 +548,7 @@ class Lists extends WidgetBase * Add custom selects */ $query->addSelect($selects); - + /* * Add bindings for polymorphic relations */ @@ -725,7 +727,7 @@ class Lists extends WidgetBase * Supplied column list */ if ($this->columnOverride === null) { - $this->columnOverride = $this->getSession('visible', null); + $this->columnOverride = $this->getUserPreference('visible', null); } if ($this->columnOverride && is_array($this->columnOverride)) { @@ -1597,12 +1599,22 @@ class Lists extends WidgetBase { if (($visibleColumns = post('visible_columns')) && is_array($visibleColumns)) { $this->columnOverride = $visibleColumns; - $this->putSession('visible', $this->columnOverride); + $this->putUserPreference('visible', $this->columnOverride); } $this->recordsPerPage = post('records_per_page', $this->recordsPerPage); $this->putSession('order', post('column_order')); - $this->putSession('per_page', $this->recordsPerPage); + $this->putUserPreference('per_page', $this->recordsPerPage); + return $this->onRefresh(); + } + + /** + * Event handler to apply the list set up. + */ + public function onResetSetup() + { + $this->clearUserPreference('visible'); + $this->clearUserPreference('per_page'); return $this->onRefresh(); } diff --git a/modules/backend/widgets/lists/partials/_setup_form.htm b/modules/backend/widgets/lists/partials/_setup_form.htm index 2b78c1b05..7bffb53a8 100644 --- a/modules/backend/widgets/lists/partials/_setup_form.htm +++ b/modules/backend/widgets/lists/partials/_setup_form.htm @@ -48,6 +48,14 @@