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:
Josh Hunt 2022-03-24 09:43:25 +00:00 committed by GitHub
parent 987afeee38
commit 89757cf58f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 244 additions and 44 deletions

View File

@ -2,7 +2,6 @@ import React, { FC } from 'react';
import { css } from '@emotion/css';
import { GrafanaTheme } from '@grafana/data';
import { ConfirmModal, stylesFactory, useTheme } from '@grafana/ui';
import { locationService } from '@grafana/runtime';
import { DashboardSection, OnDeleteItems } from '../types';
import { getCheckedUids } from '../utils';
import { deleteFoldersAndDashboards } from 'app/features/manage-dashboards/state/actions';
@ -40,8 +39,6 @@ export const ConfirmDeleteModal: FC<Props> = ({ results, onDeleteItems, isOpen,
const deleteItems = () => {
deleteFoldersAndDashboards(folders, dashboards).then(() => {
onDismiss();
// Redirect to /dashboard in case folder was deleted from f/:folder.uid
locationService.push('/dashboards');
onDeleteItems(folders, dashboards);
});
};

View File

@ -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 = {
id: 0,
@ -52,61 +79,62 @@ export const searchResults: DashboardSection[] = [
];
// Search results with more info
export const sections = [
{
export const sections: DashboardSection[] = [
makeSection({
title: 'Starred',
score: -2,
expanded: true,
items: [
{
makeSectionItem({
id: 1,
uid: 'lBdLINUWk',
title: 'Prom dash',
type: DashboardSearchItemType.DashDB,
},
}),
],
},
{
}),
makeSection({
title: 'Recent',
icon: 'clock-o',
score: -1,
removable: true,
expanded: false,
items: [
{
makeSectionItem({
id: 4072,
uid: 'OzAIf_rWz',
title: 'New dashboard Copy 3',
type: DashboardSearchItemType.DashDB,
isStarred: false,
},
{
}),
makeSectionItem({
id: 46,
uid: '8DY63kQZk',
title: 'Stocks',
type: DashboardSearchItemType.DashDB,
isStarred: false,
},
{
}),
makeSectionItem({
id: 20,
uid: '7MeksYbmk',
title: 'Alerting with TestData',
type: DashboardSearchItemType.DashDB,
isStarred: false,
folderId: 2,
},
{
}),
makeSectionItem({
id: 4073,
uid: 'j9SHflrWk',
title: 'New dashboard Copy 4',
type: DashboardSearchItemType.DashDB,
isStarred: false,
folderId: 2,
},
}),
],
},
{
}),
makeSection({
id: 2,
uid: 'JB_zdOUWk',
title: 'gdev dashboards',
@ -115,8 +143,9 @@ export const sections = [
icon: 'folder',
score: 2,
items: [],
},
{
}),
makeSection({
id: 2568,
uid: 'search-test-data',
title: 'Search test data folder',
@ -125,8 +154,9 @@ export const sections = [
url: '/dashboards/f/search-test-data/search-test-data-folder',
icon: 'folder',
score: 3,
},
{
}),
makeSection({
id: 4074,
uid: 'iN5TFj9Zk',
title: 'Test',
@ -135,38 +165,197 @@ export const sections = [
url: '/dashboards/f/iN5TFj9Zk/test',
icon: 'folder',
score: 4,
},
{
}),
makeSection({
id: 0,
title: 'General',
icon: 'folder-open',
score: 5,
expanded: true,
items: [
{
makeSectionItem({
id: 4069,
uid: 'LCFWfl9Zz',
title: 'New dashboard Copy',
uri: 'db/new-dashboard-copy',
url: '/d/LCFWfl9Zz/new-dashboard-copy',
slug: '',
type: DashboardSearchItemType.DashDB,
isStarred: false,
},
{
}),
makeSectionItem({
id: 4072,
uid: 'OzAIf_rWz',
title: 'New dashboard Copy 3',
type: DashboardSearchItemType.DashDB,
isStarred: false,
},
{
}),
makeSectionItem({
id: 1,
uid: 'lBdLINUWk',
title: 'Prom dash',
type: DashboardSearchItemType.DashDB,
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,
}),
],
}),
];

View File

@ -7,7 +7,7 @@ import {
mergeReducers,
parseRouteParams,
} from './utils';
import { sections, searchResults } from './testData';
import { sections, searchResults, checkedGeneralFolder, checkedOtherFolder, folderViewAllChecked } from './testData';
import { SearchQueryParams } from './types';
describe('Search utils', () => {
@ -131,21 +131,35 @@ describe('Search utils', () => {
});
describe('getCheckedUids', () => {
it('should return object with empty arrays if no checked items are available', () => {
expect(getCheckedUids(sections as any[])).toEqual({ folders: [], dashboards: [] });
it('should not return any UIDs if no items are checked', () => {
expect(getCheckedUids(sections)).toEqual({ folders: [], dashboards: [] });
});
it('should return uids for all checked items', () => {
expect(getCheckedUids(searchResults as any[])).toEqual({
folders: ['JB_zdOUWk'],
dashboards: ['lBdLINUWk', '8DY63kQZk'],
it('should return only dashboard UIDs if the General folder is checked', () => {
expect(getCheckedUids(checkedGeneralFolder)).toEqual({
folders: [],
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', () => {
it('should get uids of all checked dashboards', () => {
expect(getCheckedDashboardsUids(searchResults as any[])).toEqual(['lBdLINUWk', '8DY63kQZk']);
expect(getCheckedDashboardsUids(searchResults)).toEqual(['lBdLINUWk', '8DY63kQZk']);
});
});

View File

@ -165,7 +165,7 @@ export const getCheckedUids = (sections: DashboardSection[]): UidsToDelete => {
}
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;
} else {
return { ...result, dashboards: getCheckedDashboardsUids(sections) } as UidsToDelete;