DashboardImportCtrl.ts 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. import _ from 'lodash';
  2. import config from 'app/core/config';
  3. import locationUtil from 'app/core/utils/location_util';
  4. import { BackendSrv } from '@grafana/runtime';
  5. import { ValidationSrv } from './services/ValidationSrv';
  6. import { NavModelSrv } from 'app/core/core';
  7. import { ILocationService } from 'angular';
  8. export class DashboardImportCtrl {
  9. navModel: any;
  10. step: number;
  11. jsonText: string;
  12. parseError: string;
  13. nameExists: boolean;
  14. uidExists: boolean;
  15. dash: any;
  16. inputs: any[];
  17. inputsValid: boolean;
  18. gnetUrl: string;
  19. gnetError: string;
  20. gnetInfo: any;
  21. titleTouched: boolean;
  22. hasNameValidationError: boolean;
  23. nameValidationError: any;
  24. hasUidValidationError: boolean;
  25. uidValidationError: any;
  26. autoGenerateUid: boolean;
  27. autoGenerateUidValue: string;
  28. folderId: number;
  29. initialFolderTitle: string;
  30. isValidFolderSelection: boolean;
  31. /** @ngInject */
  32. constructor(
  33. private backendSrv: BackendSrv,
  34. private validationSrv: ValidationSrv,
  35. navModelSrv: NavModelSrv,
  36. private $location: ILocationService,
  37. $routeParams: any
  38. ) {
  39. this.navModel = navModelSrv.getNav('create', 'import');
  40. this.step = 1;
  41. this.nameExists = false;
  42. this.uidExists = false;
  43. this.autoGenerateUid = true;
  44. this.autoGenerateUidValue = 'auto-generated';
  45. this.folderId = $routeParams.folderId ? Number($routeParams.folderId) || 0 : null;
  46. this.initialFolderTitle = 'Select a folder';
  47. // check gnetId in url
  48. if ($routeParams.gnetId) {
  49. this.gnetUrl = $routeParams.gnetId;
  50. this.checkGnetDashboard();
  51. }
  52. }
  53. onUpload(dash: any) {
  54. this.dash = dash;
  55. this.dash.id = null;
  56. this.step = 2;
  57. this.inputs = [];
  58. if (this.dash.__inputs) {
  59. for (const input of this.dash.__inputs) {
  60. const inputModel: any = {
  61. name: input.name,
  62. label: input.label,
  63. info: input.description,
  64. value: input.value,
  65. type: input.type,
  66. pluginId: input.pluginId,
  67. options: [],
  68. };
  69. if (input.type === 'datasource') {
  70. this.setDatasourceOptions(input, inputModel);
  71. } else if (!inputModel.info) {
  72. inputModel.info = 'Specify a string constant';
  73. }
  74. this.inputs.push(inputModel);
  75. }
  76. }
  77. this.inputsValid = this.inputs.length === 0;
  78. this.titleChanged();
  79. this.uidChanged(true);
  80. }
  81. setDatasourceOptions(input: { pluginId: string; pluginName: string }, inputModel: any) {
  82. const sources = _.filter(config.datasources, val => {
  83. return val.type === input.pluginId;
  84. });
  85. if (sources.length === 0) {
  86. inputModel.info = 'No data sources of type ' + input.pluginName + ' found';
  87. } else if (!inputModel.info) {
  88. inputModel.info = 'Select a ' + input.pluginName + ' data source';
  89. }
  90. inputModel.options = sources.map(val => {
  91. return { text: val.name, value: val.name };
  92. });
  93. }
  94. inputValueChanged() {
  95. this.inputsValid = true;
  96. for (const input of this.inputs) {
  97. if (!input.value) {
  98. this.inputsValid = false;
  99. }
  100. }
  101. }
  102. titleChanged() {
  103. this.titleTouched = true;
  104. this.nameExists = false;
  105. this.validationSrv
  106. .validateNewDashboardName(this.folderId, this.dash.title)
  107. .then(() => {
  108. this.nameExists = false;
  109. this.hasNameValidationError = false;
  110. })
  111. .catch(err => {
  112. if (err.type === 'EXISTING') {
  113. this.nameExists = true;
  114. }
  115. this.hasNameValidationError = true;
  116. this.nameValidationError = err.message;
  117. });
  118. }
  119. uidChanged(initial: boolean) {
  120. this.uidExists = false;
  121. this.hasUidValidationError = false;
  122. if (initial === true && this.dash.uid) {
  123. this.autoGenerateUidValue = 'value set';
  124. }
  125. this.backendSrv
  126. // @ts-ignore
  127. .getDashboardByUid(this.dash.uid)
  128. .then((res: any) => {
  129. this.uidExists = true;
  130. this.hasUidValidationError = true;
  131. this.uidValidationError = `Dashboard named '${res.dashboard.title}' in folder '${
  132. res.meta.folderTitle
  133. }' has the same uid`;
  134. })
  135. .catch((err: any) => {
  136. err.isHandled = true;
  137. });
  138. }
  139. onFolderChange(folder: any) {
  140. this.folderId = folder.id;
  141. this.titleChanged();
  142. }
  143. onEnterFolderCreation() {
  144. this.inputsValid = false;
  145. }
  146. onExitFolderCreation() {
  147. this.inputValueChanged();
  148. }
  149. isValid() {
  150. return this.inputsValid && this.folderId !== null;
  151. }
  152. saveDashboard() {
  153. const inputs = this.inputs.map(input => {
  154. return {
  155. name: input.name,
  156. type: input.type,
  157. pluginId: input.pluginId,
  158. value: input.value,
  159. };
  160. });
  161. return this.backendSrv
  162. .post('api/dashboards/import', {
  163. dashboard: this.dash,
  164. overwrite: true,
  165. inputs: inputs,
  166. folderId: this.folderId,
  167. })
  168. .then(res => {
  169. const dashUrl = locationUtil.stripBaseFromUrl(res.importedUrl);
  170. this.$location.url(dashUrl);
  171. });
  172. }
  173. loadJsonText() {
  174. try {
  175. this.parseError = '';
  176. const dash = JSON.parse(this.jsonText);
  177. this.onUpload(dash);
  178. } catch (err) {
  179. console.log(err);
  180. this.parseError = err.message;
  181. return;
  182. }
  183. }
  184. checkGnetDashboard() {
  185. this.gnetError = '';
  186. const match = /(^\d+$)|dashboards\/(\d+)/.exec(this.gnetUrl);
  187. let dashboardId;
  188. if (match && match[1]) {
  189. dashboardId = match[1];
  190. } else if (match && match[2]) {
  191. dashboardId = match[2];
  192. } else {
  193. this.gnetError = 'Could not find dashboard';
  194. }
  195. return this.backendSrv
  196. .get('api/gnet/dashboards/' + dashboardId)
  197. .then(res => {
  198. this.gnetInfo = res;
  199. // store reference to grafana.com
  200. res.json.gnetId = res.id;
  201. this.onUpload(res.json);
  202. })
  203. .catch(err => {
  204. err.isHandled = true;
  205. this.gnetError = err.data.message || err;
  206. });
  207. }
  208. back() {
  209. this.gnetUrl = '';
  210. this.step = 1;
  211. this.gnetError = '';
  212. this.gnetInfo = '';
  213. }
  214. }
  215. export default DashboardImportCtrl;