Folders: Remove conditional hook calling in new folders hooks (#110305)
This commit is contained in:
@@ -907,12 +907,6 @@ exports[`better eslint`] = {
|
||||
"packages/grafana-ui/src/utils/useAsyncDependency.ts:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
|
||||
],
|
||||
"public/app/api/clients/folder/v1beta1/hooks.ts:5381": [
|
||||
[0, 0, 0, "Do not use any type assertions.", "0"],
|
||||
[0, 0, 0, "React Hook \\"useGetDisplayMappingQuery\\" is called conditionally. React Hooks must be called in the exact same order in every component render. Did you accidentally call a React Hook after an early return?", "1"],
|
||||
[0, 0, 0, "React Hook \\"useGetFolderParentsQuery\\" is called conditionally. React Hooks must be called in the exact same order in every component render. Did you accidentally call a React Hook after an early return?", "2"],
|
||||
[0, 0, 0, "React Hook \\"useGetFolderQuery\\" is called conditionally. React Hooks must be called in the exact same order in every component render. Did you accidentally call a React Hook after an early return?", "3"]
|
||||
],
|
||||
"public/app/core/TableModel.ts:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { QueryStatus, skipToken } from '@reduxjs/toolkit/query';
|
||||
import { useEffect, useMemo } from 'react';
|
||||
|
||||
import { AppEvents } from '@grafana/data';
|
||||
import { t } from '@grafana/i18n';
|
||||
@@ -24,7 +25,7 @@ import { PAGE_SIZE } from '../../../../features/browse-dashboards/api/services';
|
||||
import { refetchChildren, refreshParents } from '../../../../features/browse-dashboards/state/actions';
|
||||
import { GENERAL_FOLDER_UID } from '../../../../features/search/constants';
|
||||
import { useDispatch } from '../../../../types/store';
|
||||
import { useGetDisplayMappingQuery } from '../../iam/v0alpha1';
|
||||
import { useLazyGetDisplayMappingQuery } from '../../iam/v0alpha1';
|
||||
|
||||
import { isProvisionedFolderCheck } from './utils';
|
||||
import { rootFolder, sharedWithMeFolder } from './virtualFolders';
|
||||
@@ -46,20 +47,36 @@ function getFolderUrl(uid: string, title: string): string {
|
||||
* @param uid
|
||||
*/
|
||||
export function useGetFolderQueryFacade(uid?: string) {
|
||||
const shouldUseAppPlatformAPI = Boolean(config.featureToggles.foldersAppPlatformAPI);
|
||||
const isVirtualFolder = uid && [GENERAL_FOLDER_UID, config.sharedWithMeFolderUID].includes(uid);
|
||||
const params = !uid ? skipToken : { name: uid };
|
||||
|
||||
// This may look weird that we call the legacy folder anyway all the time, but the issue is we don't have good API
|
||||
// for the access control metadata yet, and so we still take it from the old api.
|
||||
// see https://github.com/grafana/identity-access-team/issues/1103
|
||||
const legacyFolderResult = useGetFolderQueryLegacy(uid || skipToken);
|
||||
let resultFolder = useGetFolderQuery(shouldUseAppPlatformAPI && !isVirtualFolder ? params : skipToken);
|
||||
// We get parents and folders for virtual folders too. Parents should just return empty array but it's easier to
|
||||
// stitch the responses this way and access can actually return different response based on the grafana setup.
|
||||
const resultParents = useGetFolderParentsQuery(shouldUseAppPlatformAPI ? params : skipToken);
|
||||
const [triggerGetUserDisplayMapping, resultUserDisplay] = useLazyGetDisplayMappingQuery();
|
||||
|
||||
if (!config.featureToggles.foldersAppPlatformAPI) {
|
||||
const needsUserData = useMemo(() => {
|
||||
const userKeys = getUserKeys(resultFolder);
|
||||
return !isVirtualFolder && Boolean(userKeys.length);
|
||||
}, [isVirtualFolder, resultFolder]);
|
||||
|
||||
useEffect(() => {
|
||||
const userKeys = getUserKeys(resultFolder);
|
||||
if (needsUserData && userKeys.length) {
|
||||
triggerGetUserDisplayMapping({ key: userKeys }, true);
|
||||
}
|
||||
}, [needsUserData, resultFolder, triggerGetUserDisplayMapping]);
|
||||
|
||||
if (!shouldUseAppPlatformAPI) {
|
||||
return legacyFolderResult;
|
||||
}
|
||||
|
||||
const isVirtualFolder = uid && [GENERAL_FOLDER_UID, config.sharedWithMeFolderUID].includes(uid);
|
||||
const params = !uid ? skipToken : { name: uid };
|
||||
|
||||
let resultFolder = useGetFolderQuery(isVirtualFolder ? skipToken : params);
|
||||
|
||||
// For virtual folders we simulate the response with hardcoded data.
|
||||
if (isVirtualFolder) {
|
||||
resultFolder = {
|
||||
@@ -77,15 +94,6 @@ export function useGetFolderQueryFacade(uid?: string) {
|
||||
};
|
||||
}
|
||||
|
||||
// We get parents and folders for virtual folders too. Parents should just return empty array but it's easier to
|
||||
// stitch the responses this way and access can actually return different response based on the grafana setup.
|
||||
const resultParents = useGetFolderParentsQuery(params);
|
||||
|
||||
// Load users info if needed.
|
||||
const userKeys = getUserKeys(resultFolder);
|
||||
const needsUserData = !isVirtualFolder && Boolean(userKeys.length);
|
||||
const resultUserDisplay = useGetDisplayMappingQuery(needsUserData ? { key: userKeys } : skipToken);
|
||||
|
||||
// Stitch together the responses to create a single FolderDTO object so on the outside this behaves as the legacy
|
||||
// api client.
|
||||
let newData: FolderDTO | undefined = undefined;
|
||||
@@ -112,6 +120,7 @@ export function useGetFolderQueryFacade(uid?: string) {
|
||||
hasAcl: false,
|
||||
id: parseInt(resultFolder.data.metadata.labels?.[DeprecatedInternalId] || '0', 10) || 0,
|
||||
parentUid: resultFolder.data.metadata.annotations?.[AnnoKeyFolder],
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
||||
managedBy: resultFolder.data.metadata.annotations?.[AnnoKeyManagerKind] as ManagerKind,
|
||||
|
||||
title: resultFolder.data.spec.title,
|
||||
@@ -147,14 +156,7 @@ export function useGetFolderQueryFacade(uid?: string) {
|
||||
...resultFolder,
|
||||
...combinedState(resultFolder, resultParents, legacyFolderResult, resultUserDisplay, needsUserData),
|
||||
refetch: async () => {
|
||||
return Promise.all([
|
||||
resultFolder.refetch(),
|
||||
resultParents.refetch(),
|
||||
legacyFolderResult.refetch(),
|
||||
// TODO: Not sure about this, if we refetch this but the response from result change and this is dependant on
|
||||
// that result what are we refetching here? Maybe this is redundant.
|
||||
resultUserDisplay.refetch(),
|
||||
]);
|
||||
return Promise.all([resultFolder.refetch(), resultParents.refetch(), legacyFolderResult.refetch()]);
|
||||
},
|
||||
data: newData,
|
||||
};
|
||||
@@ -228,7 +230,7 @@ function combinedState(
|
||||
result: ReturnType<typeof useGetFolderQuery>,
|
||||
resultParents: ReturnType<typeof useGetFolderParentsQuery>,
|
||||
resultLegacyFolder: ReturnType<typeof useGetFolderQueryLegacy>,
|
||||
resultUserDisplay: ReturnType<typeof useGetDisplayMappingQuery>,
|
||||
resultUserDisplay: ReturnType<typeof useLazyGetDisplayMappingQuery>[1],
|
||||
needsUserData: boolean
|
||||
) {
|
||||
const results = needsUserData
|
||||
|
||||
@@ -2,4 +2,4 @@ import { generatedAPI } from './endpoints.gen';
|
||||
|
||||
export const iamAPIv0alpha1 = generatedAPI.enhanceEndpoints({});
|
||||
|
||||
export const { useGetDisplayMappingQuery } = generatedAPI;
|
||||
export const { useGetDisplayMappingQuery, useLazyGetDisplayMappingQuery } = generatedAPI;
|
||||
|
||||
Reference in New Issue
Block a user