@datarailsshared/dr_renderer 1.2.10 → 1.2.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -20,7 +20,7 @@ jobs:
20
20
  name: Prepare publish version
21
21
  command: |
22
22
  postfix=""
23
- if [[ "${CIRCLE_BRANCH}" != prod ]] ; then
23
+ if [[ "${CIRCLE_BRANCH}" != master ]] ; then
24
24
  postfix="-$CIRCLE_BRANCH"
25
25
  fi
26
26
 
@@ -76,7 +76,7 @@ workflows:
76
76
  filters:
77
77
  branches:
78
78
  only:
79
- - /prod.*/
79
+ - /master/
80
80
  - /tigers/
81
81
  - /bratans/
82
82
  - /dragons/
package/README.md CHANGED
@@ -13,6 +13,11 @@ This project was generated by amazing Datarails R&D team
13
13
  let default_colors = ["#106bd0", "#00cee8", "#95c8d8", "#89cff0", "#FE746D", "#6ADC4C", "#9B9AD9", "#ff8000", "#C11B12", "#5a41f9"];
14
14
  let hr = dr_renderer.getInitHighchartsRenderer($, document, default_colors, Highcharts);
15
15
 
16
+ ## Development
17
+ ### Types
18
+ To be able to compile types with `npm run build:types` you need to install typescript globally:
19
+
20
+ ```npm i -g typescript```
16
21
 
17
22
  ## Publish to npm
18
23
  Just merge to prod branch
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datarailsshared/dr_renderer",
3
- "version": "1.2.10",
3
+ "version": "1.2.11",
4
4
  "description": "DataRails charts and tables renderer",
5
5
  "keywords": [
6
6
  "datarails",
@@ -10,7 +10,8 @@
10
10
  ],
11
11
  "scripts": {
12
12
  "login": "npm login",
13
- "test": "jest --coverage"
13
+ "test": "jest --coverage",
14
+ "build:types": "tsc --build --verbose"
14
15
  },
15
16
  "author": "Sergey Spivakov",
