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": [
|
||||
[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": [
|
||||
[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()) {
|
||||
return 'Dashboard name cannot be the same as folder name';
|
||||
}
|
||||
|
||||
try {
|
||||
await validationSrv.validateNewDashboardName(getFormValues().$folder.uid, dashboardName);
|
||||
await validationSrv.validateNewDashboardName(getFormValues().$folder.uid ?? 'general', dashboardName);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return e instanceof Error ? e.message : 'Dashboard name is invalid';
|
||||
|
@ -1,9 +1,4 @@
|
||||
import { backendSrv } from 'app/core/services/backend_srv';
|
||||
|
||||
const hitTypes = {
|
||||
FOLDER: 'dash-folder',
|
||||
DASHBOARD: 'dash-db',
|
||||
};
|
||||
import { getGrafanaSearcher } from 'app/features/search/service';
|
||||
|
||||
class ValidationError extends Error {
|
||||
type: string;
|
||||
@ -17,15 +12,19 @@ class ValidationError extends Error {
|
||||
export class ValidationSrv {
|
||||
rootName = 'general';
|
||||
|
||||
validateNewDashboardName(folderUid: any, name: string) {
|
||||
return this.validate(folderUid, name, 'A dashboard or a folder with the same name already exists');
|
||||
validateNewDashboardName(folderUID: string, name: string) {
|
||||
return this.validate(folderUID, name, 'A dashboard or a folder with the same name already exists');
|
||||
}
|
||||
|
||||
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();
|
||||
const nameLowerCased = name.toLowerCase();
|
||||
|
||||
@ -33,27 +32,20 @@ export class ValidationSrv {
|
||||
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.');
|
||||
}
|
||||
|
||||
const promises = [];
|
||||
promises.push(backendSrv.search({ type: hitTypes.FOLDER, folderIds: [folderId], query: name }));
|
||||
promises.push(backendSrv.search({ type: hitTypes.DASHBOARD, folderIds: [folderId], query: name }));
|
||||
const searcher = getGrafanaSearcher();
|
||||
|
||||
const res = await Promise.all(promises);
|
||||
let hits: any[] = [];
|
||||
const dashboardResults = await searcher.search({
|
||||
kind: ['dashboard'],
|
||||
query: name,
|
||||
location: folderUID || 'general',
|
||||
});
|
||||
|
||||
if (res.length > 0 && res[0].length > 0) {
|
||||
hits = res[0];
|
||||
}
|
||||
|
||||
if (res.length > 1 && res[1].length > 0) {
|
||||
hits = hits.concat(res[1]);
|
||||
}
|
||||
|
||||
for (const hit of hits) {
|
||||
if (nameLowerCased === hit.title.toLowerCase()) {
|
||||
for (const result of dashboardResults.view) {
|
||||
if (nameLowerCased === result.name.toLowerCase()) {
|
||||
throw new ValidationError('EXISTING', existingErrorMessage);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user