exporter.ts 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. ///<reference path="../../../headers/common.d.ts" />
  2. import config from 'app/core/config';
  3. import angular from 'angular';
  4. import _ from 'lodash';
  5. import {DynamicDashboardSrv} from '../dynamic_dashboard_srv';
  6. export class DashboardExporter {
  7. constructor(private datasourceSrv) {
  8. }
  9. makeExportable(dashboard) {
  10. var dynSrv = new DynamicDashboardSrv();
  11. // clean up repeated rows and panels,
  12. // this is done on the live real dashboard instance, not on a clone
  13. // so we need to undo this
  14. // this is pretty hacky and needs to be changed
  15. dynSrv.init(dashboard);
  16. dynSrv.process({cleanUpOnly: true});
  17. var saveModel = dashboard.getSaveModelClone();
  18. saveModel.id = null;
  19. // undo repeat cleanup
  20. dynSrv.process();
  21. var inputs = [];
  22. var requires = {};
  23. var datasources = {};
  24. var promises = [];
  25. var variableLookup: any = {};
  26. for (let variable of saveModel.templating.list) {
  27. variableLookup[variable.name] = variable;
  28. }
  29. var templateizeDatasourceUsage = obj => {
  30. // ignore data source properties that contain a variable
  31. if (obj.datasource && obj.datasource.indexOf('$') === 0) {
  32. if (variableLookup[obj.datasource.substring(1)]){
  33. return;
  34. }
  35. }
  36. promises.push(this.datasourceSrv.get(obj.datasource).then(ds => {
  37. if (ds.meta.builtIn) {
  38. return;
  39. }
  40. var refName = 'DS_' + ds.name.replace(' ', '_').toUpperCase();
  41. datasources[refName] = {
  42. name: refName,
  43. label: ds.name,
  44. description: '',
  45. type: 'datasource',
  46. pluginId: ds.meta.id,
  47. pluginName: ds.meta.name,
  48. };
  49. obj.datasource = '${' + refName +'}';
  50. requires['datasource' + ds.meta.id] = {
  51. type: 'datasource',
  52. id: ds.meta.id,
  53. name: ds.meta.name,
  54. version: ds.meta.info.version || "1.0.0",
  55. };
  56. }));
  57. };
  58. // check up panel data sources
  59. for (let row of saveModel.rows) {
  60. for (let panel of row.panels) {
  61. if (panel.datasource !== undefined) {
  62. templateizeDatasourceUsage(panel);
  63. }
  64. if (panel.targets) {
  65. for (let target of panel.targets) {
  66. if (target.datasource !== undefined) {
  67. templateizeDatasourceUsage(target);
  68. }
  69. }
  70. }
  71. var panelDef = config.panels[panel.type];
  72. if (panelDef) {
  73. requires['panel' + panelDef.id] = {
  74. type: 'panel',
  75. id: panelDef.id,
  76. name: panelDef.name,
  77. version: panelDef.info.version,
  78. };
  79. }
  80. }
  81. }
  82. // templatize template vars
  83. for (let variable of saveModel.templating.list) {
  84. if (variable.type === 'query') {
  85. templateizeDatasourceUsage(variable);
  86. variable.options = [];
  87. variable.current = {};
  88. variable.refresh = 1;
  89. }
  90. }
  91. // templatize annotations vars
  92. for (let annotationDef of saveModel.annotations.list) {
  93. templateizeDatasourceUsage(annotationDef);
  94. }
  95. // add grafana version
  96. requires['grafana'] = {
  97. type: 'grafana',
  98. id: 'grafana',
  99. name: 'Grafana',
  100. version: config.buildInfo.version
  101. };
  102. return Promise.all(promises).then(() => {
  103. _.each(datasources, (value, key) => {
  104. inputs.push(value);
  105. });
  106. // templatize constants
  107. for (let variable of saveModel.templating.list) {
  108. if (variable.type === 'constant') {
  109. var refName = 'VAR_' + variable.name.replace(' ', '_').toUpperCase();
  110. inputs.push({
  111. name: refName,
  112. type: 'constant',
  113. label: variable.label || variable.name,
  114. value: variable.current.value,
  115. description: '',
  116. });
  117. // update current and option
  118. variable.query = '${' + refName + '}';
  119. variable.options[0] = variable.current = {
  120. value: variable.query,
  121. text: variable.query,
  122. };
  123. }
  124. }
  125. requires = _.map(requires, req => {
  126. return req;
  127. });
  128. // make inputs and requires a top thing
  129. var newObj = {};
  130. newObj["__inputs"] = inputs;
  131. newObj["__requires"] = requires;
  132. _.defaults(newObj, saveModel);
  133. return newObj;
  134. }).catch(err => {
  135. console.log('Export failed:', err);
  136. return {
  137. error: err
  138. };
  139. });
  140. }
  141. }