From 6d538f62c836b34d96ed1992e8c56af01575e89c Mon Sep 17 00:00:00 2001 From: Yunwen Zheng Date: Thu, 21 Aug 2025 12:17:43 -0400 Subject: [PATCH] Provisioning components organize (#109741) * Provisioning components organize --- .../BrowseDashboardsPage.tsx | 2 +- .../BrowseActions/BrowseActions.tsx | 6 +-- .../components/BrowseActions/utils.ts | 41 ----------------- .../components/CheckboxCell.tsx | 2 +- .../components/CreateNewButton.tsx | 2 +- .../components/FolderActionsButton.tsx | 2 +- .../browse-dashboards/components/utils.ts | 45 +------------------ .../pages/DashboardScenePage.tsx | 2 +- .../saving/SaveDashboardAsForm.tsx | 2 +- .../saving/SaveDashboardDrawer.tsx | 2 +- .../dashboard-scene/saving/shared.tsx | 18 -------- .../settings/DeleteDashboardButton.tsx | 3 +- .../settings/GeneralSettingsEditView.tsx | 2 +- .../dashboard-scene/settings/utils.ts | 27 ----------- .../BulkDeleteProvisionedResource.test.tsx | 6 +-- .../BulkDeleteProvisionedResource.tsx | 14 +++--- .../BulkMoveProvisionedResource.tsx | 14 +++--- .../BulkActions/useBulkActionJob.ts | 0 .../BulkActions/useFolderNameFromSelection.ts | 7 ++- .../components/BulkActions/utils.test.ts | 0 .../components/BulkActions/utils.ts | 3 +- .../Dashboards}/DashboardPreviewBanner.tsx | 2 +- .../DeleteProvisionedDashboardDrawer.tsx | 5 ++- .../DeleteProvisionedDashboardForm.test.tsx | 19 +++++--- .../DeleteProvisionedDashboardForm.tsx | 13 +++--- .../MoveProvisionedDashboardDrawer.tsx | 5 ++- .../MoveProvisionedDashboardForm.test.tsx | 8 ++-- .../MoveProvisionedDashboardForm.tsx | 13 +++--- .../Dashboards}/SaveProvisionedDashboard.tsx | 9 ++-- .../SaveProvisionedDashboardForm.test.tsx | 11 +++-- .../SaveProvisionedDashboardForm.tsx | 19 ++++---- .../DeleteProvisionedFolderForm.test.tsx | 11 +++-- .../Folders}/DeleteProvisionedFolderForm.tsx | 20 ++++----- .../NewProvisionedFolderForm.test.tsx | 18 +++----- .../Folders}/NewProvisionedFolderForm.tsx | 16 +++---- .../ProvisionedFolderPreviewBanner.tsx | 4 +- .../Shared}/PreviewBannerViewPR.test.tsx | 0 .../Shared}/PreviewBannerViewPR.tsx | 2 +- .../Shared}/RepoInvalidStateBanner.tsx | 0 .../ResourceEditFormSharedFields.test.tsx | 5 ++- .../Shared}/ResourceEditFormSharedFields.tsx | 0 .../components}/defaults.ts | 0 .../components}/utils/getProvisionedMeta.ts | 0 .../components}/utils/path.test.ts | 0 .../components}/utils/path.ts | 0 .../components}/utils/timestamp.test.ts | 0 .../components}/utils/timestamp.ts | 0 .../hooks/useProvisionedDashboardData.ts} | 11 +++-- .../hooks/useProvisionedFolderFormData.ts | 8 ++-- .../useProvisionedRequestHandler.test.ts | 0 .../hooks}/useProvisionedRequestHandler.ts | 0 .../hooks}/useSelectionProvisioningStatus.ts | 4 +- .../hooks}/useSelectionRepoValidation.ts | 9 ++-- .../app/features/provisioning/types/form.ts | 18 ++++++++ .../features/provisioning/utils/redirect.ts | 26 +++++++++++ .../features/provisioning/utils/repository.ts | 36 +++++++++++++++ 56 files changed, 220 insertions(+), 272 deletions(-) rename public/app/features/{browse-dashboards => provisioning}/components/BulkActions/BulkDeleteProvisionedResource.test.tsx (97%) rename public/app/features/{browse-dashboards => provisioning}/components/BulkActions/BulkDeleteProvisionedResource.tsx (89%) rename public/app/features/{browse-dashboards => provisioning}/components/BulkActions/BulkMoveProvisionedResource.tsx (92%) rename public/app/features/{browse-dashboards => provisioning}/components/BulkActions/useBulkActionJob.ts (100%) rename public/app/features/{browse-dashboards => provisioning}/components/BulkActions/useFolderNameFromSelection.ts (89%) rename public/app/features/{browse-dashboards => provisioning}/components/BulkActions/utils.test.ts (100%) rename public/app/features/{browse-dashboards => provisioning}/components/BulkActions/utils.ts (97%) rename public/app/features/{dashboard-scene/saving/provisioned => provisioning/components/Dashboards}/DashboardPreviewBanner.tsx (97%) rename public/app/features/{dashboard-scene/settings => provisioning/components/Dashboards}/DeleteProvisionedDashboardDrawer.tsx (82%) rename public/app/features/{dashboard-scene/settings => provisioning/components/Dashboards}/DeleteProvisionedDashboardForm.test.tsx (92%) rename public/app/features/{dashboard-scene/settings => provisioning/components/Dashboards}/DeleteProvisionedDashboardForm.tsx (90%) rename public/app/features/{dashboard-scene/settings => provisioning/components/Dashboards}/MoveProvisionedDashboardDrawer.tsx (85%) rename public/app/features/{dashboard-scene/settings => provisioning/components/Dashboards}/MoveProvisionedDashboardForm.test.tsx (95%) rename public/app/features/{dashboard-scene/settings => provisioning/components/Dashboards}/MoveProvisionedDashboardForm.tsx (94%) rename public/app/features/{dashboard-scene/saving/provisioned => provisioning/components/Dashboards}/SaveProvisionedDashboard.tsx (70%) rename public/app/features/{dashboard-scene/saving/provisioned => provisioning/components/Dashboards}/SaveProvisionedDashboardForm.test.tsx (96%) rename public/app/features/{dashboard-scene/saving/provisioned => provisioning/components/Dashboards}/SaveProvisionedDashboardForm.tsx (93%) rename public/app/features/{browse-dashboards/components => provisioning/components/Folders}/DeleteProvisionedFolderForm.test.tsx (96%) rename public/app/features/{browse-dashboards/components => provisioning/components/Folders}/DeleteProvisionedFolderForm.tsx (88%) rename public/app/features/{browse-dashboards/components => provisioning/components/Folders}/NewProvisionedFolderForm.test.tsx (95%) rename public/app/features/{browse-dashboards/components => provisioning/components/Folders}/NewProvisionedFolderForm.tsx (93%) rename public/app/features/{browse-dashboards/components => provisioning/components/Folders}/ProvisionedFolderPreviewBanner.tsx (76%) rename public/app/features/{dashboard-scene/saving/provisioned => provisioning/components/Shared}/PreviewBannerViewPR.test.tsx (100%) rename public/app/features/{dashboard-scene/saving/provisioned => provisioning/components/Shared}/PreviewBannerViewPR.tsx (98%) rename public/app/features/{browse-dashboards/components/BulkActions => provisioning/components/Shared}/RepoInvalidStateBanner.tsx (100%) rename public/app/features/{dashboard-scene/components/Provisioned => provisioning/components/Shared}/ResourceEditFormSharedFields.test.tsx (98%) rename public/app/features/{dashboard-scene/components/Provisioned => provisioning/components/Shared}/ResourceEditFormSharedFields.tsx (100%) rename public/app/features/{dashboard-scene/saving/provisioned => provisioning/components}/defaults.ts (100%) rename public/app/features/{dashboard-scene/saving/provisioned => provisioning/components}/utils/getProvisionedMeta.ts (100%) rename public/app/features/{dashboard-scene/saving/provisioned => provisioning/components}/utils/path.test.ts (100%) rename public/app/features/{dashboard-scene/saving/provisioned => provisioning/components}/utils/path.ts (100%) rename public/app/features/{dashboard-scene/saving/provisioned => provisioning/components}/utils/timestamp.test.ts (100%) rename public/app/features/{dashboard-scene/saving/provisioned => provisioning/components}/utils/timestamp.ts (100%) rename public/app/features/{dashboard-scene/saving/provisioned/hooks.ts => provisioning/hooks/useProvisionedDashboardData.ts} (91%) rename public/app/features/{browse-dashboards => provisioning}/hooks/useProvisionedFolderFormData.ts (85%) rename public/app/features/{dashboard-scene/utils => provisioning/hooks}/useProvisionedRequestHandler.test.ts (100%) rename public/app/features/{dashboard-scene/utils => provisioning/hooks}/useProvisionedRequestHandler.ts (100%) rename public/app/features/{browse-dashboards/components/BrowseActions => provisioning/hooks}/useSelectionProvisioningStatus.ts (97%) rename public/app/features/{browse-dashboards/components/BrowseActions => provisioning/hooks}/useSelectionRepoValidation.ts (89%) create mode 100644 public/app/features/provisioning/types/form.ts create mode 100644 public/app/features/provisioning/utils/redirect.ts diff --git a/public/app/features/browse-dashboards/BrowseDashboardsPage.tsx b/public/app/features/browse-dashboards/BrowseDashboardsPage.tsx index 038a32d1af6..a5e7861a2c9 100644 --- a/public/app/features/browse-dashboards/BrowseDashboardsPage.tsx +++ b/public/app/features/browse-dashboards/BrowseDashboardsPage.tsx @@ -16,6 +16,7 @@ import { FolderRepo } from '../../core/components/NestedFolderPicker/FolderRepo' import { contextSrv } from '../../core/services/context_srv'; import { ManagerKind } from '../apiserver/types'; import { buildNavModel, getDashboardsTabID } from '../folders/state/navModel'; +import { ProvisionedFolderPreviewBanner } from '../provisioning/components/Folders/ProvisionedFolderPreviewBanner'; import { useGetResourceRepositoryView } from '../provisioning/hooks/useGetResourceRepositoryView'; import { useSearchStateManager } from '../search/state/SearchStateManager'; import { getSearchPlaceholder } from '../search/tempI18nPhrases'; @@ -26,7 +27,6 @@ import { BrowseFilters } from './components/BrowseFilters'; import { BrowseView } from './components/BrowseView'; import CreateNewButton from './components/CreateNewButton'; import { FolderActionsButton } from './components/FolderActionsButton'; -import { ProvisionedFolderPreviewBanner } from './components/ProvisionedFolderPreviewBanner'; import { SearchView } from './components/SearchView'; import { getFolderPermissions } from './permissions'; import { useHasSelection } from './state/hooks'; diff --git a/public/app/features/browse-dashboards/components/BrowseActions/BrowseActions.tsx b/public/app/features/browse-dashboards/components/BrowseActions/BrowseActions.tsx index 5e538d6e91b..ad0a72df516 100644 --- a/public/app/features/browse-dashboards/components/BrowseActions/BrowseActions.tsx +++ b/public/app/features/browse-dashboards/components/BrowseActions/BrowseActions.tsx @@ -5,6 +5,9 @@ import { config, reportInteraction } from '@grafana/runtime'; import { Button, Drawer, Stack } from '@grafana/ui'; import appEvents from 'app/core/app_events'; import { ManagerKind } from 'app/features/apiserver/types'; +import { BulkDeleteProvisionedResource } from 'app/features/provisioning/components/BulkActions/BulkDeleteProvisionedResource'; +import { BulkMoveProvisionedResource } from 'app/features/provisioning/components/BulkActions/BulkMoveProvisionedResource'; +import { useSelectionProvisioningStatus } from 'app/features/provisioning/hooks/useSelectionProvisioningStatus'; import { useSearchStateManager } from 'app/features/search/state/SearchStateManager'; import { ShowModalReactEvent } from 'app/types/events'; import { FolderDTO } from 'app/types/folders'; @@ -14,13 +17,10 @@ import { useDeleteItemsMutation, useMoveItemsMutation } from '../../api/browseDa import { useActionSelectionState } from '../../state/hooks'; import { setAllSelection } from '../../state/slice'; import { DashboardTreeSelection } from '../../types'; -import { BulkDeleteProvisionedResource } from '../BulkActions/BulkDeleteProvisionedResource'; -import { BulkMoveProvisionedResource } from '../BulkActions/BulkMoveProvisionedResource'; import { DeleteModal } from './DeleteModal'; import { MoveModal } from './MoveModal'; import { SelectedMixResourcesMsgModal } from './SelectedMixResourcesMsgModal'; -import { useSelectionProvisioningStatus } from './useSelectionProvisioningStatus'; export interface Props { folderDTO?: FolderDTO; diff --git a/public/app/features/browse-dashboards/components/BrowseActions/utils.ts b/public/app/features/browse-dashboards/components/BrowseActions/utils.ts index 59a3979cf2f..2d6b4328c53 100644 --- a/public/app/features/browse-dashboards/components/BrowseActions/utils.ts +++ b/public/app/features/browse-dashboards/components/BrowseActions/utils.ts @@ -1,8 +1,4 @@ import { t } from '@grafana/i18n'; -import { DashboardViewItem } from 'app/features/search/types'; - -import { findItem } from '../../state/utils'; -import { DashboardViewItemCollection } from '../../types'; export function buildBreakdownString( folderCount: number, @@ -30,40 +26,3 @@ export function buildBreakdownString( } return breakdownString; } - -// Utility: Get root folder for any item (reusing existing pattern from reducers.ts) -export function getItemRootFolder( - item: { uid: string; parentUID?: string; kind?: string }, - browseState: { - rootItems?: { items: DashboardViewItem[] }; - childrenByParentUID: Record; - } -): string | undefined { - const rootItems = browseState.rootItems?.items || []; - - // If it's already a root-level item, return its UID (only for folders) - if (!item.parentUID) { - return item.kind === 'folder' ? item.uid : undefined; - } - - // For nested items, traverse up to find root folder (same pattern as reducers.ts) - let nextParentUID = item.parentUID; - - while (nextParentUID) { - const parent = findItem(rootItems, browseState.childrenByParentUID, nextParentUID); - - // Safety check to prevent infinite loops (same as reducers.ts) - if (!parent) { - break; - } - - // Found the root folder (no parent) - if (!parent.parentUID) { - return parent.uid; - } - - nextParentUID = parent.parentUID; - } - - return undefined; -} diff --git a/public/app/features/browse-dashboards/components/CheckboxCell.tsx b/public/app/features/browse-dashboards/components/CheckboxCell.tsx index d232a3a4620..c86fd681c95 100644 --- a/public/app/features/browse-dashboards/components/CheckboxCell.tsx +++ b/public/app/features/browse-dashboards/components/CheckboxCell.tsx @@ -6,12 +6,12 @@ import { t } from '@grafana/i18n'; import { Checkbox, Tooltip, useStyles2 } from '@grafana/ui'; import { ManagerKind } from 'app/features/apiserver/types'; import { useIsProvisionedInstance } from 'app/features/provisioning/hooks/useIsProvisionedInstance'; +import { useSelectionRepoValidation } from 'app/features/provisioning/hooks/useSelectionRepoValidation'; import { getReadOnlyTooltipText } from 'app/features/provisioning/utils/repository'; import { useSelector } from 'app/types/store'; import { DashboardsTreeCellProps, SelectionState } from '../types'; -import { useSelectionRepoValidation } from './BrowseActions/useSelectionRepoValidation'; import { isSharedWithMe, canEditItemType } from './utils'; export default function CheckboxCell({ diff --git a/public/app/features/browse-dashboards/components/CreateNewButton.tsx b/public/app/features/browse-dashboards/components/CreateNewButton.tsx index bc8b896b8ae..3fac2239c07 100644 --- a/public/app/features/browse-dashboards/components/CreateNewButton.tsx +++ b/public/app/features/browse-dashboards/components/CreateNewButton.tsx @@ -6,6 +6,7 @@ import { config, locationService, reportInteraction } from '@grafana/runtime'; import { Button, Drawer, Dropdown, Icon, Menu, MenuItem } from '@grafana/ui'; import { useAppNotification } from 'app/core/copy/appNotification'; import { RepoType } from 'app/features/provisioning/Wizard/types'; +import { NewProvisionedFolderForm } from 'app/features/provisioning/components/Folders/NewProvisionedFolderForm'; import { useIsProvisionedInstance } from 'app/features/provisioning/hooks/useIsProvisionedInstance'; import { getReadOnlyTooltipText } from 'app/features/provisioning/utils/repository'; import { @@ -20,7 +21,6 @@ import { ManagerKind } from '../../apiserver/types'; import { useNewFolderMutation } from '../api/browseDashboardsAPI'; import { NewFolderForm } from './NewFolderForm'; -import { NewProvisionedFolderForm } from './NewProvisionedFolderForm'; interface Props { parentFolder?: FolderDTO; diff --git a/public/app/features/browse-dashboards/components/FolderActionsButton.tsx b/public/app/features/browse-dashboards/components/FolderActionsButton.tsx index c58b310e0e3..41d877a77c3 100644 --- a/public/app/features/browse-dashboards/components/FolderActionsButton.tsx +++ b/public/app/features/browse-dashboards/components/FolderActionsButton.tsx @@ -7,6 +7,7 @@ import { Button, Drawer, Dropdown, Icon, Menu, MenuItem } from '@grafana/ui'; import { Permissions } from 'app/core/components/AccessControl'; import { appEvents } from 'app/core/core'; import { RepoType } from 'app/features/provisioning/Wizard/types'; +import { DeleteProvisionedFolderForm } from 'app/features/provisioning/components/Folders/DeleteProvisionedFolderForm'; import { getReadOnlyTooltipText } from 'app/features/provisioning/utils/repository'; import { ShowModalReactEvent } from 'app/types/events'; import { FolderDTO } from 'app/types/folders'; @@ -18,7 +19,6 @@ import { getFolderPermissions } from '../permissions'; import { DeleteModal } from './BrowseActions/DeleteModal'; import { MoveModal } from './BrowseActions/MoveModal'; -import { DeleteProvisionedFolderForm } from './DeleteProvisionedFolderForm'; interface Props { folder: FolderDTO; diff --git a/public/app/features/browse-dashboards/components/utils.ts b/public/app/features/browse-dashboards/components/utils.ts index de03451146f..818b96ebba7 100644 --- a/public/app/features/browse-dashboards/components/utils.ts +++ b/public/app/features/browse-dashboards/components/utils.ts @@ -1,17 +1,8 @@ import { config } from '@grafana/runtime'; import { contextSrv } from 'app/core/core'; -import { ManagerKind } from 'app/features/apiserver/types'; -import { DashboardViewItem } from 'app/features/search/types'; +import { ResourceRef } from 'app/features/provisioning/components/BulkActions/useBulkActionJob'; -import { findItem } from '../state/utils'; -import { - DashboardTreeSelection, - DashboardViewItemWithUIItems, - BrowseDashboardsPermissions, - BrowseDashboardsState, -} from '../types'; - -import { ResourceRef } from './BulkActions/useBulkActionJob'; +import { DashboardTreeSelection, DashboardViewItemWithUIItems, BrowseDashboardsPermissions } from '../types'; export function makeRowID(baseId: string, item: DashboardViewItemWithUIItems) { return baseId + item.uid; @@ -69,35 +60,3 @@ export function canSelectItems(permissions: BrowseDashboardsPermissions) { const canSelectDashboards = canEditDashboards || canDeleteDashboards; return Boolean(canSelectFolders || canSelectDashboards); } - -/** - * Finds the repository name for an item by traversing up the tree to find the root provisioned folder (managed by ManagerKind.Repo) - * This should be an edge case where user have multiple provisioned folders and try to managing resources on root folder - */ -export function getItemRepositoryUid( - item: DashboardViewItem, - rootItems: DashboardViewItem[], - childrenByParentUID: BrowseDashboardsState['childrenByParentUID'] -): string { - // For root provisioned folders, the UID is the repository name - if (item.managedBy === ManagerKind.Repo && !item.parentUID && item.kind === 'folder') { - return item.uid; - } - - // Traverse up the tree to find the root provisioned folder - let currentItem = item; - while (currentItem.parentUID) { - const parent = findItem(rootItems, childrenByParentUID, currentItem.parentUID); - if (!parent) { - break; - } - - if (parent.managedBy === ManagerKind.Repo && !parent.parentUID) { - return currentItem.parentUID; - } - - currentItem = parent; - } - - return 'non_provisioned'; -} diff --git a/public/app/features/dashboard-scene/pages/DashboardScenePage.tsx b/public/app/features/dashboard-scene/pages/DashboardScenePage.tsx index d7eb249f1c7..4aa7e2e8987 100644 --- a/public/app/features/dashboard-scene/pages/DashboardScenePage.tsx +++ b/public/app/features/dashboard-scene/pages/DashboardScenePage.tsx @@ -12,10 +12,10 @@ import { GrafanaRouteComponentProps } from 'app/core/navigation/types'; import { DashboardPageError } from 'app/features/dashboard/containers/DashboardPageError'; import { DashboardPageRouteParams, DashboardPageRouteSearchParams } from 'app/features/dashboard/containers/types'; import { getDashboardSceneProfiler } from 'app/features/dashboard/services/DashboardProfiler'; +import { DashboardPreviewBanner } from 'app/features/provisioning/components/Dashboards/DashboardPreviewBanner'; import { DashboardRoutes } from 'app/types/dashboard'; import { DashboardPrompt } from '../saving/DashboardPrompt'; -import { DashboardPreviewBanner } from '../saving/provisioned/DashboardPreviewBanner'; import { preserveDashboardSceneStateInLocalStorage } from '../utils/dashboardSessionState'; import { getDashboardScenePageStateManager } from './DashboardScenePageStateManager'; diff --git a/public/app/features/dashboard-scene/saving/SaveDashboardAsForm.tsx b/public/app/features/dashboard-scene/saving/SaveDashboardAsForm.tsx index 00001fac1f8..cc437b74486 100644 --- a/public/app/features/dashboard-scene/saving/SaveDashboardAsForm.tsx +++ b/public/app/features/dashboard-scene/saving/SaveDashboardAsForm.tsx @@ -7,10 +7,10 @@ import { Trans, t } from '@grafana/i18n'; import { Button, Input, Switch, Field, Label, TextArea, Stack, Alert, Box } from '@grafana/ui'; import { FolderPicker } from 'app/core/components/Select/FolderPicker'; import { validationSrv } from 'app/features/manage-dashboards/services/ValidationSrv'; +import { getProvisionedMeta } from 'app/features/provisioning/components/utils/getProvisionedMeta'; import { DashboardScene } from '../scene/DashboardScene'; -import { getProvisionedMeta } from './provisioned/utils/getProvisionedMeta'; import { DashboardChangeInfo, NameAlreadyExistsError, SaveButton, isNameExistsError } from './shared'; import { useSaveDashboard } from './useSaveDashboard'; diff --git a/public/app/features/dashboard-scene/saving/SaveDashboardDrawer.tsx b/public/app/features/dashboard-scene/saving/SaveDashboardDrawer.tsx index 8d8e8f1fe13..10be6f94900 100644 --- a/public/app/features/dashboard-scene/saving/SaveDashboardDrawer.tsx +++ b/public/app/features/dashboard-scene/saving/SaveDashboardDrawer.tsx @@ -2,6 +2,7 @@ import { t } from '@grafana/i18n'; import { SceneComponentProps, SceneObjectBase, SceneObjectState, SceneObjectRef } from '@grafana/scenes'; import { Drawer, Tab, TabsBar } from '@grafana/ui'; import { SaveDashboardDiff } from 'app/features/dashboard/components/SaveDashboard/SaveDashboardDiff'; +import { SaveProvisionedDashboard } from 'app/features/provisioning/components/Dashboards/SaveProvisionedDashboard'; import { useIsProvisionedNG } from 'app/features/provisioning/hooks/useIsProvisionedNG'; import { DashboardScene } from '../scene/DashboardScene'; @@ -9,7 +10,6 @@ import { DashboardScene } from '../scene/DashboardScene'; import { SaveDashboardAsForm } from './SaveDashboardAsForm'; import { SaveDashboardForm } from './SaveDashboardForm'; import { SaveProvisionedDashboardForm } from './SaveProvisionedDashboardForm'; -import { SaveProvisionedDashboard } from './provisioned/SaveProvisionedDashboard'; interface SaveDashboardDrawerState extends SceneObjectState { dashboardRef: SceneObjectRef; diff --git a/public/app/features/dashboard-scene/saving/shared.tsx b/public/app/features/dashboard-scene/saving/shared.tsx index fece190d860..0eb70a1fe3b 100644 --- a/public/app/features/dashboard-scene/saving/shared.tsx +++ b/public/app/features/dashboard-scene/saving/shared.tsx @@ -6,7 +6,6 @@ import { config, isFetchError } from '@grafana/runtime'; import { Dashboard } from '@grafana/schema'; import { Spec as DashboardV2Spec } from '@grafana/schema/dist/esm/schema/dashboard/v2'; import { Alert, Box, Button, Stack } from '@grafana/ui'; -import { WorkflowOption } from 'app/features/provisioning/types'; import { Diffs } from '../settings/version-history/utils'; @@ -24,23 +23,6 @@ export interface DashboardChangeInfo { hasMigratedToV2?: boolean; } -export interface BaseProvisionedFormData { - ref?: string; - path: string; - comment?: string; - repo: string; - workflow?: WorkflowOption; - title: string; -} - -export interface ProvisionedDashboardFormData extends BaseProvisionedFormData { - description: string; - folder: { - uid?: string; - title?: string; - }; -} - export function isVersionMismatchError(error?: Error) { return isFetchError(error) && error.data && error.data.status === 'version-mismatch'; } diff --git a/public/app/features/dashboard-scene/settings/DeleteDashboardButton.tsx b/public/app/features/dashboard-scene/settings/DeleteDashboardButton.tsx index 1a902f78031..5f88d334eae 100644 --- a/public/app/features/dashboard-scene/settings/DeleteDashboardButton.tsx +++ b/public/app/features/dashboard-scene/settings/DeleteDashboardButton.tsx @@ -4,12 +4,11 @@ import { selectors } from '@grafana/e2e-selectors'; import { Trans, t } from '@grafana/i18n'; import { config, reportInteraction } from '@grafana/runtime'; import { Button, ConfirmModal, Modal, Space, Text, TextLink } from '@grafana/ui'; +import { DeleteProvisionedDashboardDrawer } from 'app/features/provisioning/components/Dashboards/DeleteProvisionedDashboardDrawer'; import { useDeleteItemsMutation } from '../../browse-dashboards/api/browseDashboardsAPI'; import { DashboardScene } from '../scene/DashboardScene'; -import { DeleteProvisionedDashboardDrawer } from './DeleteProvisionedDashboardDrawer'; - interface ButtonProps { dashboard: DashboardScene; } diff --git a/public/app/features/dashboard-scene/settings/GeneralSettingsEditView.tsx b/public/app/features/dashboard-scene/settings/GeneralSettingsEditView.tsx index ad47d202db9..aee4461f43e 100644 --- a/public/app/features/dashboard-scene/settings/GeneralSettingsEditView.tsx +++ b/public/app/features/dashboard-scene/settings/GeneralSettingsEditView.tsx @@ -23,6 +23,7 @@ import { FolderPicker } from 'app/core/components/Select/FolderPicker'; import { TimePickerSettings } from 'app/features/dashboard/components/DashboardSettings/TimePickerSettings'; import { GenAIDashDescriptionButton } from 'app/features/dashboard/components/GenAI/GenAIDashDescriptionButton'; import { GenAIDashTitleButton } from 'app/features/dashboard/components/GenAI/GenAIDashTitleButton'; +import { MoveProvisionedDashboardDrawer } from 'app/features/provisioning/components/Dashboards/MoveProvisionedDashboardDrawer'; import { updateNavModel } from '../pages/utils'; import { DashboardScene } from '../scene/DashboardScene'; @@ -31,7 +32,6 @@ import { dashboardSceneGraph } from '../utils/dashboardSceneGraph'; import { getDashboardSceneFor } from '../utils/utils'; import { DeleteDashboardButton } from './DeleteDashboardButton'; -import { MoveProvisionedDashboardDrawer } from './MoveProvisionedDashboardDrawer'; import { DashboardEditView, DashboardEditViewState, useDashboardEditPageNav } from './utils'; export interface GeneralSettingsEditViewState extends DashboardEditViewState { diff --git a/public/app/features/dashboard-scene/settings/utils.ts b/public/app/features/dashboard-scene/settings/utils.ts index 741830b8ec5..88011f08b00 100644 --- a/public/app/features/dashboard-scene/settings/utils.ts +++ b/public/app/features/dashboard-scene/settings/utils.ts @@ -111,30 +111,3 @@ export function createDashboardEditViewFor(editview: string): DashboardEditView return new GeneralSettingsEditView({}); } } - -export type ResourceBranchUrlOptions = { - baseUrl?: string; - paramName?: string; - paramValue?: string; - repoType?: string; -}; - -export function buildResourceBranchRedirectUrl({ - baseUrl = '/dashboards', - paramName, - paramValue, - repoType, -}: ResourceBranchUrlOptions): string { - const params = new URLSearchParams(); - - if (paramName && paramValue) { - params.set(paramName, paramValue); - } - - if (repoType) { - params.set('repo_type', repoType); - } - - const queryString = params.toString(); - return queryString ? `${baseUrl}?${queryString}` : baseUrl; -} diff --git a/public/app/features/browse-dashboards/components/BulkActions/BulkDeleteProvisionedResource.test.tsx b/public/app/features/provisioning/components/BulkActions/BulkDeleteProvisionedResource.test.tsx similarity index 97% rename from public/app/features/browse-dashboards/components/BulkActions/BulkDeleteProvisionedResource.test.tsx rename to public/app/features/provisioning/components/BulkActions/BulkDeleteProvisionedResource.test.tsx index 2a5be2aa309..fbcca6165e8 100644 --- a/public/app/features/browse-dashboards/components/BulkActions/BulkDeleteProvisionedResource.test.tsx +++ b/public/app/features/provisioning/components/BulkActions/BulkDeleteProvisionedResource.test.tsx @@ -3,12 +3,12 @@ import { render } from 'test/test-utils'; import { Job, RepositoryView } from 'app/api/clients/provisioning/v0alpha1'; -import { useSelectionRepoValidation } from '../BrowseActions/useSelectionRepoValidation'; +import { useSelectionRepoValidation } from '../../hooks/useSelectionRepoValidation'; import { BulkDeleteProvisionedResource } from './BulkDeleteProvisionedResource'; import { ResponseType } from './useBulkActionJob'; -jest.mock('../BrowseActions/DescendantCount', () => ({ +jest.mock('app/features/browse-dashboards/components/BrowseActions/DescendantCount', () => ({ DescendantCount: jest.fn(({ selectedItems }) => (
Mocked descendant count for {Object.keys(selectedItems.folder).length} folders and{' '} @@ -21,7 +21,7 @@ jest.mock('app/features/provisioning/hooks/useGetResourceRepositoryView', () => useGetResourceRepositoryView: jest.fn(), })); -jest.mock('../BrowseActions/useSelectionRepoValidation', () => ({ +jest.mock('../../hooks/useSelectionRepoValidation', () => ({ useSelectionRepoValidation: jest.fn(), })); diff --git a/public/app/features/browse-dashboards/components/BulkActions/BulkDeleteProvisionedResource.tsx b/public/app/features/provisioning/components/BulkActions/BulkDeleteProvisionedResource.tsx similarity index 89% rename from public/app/features/browse-dashboards/components/BulkActions/BulkDeleteProvisionedResource.tsx rename to public/app/features/provisioning/components/BulkActions/BulkDeleteProvisionedResource.tsx index 16970ee282d..96a3da40057 100644 --- a/public/app/features/browse-dashboards/components/BulkActions/BulkDeleteProvisionedResource.tsx +++ b/public/app/features/provisioning/components/BulkActions/BulkDeleteProvisionedResource.tsx @@ -6,18 +6,18 @@ import { Trans, t } from '@grafana/i18n'; import { getAppEvents } from '@grafana/runtime'; import { Box, Button, Stack } from '@grafana/ui'; import { Job, RepositoryView } from 'app/api/clients/provisioning/v0alpha1'; -import { ResourceEditFormSharedFields } from 'app/features/dashboard-scene/components/Provisioned/ResourceEditFormSharedFields'; -import { getDefaultWorkflow, getWorkflowOptions } from 'app/features/dashboard-scene/saving/provisioned/defaults'; -import { generateTimestamp } from 'app/features/dashboard-scene/saving/provisioned/utils/timestamp'; +import { DescendantCount } from 'app/features/browse-dashboards/components/BrowseActions/DescendantCount'; +import { collectSelectedItems } from 'app/features/browse-dashboards/components/utils'; import { JobStatus } from 'app/features/provisioning/Job/JobStatus'; import { useGetResourceRepositoryView } from 'app/features/provisioning/hooks/useGetResourceRepositoryView'; import { GENERAL_FOLDER_UID } from 'app/features/search/constants'; -import { DescendantCount } from '../BrowseActions/DescendantCount'; -import { useSelectionRepoValidation } from '../BrowseActions/useSelectionRepoValidation'; -import { collectSelectedItems } from '../utils'; +import { useSelectionRepoValidation } from '../../hooks/useSelectionRepoValidation'; +import { RepoInvalidStateBanner } from '../Shared/RepoInvalidStateBanner'; +import { ResourceEditFormSharedFields } from '../Shared/ResourceEditFormSharedFields'; +import { getDefaultWorkflow, getWorkflowOptions } from '../defaults'; +import { generateTimestamp } from '../utils/timestamp'; -import { RepoInvalidStateBanner } from './RepoInvalidStateBanner'; import { DeleteJobSpec, useBulkActionJob } from './useBulkActionJob'; import { BulkActionFormData, BulkActionProvisionResourceProps } from './utils'; diff --git a/public/app/features/browse-dashboards/components/BulkActions/BulkMoveProvisionedResource.tsx b/public/app/features/provisioning/components/BulkActions/BulkMoveProvisionedResource.tsx similarity index 92% rename from public/app/features/browse-dashboards/components/BulkActions/BulkMoveProvisionedResource.tsx rename to public/app/features/provisioning/components/BulkActions/BulkMoveProvisionedResource.tsx index 9133fb2f72f..0aeca36f3b9 100644 --- a/public/app/features/browse-dashboards/components/BulkActions/BulkMoveProvisionedResource.tsx +++ b/public/app/features/provisioning/components/BulkActions/BulkMoveProvisionedResource.tsx @@ -9,18 +9,18 @@ import { Box, Button, Field, Stack } from '@grafana/ui'; import { useGetFolderQuery } from 'app/api/clients/folder/v1beta1'; import { RepositoryView, Job } from 'app/api/clients/provisioning/v0alpha1'; import { AnnoKeySourcePath } from 'app/features/apiserver/types'; -import { ResourceEditFormSharedFields } from 'app/features/dashboard-scene/components/Provisioned/ResourceEditFormSharedFields'; -import { getDefaultWorkflow, getWorkflowOptions } from 'app/features/dashboard-scene/saving/provisioned/defaults'; -import { generateTimestamp } from 'app/features/dashboard-scene/saving/provisioned/utils/timestamp'; +import { DescendantCount } from 'app/features/browse-dashboards/components/BrowseActions/DescendantCount'; +import { collectSelectedItems } from 'app/features/browse-dashboards/components/utils'; import { JobStatus } from 'app/features/provisioning/Job/JobStatus'; +import { getDefaultWorkflow, getWorkflowOptions } from 'app/features/provisioning/components/defaults'; import { useGetResourceRepositoryView } from 'app/features/provisioning/hooks/useGetResourceRepositoryView'; import { GENERAL_FOLDER_UID } from 'app/features/search/constants'; -import { DescendantCount } from '../BrowseActions/DescendantCount'; -import { useSelectionRepoValidation } from '../BrowseActions/useSelectionRepoValidation'; -import { collectSelectedItems } from '../utils'; +import { useSelectionRepoValidation } from '../../hooks/useSelectionRepoValidation'; +import { RepoInvalidStateBanner } from '../Shared/RepoInvalidStateBanner'; +import { ResourceEditFormSharedFields } from '../Shared/ResourceEditFormSharedFields'; +import { generateTimestamp } from '../utils/timestamp'; -import { RepoInvalidStateBanner } from './RepoInvalidStateBanner'; import { MoveJobSpec, useBulkActionJob } from './useBulkActionJob'; import { BulkActionFormData, BulkActionProvisionResourceProps, getTargetFolderPathInRepo } from './utils'; diff --git a/public/app/features/browse-dashboards/components/BulkActions/useBulkActionJob.ts b/public/app/features/provisioning/components/BulkActions/useBulkActionJob.ts similarity index 100% rename from public/app/features/browse-dashboards/components/BulkActions/useBulkActionJob.ts rename to public/app/features/provisioning/components/BulkActions/useBulkActionJob.ts diff --git a/public/app/features/browse-dashboards/components/BulkActions/useFolderNameFromSelection.ts b/public/app/features/provisioning/components/BulkActions/useFolderNameFromSelection.ts similarity index 89% rename from public/app/features/browse-dashboards/components/BulkActions/useFolderNameFromSelection.ts rename to public/app/features/provisioning/components/BulkActions/useFolderNameFromSelection.ts index a21b74129fa..b365831882e 100644 --- a/public/app/features/browse-dashboards/components/BulkActions/useFolderNameFromSelection.ts +++ b/public/app/features/provisioning/components/BulkActions/useFolderNameFromSelection.ts @@ -2,10 +2,9 @@ import { useMemo } from 'react'; import { useSelector } from 'react-redux'; import { ManagerKind } from 'app/features/apiserver/types'; - -import { rootItemsSelector, useChildrenByParentUIDState } from '../../state/hooks'; -import { findItem } from '../../state/utils'; -import { DashboardTreeSelection } from '../../types'; +import { rootItemsSelector, useChildrenByParentUIDState } from 'app/features/browse-dashboards/state/hooks'; +import { findItem } from 'app/features/browse-dashboards/state/utils'; +import { DashboardTreeSelection } from 'app/features/browse-dashboards/types'; // This hook retrieves the folder UID from the selection state. Because search endpoint currently does not return resource metadata // NOTE: This is a temporary workaround until the search endpoint is updated diff --git a/public/app/features/browse-dashboards/components/BulkActions/utils.test.ts b/public/app/features/provisioning/components/BulkActions/utils.test.ts similarity index 100% rename from public/app/features/browse-dashboards/components/BulkActions/utils.test.ts rename to public/app/features/provisioning/components/BulkActions/utils.test.ts diff --git a/public/app/features/browse-dashboards/components/BulkActions/utils.ts b/public/app/features/provisioning/components/BulkActions/utils.ts similarity index 97% rename from public/app/features/browse-dashboards/components/BulkActions/utils.ts rename to public/app/features/provisioning/components/BulkActions/utils.ts index 01dbcf2517a..f86fef030b5 100644 --- a/public/app/features/browse-dashboards/components/BulkActions/utils.ts +++ b/public/app/features/provisioning/components/BulkActions/utils.ts @@ -1,9 +1,8 @@ import { Folder } from 'app/api/clients/folder/v1beta1'; import { AnnoKeySourcePath } from 'app/features/apiserver/types'; +import { DashboardTreeSelection } from 'app/features/browse-dashboards/types'; import { WorkflowOption } from 'app/features/provisioning/types'; -import { DashboardTreeSelection } from '../../types'; - export type BulkActionFormData = { comment: string; ref: string; diff --git a/public/app/features/dashboard-scene/saving/provisioned/DashboardPreviewBanner.tsx b/public/app/features/provisioning/components/Dashboards/DashboardPreviewBanner.tsx similarity index 97% rename from public/app/features/dashboard-scene/saving/provisioned/DashboardPreviewBanner.tsx rename to public/app/features/provisioning/components/Dashboards/DashboardPreviewBanner.tsx index e3b16d1e2bb..77df93f0f8b 100644 --- a/public/app/features/dashboard-scene/saving/provisioned/DashboardPreviewBanner.tsx +++ b/public/app/features/provisioning/components/Dashboards/DashboardPreviewBanner.tsx @@ -6,7 +6,7 @@ import { DashboardPageRouteSearchParams } from 'app/features/dashboard/container import { usePullRequestParam } from 'app/features/provisioning/hooks/usePullRequestParam'; import { DashboardRoutes } from 'app/types/dashboard'; -import { PreviewBannerViewPR } from './PreviewBannerViewPR'; +import { PreviewBannerViewPR } from '../Shared/PreviewBannerViewPR'; export interface CommonBannerProps { queryParams: DashboardPageRouteSearchParams; diff --git a/public/app/features/dashboard-scene/settings/DeleteProvisionedDashboardDrawer.tsx b/public/app/features/provisioning/components/Dashboards/DeleteProvisionedDashboardDrawer.tsx similarity index 82% rename from public/app/features/dashboard-scene/settings/DeleteProvisionedDashboardDrawer.tsx rename to public/app/features/provisioning/components/Dashboards/DeleteProvisionedDashboardDrawer.tsx index 43f02e399e4..784dc433028 100644 --- a/public/app/features/dashboard-scene/settings/DeleteProvisionedDashboardDrawer.tsx +++ b/public/app/features/provisioning/components/Dashboards/DeleteProvisionedDashboardDrawer.tsx @@ -1,5 +1,6 @@ -import { useProvisionedDashboardData } from '../saving/provisioned/hooks'; -import { DashboardScene } from '../scene/DashboardScene'; +import { DashboardScene } from 'app/features/dashboard-scene/scene/DashboardScene'; + +import { useProvisionedDashboardData } from '../../hooks/useProvisionedDashboardData'; import { DeleteProvisionedDashboardForm } from './DeleteProvisionedDashboardForm'; diff --git a/public/app/features/dashboard-scene/settings/DeleteProvisionedDashboardForm.test.tsx b/public/app/features/provisioning/components/Dashboards/DeleteProvisionedDashboardForm.test.tsx similarity index 92% rename from public/app/features/dashboard-scene/settings/DeleteProvisionedDashboardForm.test.tsx rename to public/app/features/provisioning/components/Dashboards/DeleteProvisionedDashboardForm.test.tsx index b8a87e27bda..7eb0409ded7 100644 --- a/public/app/features/dashboard-scene/settings/DeleteProvisionedDashboardForm.test.tsx +++ b/public/app/features/provisioning/components/Dashboards/DeleteProvisionedDashboardForm.test.tsx @@ -4,13 +4,16 @@ import userEvent from '@testing-library/user-event'; import { AppEvents } from '@grafana/data'; import { getAppEvents } from '@grafana/runtime'; import { useDeleteRepositoryFilesWithPathMutation } from 'app/api/clients/provisioning/v0alpha1'; +import { DashboardScene } from 'app/features/dashboard-scene/scene/DashboardScene'; -import { useProvisionedDashboardData, ProvisionedDashboardData } from '../saving/provisioned/hooks'; -import { DashboardScene } from '../scene/DashboardScene'; +import { ProvisionedDashboardData, useProvisionedDashboardData } from '../../hooks/useProvisionedDashboardData'; import { DeleteProvisionedDashboardDrawer, Props } from './DeleteProvisionedDashboardDrawer'; -// Mock the hooks and dependencies +jest.mock('../../hooks/useProvisionedDashboardData', () => ({ + useProvisionedDashboardData: jest.fn(), +})); + jest.mock('app/api/clients/provisioning/v0alpha1', () => ({ useDeleteRepositoryFilesWithPathMutation: jest.fn(), provisioningAPIv0alpha1: { @@ -28,7 +31,13 @@ jest.mock('react-redux', () => { useDispatch: jest.fn(), }; }); -jest.mock('../saving/provisioned/hooks'); +jest.mock('../../hooks/useProvisionedRequestHandler', () => ({ + useProvisionedRequestHandler: jest.fn(({ request, handlers }) => { + if (request.isError && handlers.onError) { + handlers.onError(request.error, { repoType: 'github', resourceType: 'dashboard', workflow: 'branch' }); + } + }), +})); jest.mock('@grafana/runtime', () => ({ ...jest.requireActual('@grafana/runtime'), getAppEvents: jest.fn(), @@ -41,7 +50,7 @@ jest.mock('react-router-dom-v5-compat', () => ({ const mockNavigate = jest.fn(); // Mock shared form components -jest.mock('../components/Provisioned/ResourceEditFormSharedFields', () => ({ +jest.mock('../Shared/ResourceEditFormSharedFields', () => ({ ResourceEditFormSharedFields: ({ disabled }: { disabled: boolean }) => (