fix(ns): save filter to local storage [EE-5287] (#8723)

* fix(ns): save filter to local storage [EE-5287]

* allow system ns and save per user

---------

Co-authored-by: testa113 <testa113>
pull/8728/head
Ali 2023-03-30 11:21:05 +13:00 committed by GitHub
parent 308a78db21
commit 7f805ac5be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 42 additions and 19 deletions

View File

@ -144,15 +144,17 @@ angular.module('portainer.docker').controller('KubernetesApplicationsDatatableCo
}; };
this.updateNamespace = function () { this.updateNamespace = function () {
if (this.namespaces) { if (this.namespaces && this.settingsLoaded) {
const namespaces = [{ Name: 'All namespaces', Value: '', IsSystem: false }]; const allNamespacesOption = { Name: 'All namespaces', Value: '', IsSystem: false };
this.namespaces.find((ns) => { const visibleNamespaceOptions = this.namespaces
.filter((ns) => {
if (!this.settings.showSystem && ns.IsSystem) { if (!this.settings.showSystem && ns.IsSystem) {
return false; return false;
} }
namespaces.push({ Name: ns.Name, Value: ns.Name, IsSystem: ns.IsSystem }); return true;
}); })
this.state.namespaces = namespaces; .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.namespace && !this.state.namespaces.find((ns) => ns.Name === this.state.namespace)) {
if (this.state.namespaces.length > 1) { if (this.state.namespaces.length > 1) {
@ -216,7 +218,7 @@ angular.module('portainer.docker').controller('KubernetesApplicationsDatatableCo
this.setSystemResources && this.setSystemResources(this.settings.showSystem); this.setSystemResources && this.setSystemResources(this.settings.showSystem);
} }
this.settingsLoaded = true;
// Set the default selected namespace // Set the default selected namespace
if (!this.state.namespace) { if (!this.state.namespace) {
this.state.namespace = this.namespace; this.state.namespace = this.namespace;

View File

@ -20,7 +20,7 @@
on-publishing-mode-click="(ctrl.onPublishingModeClick)" on-publishing-mode-click="(ctrl.onPublishingModeClick)"
is-primary="true" is-primary="true"
namespaces="ctrl.state.namespaces" namespaces="ctrl.state.namespaces"
namespace="ctrl.state.namespace" namespace="ctrl.state.namespaceName"
on-change-namespace-dropdown="(ctrl.onChangeNamespaceDropdown)" on-change-namespace-dropdown="(ctrl.onChangeNamespaceDropdown)"
is-system-resources="ctrl.state.isSystemResources" is-system-resources="ctrl.state.isSystemResources"
set-system-resources="(ctrl.setSystemResources)" set-system-resources="(ctrl.setSystemResources)"
@ -36,7 +36,7 @@
refresh-callback="ctrl.getApplications" refresh-callback="ctrl.getApplications"
remove-action="ctrl.removeStacksAction" remove-action="ctrl.removeStacksAction"
namespaces="ctrl.state.namespaces" namespaces="ctrl.state.namespaces"
namespace="ctrl.state.namespace" namespace="ctrl.state.namespaceName"
on-change-namespace-dropdown="(ctrl.onChangeNamespaceDropdown)" on-change-namespace-dropdown="(ctrl.onChangeNamespaceDropdown)"
is-system-resources="ctrl.state.isSystemResources" is-system-resources="ctrl.state.isSystemResources"
set-system-resources="(ctrl.setSystemResources)" set-system-resources="(ctrl.setSystemResources)"

View File

@ -13,11 +13,11 @@ class KubernetesApplicationsController {
$async, $async,
$state, $state,
$scope, $scope,
Authentication,
Notifications, Notifications,
KubernetesApplicationService, KubernetesApplicationService,
HelmService, HelmService,
KubernetesConfigurationService, KubernetesConfigurationService,
Authentication,
LocalStorage, LocalStorage,
StackService, StackService,
KubernetesNamespaceService KubernetesNamespaceService
@ -25,6 +25,7 @@ class KubernetesApplicationsController {
this.$async = $async; this.$async = $async;
this.$state = $state; this.$state = $state;
this.$scope = $scope; this.$scope = $scope;
this.Authentication = Authentication;
this.Notifications = Notifications; this.Notifications = Notifications;
this.KubernetesApplicationService = KubernetesApplicationService; this.KubernetesApplicationService = KubernetesApplicationService;
this.HelmService = HelmService; this.HelmService = HelmService;
@ -142,16 +143,18 @@ class KubernetesApplicationsController {
}); });
} }
onChangeNamespaceDropdown(namespace) { onChangeNamespaceDropdown(namespaceName) {
this.state.namespace = namespace; 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(); this.getApplicationsAsync();
} }
async getApplicationsAsync() { async getApplicationsAsync() {
try { try {
const [applications, configurations] = await Promise.all([ const [applications, configurations] = await Promise.all([
this.KubernetesApplicationService.get(this.state.namespace), this.KubernetesApplicationService.get(this.state.namespaceName),
this.KubernetesConfigurationService.get(this.state.namespace), this.KubernetesConfigurationService.get(this.state.namespaceName),
]); ]);
const configuredApplications = KubernetesConfigurationHelper.getApplicationConfigurations(applications, configurations); const configuredApplications = KubernetesConfigurationHelper.getApplicationConfigurations(applications, configurations);
const { helmApplications, nonHelmApplications } = KubernetesApplicationHelper.getNestedApplications(configuredApplications); const { helmApplications, nonHelmApplications } = KubernetesApplicationHelper.getNestedApplications(configuredApplications);
@ -184,14 +187,25 @@ class KubernetesApplicationsController {
stacks: [], stacks: [],
ports: [], ports: [],
namespaces: [], namespaces: [],
namespace: '', namespaceName: '',
isSystemResources: undefined, isSystemResources: undefined,
}; };
this.user = this.Authentication.getUserDetails();
this.state.namespaces = await this.KubernetesNamespaceService.get(); 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 = this.state.namespaces.filter((n) => n.Status === 'Active');
this.state.namespaces = _.sortBy(this.state.namespaces, 'Name'); 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(); await this.getApplications();

View File

@ -105,6 +105,13 @@ angular.module('portainer.app').factory('LocalStorage', [
const activeTab = localStorageService.get('active_tab_' + key); const activeTab = localStorageService.get('active_tab_' + key);
return activeTab === null ? 0 : activeTab; 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), storeLogoutReason: (reason) => localStorageService.set('logout_reason', reason),
getLogoutReason: () => localStorageService.get('logout_reason'), getLogoutReason: () => localStorageService.get('logout_reason'),
cleanLogoutReason: () => localStorageService.remove('logout_reason'), cleanLogoutReason: () => localStorageService.remove('logout_reason'),