diff --git a/public/app/plugins/panel/dashlist/migrations.test.ts b/public/app/plugins/panel/dashlist/migrations.test.ts index 2f708ef576c..62f1f51172a 100644 --- a/public/app/plugins/panel/dashlist/migrations.test.ts +++ b/public/app/plugins/panel/dashlist/migrations.test.ts @@ -74,4 +74,48 @@ describe('dashlist migrations', () => { folderUID: 'abc-124', }); }); + + it("doesn't fail if the api request fails", async () => { + const spyConsoleWarn = jest.spyOn(console, 'warn').mockImplementation(); + + getMock.mockRejectedValue({ + status: 403, + statusText: 'Forbidden', + data: { + accessErrorId: 'ACE0577385389', + message: "You'll need additional permissions to perform this action. Permissions needed: folders:read", + title: 'Access denied', + }, + config: { + showErrorAlert: false, + method: 'GET', + url: 'api/folders/id/0', + retry: 0, + headers: { + 'X-Grafana-Org-Id': 1, + }, + hideFromInspector: true, + }, + }); + + const basePanelOptions = { + showStarred: true, + showRecentlyViewed: true, + showSearch: true, + showHeadings: true, + maxItems: 7, + query: 'hello, query', + includeVars: false, + keepTime: false, + tags: [], + folderId: 77, + }; + const panelModel = wellFormedPanelModel(basePanelOptions); + + // We expect it to not reject + const newOptions = await dashlistMigrationHandler(panelModel); + + expect(newOptions).toStrictEqual(basePanelOptions); + expect(spyConsoleWarn).toHaveBeenCalledTimes(1); + }); }); diff --git a/public/app/plugins/panel/dashlist/migrations.ts b/public/app/plugins/panel/dashlist/migrations.ts index ce03112190f..25f420108d2 100644 --- a/public/app/plugins/panel/dashlist/migrations.ts +++ b/public/app/plugins/panel/dashlist/migrations.ts @@ -4,8 +4,17 @@ import { FolderDTO } from 'app/types'; import { Options } from './panelcfg.gen'; -function getFolderByID(folderID: number) { - return getBackendSrv().get(`/api/folders/id/${folderID}`); +async function getFolderUID(folderID: number): Promise { + // folderID 0 is always the fake General/Dashboards folder, which always has a UID of empty string + if (folderID === 0) { + return ''; + } + + const folderDTO = await getBackendSrv().get(`/api/folders/id/${folderID}`, undefined, undefined, { + showErrorAlert: false, + }); + + return folderDTO.uid; } export interface AngularModel { @@ -51,9 +60,15 @@ export async function dashlistMigrationHandler(panel: PanelModel & Angu // Convert the folderId to folderUID. Uses the API to do the conversion. if (newOptions.folderId !== undefined) { const folderId = newOptions.folderId; - const folderResp = await getFolderByID(folderId); - newOptions.folderUID = folderResp.uid; - delete newOptions.folderId; + + // If converting ID to UID fails, the panel will not be migrated and will show incorrectly + try { + const folderUID = await getFolderUID(folderId); + newOptions.folderUID = folderUID; + delete newOptions.folderId; + } catch (err) { + console.warn('Dashlist: Error migrating folder ID to UID', err); + } } return newOptions; diff --git a/public/app/plugins/panel/dashlist/module.tsx b/public/app/plugins/panel/dashlist/module.tsx index 13a438e14dc..6cbc76f964d 100644 --- a/public/app/plugins/panel/dashlist/module.tsx +++ b/public/app/plugins/panel/dashlist/module.tsx @@ -52,9 +52,9 @@ export const plugin = new PanelPlugin(DashList) defaultValue: defaultOptions.query, }) .addCustomEditor({ - path: 'folderUid', + path: 'folderUID', name: 'Folder', - id: 'folderUid', + id: 'folderUID', defaultValue: undefined, editor: function RenderFolderPicker({ value, onChange }) { return onChange(folderUID)} />;