16
17
  "repository": {
@@ -0,0 +1,566 @@
1
+ const _ = require('lodash');
2
+ const { DrChartTooltip } = require("../dr_chart_tooltip");
3
+ const helpers = require("../dr-renderer-helpers");
4
+
5
+ const GAUGE_OPTIONS_DEFAULT = {
6
+ gauge: {
7
+ background: "#fff",
8
+ startAngle: -90,
9
+ endAngle: 90,
10
+ thickness: 16,
11
+ tickLength: 40,
12
+ tickWidth: 2,
13
+ valueOffset: [20, 0, 8, 0],
14
+ offset: [8, 8, 8, 8],
15
+ goalIcon:
16
+ "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNSIgdmlld0JveD0iMCAwIDE2IDE1IiBmaWxsPSJub25lIj4KICAgIDxwYXRoIGQ9Ik04IDBMOS43OTYxMSA1LjUyNzg2SDE1LjYwODVMMTAuOTA2MiA4Ljk0NDI3TDEyLjcwMjMgMTQuNDcyMUw4IDExLjA1NTdMMy4yOTc3MiAxNC40NzIxTDUuMDkzODMgOC45NDQyN0wwLjM5MTU0OCA1LjUyNzg2SDYuMjAzODlMOCAwWiIgZmlsbD0iIzQ2NDZDRSIvPgo8L3N2Zz4=",
17
+ goalIconSize: [16, 16],
18
+ pivot: {
19
+ radius: 5,
20
+ color: "#808080",
21
+ },
22
+ colors: {
23
+ meta: "#6D6E6F",
24
+ goal: "#4646CE",
25
+ },
26
+ },
27
+ goal: {
28
+ title: "Goal",
29
+ value: 1000000,
30
+ },
31
+ isAbsoluteValue: false,
32
+ segments: [
33
+ {
34
+ from: 0,
35
+ to: 50,
36
+ title: "Low",
37
+ color: "#BF1D30",
38
+ },
39
+ {
40
+ from: 51,
41
+ to: 90,
42
+ title: "Medium",
43
+ color: "#FFA310",
44
+ },
45
+ {
46
+ from: 91,
47
+ to: 100,
48
+ title: "High",
49
+ color: "#037C5A",
50
+ },
51
+ ],
52
+ };
53
+
54
+ function DrGaugeChart(pivotData, opts) {
55
+ this.render = function () {
56
+ return DrGaugeChart.highchartsRenderer.ptCreateElementAndDraw(this.configChart(), opts);
57
+ };
58
+
59
+ this.formatValue = function (data_type, number_format, value, widget_values_format) {
60
+ return DrGaugeChart.highchartsRenderer.formatValue(data_type, number_format, value, widget_values_format);
61
+ };
62
+
63
+ this.getDefaultValueForChart = function (type, existing_options) {
64
+ return DrGaugeChart.highchartsRenderer.getDefaultValueForChart(type, existing_options);
65
+ };
66
+
67
+ this.ptCreateBasicLineSeries = function (pivotData, colors, onlyNumbers, isUniqueVals, additionOptions, opts, chartOptions) {
68
+ return DrGaugeChart.highchartsRenderer.ptCreateBasicLineSeries(
69
+ pivotData,
70
+ colors,
71
+ onlyNumbers,
72
+ isUniqueVals,
73
+ additionOptions,
74
+ opts,
75
+ chartOptions
76
+ );
77
+ };
78
+
79
+ this.getSingleValueAgg = function (opts, aggfunc, base) {
80
+ return DrGaugeChart.highchartsRenderer.getSingleValueAgg(opts, aggfunc, base);
81
+ };
82
+
83
+ this.isLeftQuarter = function (value, max = this.max) {
84
+ return value < max / 2;
85
+ };
86
+
87
+ this.createPlotBands = function (options) {
88
+ const {
89
+ segments,
90
+ isAbsoluteValue,
91
+ goal: { value: goalValue },
92
+ gauge: { thickness },
93
+ } = options;
94
+
95
+ const bands = segments.map((item, index) => {
96
+ const itemFrom = !!index ? item.from - 1 : item.from;
97
+ return {
98
+ from: isAbsoluteValue ? itemFrom : (itemFrom * goalValue) / 100,
99
+ to: isAbsoluteValue ? item.to : (item.to * goalValue) / 100,
100
+ color: item.color,
101
+ thickness: thickness,
102
+ title: item.title,
103
+ };
104
+ });
105
+
106
+ // clamp last segment
107
+ bands[bands.length - 1].to = Math.max(bands[bands.length - 1].to, goalValue);
108
+
109
+ return bands;
110
+ };
111
+
112
+ this.createTicks = function (plotBands, options) {
113
+ return _.uniq([plotBands[0].from || 0, ...plotBands.map((b) => b.to), options.goal.value]).sort((a, b) => a - b);
114
+ };
115
+
116
+ this.mergeOptions = function (options) {
117
+ return helpers.mergeDeep(
118
+ JSON.parse(JSON.stringify(GAUGE_OPTIONS_DEFAULT)),
119
+ this.getDefaultValueForChart(DrGaugeChart.highchartsRenderer.CHART_TYPES.GAUGE_CHART_ENHANCED),
120
+ options
121
+ );
122
+ };
123
+
124
+ this.getAngleForValue = function (
125
+ value,
126
+ min = this.min,
127
+ max = this.max,
128
+ startAngle = this.options.gauge.startAngle,
129
+ endAngle = this.options.gauge.endAngle
130
+ ) {
131
+ const degrees = ((value - min) / (max - min)) * (endAngle - startAngle);
132
+ const radians = degrees * (Math.PI / 180);
133
+ return radians;
134
+ };
135
+
136
+ this.formatValue = function (value, format = this.format) {
137
+ return helpers.isNumber(value) ? DrGaugeChart.highchartsRenderer.formatValue("n", format, value).value : value;
138
+ };
139
+
140
+ this.toPercent = function (value) {
141
+ return `${Math.round((value * 100) / (this.options.isAbsoluteValue ? this.max : this.goal.value))}%`;
142
+ };
143
+
144
+ this.formatValueLabel = function (value, options) {
145
+ return `<span style="display: flex; flex-direction: column; align-items: center; gap: 6px; font-size: ${
146
+ options.label.font_size
147
+ }px;">
148
+ <span style="font-weight: 600; font-size: 1.5em; line-height: 1; color: ${options.label.font_color}">
149
+ ${this.formatValue(value)}
150
+ ${
151
+ options.label.show_percentage_in_value
152
+ ? `<span style="font-size: 0.5833em; font-weight: 600; color: ${
153
+ options.gauge.colors.meta
154
+ };">(${this.toPercent(value)})</span>`
155
+ : ""
156
+ }
157
+ </span>
158
+ <span style="font-weight: 500; font-size: 0.875em; line-height: 1; color: ${
159
+ options.gauge.colors.meta
160
+ };">Current status</span>
161
+ </span>`;
162
+ };
163
+
164
+ this.formatTickLabel = function (value, options) {
165
+ const isGoal = value === options.goal.value;
166
+ const isLeftQuarter = this.isLeftQuarter(value);
167
+ const formattedValue = this.formatValue(value);
168
+
169
+ const goalStyles = isGoal ? `padding-${isLeftQuarter ? "right" : "left"}: 12px;` : "";
170
+ const goalValue = isGoal
171
+ ? `<span style="font-size: 1.125em; color: ${options.gauge.colors.goal};">${formattedValue}</span>`
172
+ : `<span style="color: ${options.label.font_color};">${formattedValue}</span>`;
173
+ const goalTitle =
174
+ isGoal && options.label.show_goal_name && options.goal.title
175
+ ? `<span style="font-size: 0.75em; color: ${options.gauge.colors.goal};">${options.goal.title}</span>`
176
+ : "";
177
+ const percentage = options.label.show_percentage_in_segments
178
+ ? `<span style="font-size: 0.75em; color: ${options.gauge.colors.meta}; font-weight: 400;">(${this.toPercent(
179
+ value
180
+ )})</span>`
181
+ : "";
182
+
183
+ return `<span style="
184
+ display: flex;
185
+ align-items: center;
186
+ gap: 4px;
187
+ font-weight: 600;
188
+ font-size: ${options.label.font_size}px;
189
+ ${goalStyles}
190
+ ">
191
+ ${goalValue}
192
+ ${goalTitle}
193
+ ${percentage}
194
+ </span>`;
195
+ };
196
+
197
+ this.getValue = function (pivotData, opts) {
198
+ const lineSeries = this.ptCreateBasicLineSeries(pivotData, null, true, null, null, opts, {});
199
+
200
+ let total = _.flatten(lineSeries
201
+ .map((s) => s.data.map((v) => v))
202
+ .filter((v) => !_.isNaN(v))
203
+ );
204
+
205
+ let aggfunc = (a, b) => a + b;
206
+ let base = 0;
207
+ let singleValueAgg = this.getSingleValueAgg(
208
+ {
209
+ value: {
210
+ value: "Sum",
211
+ },
212
+ },
213
+ aggfunc,
214
+ base
215
+ );
216
+
217
+ aggfunc = singleValueAgg.aggfunc;
218
+ base = singleValueAgg.base;
219
+
220
+ const aggregator = pivotData.getAggregator([], []);
221
+ const value = total.length > 0 ? total.reduce(aggfunc, base) : aggregator.value();
222
+
223
+ return value;
224
+ };
225
+
226
+ this.getBorderPosition = function (chart, options, position) {
227
+ const { center, size } = chart.pane[0].options;
228
+ const {
229
+ gauge: { tickLength, tickWidth },
230
+ } = options;
231
+
232
+ return {
233
+ x: position === "start" ? center[0] - size / 2 + tickLength / 2 : center[0] + size / 2 - tickLength / 2,
234
+ y: center[1] + tickWidth / 2,
235
+ };
236
+ };
237
+
238
+ this.createBorder = function (chart, options, position) {
239
+ return chart.renderer
240
+ .arc(
241
+ Object.assign(this.getBorderPosition(chart, options, position), {
242
+ r: options.gauge.thickness / 2,
243
+ innerR: 0,
244
+ start: 0,
245
+ end: Math.PI,
246
+ })
247
+ )
248
+ .attr({
249
+ fill:
250
+ position === "start"
251
+ ? chart.yAxis[0].options.plotBands[0].color
252
+ : chart.yAxis[0].options.plotBands.slice(-1)[0].color,
253
+ })
254
+ .add()
255
+ .toFront();
256
+ };
257
+
258
+ this.getGoalIconPosition = function (chart, options) {
259
+ const { center, size } = chart.pane[0].options;
260
+ const radius = size / 2;
261
+ const {
262
+ gauge: { goalIconSize },
263
+ goal: { value },
264
+ } = options;
265
+
266
+ return {
267
+ x: center[0] - radius * Math.sin(Math.PI / 2 - this.getAngleForValue(value)) - goalIconSize[0] / 2,
268
+ y: center[1] - radius * Math.cos(Math.PI / 2 - this.getAngleForValue(value)) - goalIconSize[1] / 2,
269
+ };
270
+ };
271
+
272
+ this.createGoalIcon = function (chart, options) {
273
+ const point = this.getGoalIconPosition(chart, options);
274
+ return chart.renderer
275
+ .image(options.gauge.goalIcon, point.x, point.y, options.gauge.goalIconSize[0], options.gauge.goalIconSize[1])
276
+ .add()
277
+ .toFront();
278
+ };
279
+
280
+ this.getValueLabelPosition = function (chart, options) {
281
+ const { center } = chart.pane[0].options;
282
+ return {
283
+ x: center[0],
284
+ y: center[1] + options.gauge.valueOffset[0],
285
+ };
286
+ };
287
+
288
+ this.createValueLabel = function (chart, options) {
289
+ const label = chart.renderer.text(this.formatValueLabel(this.value, options), 0, 0, true).add().toFront();
290
+
291
+ helpers.removeSVGTextCorrection(label, "yCorr");
292
+
293
+ label.attr(this.getValueLabelPosition(chart, options)).css({
294
+ transform: "translateX(-50%)",
295
+ });
296
+
297
+ return label;
298
+ };
299
+
300
+ this.getPaneDimensions = function (chart, options) {
301
+ const { renderer } = chart;
302
+ const valueLabel = this.createValueLabel(chart, this.options);
303
+ const { offset } = options.gauge;
304
+ const { height: labelH } = valueLabel.getBBox();
305
+
306
+ const offsetBottom = labelH + options.gauge.valueOffset[0] + options.gauge.valueOffset[2] + offset[2];
307
+ valueLabel.destroy();
308
+
309
+ const radiuses = [chart.chartWidth / 2 - Math.max(offset[1], offset[3]), chart.chartHeight - offsetBottom - offset[0]];
310
+ if (options.label.show) {
311
+ this.ticks.forEach((tick) => {
312
+ const label = renderer.label(this.formatTickLabel(tick, options), 0, 0, null, null, null, true).add();
313
+ const angle = this.getAngleForValue(tick);
314
+ // depends on label width
315
+ radiuses.push(
316
+ (chart.chartWidth / 2 - label.bBox.width - Math.max(offset[1], offset[3])) /
317
+ Math.sin(Math.abs(Math.PI / 2 - angle))
318
+ );
319
+ // depends on label height
320
+ radiuses.push(
321
+ (chart.chartHeight - offsetBottom - label.bBox.height / 2 - offset[0]) /
322
+ Math.cos(Math.abs(Math.PI / 2 - angle))
323
+ );
324
+ label.destroy();
325
+ });
326
+ } else {
327
+ // reserve space for the goal icon
328
+ const angle = this.getAngleForValue(options.goal.value);
329
+ const [iconW, iconH] = options.gauge.goalIconSize;
330
+ radiuses.push((chart.chartWidth / 2 - iconW / 2 - offset[1]) / Math.sin(Math.abs(Math.PI / 2 - angle)));
331
+ radiuses.push((chart.chartHeight - offsetBottom - iconH / 2 - offset[0]) / Math.cos(Math.abs(Math.PI / 2 - angle)));
332
+ }
333
+
334
+ return {
335
+ radius: Math.min(...radiuses),
336
+ center: [chart.chartWidth / 2, chart.chartHeight - offsetBottom],
337
+ };
338
+ };
339
+
340
+ this.setTicksStyles = function (chart, options) {
341
+ Object.keys(chart.yAxis[0].ticks).forEach((i) => {
342
+ const tick = chart.yAxis[0].ticks[i];
343
+ const isLeftQuarter = this.isLeftQuarter(tick.pos);
344
+
345
+ if (tick.pos === options.goal.value) {
346
+ tick.mark.attr({
347
+ stroke: options.gauge.colors.goal,
348
+ "stroke-dasharray": 2,
349
+ "pointer-events": "none",
350
+ });
351
+ }
352
+
353
+ if (!tick.label) return;
354
+
355
+ // align left querter's labels
356
+ tick.label.css({
357
+ transform: `translate(${isLeftQuarter ? "-100%" : 0}, 0)`,
358
+ });
359
+ });
360
+ };
361
+
362
+ this.addTooltips = function (chart, options) {
363
+ if (!options.tooltips.show) {
364
+ return false;
365
+ }
366
+
367
+ const drTooltip = new DrChartTooltip(chart, {
368
+ fontSize: options.tooltips.font_size,
369
+ fontFamily: options.tooltips.font_style,
370
+ color: options.tooltips.font_color,
371
+ });
372
+
373
+ // segment title tooltip
374
+ if (options.tooltips.show_segment_name) {
375
+ chart.yAxis[0].plotLinesAndBands.forEach((band, i) => {
376
+ drTooltip.add(band.options.title, band.svgElem.element, {
377
+ direction: "top",
378
+ followPointer: true,
379
+ });
380
+ });
381
+ }
382
+
383
+ // value label tooltip
384
+ if (options.tooltips.show_percentage_in_value && !options.label.show_percentage_in_value) {
385
+ drTooltip.add(this.toPercent(this.value), chart.label.element, {
386
+ direction: "top",
387
+ });
388
+ }
389
+
390
+ // segment name tooltips
391
+ Object.keys(chart.yAxis[0].ticks).forEach((i) => {
392
+ const tick = chart.yAxis[0].ticks[i];
393
+ const isLeftQuarter = this.isLeftQuarter(tick.pos);
394
+
395
+ // goal tooltip if lebels are hidden
396
+ if (tick.pos === options.goal.value && !options.label.show) {
397
+ drTooltip.add(
398
+ `${
399
+ options.label.show_goal_name ? options.goal.title || "" : ""
400
+ }<span style="font-weight: 600">${this.formatValue(options.goal.value)}</span>`,
401
+ chart.goalIcon.element,
402
+ {
403
+ direction: isLeftQuarter ? "left" : "right",
404
+ }
405
+ );
406
+ }
407
+
408
+ // segment label percentage tooltips
409
+ if (tick.label && options.tooltips.show_percentage_in_segments && !options.label.show_percentage_in_segments) {
410
+ drTooltip.add(this.toPercent(tick.pos), tick.label.element, {
411
+ direction: isLeftQuarter ? "left" : "right",
412
+ });
413
+ }
414
+ });
415
+ };
416
+
417
+ this.setPane = function (chart, options) {
418
+ const { radius, center } = this.getPaneDimensions(chart, options);
419
+ chart.pane[0].options.size = 2 * radius;
420
+ chart.pane[0].options.center = center;
421
+ chart.yAxis[0].options.plotBands.forEach((band) => {
422
+ band.outerRadius = radius - (options.gauge.tickLength - options.gauge.thickness) / 2;
423
+ });
424
+ chart.series[0].options.dial.radius = Math.round((100 * (radius - options.gauge.tickLength - 10)) / radius) + "%";
425
+ };
426
+
427
+ this.setCustomElements = function (chart, options) {
428
+ chart.label = this.createValueLabel(chart, options);
429
+ chart.startBorder = this.createBorder(chart, options, "start");
430
+ chart.endBorder = this.createBorder(chart, options, "end");
431
+ chart.goalIcon = this.createGoalIcon(chart, options);
432
+ };
433
+
434
+ this.updateCustomElements = function (chart, options) {
435
+ chart.startBorder.attr(this.getBorderPosition(chart, options, "start"));
436
+ chart.endBorder.attr(this.getBorderPosition(chart, options, "end"));
437
+ chart.goalIcon.attr(this.getGoalIconPosition(chart, options));
438
+ chart.label.attr(this.getValueLabelPosition(chart, options));
439
+ };
440
+
441
+ this.moveCustomElementsToFront = function (chart) {
442
+ chart.startBorder.toFront();
443
+ chart.endBorder.toFront();
444
+ chart.goalIcon.toFront();
445
+ };
446
+
447
+ this.clampValueToPane = function (value, max = this.max, min = this.min) {
448
+ const correction = Math.abs(max - min) * 0.02;
449
+ return helpers.clamp(min - correction, value, max + correction);
450
+ };
451
+
452
+ this.configChart = function () {
453
+ return {
454
+ title: {
455
+ text: null,
456
+ },
457
+ subtitle: null,
458
+ exporting: {
459
+ allowHTML: true,
460
+ },
461
+ tooltip: {
462
+ enabled: false,
463
+ },
464
+ chart: {
465
+ type: "gauge",
466
+ backgroundColor: this.options.gauge.background,
467
+ plotBackgroundColor: null,
468
+ plotBackgroundImage: null,
469
+ plotBorderWidth: 0,
470
+ plotShadow: false,
471
+ events: {
472
+ render: ({ target: chart }) => {
473
+ this.moveCustomElementsToFront(chart);
474
+ this.setTicksStyles(chart, this.options);
475
+ },
476
+ beforeRedraw: ({ target: chart }) => {
477
+ this.setPane(chart, this.options);
478
+ this.updateCustomElements(chart, this.options);
479
+ },
480
+ beforeRender: ({ target: chart }) => {
481
+ this.setPane(chart, this.options);
482
+ this.setCustomElements(chart, this.options);
483
+ },
484
+ load: ({ target: chart }) => {
485
+ this.addTooltips(chart, this.options);
486
+ },
487
+ },
488
+ margin: [0, 0, 0, 0],
489
+ spacing: [0, 0, 0, 0],
490
+ },
491
+
492
+ pane: {
493
+ startAngle: -90,
494
+ endAngle: 90,
495
+ background: null,
496
+ center: [0, 0],
497
+ },
498
+
499
+ // the value axis
500
+ yAxis: {
501
+ min: this.min,
502
+ max: this.max,
503
+ tickPositions: this.ticks,
504
+ tickPosition: "inside",
505
+ tickColor: this.options.gauge.background,
506
+ tickLength: this.options.gauge.tickLength,
507
+ tickWidth: this.options.gauge.tickWidth,
508
+ minorTickInterval: null,
509
+
510
+ labels: {
511
+ enabled: !!this.options.label.show,
512
+ distance: 0,
513
+ verticalAlign: "middle",
514
+ allowOverlap: true,
515
+ align: "left",
516
+ style: {
517
+ whiteSpace: "nowrap",
518
+ width: "auto",
519
+ },
520
+ formatter: ({ value }) => {
521
+ return this.formatTickLabel(value, this.options);
522
+ },
523
+ useHTML: true,
524
+ },
525
+ lineWidth: 0,
526
+ plotBands: this.plotBands,
527
+ },
528
+
529
+ series: [
530
+ {
531
+ name: null,
532
+ data: [this.clampValueToPane(this.value)],
533
+ dataLabels: [
534
+ {
535
+ enabled: false,
536
+ },
537
+ ],
538
+ dial: {
539
+ radius: "70%",
540
+ backgroundColor: this.options.gauge.pivot.color,
541
+ baseWidth: 2 * this.options.gauge.pivot.radius,
542
+ baseLength: "0%",
543
+ rearLength: "0%",
544
+ },
545
+ pivot: {
546
+ backgroundColor: this.options.gauge.pivot.color,
547
+ radius: this.options.gauge.pivot.radius,
548
+ },
549
+ },
550
+ ],
551
+ };
552
+ };
553
+
554
+ this.originalOptions = opts;
555
+ this.options = this.mergeOptions(opts.chartOptions);
556
+ this.aggregation = pivotData.getAggregator([], []);
557
+ this.format = this.aggregation.widget_values_format;
558
+ this.goal = this.options.goal;
559
+ this.plotBands = this.createPlotBands(this.options);
560
+ this.ticks = this.createTicks(this.plotBands, this.options);
561
+ this.value = this.getValue(pivotData, opts);
562
+ this.max = this.ticks[this.ticks.length - 1];
563
+ this.min = this.ticks[0];
564
+ }
565
+
566
+ module.exports = { DrGaugeChart, GAUGE_OPTIONS_DEFAULT };
@@ -0,0 +1,13 @@
1
+ declare interface IFormatValueResult {
2
+ value: string,
3
+ align?: 'right' | '',
4
+ color?: 'Red' | 'Green' | 'White' | 'Blue' | 'Magenta' | 'Yellow' | 'Cyan' | 'Black' | '',
5
+ pattern: string
6
+ }
7
+
8
+ declare class DataFormatterImpl {
9
+ formatValue(type: string, format: string, value: number, overrideFormat?: string): IFormatValueResult
10
+ }
11
+
12
+ declare const DataFormatter: DataFormatterImpl;
13
+ export = DataFormatter;
@@ -1,3 +1,5 @@
1
+ const _ = require('lodash');
2
+
1
3
  var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
2
4
 
3
5
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
@@ -350,7 +352,7 @@ var DataFormatterImpl = function () {
350
352
 
351
353
  n = this.roundDecimals(n, decimals).toString().split('.');
352
354
  var integerPart = n[0];
353
- var decimalPart = n[1] || 0;
355
+ var decimalPart = _.padEnd(String(n[1] || 0), decimals, '0');
354
356
 
355
357
  return this.applyNumberPattern(integerPart, patternIntegerPart) + this.locale.decimalSeparator + this.applyNumberPattern(decimalPart, patternDecimalPart, n[1] && n[1][0] == '0' ? '' : 'right');
356
358
  }
@@ -1026,9 +1028,49 @@ var DataFormatterImpl = function () {
1026
1028
 
1027
1029
  return result;
1028
1030
  }
1031
+ }, {
1032
+ key: 'formatValue',
1033
+ value: function formatValue(data_type, number_format, value, override_values_format) {
1034
+ if (!number_format) {
1035
+ number_format = 'General';
1036
+ }
1037
+
1038
+ if (Number.isNaN(value)) {
1039
+ return { value: "#Error" };
1040
+ }
1041
+
1042
+ if (data_type === 'n' && value != null) {
1043
+ if (override_values_format) {
1044
+ number_format = override_values_format;
1045
+ }
1046
+
1047
+ if (number_format.indexOf('[kilo]') >= 0) {
1048
+ value = value / 1000;
1049
+ number_format = number_format.replace('[kilo]', '');
1050
+ } else if (number_format.indexOf('[mega]') >= 0) {
1051
+ value = value / 1000000;
1052
+ number_format = number_format.replace('[mega]', '');
1053
+ } else if (number_format.indexOf('[kilomega]') >= 0) {
1054
+ number_format = number_format.replace('[kilomega]', '');
1055
+ }
1056
+
1057
+ return this.format(value, 'Number', number_format);
1058
+ } else if (data_type === 'd') {
1059
+ number_format = number_format.split(';')[0];
1060
+ let d;
1061
+ if (value instanceof Date || typeof value === 'string') {
1062
+ d = new Date(value);
1063
+ } else {
1064
+ d = new Date(value * 1000);
1065
+ }
1066
+ return this.format(d.toString(), 'DateTime', number_format);
1067
+ } else {
1068
+ return value;
1069
+ }
1070
+ }
1029
1071
  }]);
1030
1072
 
1031
1073
  return DataFormatterImpl;
1032
1074
  }();
1033
1075
 
1034
- module.exports = new DataFormatterImpl();
1076
+ module.exports = new DataFormatterImpl();