diff --git a/.betterer.results b/.betterer.results
index cb4405c350e..47b5fb03d2b 100644
--- a/.betterer.results
+++ b/.betterer.results
@@ -3388,6 +3388,13 @@ exports[`better eslint`] = {
[0, 0, 0, "No untranslated strings. Wrap text with ", "3"],
[0, 0, 0, "No untranslated strings. Wrap text with ", "4"]
],
+ "public/app/features/dashboard-scene/saving/provisioned/ProvisionedResourceDeleteModal.tsx:5381": [
+ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
+ [0, 0, 0, "No untranslated strings. Wrap text with ", "1"],
+ [0, 0, 0, "No untranslated strings. Wrap text with ", "2"],
+ [0, 0, 0, "No untranslated strings. Wrap text with ", "3"],
+ [0, 0, 0, "No untranslated strings. Wrap text with ", "4"]
+ ],
"public/app/features/dashboard-scene/saving/provisioned/SaveProvisionedDashboard.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"],
diff --git a/public/app/features/browse-dashboards/api/browseDashboardsAPI.ts b/public/app/features/browse-dashboards/api/browseDashboardsAPI.ts
index 3e3aa805a52..9448c5b97ff 100644
--- a/public/app/features/browse-dashboards/api/browseDashboardsAPI.ts
+++ b/public/app/features/browse-dashboards/api/browseDashboardsAPI.ts
@@ -442,7 +442,7 @@ export const {
export { skipToken } from '@reduxjs/toolkit/query/react';
-type FolderDataType = FolderListItemDTO | NestedFolderDTO | FolderDTO;
+export type FolderDataType = FolderListItemDTO | NestedFolderDTO | FolderDTO;
// Overloaded function signatures to handle different input types
export async function addRepositoryData(data: FolderListItemDTO[]): Promise;
@@ -465,7 +465,12 @@ export async function addRepositoryData(
}
const addRepositoryToItem = (item: FolderDataType) => {
- const repository = settings.items.find((repo) => repo.name === item.uid);
+ const repository = settings.items.find((repo) => {
+ if (typeof item.repository === 'string') {
+ return repo.name === item.repository;
+ }
+ return repo.name === item.uid;
+ });
return repository ? { ...item, repository } : item;
};
diff --git a/public/app/features/browse-dashboards/components/FolderActionsButton.tsx b/public/app/features/browse-dashboards/components/FolderActionsButton.tsx
index 1c4f3984d86..88ef8c79f0e 100644
--- a/public/app/features/browse-dashboards/components/FolderActionsButton.tsx
+++ b/public/app/features/browse-dashboards/components/FolderActionsButton.tsx
@@ -8,6 +8,7 @@ import { t, Trans } from 'app/core/internationalization';
import { FolderDTO } from 'app/types';
import { ShowModalReactEvent } from 'app/types/events';
+import { ProvisionedResourceDeleteModal } from '../../dashboard-scene/saving/provisioned/ProvisionedResourceDeleteModal';
import { useDeleteFolderMutation, useMoveFolderMutation } from '../api/browseDashboardsAPI';
import { getFolderPermissions } from '../permissions';
@@ -25,7 +26,7 @@ export function FolderActionsButton({ folder }: Props) {
const [deleteFolder] = useDeleteFolderMutation();
const { canEditFolders, canDeleteFolders, canViewPermissions, canSetPermissions } = getFolderPermissions(folder);
// Can only move folders when nestedFolders is enabled
- const canMoveFolder = config.featureToggles.nestedFolders && canEditFolders;
+ const canMoveFolder = config.featureToggles.nestedFolders && canEditFolders && !folder.repository;
const onMove = async (destinationUID: string) => {
await moveFolder({ folder, destinationUID });
@@ -86,6 +87,17 @@ export function FolderActionsButton({ folder }: Props) {
);
};
+ const showDeleteProvisionedModal = () => {
+ appEvents.publish(
+ new ShowModalReactEvent({
+ component: ProvisionedResourceDeleteModal,
+ props: {
+ resource: folder,
+ },
+ })
+ );
+ };
+
const managePermissionsLabel = t('browse-dashboards.folder-actions-button.manage-permissions', 'Manage permissions');
const moveLabel = t('browse-dashboards.folder-actions-button.move', 'Move');
const deleteLabel = t('browse-dashboards.folder-actions-button.delete', 'Delete');
@@ -94,7 +106,13 @@ export function FolderActionsButton({ folder }: Props) {
);
diff --git a/public/app/features/dashboard-scene/saving/provisioned/ProvisionedResourceDeleteModal.tsx b/public/app/features/dashboard-scene/saving/provisioned/ProvisionedResourceDeleteModal.tsx
new file mode 100644
index 00000000000..d797d0fd6b9
--- /dev/null
+++ b/public/app/features/dashboard-scene/saving/provisioned/ProvisionedResourceDeleteModal.tsx
@@ -0,0 +1,38 @@
+import { Button, Modal } from '@grafana/ui';
+
+import { FolderDataType } from '../../../browse-dashboards/api/browseDashboardsAPI';
+import { DashboardScene } from '../../scene/DashboardScene';
+
+export interface Props {
+ onDismiss: () => void;
+ resource: DashboardScene | FolderDataType;
+}
+
+export function ProvisionedResourceDeleteModal({ onDismiss, resource }: Props) {
+ const type = isDashboard(resource) ? 'dashboard' : 'folder';
+ return (
+
+ <>
+
+ This {type} is managed by version control and cannot be deleted. To remove it, delete it from the repository
+ and synchronise to apply the changes.
+