From 23e6a982b98299de909c8919916eb78272ba9919 Mon Sep 17 00:00:00 2001 From: Ali <83188384+testA113@users.noreply.github.com> Date: Thu, 30 Mar 2023 11:21:08 +1300 Subject: [PATCH] fix(ns): save filter to local storage [EE-5287] (#8724) * fix(ns): save filter to local storage [EE-5287] * allow system ns and save per user --------- Co-authored-by: testa113 --- .../applicationsDatatableController.js | 22 ++++++++------- .../views/applications/applications.html | 4 +-- .../applications/applicationsController.js | 28 ++++++++++++++----- app/portainer/services/localStorage.js | 7 +++++ 4 files changed, 42 insertions(+), 19 deletions(-) diff --git a/app/kubernetes/components/datatables/applications-datatable/applicationsDatatableController.js b/app/kubernetes/components/datatables/applications-datatable/applicationsDatatableController.js index 5d352c752..386b495ce 100644 --- a/app/kubernetes/components/datatables/applications-datatable/applicationsDatatableController.js +++ b/app/kubernetes/components/datatables/applications-datatable/applicationsDatatableController.js @@ -144,15 +144,17 @@ angular.module('portainer.docker').controller('KubernetesApplicationsDatatableCo }; this.updateNamespace = function () { - if (this.namespaces) { - const namespaces = [{ Name: 'All namespaces', Value: '', IsSystem: false }]; - this.namespaces.find((ns) => { - if (!this.settings.showSystem && ns.IsSystem) { - return false; - } - namespaces.push({ Name: ns.Name, Value: ns.Name, IsSystem: ns.IsSystem }); - }); - this.state.namespaces = namespaces; + if (this.namespaces && this.settingsLoaded) { + const allNamespacesOption = { Name: 'All namespaces', Value: '', IsSystem: false }; + const visibleNamespaceOptions = this.namespaces + .filter((ns) => { + if (!this.settings.showSystem && ns.IsSystem) { + return false; + } + return true; + }) + .map((ns) => ({ Name: ns.Name, Value: ns.Name, IsSystem: ns.IsSystem })); + this.state.namespaces = [allNamespacesOption, ...visibleNamespaceOptions]; if (this.state.namespace && !this.state.namespaces.find((ns) => ns.Name === this.state.namespace)) { if (this.state.namespaces.length > 1) { @@ -216,7 +218,7 @@ angular.module('portainer.docker').controller('KubernetesApplicationsDatatableCo this.setSystemResources && this.setSystemResources(this.settings.showSystem); } - + this.settingsLoaded = true; // Set the default selected namespace if (!this.state.namespace) { this.state.namespace = this.namespace; diff --git a/app/kubernetes/views/applications/applications.html b/app/kubernetes/views/applications/applications.html index a7fecea89..c36899adf 100644 --- a/app/kubernetes/views/applications/applications.html +++ b/app/kubernetes/views/applications/applications.html @@ -20,7 +20,7 @@ on-publishing-mode-click="(ctrl.onPublishingModeClick)" is-primary="true" namespaces="ctrl.state.namespaces" - namespace="ctrl.state.namespace" + namespace="ctrl.state.namespaceName" on-change-namespace-dropdown="(ctrl.onChangeNamespaceDropdown)" is-system-resources="ctrl.state.isSystemResources" set-system-resources="(ctrl.setSystemResources)" @@ -36,7 +36,7 @@ refresh-callback="ctrl.getApplications" remove-action="ctrl.removeStacksAction" namespaces="ctrl.state.namespaces" - namespace="ctrl.state.namespace" + namespace="ctrl.state.namespaceName" on-change-namespace-dropdown="(ctrl.onChangeNamespaceDropdown)" is-system-resources="ctrl.state.isSystemResources" set-system-resources="(ctrl.setSystemResources)" diff --git a/app/kubernetes/views/applications/applicationsController.js b/app/kubernetes/views/applications/applicationsController.js index ceeb83fe1..424f47622 100644 --- a/app/kubernetes/views/applications/applicationsController.js +++ b/app/kubernetes/views/applications/applicationsController.js @@ -13,11 +13,11 @@ class KubernetesApplicationsController { $async, $state, $scope, + Authentication, Notifications, KubernetesApplicationService, HelmService, KubernetesConfigurationService, - Authentication, LocalStorage, StackService, KubernetesNamespaceService @@ -25,6 +25,7 @@ class KubernetesApplicationsController { this.$async = $async; this.$state = $state; this.$scope = $scope; + this.Authentication = Authentication; this.Notifications = Notifications; this.KubernetesApplicationService = KubernetesApplicationService; this.HelmService = HelmService; @@ -142,16 +143,18 @@ class KubernetesApplicationsController { }); } - onChangeNamespaceDropdown(namespace) { - this.state.namespace = namespace; + onChangeNamespaceDropdown(namespaceName) { + this.state.namespaceName = namespaceName; + // save the selected namespaceName in local storage with the key 'kubernetes_namespace_filter_${environmentId}_${userID}' + this.LocalStorage.storeNamespaceFilter(this.endpoint.Id, this.user.ID, namespaceName); this.getApplicationsAsync(); } async getApplicationsAsync() { try { const [applications, configurations] = await Promise.all([ - this.KubernetesApplicationService.get(this.state.namespace), - this.KubernetesConfigurationService.get(this.state.namespace), + this.KubernetesApplicationService.get(this.state.namespaceName), + this.KubernetesConfigurationService.get(this.state.namespaceName), ]); const configuredApplications = KubernetesConfigurationHelper.getApplicationConfigurations(applications, configurations); const { helmApplications, nonHelmApplications } = KubernetesApplicationHelper.getNestedApplications(configuredApplications); @@ -184,14 +187,25 @@ class KubernetesApplicationsController { stacks: [], ports: [], namespaces: [], - namespace: '', + namespaceName: '', isSystemResources: undefined, }; + this.user = this.Authentication.getUserDetails(); this.state.namespaces = await this.KubernetesNamespaceService.get(); + + const savedNamespace = this.LocalStorage.getNamespaceFilter(this.endpoint.Id, this.user.ID); // could be null if not found, and '' if all namepsaces is selected + const preferredNamespace = savedNamespace === null ? 'default' : savedNamespace; + this.state.namespaces = this.state.namespaces.filter((n) => n.Status === 'Active'); this.state.namespaces = _.sortBy(this.state.namespaces, 'Name'); - this.state.namespace = this.state.namespaces.length ? (this.state.namespaces.find((n) => n.Name === 'default') ? 'default' : this.state.namespaces[0].Name) : ''; + // set all namespaces ('') if there are no namespaces, or if all namespaces is selected + if (!this.state.namespaces.length || preferredNamespace === '') { + this.state.namespaceName = ''; + } else { + // otherwise, set the preferred namespaceName if it exists, otherwise set the first namespaceName + this.state.namespaceName = this.state.namespaces.find((n) => n.Name === preferredNamespace) ? preferredNamespace : this.state.namespaces[0].Name; + } await this.getApplications(); diff --git a/app/portainer/services/localStorage.js b/app/portainer/services/localStorage.js index 3256d523b..10ada0cdc 100644 --- a/app/portainer/services/localStorage.js +++ b/app/portainer/services/localStorage.js @@ -105,6 +105,13 @@ angular.module('portainer.app').factory('LocalStorage', [ const activeTab = localStorageService.get('active_tab_' + key); return activeTab === null ? 0 : activeTab; }, + storeNamespaceFilter: function (environmentId, userID, data) { + // store one filter per environment + localStorageService.set(`kubernetes_namespace_filter_${environmentId}_${userID}`, data); + }, + getNamespaceFilter: function (environmentId, userID) { + return localStorageService.get(`kubernetes_namespace_filter_${environmentId}_${userID}`); + }, storeLogoutReason: (reason) => localStorageService.set('logout_reason', reason), getLogoutReason: () => localStorageService.get('logout_reason'), cleanLogoutReason: () => localStorageService.remove('logout_reason'),