mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
ManageDashboards: Fix error when deleting all dashboards from folder view (#46877)
* user essentials mob! 🔱
* draft tests
* tests!
* better default ids for test data
This commit is contained in:
parent
987afeee38
commit
89757cf58f
@ -2,7 +2,6 @@ import React, { FC } from 'react';
|
|||||||
import { css } from '@emotion/css';
|
import { css } from '@emotion/css';
|
||||||
import { GrafanaTheme } from '@grafana/data';
|
import { GrafanaTheme } from '@grafana/data';
|
||||||
import { ConfirmModal, stylesFactory, useTheme } from '@grafana/ui';
|
import { ConfirmModal, stylesFactory, useTheme } from '@grafana/ui';
|
||||||
import { locationService } from '@grafana/runtime';
|
|
||||||
import { DashboardSection, OnDeleteItems } from '../types';
|
import { DashboardSection, OnDeleteItems } from '../types';
|
||||||
import { getCheckedUids } from '../utils';
|
import { getCheckedUids } from '../utils';
|
||||||
import { deleteFoldersAndDashboards } from 'app/features/manage-dashboards/state/actions';
|
import { deleteFoldersAndDashboards } from 'app/features/manage-dashboards/state/actions';
|
||||||
@ -40,8 +39,6 @@ export const ConfirmDeleteModal: FC<Props> = ({ results, onDeleteItems, isOpen,
|
|||||||
const deleteItems = () => {
|
const deleteItems = () => {
|
||||||
deleteFoldersAndDashboards(folders, dashboards).then(() => {
|
deleteFoldersAndDashboards(folders, dashboards).then(() => {
|
||||||
onDismiss();
|
onDismiss();
|
||||||
// Redirect to /dashboard in case folder was deleted from f/:folder.uid
|
|
||||||
locationService.push('/dashboards');
|
|
||||||
onDeleteItems(folders, dashboards);
|
onDeleteItems(folders, dashboards);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,31 @@
|
|||||||
import { DashboardSearchItemType, DashboardSection } from './types';
|
import { DashboardSearchItemType, DashboardSection, DashboardSectionItem } from './types';
|
||||||
|
|
||||||
|
function makeSection(sectionPartial: Partial<DashboardSection>): DashboardSection {
|
||||||
|
return {
|
||||||
|
title: 'Default title',
|
||||||
|
id: Number.MAX_SAFE_INTEGER - 1,
|
||||||
|
score: -99,
|
||||||
|
expanded: true,
|
||||||
|
type: DashboardSearchItemType.DashFolder,
|
||||||
|
items: [],
|
||||||
|
url: '/default-url',
|
||||||
|
...sectionPartial,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const makeSectionItem = (itemPartial: Partial<DashboardSectionItem>): DashboardSectionItem => {
|
||||||
|
return {
|
||||||
|
id: Number.MAX_SAFE_INTEGER - 2,
|
||||||
|
uid: 'default-uid',
|
||||||
|
title: 'Default dashboard title',
|
||||||
|
type: DashboardSearchItemType.DashDB,
|
||||||
|
isStarred: false,
|
||||||
|
tags: [],
|
||||||
|
uri: 'db/default-slug',
|
||||||
|
url: '/d/default-uid/default-slug',
|
||||||
|
...itemPartial,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export const generalFolder: DashboardSection = {
|
export const generalFolder: DashboardSection = {
|
||||||
id: 0,
|
id: 0,
|
||||||
@ -52,61 +79,62 @@ export const searchResults: DashboardSection[] = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
// Search results with more info
|
// Search results with more info
|
||||||
export const sections = [
|
export const sections: DashboardSection[] = [
|
||||||
{
|
makeSection({
|
||||||
title: 'Starred',
|
title: 'Starred',
|
||||||
score: -2,
|
score: -2,
|
||||||
expanded: true,
|
expanded: true,
|
||||||
items: [
|
items: [
|
||||||
{
|
makeSectionItem({
|
||||||
id: 1,
|
id: 1,
|
||||||
uid: 'lBdLINUWk',
|
uid: 'lBdLINUWk',
|
||||||
title: 'Prom dash',
|
title: 'Prom dash',
|
||||||
type: DashboardSearchItemType.DashDB,
|
type: DashboardSearchItemType.DashDB,
|
||||||
},
|
}),
|
||||||
],
|
],
|
||||||
},
|
}),
|
||||||
{
|
|
||||||
|
makeSection({
|
||||||
title: 'Recent',
|
title: 'Recent',
|
||||||
icon: 'clock-o',
|
icon: 'clock-o',
|
||||||
score: -1,
|
score: -1,
|
||||||
removable: true,
|
|
||||||
expanded: false,
|
expanded: false,
|
||||||
items: [
|
items: [
|
||||||
{
|
makeSectionItem({
|
||||||
id: 4072,
|
id: 4072,
|
||||||
uid: 'OzAIf_rWz',
|
uid: 'OzAIf_rWz',
|
||||||
title: 'New dashboard Copy 3',
|
title: 'New dashboard Copy 3',
|
||||||
|
|
||||||
type: DashboardSearchItemType.DashDB,
|
type: DashboardSearchItemType.DashDB,
|
||||||
isStarred: false,
|
isStarred: false,
|
||||||
},
|
}),
|
||||||
{
|
makeSectionItem({
|
||||||
id: 46,
|
id: 46,
|
||||||
uid: '8DY63kQZk',
|
uid: '8DY63kQZk',
|
||||||
title: 'Stocks',
|
title: 'Stocks',
|
||||||
type: DashboardSearchItemType.DashDB,
|
type: DashboardSearchItemType.DashDB,
|
||||||
isStarred: false,
|
isStarred: false,
|
||||||
},
|
}),
|
||||||
{
|
makeSectionItem({
|
||||||
id: 20,
|
id: 20,
|
||||||
uid: '7MeksYbmk',
|
uid: '7MeksYbmk',
|
||||||
title: 'Alerting with TestData',
|
title: 'Alerting with TestData',
|
||||||
type: DashboardSearchItemType.DashDB,
|
type: DashboardSearchItemType.DashDB,
|
||||||
isStarred: false,
|
isStarred: false,
|
||||||
folderId: 2,
|
folderId: 2,
|
||||||
},
|
}),
|
||||||
{
|
makeSectionItem({
|
||||||
id: 4073,
|
id: 4073,
|
||||||
uid: 'j9SHflrWk',
|
uid: 'j9SHflrWk',
|
||||||
title: 'New dashboard Copy 4',
|
title: 'New dashboard Copy 4',
|
||||||
type: DashboardSearchItemType.DashDB,
|
type: DashboardSearchItemType.DashDB,
|
||||||
isStarred: false,
|
isStarred: false,
|
||||||
folderId: 2,
|
folderId: 2,
|
||||||
},
|
}),
|
||||||
],
|
],
|
||||||
},
|
}),
|
||||||
{
|
|
||||||
|
makeSection({
|
||||||
id: 2,
|
id: 2,
|
||||||
uid: 'JB_zdOUWk',
|
uid: 'JB_zdOUWk',
|
||||||
title: 'gdev dashboards',
|
title: 'gdev dashboards',
|
||||||
@ -115,8 +143,9 @@ export const sections = [
|
|||||||
icon: 'folder',
|
icon: 'folder',
|
||||||
score: 2,
|
score: 2,
|
||||||
items: [],
|
items: [],
|
||||||
},
|
}),
|
||||||
{
|
|
||||||
|
makeSection({
|
||||||
id: 2568,
|
id: 2568,
|
||||||
uid: 'search-test-data',
|
uid: 'search-test-data',
|
||||||
title: 'Search test data folder',
|
title: 'Search test data folder',
|
||||||
@ -125,8 +154,9 @@ export const sections = [
|
|||||||
url: '/dashboards/f/search-test-data/search-test-data-folder',
|
url: '/dashboards/f/search-test-data/search-test-data-folder',
|
||||||
icon: 'folder',
|
icon: 'folder',
|
||||||
score: 3,
|
score: 3,
|
||||||
},
|
}),
|
||||||
{
|
|
||||||
|
makeSection({
|
||||||
id: 4074,
|
id: 4074,
|
||||||
uid: 'iN5TFj9Zk',
|
uid: 'iN5TFj9Zk',
|
||||||
title: 'Test',
|
title: 'Test',
|
||||||
@ -135,38 +165,197 @@ export const sections = [
|
|||||||
url: '/dashboards/f/iN5TFj9Zk/test',
|
url: '/dashboards/f/iN5TFj9Zk/test',
|
||||||
icon: 'folder',
|
icon: 'folder',
|
||||||
score: 4,
|
score: 4,
|
||||||
},
|
}),
|
||||||
{
|
|
||||||
|
makeSection({
|
||||||
id: 0,
|
id: 0,
|
||||||
title: 'General',
|
title: 'General',
|
||||||
icon: 'folder-open',
|
icon: 'folder-open',
|
||||||
score: 5,
|
score: 5,
|
||||||
expanded: true,
|
expanded: true,
|
||||||
items: [
|
items: [
|
||||||
{
|
makeSectionItem({
|
||||||
id: 4069,
|
id: 4069,
|
||||||
uid: 'LCFWfl9Zz',
|
uid: 'LCFWfl9Zz',
|
||||||
title: 'New dashboard Copy',
|
title: 'New dashboard Copy',
|
||||||
uri: 'db/new-dashboard-copy',
|
uri: 'db/new-dashboard-copy',
|
||||||
url: '/d/LCFWfl9Zz/new-dashboard-copy',
|
url: '/d/LCFWfl9Zz/new-dashboard-copy',
|
||||||
slug: '',
|
|
||||||
type: DashboardSearchItemType.DashDB,
|
type: DashboardSearchItemType.DashDB,
|
||||||
isStarred: false,
|
isStarred: false,
|
||||||
},
|
}),
|
||||||
{
|
makeSectionItem({
|
||||||
id: 4072,
|
id: 4072,
|
||||||
uid: 'OzAIf_rWz',
|
uid: 'OzAIf_rWz',
|
||||||
title: 'New dashboard Copy 3',
|
title: 'New dashboard Copy 3',
|
||||||
type: DashboardSearchItemType.DashDB,
|
type: DashboardSearchItemType.DashDB,
|
||||||
isStarred: false,
|
isStarred: false,
|
||||||
},
|
}),
|
||||||
{
|
makeSectionItem({
|
||||||
id: 1,
|
id: 1,
|
||||||
uid: 'lBdLINUWk',
|
uid: 'lBdLINUWk',
|
||||||
title: 'Prom dash',
|
title: 'Prom dash',
|
||||||
type: DashboardSearchItemType.DashDB,
|
type: DashboardSearchItemType.DashDB,
|
||||||
isStarred: true,
|
isStarred: true,
|
||||||
},
|
}),
|
||||||
],
|
],
|
||||||
},
|
}),
|
||||||
|
];
|
||||||
|
|
||||||
|
export const checkedGeneralFolder: DashboardSection[] = [
|
||||||
|
makeSection({
|
||||||
|
id: 4074,
|
||||||
|
uid: 'other-folder-dash',
|
||||||
|
title: 'Test',
|
||||||
|
expanded: false,
|
||||||
|
type: DashboardSearchItemType.DashFolder,
|
||||||
|
items: [
|
||||||
|
makeSectionItem({
|
||||||
|
id: 4072,
|
||||||
|
uid: 'other-folder-dash-abc',
|
||||||
|
title: 'New dashboard Copy 3',
|
||||||
|
type: DashboardSearchItemType.DashDB,
|
||||||
|
isStarred: false,
|
||||||
|
}),
|
||||||
|
makeSectionItem({
|
||||||
|
id: 46,
|
||||||
|
uid: 'other-folder-dash-def',
|
||||||
|
title: 'Stocks',
|
||||||
|
type: DashboardSearchItemType.DashDB,
|
||||||
|
isStarred: false,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
url: '/dashboards/f/iN5TFj9Zk/test',
|
||||||
|
icon: 'folder',
|
||||||
|
score: 4,
|
||||||
|
}),
|
||||||
|
|
||||||
|
makeSection({
|
||||||
|
id: 0,
|
||||||
|
title: 'General',
|
||||||
|
uid: 'other-folder-abc',
|
||||||
|
score: 5,
|
||||||
|
expanded: true,
|
||||||
|
checked: true,
|
||||||
|
type: DashboardSearchItemType.DashFolder,
|
||||||
|
items: [
|
||||||
|
makeSectionItem({
|
||||||
|
id: 4069,
|
||||||
|
uid: 'general-abc',
|
||||||
|
title: 'New dashboard Copy',
|
||||||
|
uri: 'db/new-dashboard-copy',
|
||||||
|
url: '/d/LCFWfl9Zz/new-dashboard-copy',
|
||||||
|
type: DashboardSearchItemType.DashDB,
|
||||||
|
isStarred: false,
|
||||||
|
checked: true,
|
||||||
|
}),
|
||||||
|
makeSectionItem({
|
||||||
|
id: 4072,
|
||||||
|
uid: 'general-def',
|
||||||
|
title: 'New dashboard Copy 3',
|
||||||
|
type: DashboardSearchItemType.DashDB,
|
||||||
|
isStarred: false,
|
||||||
|
checked: true,
|
||||||
|
}),
|
||||||
|
makeSectionItem({
|
||||||
|
id: 1,
|
||||||
|
uid: 'general-ghi',
|
||||||
|
title: 'Prom dash',
|
||||||
|
type: DashboardSearchItemType.DashDB,
|
||||||
|
isStarred: true,
|
||||||
|
checked: true,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
|
||||||
|
export const checkedOtherFolder: DashboardSection[] = [
|
||||||
|
makeSection({
|
||||||
|
id: 4074,
|
||||||
|
uid: 'other-folder-abc',
|
||||||
|
title: 'Test',
|
||||||
|
expanded: false,
|
||||||
|
checked: true,
|
||||||
|
type: DashboardSearchItemType.DashFolder,
|
||||||
|
items: [
|
||||||
|
makeSectionItem({
|
||||||
|
id: 4072,
|
||||||
|
uid: 'other-folder-dash-abc',
|
||||||
|
title: 'New dashboard Copy 3',
|
||||||
|
type: DashboardSearchItemType.DashDB,
|
||||||
|
isStarred: false,
|
||||||
|
checked: true,
|
||||||
|
}),
|
||||||
|
makeSectionItem({
|
||||||
|
id: 46,
|
||||||
|
uid: 'other-folder-dash-def',
|
||||||
|
title: 'Stocks',
|
||||||
|
type: DashboardSearchItemType.DashDB,
|
||||||
|
isStarred: false,
|
||||||
|
checked: true,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
url: '/dashboards/f/iN5TFj9Zk/test',
|
||||||
|
icon: 'folder',
|
||||||
|
score: 4,
|
||||||
|
}),
|
||||||
|
|
||||||
|
makeSection({
|
||||||
|
id: 0,
|
||||||
|
title: 'General',
|
||||||
|
icon: 'folder-open',
|
||||||
|
score: 5,
|
||||||
|
expanded: true,
|
||||||
|
type: DashboardSearchItemType.DashFolder,
|
||||||
|
items: [
|
||||||
|
makeSectionItem({
|
||||||
|
id: 4069,
|
||||||
|
uid: 'general-abc',
|
||||||
|
title: 'New dashboard Copy',
|
||||||
|
uri: 'db/new-dashboard-copy',
|
||||||
|
url: '/d/LCFWfl9Zz/new-dashboard-copy',
|
||||||
|
type: DashboardSearchItemType.DashDB,
|
||||||
|
isStarred: false,
|
||||||
|
}),
|
||||||
|
makeSectionItem({
|
||||||
|
id: 4072,
|
||||||
|
uid: 'general-def',
|
||||||
|
title: 'New dashboard Copy 3',
|
||||||
|
type: DashboardSearchItemType.DashDB,
|
||||||
|
isStarred: false,
|
||||||
|
}),
|
||||||
|
makeSectionItem({
|
||||||
|
id: 1,
|
||||||
|
uid: 'general-ghi',
|
||||||
|
title: 'Prom dash',
|
||||||
|
type: DashboardSearchItemType.DashDB,
|
||||||
|
isStarred: true,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
|
||||||
|
export const folderViewAllChecked: DashboardSection[] = [
|
||||||
|
makeSection({
|
||||||
|
checked: true,
|
||||||
|
selected: true,
|
||||||
|
title: '',
|
||||||
|
items: [
|
||||||
|
makeSectionItem({
|
||||||
|
id: 4072,
|
||||||
|
uid: 'other-folder-dash-abc',
|
||||||
|
title: 'New dashboard Copy 3',
|
||||||
|
type: DashboardSearchItemType.DashDB,
|
||||||
|
isStarred: false,
|
||||||
|
checked: true,
|
||||||
|
}),
|
||||||
|
makeSectionItem({
|
||||||
|
id: 46,
|
||||||
|
uid: 'other-folder-dash-def',
|
||||||
|
title: 'Stocks',
|
||||||
|
type: DashboardSearchItemType.DashDB,
|
||||||
|
isStarred: false,
|
||||||
|
checked: true,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
];
|
];
|
||||||
|
@ -7,7 +7,7 @@ import {
|
|||||||
mergeReducers,
|
mergeReducers,
|
||||||
parseRouteParams,
|
parseRouteParams,
|
||||||
} from './utils';
|
} from './utils';
|
||||||
import { sections, searchResults } from './testData';
|
import { sections, searchResults, checkedGeneralFolder, checkedOtherFolder, folderViewAllChecked } from './testData';
|
||||||
import { SearchQueryParams } from './types';
|
import { SearchQueryParams } from './types';
|
||||||
|
|
||||||
describe('Search utils', () => {
|
describe('Search utils', () => {
|
||||||
@ -131,21 +131,35 @@ describe('Search utils', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('getCheckedUids', () => {
|
describe('getCheckedUids', () => {
|
||||||
it('should return object with empty arrays if no checked items are available', () => {
|
it('should not return any UIDs if no items are checked', () => {
|
||||||
expect(getCheckedUids(sections as any[])).toEqual({ folders: [], dashboards: [] });
|
expect(getCheckedUids(sections)).toEqual({ folders: [], dashboards: [] });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return uids for all checked items', () => {
|
it('should return only dashboard UIDs if the General folder is checked', () => {
|
||||||
expect(getCheckedUids(searchResults as any[])).toEqual({
|
expect(getCheckedUids(checkedGeneralFolder)).toEqual({
|
||||||
folders: ['JB_zdOUWk'],
|
folders: [],
|
||||||
dashboards: ['lBdLINUWk', '8DY63kQZk'],
|
dashboards: ['general-abc', 'general-def', 'general-ghi'],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return only dashboard UIDs if all items are checked when viewing a folder', () => {
|
||||||
|
expect(getCheckedUids(folderViewAllChecked)).toEqual({
|
||||||
|
folders: [],
|
||||||
|
dashboards: ['other-folder-dash-abc', 'other-folder-dash-def'],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return folder + dashboard UIDs when folder is checked in the root view', () => {
|
||||||
|
expect(getCheckedUids(checkedOtherFolder)).toEqual({
|
||||||
|
folders: ['other-folder-abc'],
|
||||||
|
dashboards: ['other-folder-dash-abc', 'other-folder-dash-def'],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('getCheckedDashboardsUids', () => {
|
describe('getCheckedDashboardsUids', () => {
|
||||||
it('should get uids of all checked dashboards', () => {
|
it('should get uids of all checked dashboards', () => {
|
||||||
expect(getCheckedDashboardsUids(searchResults as any[])).toEqual(['lBdLINUWk', '8DY63kQZk']);
|
expect(getCheckedDashboardsUids(searchResults)).toEqual(['lBdLINUWk', '8DY63kQZk']);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -165,7 +165,7 @@ export const getCheckedUids = (sections: DashboardSection[]): UidsToDelete => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return sections.reduce((result, section) => {
|
return sections.reduce((result, section) => {
|
||||||
if (section?.id !== 0 && section.checked) {
|
if (section?.id !== 0 && section.checked && section.uid) {
|
||||||
return { ...result, folders: [...result.folders, section.uid] } as UidsToDelete;
|
return { ...result, folders: [...result.folders, section.uid] } as UidsToDelete;
|
||||||
} else {
|
} else {
|
||||||
return { ...result, dashboards: getCheckedDashboardsUids(sections) } as UidsToDelete;
|
return { ...result, dashboards: getCheckedDashboardsUids(sections) } as UidsToDelete;
|
||||||
|
Loading…
Reference in New Issue
Block a user