diff --git a/public/app/features/dashboard/export/exporter.ts b/public/app/features/dashboard/export/exporter.ts index 8b93c12bf50..fc24de76fcc 100644 --- a/public/app/features/dashboard/export/exporter.ts +++ b/public/app/features/dashboard/export/exporter.ts @@ -63,8 +63,7 @@ export class DashboardExporter { ); }; - // check up panel data sources - for (let panel of saveModel.panels) { + const processPanel = panel => { if (panel.datasource !== undefined) { templateizeDatasourceUsage(panel); } @@ -86,6 +85,18 @@ export class DashboardExporter { version: panelDef.info.version, }; } + }; + + // check up panel data sources + for (let panel of saveModel.panels) { + processPanel(panel); + + // handle collapsed rows + if (panel.collapsed !== undefined && panel.collapsed === true && panel.panels) { + for (let rowPanel of panel.panels) { + processPanel(rowPanel); + } + } } // templatize template vars diff --git a/public/app/features/dashboard/specs/exporter.jest.ts b/public/app/features/dashboard/specs/exporter.jest.ts index f94d1368aa5..aa574a4b85a 100644 --- a/public/app/features/dashboard/specs/exporter.jest.ts +++ b/public/app/features/dashboard/specs/exporter.jest.ts @@ -62,6 +62,27 @@ describe('given dashboard with repeated panels', () => { type: 'graph', }, { id: 3, repeat: null, repeatPanelId: 2 }, + { + id: 4, + collapsed: true, + panels: [ + { id: 10, datasource: 'gfdb', type: 'table' }, + { id: 11 }, + { + id: 12, + datasource: '-- Mixed --', + targets: [{ datasource: 'other' }], + }, + { id: 13, datasource: '$ds' }, + { + id: 14, + repeat: 'apps', + datasource: 'gfdb', + type: 'heatmap', + }, + { id: 15, repeat: null, repeatPanelId: 14 }, + ], + }, ], }; @@ -78,6 +99,18 @@ describe('given dashboard with repeated panels', () => { info: { version: '1.1.0' }, }; + config.panels['table'] = { + id: 'table', + name: 'Table', + info: { version: '1.1.1' }, + }; + + config.panels['heatmap'] = { + id: 'heatmap', + name: 'Heatmap', + info: { version: '1.1.2' }, + }; + dash = new DashboardModel(dash, {}); var exporter = new DashboardExporter(datasourceSrvStub); exporter.makeExportable(dash).then(clean => { @@ -91,6 +124,11 @@ describe('given dashboard with repeated panels', () => { expect(panel.datasource).toBe('${DS_GFDB}'); }); + it('should replace datasource refs in collapsed row', () => { + var panel = exported.panels[5].panels[0]; + expect(panel.datasource).toBe('${DS_GFDB}'); + }); + it('should replace datasource in variable query', () => { expect(exported.templating.list[0].datasource).toBe('${DS_GFDB}'); expect(exported.templating.list[0].options.length).toBe(0); @@ -126,13 +164,27 @@ describe('given dashboard with repeated panels', () => { expect(require).not.toBe(undefined); }); - it('should add panel to required', () => { + it('should add graph panel to required', () => { var require = _.find(exported.__requires, { name: 'Graph' }); expect(require.name).toBe('Graph'); expect(require.id).toBe('graph'); expect(require.version).toBe('1.1.0'); }); + it('should add table panel to required', () => { + var require = _.find(exported.__requires, { name: 'Table' }); + expect(require.name).toBe('Table'); + expect(require.id).toBe('table'); + expect(require.version).toBe('1.1.1'); + }); + + it('should add heatmap panel to required', () => { + var require = _.find(exported.__requires, { name: 'Heatmap' }); + expect(require.name).toBe('Heatmap'); + expect(require.id).toBe('heatmap'); + expect(require.version).toBe('1.1.2'); + }); + it('should add grafana version', () => { var require = _.find(exported.__requires, { name: 'Grafana' }); expect(require.type).toBe('grafana');