|
|
|
@ -3,7 +3,7 @@ import { createSelector } from 'reselect'; |
|
|
|
|
import { DashboardViewItem } from 'app/features/search/types'; |
|
|
|
|
import { useSelector, StoreState } from 'app/types'; |
|
|
|
|
|
|
|
|
|
import { DashboardsTreeItem } from '../types'; |
|
|
|
|
import { DashboardsTreeItem, DashboardTreeSelection } from '../types'; |
|
|
|
|
|
|
|
|
|
const flatTreeSelector = createSelector( |
|
|
|
|
(wholeState: StoreState) => wholeState.browseDashboards.rootItems, |
|
|
|
@ -24,6 +24,14 @@ const hasSelectionSelector = createSelector( |
|
|
|
|
} |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
const selectedItemsForActionsSelector = createSelector( |
|
|
|
|
(wholeState: StoreState) => wholeState.browseDashboards.selectedItems, |
|
|
|
|
(wholeState: StoreState) => wholeState.browseDashboards.childrenByParentUID, |
|
|
|
|
(selectedItems, childrenByParentUID) => { |
|
|
|
|
return getSelectedItemsForActions(selectedItems, childrenByParentUID); |
|
|
|
|
} |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
export function useFlatTreeState(folderUID: string | undefined) { |
|
|
|
|
return useSelector((state) => flatTreeSelector(state, folderUID)); |
|
|
|
|
} |
|
|
|
@ -32,10 +40,14 @@ export function useHasSelection() { |
|
|
|
|
return useSelector((state) => hasSelectionSelector(state)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export function useSelectedItemsState() { |
|
|
|
|
export function useCheckboxSelectionState() { |
|
|
|
|
return useSelector((wholeState: StoreState) => wholeState.browseDashboards.selectedItems); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export function useActionSelectionState() { |
|
|
|
|
return useSelector((state) => selectedItemsForActionsSelector(state)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Creates a list of items, with level indicating it's 'nested' in the tree structure |
|
|
|
|
* |
|
|
|
@ -83,3 +95,43 @@ function createFlatTree( |
|
|
|
|
|
|
|
|
|
return items.flatMap((item) => mapItem(item, folderUID, level)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Returns a DashboardTreeSelection but unselects any selected folder's children. |
|
|
|
|
* This is useful when making backend requests to move or delete items. |
|
|
|
|
* In this case, we only need to move/delete the parent folder and it will cascade to the children. |
|
|
|
|
* @param selectedItemsState Overall selection state |
|
|
|
|
* @param childrenByParentUID Arrays of children keyed by their parent UID |
|
|
|
|
*/ |
|
|
|
|
function getSelectedItemsForActions( |
|
|
|
|
selectedItemsState: DashboardTreeSelection, |
|
|
|
|
childrenByParentUID: Record<string, DashboardViewItem[] | undefined> |
|
|
|
|
): Omit<DashboardTreeSelection, 'panel'> { |
|
|
|
|
// Take a copy of the selected items to work with
|
|
|
|
|
// We don't care about panels here, only dashboards and folders can be moved or deleted
|
|
|
|
|
const result: Omit<DashboardTreeSelection, 'panel'> = { |
|
|
|
|
dashboard: { ...selectedItemsState.dashboard }, |
|
|
|
|
folder: { ...selectedItemsState.folder }, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
// Loop over selected folders in the input
|
|
|
|
|
for (const folderUID of Object.keys(selectedItemsState.folder)) { |
|
|
|
|
const isSelected = selectedItemsState.folder[folderUID]; |
|
|
|
|
if (isSelected) { |
|
|
|
|
// Unselect any children in the output
|
|
|
|
|
const children = childrenByParentUID[folderUID]; |
|
|
|
|
if (children) { |
|
|
|
|
for (const child of children) { |
|
|
|
|
if (child.kind === 'dashboard') { |
|
|
|
|
result.dashboard[child.uid] = false; |
|
|
|
|
} |
|
|
|
|
if (child.kind === 'folder') { |
|
|
|
|
result.folder[child.uid] = false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|