diff --git a/public/app/features/api-keys/state/actions.ts b/public/app/features/api-keys/state/actions.ts index ca9da51bee7..e07ae604437 100644 --- a/public/app/features/api-keys/state/actions.ts +++ b/public/app/features/api-keys/state/actions.ts @@ -1,5 +1,7 @@ import { config } from '@grafana/runtime'; import { getBackendSrv } from 'app/core/services/backend_srv'; +import store from 'app/core/store'; +import { API_KEYS_MIGRATION_INFO_STORAGE_KEY } from 'app/features/serviceaccounts/constants'; import { ApiKey, ThunkResult } from 'app/types'; import { @@ -52,6 +54,7 @@ export function migrateAll(): ThunkResult { return async (dispatch) => { try { await getBackendSrv().post('/api/serviceaccounts/migrate'); + store.set(API_KEYS_MIGRATION_INFO_STORAGE_KEY, true); } finally { dispatch(getApiKeysMigrationStatus()); dispatch(loadApiKeys()); diff --git a/public/app/features/serviceaccounts/ServiceAccountsListPage.test.tsx b/public/app/features/serviceaccounts/ServiceAccountsListPage.test.tsx index d40a59b4071..e2222f4f628 100644 --- a/public/app/features/serviceaccounts/ServiceAccountsListPage.test.tsx +++ b/public/app/features/serviceaccounts/ServiceAccountsListPage.test.tsx @@ -23,6 +23,8 @@ const setup = (propOverrides: Partial) => { const changeStateFilterMock = jest.fn(); const createServiceAccountTokenMock = jest.fn(); const getApiKeysMigrationStatusMock = jest.fn(); + const getApiKeysMigrationInfoMock = jest.fn(); + const closeApiKeysMigrationInfoMock = jest.fn(); const props: Props = { navModel: { main: { @@ -43,6 +45,7 @@ const setup = (propOverrides: Partial) => { totalPages: 1, serviceAccounts: [], apiKeysMigrated: false, + showApiKeysMigrationInfo: false, changeQuery: changeQueryMock, fetchACOptions: fetchACOptionsMock, fetchServiceAccounts: fetchServiceAccountsMock, @@ -51,6 +54,8 @@ const setup = (propOverrides: Partial) => { changeStateFilter: changeStateFilterMock, createServiceAccountToken: createServiceAccountTokenMock, getApiKeysMigrationStatus: getApiKeysMigrationStatusMock, + getApiKeysMigrationInfo: getApiKeysMigrationInfoMock, + closeApiKeysMigrationInfo: closeApiKeysMigrationInfoMock, }; Object.assign(props, propOverrides); diff --git a/public/app/features/serviceaccounts/ServiceAccountsListPage.tsx b/public/app/features/serviceaccounts/ServiceAccountsListPage.tsx index 070dc7a9fd8..b713b28d3b3 100644 --- a/public/app/features/serviceaccounts/ServiceAccountsListPage.tsx +++ b/public/app/features/serviceaccounts/ServiceAccountsListPage.tsx @@ -23,6 +23,8 @@ import { changeStateFilter, createServiceAccountToken, getApiKeysMigrationStatus, + getApiKeysMigrationInfo, + closeApiKeysMigrationInfo, } from './state/actions'; interface OwnProps {} @@ -45,6 +47,8 @@ const mapDispatchToProps = { changeStateFilter, createServiceAccountToken, getApiKeysMigrationStatus, + getApiKeysMigrationInfo, + closeApiKeysMigrationInfo, }; const connector = connect(mapStateToProps, mapDispatchToProps); @@ -58,6 +62,7 @@ export const ServiceAccountsListPageUnconnected = ({ query, serviceAccountStateFilter, apiKeysMigrated, + showApiKeysMigrationInfo, changeQuery, fetchACOptions, fetchServiceAccounts, @@ -66,6 +71,8 @@ export const ServiceAccountsListPageUnconnected = ({ changeStateFilter, createServiceAccountToken, getApiKeysMigrationStatus, + getApiKeysMigrationInfo, + closeApiKeysMigrationInfo, }: Props): JSX.Element => { const styles = useStyles2(getStyles); const [isAddModalOpen, setIsAddModalOpen] = useState(false); @@ -77,10 +84,11 @@ export const ServiceAccountsListPageUnconnected = ({ useEffect(() => { fetchServiceAccounts({ withLoadingIndicator: true }); getApiKeysMigrationStatus(); + getApiKeysMigrationInfo(); if (contextSrv.licensedAccessControlEnabled()) { fetchACOptions(); } - }, [fetchACOptions, fetchServiceAccounts, getApiKeysMigrationStatus]); + }, [fetchACOptions, fetchServiceAccounts, getApiKeysMigrationStatus, getApiKeysMigrationInfo]); const noServiceAccountsCreated = serviceAccounts.length === 0 && serviceAccountStateFilter === ServiceAccountStateFilter.All && !query; @@ -157,13 +165,13 @@ export const ServiceAccountsListPageUnconnected = ({ }; const onMigrationInfoClose = () => { - // TODO: dismiss banner permanently + closeApiKeysMigrationInfo(); }; return ( - {apiKeysMigrated && ( + {apiKeysMigrated && showApiKeysMigrationInfo && ( { dispatch(fetchServiceAccounts()); }; } + +export function getApiKeysMigrationInfo(): ThunkResult { + return async (dispatch) => { + const showApiKeysMigrationInfo = store.getBool(API_KEYS_MIGRATION_INFO_STORAGE_KEY, false); + dispatch(showApiKeysMigrationInfoLoaded(showApiKeysMigrationInfo)); + }; +} + +export function closeApiKeysMigrationInfo(): ThunkResult { + return async (dispatch) => { + store.set(API_KEYS_MIGRATION_INFO_STORAGE_KEY, false); + dispatch(getApiKeysMigrationInfo()); + }; +} diff --git a/public/app/features/serviceaccounts/state/reducers.ts b/public/app/features/serviceaccounts/state/reducers.ts index 571ec2b40d7..ad03360aeed 100644 --- a/public/app/features/serviceaccounts/state/reducers.ts +++ b/public/app/features/serviceaccounts/state/reducers.ts @@ -52,6 +52,7 @@ export const initialStateList: ServiceAccountsState = { showPaging: false, serviceAccountStateFilter: ServiceAccountStateFilter.All, apiKeysMigrated: false, + showApiKeysMigrationInfo: false, }; interface ServiceAccountsFetched { @@ -93,6 +94,9 @@ const serviceAccountsSlice = createSlice({ apiKeysMigrationStatusLoaded: (state, action): ServiceAccountsState => { return { ...state, apiKeysMigrated: action.payload }; }, + showApiKeysMigrationInfoLoaded: (state, action): ServiceAccountsState => { + return { ...state, showApiKeysMigrationInfo: action.payload }; + }, queryChanged: (state, action: PayloadAction) => { return { ...state, @@ -119,6 +123,7 @@ export const { acOptionsLoaded, builtInRolesLoaded, apiKeysMigrationStatusLoaded, + showApiKeysMigrationInfoLoaded, pageChanged, stateFilterChanged, queryChanged, diff --git a/public/app/types/serviceaccount.ts b/public/app/types/serviceaccount.ts index 836bdaaf8f1..b99131be095 100644 --- a/public/app/types/serviceaccount.ts +++ b/public/app/types/serviceaccount.ts @@ -67,6 +67,7 @@ export interface ServiceAccountsState { roleOptions: Role[]; builtInRoles: Record; apiKeysMigrated: boolean; + showApiKeysMigrationInfo: boolean; // search / filtering query: string;