diff --git a/packages/grafana-runtime/src/components/FolderPicker.tsx b/packages/grafana-runtime/src/components/FolderPicker.tsx index 3a22b761e96..2e129480908 100644 --- a/packages/grafana-runtime/src/components/FolderPicker.tsx +++ b/packages/grafana-runtime/src/components/FolderPicker.tsx @@ -13,6 +13,9 @@ interface FolderPickerProps { /* Folder UIDs to exclude from the picker, to prevent invalid operations */ excludeUIDs?: string[]; + /* Start tree from this folder instead of root */ + rootFolderUID?: string; + /* Show folders matching this permission, mainly used to also show folders user can view. Defaults to showing only folders user has Edit */ permission?: 'view' | 'edit'; diff --git a/public/app/core/components/NestedFolderPicker/NestedFolderPicker.tsx b/public/app/core/components/NestedFolderPicker/NestedFolderPicker.tsx index 042ec10f9ce..fc8bd0bf00c 100644 --- a/public/app/core/components/NestedFolderPicker/NestedFolderPicker.tsx +++ b/public/app/core/components/NestedFolderPicker/NestedFolderPicker.tsx @@ -36,6 +36,9 @@ export interface NestedFolderPickerProps { /* Folder UIDs to exclude from the picker, to prevent invalid operations */ excludeUIDs?: string[]; + /* Start tree from this folder instead of root */ + rootFolderUID?: string; + /* Show folders matching this permission, mainly used to also show folders user can view. Defaults to showing only folders user has Edit */ permission?: 'view' | 'edit'; @@ -66,6 +69,7 @@ export function NestedFolderPicker({ showRootFolder = true, clearable = false, excludeUIDs, + rootFolderUID, permission = 'edit', onChange, }: NestedFolderPickerProps) { @@ -102,7 +106,7 @@ export function NestedFolderPicker({ items: browseFlatTree, isLoading: isBrowseLoading, requestNextPage: fetchFolderPage, - } = useFoldersQuery(isBrowsing, foldersOpenState, permissionLevel); + } = useFoldersQuery(isBrowsing, foldersOpenState, permissionLevel, rootFolderUID); useEffect(() => { if (!search) { diff --git a/public/app/core/components/NestedFolderPicker/useFoldersQuery.ts b/public/app/core/components/NestedFolderPicker/useFoldersQuery.ts index 6fe4c0ef440..ee96989b9a8 100644 --- a/public/app/core/components/NestedFolderPicker/useFoldersQuery.ts +++ b/public/app/core/components/NestedFolderPicker/useFoldersQuery.ts @@ -7,10 +7,12 @@ import { useFoldersQueryLegacy } from './useFoldersQueryLegacy'; export function useFoldersQuery( isBrowsing: boolean, openFolders: Record, - permission?: PermissionLevelString + permission?: PermissionLevelString, + /* Start tree from this folder instead of root */ + rootFolderUID?: string ) { - const resultLegacy = useFoldersQueryLegacy(isBrowsing, openFolders, permission); - const resultAppPlatform = useFoldersQueryAppPlatform(isBrowsing, openFolders); + const resultLegacy = useFoldersQueryLegacy(isBrowsing, openFolders, permission, rootFolderUID); + const resultAppPlatform = useFoldersQueryAppPlatform(isBrowsing, openFolders, rootFolderUID); // Running the hooks themselves don't have any side effects, so we can just conditionally use one or the other // requestNextPage function from the result diff --git a/public/app/core/components/NestedFolderPicker/useFoldersQueryAppPlatform.ts b/public/app/core/components/NestedFolderPicker/useFoldersQueryAppPlatform.ts index b877c69aba0..b1541cbfcd2 100644 --- a/public/app/core/components/NestedFolderPicker/useFoldersQueryAppPlatform.ts +++ b/public/app/core/components/NestedFolderPicker/useFoldersQueryAppPlatform.ts @@ -25,7 +25,12 @@ const collator = new Intl.Collator(); * This version uses the getFolderChildren API from the folder v1beta1 API. Compared to legacy API, the v1beta1 API * does not have pagination at the moment. */ -export function useFoldersQueryAppPlatform(isBrowsing: boolean, openFolders: Record) { +export function useFoldersQueryAppPlatform( + isBrowsing: boolean, + openFolders: Record, + /* rootFolderUID: configure which folder to start browsing from */ + rootFolderUID?: string +) { const dispatch = useDispatch(); // Keep a list of all request subscriptions so we can unsubscribe from them when the component is unmounted @@ -150,11 +155,12 @@ export function useFoldersQueryAppPlatform(isBrowsing: boolean, openFolders: Rec return list; } - const rootFlatTree = createFlatList(rootFolderToken, state.responseByParent[rootFolderToken], 1); + const startingToken = rootFolderUID ?? rootFolderToken; + const rootFlatTree = createFlatList(startingToken, state.responseByParent[startingToken], 1); rootFlatTree.unshift(getRootFolderItem()); return rootFlatTree; - }, [state, isBrowsing, openFolders]); + }, [state, isBrowsing, openFolders, rootFolderUID]); return { items: treeList, diff --git a/public/app/core/components/NestedFolderPicker/useFoldersQueryLegacy.ts b/public/app/core/components/NestedFolderPicker/useFoldersQueryLegacy.ts index 84c540f7f71..52e33a538d7 100644 --- a/public/app/core/components/NestedFolderPicker/useFoldersQueryLegacy.ts +++ b/public/app/core/components/NestedFolderPicker/useFoldersQueryLegacy.ts @@ -48,7 +48,9 @@ function getPagesLoadStatus(pages: ListFoldersQuery[]): [boolean, number | undef export function useFoldersQueryLegacy( isBrowsing: boolean, openFolders: Record, - permission?: PermissionLevelString + permission?: PermissionLevelString, + /* rootFolderUID: configure which folder to start browsing from */ + rootFolderUID?: string ) { const dispatch = useDispatch(); @@ -178,11 +180,13 @@ export function useFoldersQueryLegacy( return flatList; } - const rootFlatTree = createFlatList(undefined, state.rootPages, 1); + const startingPages = rootFolderUID ? state.pagesByParent[rootFolderUID] : state.rootPages; + + const rootFlatTree = createFlatList(rootFolderUID ?? undefined, startingPages ?? [], 1); rootFlatTree.unshift(getRootFolderItem()); return rootFlatTree; - }, [state, isBrowsing, openFolders]); + }, [state, isBrowsing, openFolders, rootFolderUID]); return { items: treeList,