step2_controller.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. var App = require('app');
  19. App.WidgetWizardStep2Controller = Em.Controller.extend({
  20. name: "widgetWizardStep2Controller",
  21. EXPRESSION_PREFIX: 'Expression',
  22. /**
  23. * actual values of properties in API format
  24. * @type {object}
  25. */
  26. widgetProperties: {},
  27. /**
  28. * @type {Array}
  29. */
  30. widgetValues: [],
  31. /**
  32. * @type {Array}
  33. */
  34. widgetMetrics: [],
  35. /**
  36. * @type {Array}
  37. */
  38. expressions: [],
  39. /**
  40. * used only for GRAPH widget
  41. * @type {Array}
  42. */
  43. dataSets: [],
  44. /**
  45. * content of template of Template widget
  46. * @type {string}
  47. */
  48. templateValue: '',
  49. /**
  50. * views of properties
  51. * @type {Array}
  52. */
  53. widgetPropertiesViews: [],
  54. propertiesMap: {
  55. "warning_threshold": {
  56. name: 'threshold',
  57. property: 'smallValue'
  58. },
  59. "error_threshold": {
  60. name: 'threshold',
  61. property: 'bigValue'
  62. },
  63. "display_unit": {
  64. name: 'display-unit',
  65. property: 'value'
  66. },
  67. "graph_type": {
  68. name: 'graph_type',
  69. property: 'value'
  70. },
  71. "time_range": {
  72. name: 'time_range',
  73. property: 'value'
  74. }
  75. },
  76. /**
  77. * metrics filtered by type
  78. * @type {Array}
  79. */
  80. filteredMetrics: function () {
  81. var type = this.get('content.widgetType');
  82. return this.get('content.allMetrics').filter(function (metric) {
  83. if (type === 'GRAPH') {
  84. return metric.temporal;
  85. } else {
  86. return metric.point_in_time;
  87. }
  88. }, this);
  89. }.property('content.allMetrics'),
  90. /**
  91. * @type {boolean}
  92. */
  93. isSubmitDisabled: function() {
  94. if (this.get('widgetPropertiesViews').someProperty('isValid', false)) {
  95. return true;
  96. }
  97. switch (this.get('content.widgetType')) {
  98. case "NUMBER":
  99. case "GAUGE":
  100. return this.get('expressions')[0] &&
  101. (this.get('expressions')[0].get('editMode') ||
  102. this.get('expressions')[0].get('data.length') === 0);
  103. case "GRAPH":
  104. return this.get('dataSets.length') > 0 &&
  105. (this.get('dataSets').someProperty('expression.editMode') ||
  106. this.get('dataSets').someProperty('expression.data.length', 0));
  107. case "TEMPLATE":
  108. return !this.get('templateValue') ||
  109. this.get('expressions.length') > 0 &&
  110. (this.get('expressions').someProperty('editMode') ||
  111. this.get('expressions').someProperty('data.length', 0));
  112. }
  113. return false;
  114. }.property('widgetPropertiesViews.@each.isValid',
  115. 'expressions.@each.editMode',
  116. 'dataSets.@each.expression'),
  117. /**
  118. * Add data set
  119. * @param {object|null} event
  120. * @param {boolean} isDefault
  121. */
  122. addDataSet: function(event, isDefault) {
  123. var id = (isDefault) ? 1 :(Math.max.apply(this, this.get('dataSets').mapProperty('id')) + 1);
  124. this.get('dataSets').pushObject(Em.Object.create({
  125. id: id,
  126. label: '',
  127. isRemovable: !isDefault,
  128. expression: {
  129. data: [],
  130. editMode: false
  131. }
  132. }));
  133. },
  134. /**
  135. * Remove data set
  136. * @param {object} event
  137. */
  138. removeDataSet: function(event) {
  139. this.get('dataSets').removeObject(event.context);
  140. },
  141. /**
  142. * Add expression
  143. * @param {object|null} event
  144. * @param {boolean} isDefault
  145. */
  146. addExpression: function(event, isDefault) {
  147. var id = (isDefault) ? 1 :(Math.max.apply(this, this.get('expressions').mapProperty('id')) + 1);
  148. this.get('expressions').pushObject(Em.Object.create({
  149. id: id,
  150. isRemovable: !isDefault,
  151. data: [],
  152. alias: '{{' + this.get('EXPRESSION_PREFIX') + id + '}}',
  153. editMode: false
  154. }));
  155. },
  156. /**
  157. * Remove expression
  158. * @param {object} event
  159. */
  160. removeExpression: function(event) {
  161. this.get('expressions').removeObject(event.context);
  162. },
  163. /**
  164. * initialize data
  165. * widget should have at least one expression or dataSet
  166. */
  167. initWidgetData: function() {
  168. this.set('widgetProperties', this.get('content.widgetProperties'));
  169. this.set('widgetValues', this.get('content.widgetValues'));
  170. this.set('widgetMetrics', this.get('content.widgetMetrics'));
  171. this.set('expressions', this.get('content.expressions').map(function (item) {
  172. return Em.Object.create(item);
  173. }, this));
  174. this.set('dataSets', this.get('content.dataSets').map(function (item) {
  175. return Em.Object.create(item);
  176. }, this));
  177. this.set('templateValue', this.get('content.templateValue'));
  178. if (this.get('expressions.length') === 0) {
  179. this.addExpression(null, true);
  180. }
  181. if (this.get('dataSets.length') === 0) {
  182. this.addDataSet(null, true);
  183. }
  184. },
  185. /**
  186. * update preview widget with latest expression data
  187. * @param {Em.View} view
  188. */
  189. updateExpressions: function () {
  190. var widgetType = this.get('content.widgetType');
  191. var expressionData = {
  192. values: [],
  193. metrics: []
  194. };
  195. if (this.get('expressions').length > 0 && this.get('dataSets').length > 0) {
  196. switch (widgetType) {
  197. case 'GAUGE':
  198. case 'NUMBER':
  199. expressionData = this.parseExpression(this.get('expressions')[0]);
  200. expressionData.values = [
  201. {
  202. value: expressionData.value
  203. }
  204. ];
  205. break;
  206. case 'TEMPLATE':
  207. expressionData = this.parseTemplateExpression(this);
  208. break;
  209. case 'GRAPH':
  210. expressionData = this.parseGraphDataset(this);
  211. break;
  212. }
  213. }
  214. this.set('widgetValues', expressionData.values);
  215. this.set('widgetMetrics', expressionData.metrics);
  216. }.observes('templateValue', 'dataSets.@each.label'),
  217. /**
  218. * parse Graph data set
  219. * @param {Ember.View} view
  220. * @returns {{metrics: Array, values: Array}}
  221. */
  222. parseGraphDataset: function (view) {
  223. var metrics = [];
  224. var values = [];
  225. view.get('dataSets').forEach(function (dataSet) {
  226. var result = this.parseExpression(dataSet.get('expression'));
  227. metrics.pushObjects(result.metrics);
  228. values.push({
  229. name: dataSet.get('label'),
  230. value: result.value
  231. });
  232. }, this);
  233. return {
  234. metrics: metrics,
  235. values: values
  236. };
  237. },
  238. /**
  239. * parse expression from template
  240. * @param {Ember.View} view
  241. * @returns {{metrics: Array, values: {value: *}[]}}
  242. */
  243. parseTemplateExpression: function (view) {
  244. var metrics = [];
  245. var self = this;
  246. var expression = view.get('templateValue').replace(/\{\{Expression[\d]\}\}/g, function (exp) {
  247. var result;
  248. if (view.get('expressions').someProperty('alias', exp)) {
  249. result = self.parseExpression(view.get('expressions').findProperty('alias', exp));
  250. metrics.pushObjects(result.metrics);
  251. return result.value;
  252. }
  253. return exp;
  254. });
  255. return {
  256. metrics: metrics,
  257. values: [
  258. {
  259. value: expression
  260. }
  261. ]
  262. };
  263. },
  264. /**
  265. *
  266. * @param {object} expression
  267. * @returns {{metrics: Array, value: string}}
  268. */
  269. parseExpression: function (expression) {
  270. var value = '';
  271. var metrics = [];
  272. if (expression.data.length > 0) {
  273. value = '${';
  274. expression.data.forEach(function (element) {
  275. if (element.isMetric) {
  276. metrics.push({
  277. name: element.name,
  278. componentName: element.componentName,
  279. serviceName: element.serviceName
  280. });
  281. }
  282. value += element.name;
  283. }, this);
  284. value += '}';
  285. }
  286. return {
  287. metrics: metrics,
  288. value: value
  289. };
  290. },
  291. /**
  292. * update properties of preview widget
  293. */
  294. updateProperties: function () {
  295. var propertiesMap = this.get('propertiesMap');
  296. var result = {};
  297. var widgetProperty;
  298. for (var i in propertiesMap) {
  299. widgetProperty = this.get('widgetPropertiesViews').findProperty('name', propertiesMap[i].name);
  300. if (widgetProperty && widgetProperty.get('isValid')) {
  301. result[i] = widgetProperty.get(propertiesMap[i].property);
  302. }
  303. }
  304. this.set('widgetProperties', result);
  305. }.observes('widgetPropertiesViews.@each.value', 'widgetPropertiesViews.@each.bigValue', 'widgetPropertiesViews.@each.smallValue'),
  306. /*
  307. * Generate the thresholds, unit, time range.etc object based on the widget type selected in previous step.
  308. */
  309. renderProperties: function () {
  310. var widgetType = this.get('content.widgetType');
  311. var widgetProperties = App.WidgetType.find().findProperty('name', widgetType).get('properties');
  312. var properties = [];
  313. switch (widgetType) {
  314. case 'GAUGE':
  315. properties = this.renderGaugeProperties(widgetProperties);
  316. break;
  317. case 'NUMBER':
  318. properties = this.renderNumberProperties(widgetProperties);
  319. break;
  320. case 'GRAPH':
  321. properties = this.renderGraphProperties(widgetProperties);
  322. break;
  323. case 'TEMPLATE':
  324. properties = this.renderTemplateProperties(widgetProperties);
  325. break;
  326. default:
  327. console.error('Incorrect Widget Type: ', widgetType);
  328. }
  329. this.set('widgetPropertiesViews', properties);
  330. },
  331. /**
  332. * Render properties for gauge-type widget
  333. * @method renderGaugeProperties
  334. * @returns {App.WidgetProperties[]}
  335. */
  336. renderGaugeProperties: function () {
  337. return [
  338. App.WidgetProperties.Thresholds.PercentageThreshold.create({
  339. smallValue: this.get('widgetProperties.warning_threshold') || '0.7',
  340. bigValue: this.get('widgetProperties.error_threshold') || '0.9',
  341. isRequired: true
  342. })
  343. ];
  344. },
  345. /**
  346. * Render properties for number-type widget
  347. * @method renderNumberProperties
  348. * @returns {App.WidgetProperties[]}
  349. */
  350. renderNumberProperties: function () {
  351. return [
  352. App.WidgetProperties.Threshold.create({
  353. smallValue: this.get('widgetProperties.warning_threshold') || '10',
  354. bigValue: this.get('widgetProperties.error_threshold') || '20',
  355. isRequired: false
  356. }),
  357. App.WidgetProperties.Unit.create({
  358. value: this.get('widgetProperties.display_unit') || 'MB',
  359. isRequired: false
  360. })
  361. ];
  362. },
  363. /**
  364. * Render properties for template-type widget
  365. * @method renderTemplateProperties
  366. * @returns {App.WidgetProperties[]}
  367. */
  368. renderTemplateProperties: function (widgetProperties) {
  369. return [
  370. App.WidgetProperties.Unit.create({
  371. value: this.get('widgetProperties.display_unit') || 'MB',
  372. isRequired: false
  373. })
  374. ];
  375. },
  376. /**
  377. * Render properties for graph-type widget
  378. * @method renderGraphProperties
  379. * @returns {App.WidgetProperties[]}
  380. */
  381. renderGraphProperties: function (widgetProperties) {
  382. return [
  383. App.WidgetProperties.GraphType.create({
  384. value: this.get('widgetProperties.graph_type') || 'LINE',
  385. isRequired: true
  386. }),
  387. App.WidgetProperties.TimeRange.create({
  388. value: this.get('widgetProperties.time_range') || 'Last 1 hour',
  389. isRequired: true
  390. }),
  391. App.WidgetProperties.Unit.create({
  392. value: this.get('widgetProperties.display_unit') || 'MB',
  393. isRequired: false
  394. })
  395. ];
  396. },
  397. next: function () {
  398. if (!this.get('isSubmitDisabled')) {
  399. App.router.send('next');
  400. }
  401. }
  402. });