mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Dashboards: Allow dashboards with same name in different folders (#70378)
* Dashboards: Allow dashboards with same name in different folders Co-authored-by: Tobias Skarhed <tobias.skarhed@gmail.com> Co-authored-by: Ashley Harrison <ashley.harrison@grafana.com> Co-authored-by: joshhunt <josh@trtr.co> * fix --------- Co-authored-by: Tobias Skarhed <tobias.skarhed@gmail.com> Co-authored-by: Ashley Harrison <ashley.harrison@grafana.com>
This commit is contained in:
parent
9e0f6ceb57
commit
e50cf55649
@ -2710,11 +2710,6 @@ exports[`better eslint`] = {
|
|||||||
"public/app/features/manage-dashboards/components/ImportDashboardLibraryPanelsList.tsx:5381": [
|
"public/app/features/manage-dashboards/components/ImportDashboardLibraryPanelsList.tsx:5381": [
|
||||||
[0, 0, 0, "Do not use any type assertions.", "0"]
|
[0, 0, 0, "Do not use any type assertions.", "0"]
|
||||||
],
|
],
|
||||||
"public/app/features/manage-dashboards/services/ValidationSrv.ts:5381": [
|
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
|
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "2"]
|
|
||||||
],
|
|
||||||
"public/app/features/manage-dashboards/state/actions.test.ts:5381": [
|
"public/app/features/manage-dashboards/state/actions.test.ts:5381": [
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
|
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
|
||||||
],
|
],
|
||||||
|
@ -52,8 +52,9 @@ export const SaveDashboardAsForm = ({ dashboard, isNew, onSubmit, onCancel, onSu
|
|||||||
if (dashboardName && dashboardName === getFormValues().$folder.title?.trim()) {
|
if (dashboardName && dashboardName === getFormValues().$folder.title?.trim()) {
|
||||||
return 'Dashboard name cannot be the same as folder name';
|
return 'Dashboard name cannot be the same as folder name';
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await validationSrv.validateNewDashboardName(getFormValues().$folder.uid, dashboardName);
|
await validationSrv.validateNewDashboardName(getFormValues().$folder.uid ?? 'general', dashboardName);
|
||||||
return true;
|
return true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return e instanceof Error ? e.message : 'Dashboard name is invalid';
|
return e instanceof Error ? e.message : 'Dashboard name is invalid';
|
||||||
|
@ -1,9 +1,4 @@
|
|||||||
import { backendSrv } from 'app/core/services/backend_srv';
|
import { getGrafanaSearcher } from 'app/features/search/service';
|
||||||
|
|
||||||
const hitTypes = {
|
|
||||||
FOLDER: 'dash-folder',
|
|
||||||
DASHBOARD: 'dash-db',
|
|
||||||
};
|
|
||||||
|
|
||||||
class ValidationError extends Error {
|
class ValidationError extends Error {
|
||||||
type: string;
|
type: string;
|
||||||
@ -17,15 +12,19 @@ class ValidationError extends Error {
|
|||||||
export class ValidationSrv {
|
export class ValidationSrv {
|
||||||
rootName = 'general';
|
rootName = 'general';
|
||||||
|
|
||||||
validateNewDashboardName(folderUid: any, name: string) {
|
validateNewDashboardName(folderUID: string, name: string) {
|
||||||
return this.validate(folderUid, name, 'A dashboard or a folder with the same name already exists');
|
return this.validate(folderUID, name, 'A dashboard or a folder with the same name already exists');
|
||||||
}
|
}
|
||||||
|
|
||||||
validateNewFolderName(name?: string) {
|
validateNewFolderName(name?: string) {
|
||||||
return this.validate(0, name, 'A folder or dashboard in the general folder with the same name already exists');
|
return this.validate(
|
||||||
|
this.rootName,
|
||||||
|
name,
|
||||||
|
'A folder or dashboard in the general folder with the same name already exists'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async validate(folderId: any, name: string | undefined, existingErrorMessage: string) {
|
private async validate(folderUID: string, name: string | undefined, existingErrorMessage: string) {
|
||||||
name = (name || '').trim();
|
name = (name || '').trim();
|
||||||
const nameLowerCased = name.toLowerCase();
|
const nameLowerCased = name.toLowerCase();
|
||||||
|
|
||||||
@ -33,27 +32,20 @@ export class ValidationSrv {
|
|||||||
throw new ValidationError('REQUIRED', 'Name is required');
|
throw new ValidationError('REQUIRED', 'Name is required');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (folderId === 0 && nameLowerCased === this.rootName) {
|
if (nameLowerCased === this.rootName) {
|
||||||
throw new ValidationError('EXISTING', 'This is a reserved name and cannot be used for a folder.');
|
throw new ValidationError('EXISTING', 'This is a reserved name and cannot be used for a folder.');
|
||||||
}
|
}
|
||||||
|
|
||||||
const promises = [];
|
const searcher = getGrafanaSearcher();
|
||||||
promises.push(backendSrv.search({ type: hitTypes.FOLDER, folderIds: [folderId], query: name }));
|
|
||||||
promises.push(backendSrv.search({ type: hitTypes.DASHBOARD, folderIds: [folderId], query: name }));
|
|
||||||
|
|
||||||
const res = await Promise.all(promises);
|
const dashboardResults = await searcher.search({
|
||||||
let hits: any[] = [];
|
kind: ['dashboard'],
|
||||||
|
query: name,
|
||||||
|
location: folderUID || 'general',
|
||||||
|
});
|
||||||
|
|
||||||
if (res.length > 0 && res[0].length > 0) {
|
for (const result of dashboardResults.view) {
|
||||||
hits = res[0];
|
if (nameLowerCased === result.name.toLowerCase()) {
|
||||||
}
|
|
||||||
|
|
||||||
if (res.length > 1 && res[1].length > 0) {
|
|
||||||
hits = hits.concat(res[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const hit of hits) {
|
|
||||||
if (nameLowerCased === hit.title.toLowerCase()) {
|
|
||||||
throw new ValidationError('EXISTING', existingErrorMessage);
|
throw new ValidationError('EXISTING', existingErrorMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user