@datarailsshared/dr_renderer 1.4.10 → 1.4.12
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.
- package/.github/workflows/release.yml +44 -0
- package/.whitesource +3 -0
- package/CODEOWNERS +1 -1
- package/README.md +46 -4
- package/package.json +5 -6
- package/src/charts/dr_donut_chart.js +3 -3
- package/src/charts/dr_gauge_categories_summary_chart.js +17 -17
- package/src/charts/dr_gauge_chart.js +226 -64
- package/src/dr-renderer-helpers.js +30 -13
- package/src/dr_pivottable.js +21 -29
- package/src/errors.js +174 -0
- package/src/highcharts_renderer.js +530 -343
- package/src/index.d.ts +63 -0
- package/src/index.js +14 -1
- package/src/pivot.css +0 -11
- package/src/pivottable.js +469 -508
- package/src/seriesPointStyles-helper.js +1 -1
- package/src/smart_queries_helper.js +62 -14
- package/src/types/errors.d.ts +120 -0
- package/src/types/index.d.ts +2 -0
- package/src/value.formatter.js +41 -0
- package/tests/dr-renderer-helpers.test.js +33 -0
- package/tests/dr_gauge_chart.test.js +88 -0
- package/tests/errors.test.js +157 -0
- package/tests/highcharts_renderer.test.js +1029 -67
- package/tests/mock/widgets.json +1 -3
- package/tests/ptCreateDrillDownSeriesToDrilldownChart.test.js +511 -0
- package/tests/value.formatter.test.js +143 -0
- package/tsconfig.json +2 -2
- package/tsconfig.tsbuildinfo +7 -0
- package/.github/workflows/build-deploy.yml +0 -30
- package/types/index.d.ts +0 -1
- /package/{types → src/types}/graph-table-renderer.d.ts +0 -0
@@ -51,7 +51,7 @@ const GAUGE_OPTIONS_DEFAULT = {
|
|
51
51
|
],
|
52
52
|
};
|
53
53
|
|
54
|
-
function DrGaugeChart(pivotData, opts) {
|
54
|
+
function DrGaugeChart(pivotData, opts, isDynamicGoal) {
|
55
55
|
this.render = function () {
|
56
56
|
return DrGaugeChart.highchartsRenderer.ptCreateElementAndDraw(this.configChart(), opts);
|
57
57
|
};
|
@@ -84,13 +84,20 @@ function DrGaugeChart(pivotData, opts) {
|
|
84
84
|
return (value - min) < (max - min) / 2;
|
85
85
|
};
|
86
86
|
|
87
|
-
this.createTicks =
|
87
|
+
this.createTicks = function(plotBands, options) {
|
88
|
+
return DrGaugeChart.createTicks(plotBands, options);
|
89
|
+
}
|
88
90
|
|
89
91
|
this.mergeOptions = function (options) {
|
92
|
+
const clone = (o) =>
|
93
|
+
o && typeof o === 'object'
|
94
|
+
? (globalThis.structuredClone ? structuredClone(o) : JSON.parse(JSON.stringify(o)))
|
95
|
+
: o;
|
96
|
+
|
90
97
|
return helpers.mergeDeep(
|
91
|
-
|
92
|
-
this.getDefaultValueForChart(DrGaugeChart.highchartsRenderer.CHART_TYPES.GAUGE_CHART_ENHANCED),
|
93
|
-
options
|
98
|
+
clone(GAUGE_OPTIONS_DEFAULT),
|
99
|
+
clone(this.getDefaultValueForChart(DrGaugeChart.highchartsRenderer.CHART_TYPES.GAUGE_CHART_ENHANCED)),
|
100
|
+
clone(options || {})
|
94
101
|
);
|
95
102
|
};
|
96
103
|
|
@@ -111,7 +118,7 @@ function DrGaugeChart(pivotData, opts) {
|
|
111
118
|
};
|
112
119
|
|
113
120
|
this.toPercent = function (value) {
|
114
|
-
return `${Math.round((value * 100) / (this.options.isAbsoluteValue ? this.max : this.goal.value))}%`;
|
121
|
+
return `${Math.round((value * 100) / (this.options.isAbsoluteValue ? this.max : this.options.goal.value))}%`;
|
115
122
|
};
|
116
123
|
|
117
124
|
this.formatValueLabel = function (value, options) {
|
@@ -139,9 +146,11 @@ function DrGaugeChart(pivotData, opts) {
|
|
139
146
|
const goalValue = isGoal
|
140
147
|
? `<span style="font-size: 1.125em; color: ${options.gauge.colors.goal};">${formattedValue}</span>`
|
141
148
|
: `<span style="color: ${options.label.font_color};">${formattedValue}</span>`;
|
149
|
+
|
150
|
+
const goalTitleText = DrGaugeChart.getGoalTitleText(options);
|
142
151
|
const goalTitle =
|
143
|
-
isGoal && options.label.show_goal_name &&
|
144
|
-
? `<span style="font-size: 0.75em; color: ${options.gauge.colors.goal};">${
|
152
|
+
isGoal && options.label.show_goal_name && goalTitleText
|
153
|
+
? `<span style="font-size: 0.75em; color: ${options.gauge.colors.goal};">${goalTitleText}</span>`
|
145
154
|
: "";
|
146
155
|
const percentage = options.label.show_percentage_in_segments
|
147
156
|
? `<span style="font-size: 0.75em; color: ${options.gauge.colors.meta}; font-weight: 400;">(${this.toPercent(
|
@@ -171,9 +180,17 @@ function DrGaugeChart(pivotData, opts) {
|
|
171
180
|
goal: { value },
|
172
181
|
} = options;
|
173
182
|
|
183
|
+
let valueForPosition = value;
|
184
|
+
let verticalOffset = 0;
|
185
|
+
|
186
|
+
if (DrGaugeChart.dynamicGoalFeatureEnabled() && (value > this.max || value < this.min)) {
|
187
|
+
valueForPosition = value > this.max ? this.max : this.min;
|
188
|
+
verticalOffset = 30;
|
189
|
+
}
|
190
|
+
|
174
191
|
return {
|
175
|
-
x: center[0] - radius * Math.sin(Math.PI / 2 - this.getAngleForValue(
|
176
|
-
y: center[1] - radius * Math.cos(Math.PI / 2 - this.getAngleForValue(
|
192
|
+
x: center[0] - radius * Math.sin(Math.PI / 2 - this.getAngleForValue(valueForPosition)) - goalIconSize[0] / 2,
|
193
|
+
y: center[1] + verticalOffset - radius * Math.cos(Math.PI / 2 - this.getAngleForValue(valueForPosition)) - goalIconSize[1] / 2,
|
177
194
|
};
|
178
195
|
};
|
179
196
|
|
@@ -197,46 +214,112 @@ function DrGaugeChart(pivotData, opts) {
|
|
197
214
|
return label;
|
198
215
|
};
|
199
216
|
|
217
|
+
this.getGoalLabelPosition = function (chart, options, goalLabel) {
|
218
|
+
const padding = 7;
|
219
|
+
const point = this.getGoalIconPosition(chart, options);
|
220
|
+
const isLower = options.goal.value < this.min;
|
221
|
+
|
222
|
+
return {
|
223
|
+
x: point.x + (isLower ? -goalLabel.element.clientWidth : padding),
|
224
|
+
y: point.y + padding,
|
225
|
+
};
|
226
|
+
}
|
227
|
+
|
228
|
+
this.createGoalLabel = function (chart, options) {
|
229
|
+
const label = chart.renderer.text(
|
230
|
+
this.formatTickLabel(options.goal.value, options), 0, 0, true
|
231
|
+
).add().toFront();
|
232
|
+
|
233
|
+
label.attr(this.getGoalLabelPosition(chart, options, label));
|
234
|
+
|
235
|
+
if (options.tooltips.show) {
|
236
|
+
const drTooltip = new DrChartTooltip(chart, {
|
237
|
+
fontSize: options.tooltips.font_size,
|
238
|
+
fontFamily: options.tooltips.font_style,
|
239
|
+
color: options.tooltips.font_color,
|
240
|
+
});
|
241
|
+
drTooltip.add(
|
242
|
+
this.toPercent(options.goal.value),
|
243
|
+
label.element,
|
244
|
+
{
|
245
|
+
direction: "right",
|
246
|
+
}
|
247
|
+
);
|
248
|
+
}
|
249
|
+
|
250
|
+
return label;
|
251
|
+
};
|
252
|
+
|
200
253
|
this.getPaneDimensions = function (chart, options) {
|
201
|
-
const
|
202
|
-
const
|
254
|
+
const valueLabel = this.createValueLabel(chart, options);
|
255
|
+
const { height: labelH } = valueLabel.getBBox ? valueLabel.getBBox() : { height: 0 };
|
256
|
+
valueLabel.destroy && valueLabel.destroy();
|
257
|
+
|
203
258
|
const { offset } = options.gauge;
|
204
|
-
const
|
259
|
+
const offsetTop = Array.isArray(offset) ? offset[0] : 0;
|
260
|
+
const offsetRight = Array.isArray(offset) ? offset[1] : 0;
|
261
|
+
const offsetBottomG= Array.isArray(offset) ? offset[2] : 0;
|
262
|
+
const offsetLeft = Array.isArray(offset) ? offset[3] : 0;
|
263
|
+
|
264
|
+
const vOff = options.gauge.valueOffset || [0,0,0,0];
|
205
265
|
|
206
|
-
const offsetBottom = labelH +
|
207
|
-
|
266
|
+
const offsetBottom = (labelH || 0) + (vOff[0] || 0) + (vOff[2] || 0) + (offsetBottomG || 0);
|
267
|
+
|
268
|
+
const safeDiv = (num, den) => {
|
269
|
+
const v = num / den;
|
270
|
+
return Number.isFinite(v) ? v : Infinity;
|
271
|
+
};
|
272
|
+
|
273
|
+
const radiuses = [
|
274
|
+
chart.chartWidth / 2 - Math.max(offsetRight || 0, offsetLeft || 0),
|
275
|
+
chart.chartHeight - offsetBottom - (offsetTop || 0),
|
276
|
+
];
|
208
277
|
|
209
|
-
const radiuses = [chart.chartWidth / 2 - Math.max(offset[1], offset[3]), chart.chartHeight - offsetBottom - offset[0]];
|
210
278
|
if (options.label.show) {
|
211
279
|
this.ticks.forEach((tick) => {
|
212
|
-
const label = renderer
|
280
|
+
const label = chart.renderer
|
281
|
+
.label(this.formatTickLabel(tick, options), 0, 0, null, null, null, true)
|
282
|
+
.add();
|
283
|
+
|
213
284
|
const angle = this.getAngleForValue(tick);
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
Math.sin(Math.abs(Math.PI / 2 - angle))
|
218
|
-
);
|
219
|
-
// depends on label height
|
285
|
+
const s = Math.sin(Math.abs(Math.PI / 2 - angle));
|
286
|
+
const c = Math.cos(Math.abs(Math.PI / 2 - angle));
|
287
|
+
|
220
288
|
radiuses.push(
|
221
|
-
(
|
222
|
-
|
289
|
+
safeDiv(
|
290
|
+
chart.chartWidth / 2 - label.bBox.width - Math.max(offsetRight || 0, offsetLeft || 0),
|
291
|
+
s
|
292
|
+
),
|
293
|
+
safeDiv(
|
294
|
+
chart.chartHeight - offsetBottom - label.bBox.height / 2 - (offsetTop || 0),
|
295
|
+
c
|
296
|
+
)
|
223
297
|
);
|
224
|
-
|
298
|
+
|
299
|
+
label.destroy && label.destroy();
|
225
300
|
});
|
226
301
|
} else {
|
227
|
-
// reserve space for the goal icon
|
228
302
|
const angle = this.getAngleForValue(options.goal.value);
|
229
|
-
const [iconW, iconH] = options.gauge.goalIconSize;
|
230
|
-
|
231
|
-
|
303
|
+
const [iconW, iconH] = options.gauge.goalIconSize || [0, 0];
|
304
|
+
const s = Math.sin(Math.abs(Math.PI / 2 - angle));
|
305
|
+
const c = Math.cos(Math.abs(Math.PI / 2 - angle));
|
306
|
+
|
307
|
+
radiuses.push(
|
308
|
+
safeDiv(chart.chartWidth / 2 - iconW / 2 - (offsetRight || 0), s),
|
309
|
+
safeDiv(chart.chartHeight - offsetBottom - iconH / 2 - (offsetTop || 0), c)
|
310
|
+
);
|
232
311
|
}
|
233
312
|
|
313
|
+
const finite = radiuses.filter(Number.isFinite);
|
314
|
+
const radius = finite.length ? Math.min(...finite) : 0;
|
315
|
+
|
234
316
|
return {
|
235
|
-
radius
|
317
|
+
radius,
|
236
318
|
center: [chart.chartWidth / 2, chart.chartHeight - offsetBottom],
|
237
319
|
};
|
238
320
|
};
|
239
321
|
|
322
|
+
|
240
323
|
this.setTicksStyles = function (chart, options) {
|
241
324
|
const ticks = chart.yAxis[0].ticks;
|
242
325
|
Object.keys(ticks).forEach((i) => {
|
@@ -265,7 +348,7 @@ function DrGaugeChart(pivotData, opts) {
|
|
265
348
|
};
|
266
349
|
|
267
350
|
this.updateLabelsWhenGoalIsHidden = function (ticks, options) {
|
268
|
-
if (ticks[options.goal.value].label.opacity === 0) {
|
351
|
+
if (ticks[options.goal.value] && ticks[options.goal.value].label.opacity === 0) {
|
269
352
|
|
270
353
|
const ticksArray = Object.entries(ticks);
|
271
354
|
|
@@ -330,7 +413,7 @@ function DrGaugeChart(pivotData, opts) {
|
|
330
413
|
// goal tooltip if lebels are hidden
|
331
414
|
if (tick.pos === options.goal.value && !options.label.show) {
|
332
415
|
drTooltip.add(
|
333
|
-
`${options.label.show_goal_name ? options
|
416
|
+
`${options.label.show_goal_name ? DrGaugeChart.getGoalTitleText(options) || "" : ""
|
334
417
|
}<span style="font-weight: 600">${this.formatValue(options.goal.value)}</span>`,
|
335
418
|
chart.goalIcon.element,
|
336
419
|
{
|
@@ -350,19 +433,35 @@ function DrGaugeChart(pivotData, opts) {
|
|
350
433
|
|
351
434
|
this.setPane = function (chart, options) {
|
352
435
|
const { radius, center } = this.getPaneDimensions(chart, options);
|
353
|
-
|
436
|
+
|
437
|
+
const MIN_RADIUS = Math.max(8, options.gauge.thickness / 2 + 1);
|
438
|
+
const R = Math.max(MIN_RADIUS, radius);
|
439
|
+
|
440
|
+
chart.pane[0].options.size = 2 * R;
|
354
441
|
chart.pane[0].options.center = center;
|
442
|
+
|
443
|
+
const effectiveTick = Math.min(options.gauge.tickLength, Math.floor(R * 0.8));
|
444
|
+
chart.yAxis[0].options.tickLength = effectiveTick;
|
445
|
+
|
355
446
|
chart.yAxis[0].options.plotBands.forEach((band) => {
|
356
|
-
band.outerRadius =
|
447
|
+
band.outerRadius = Math.max(1, R - (effectiveTick - options.gauge.thickness) / 2);
|
357
448
|
});
|
358
|
-
|
449
|
+
|
450
|
+
chart.series[0].options.dial.radius = R > 0
|
451
|
+
? Math.round((100 * (R - effectiveTick - 10)) / R) + "%"
|
452
|
+
: "0%";
|
359
453
|
};
|
360
454
|
|
455
|
+
|
361
456
|
this.setCustomElements = function (chart, options) {
|
362
457
|
chart.label = this.createValueLabel(chart, options);
|
363
458
|
chart.startBorder = DrGaugeChart.createBorder(chart, options, "start");
|
364
459
|
chart.endBorder = DrGaugeChart.createBorder(chart, options, "end");
|
365
460
|
chart.goalIcon = this.createGoalIcon(chart, options);
|
461
|
+
|
462
|
+
if (DrGaugeChart.dynamicGoalFeatureEnabled() && (options.goal.value > this.max || options.goal.value < this.min)) {
|
463
|
+
chart.goalLabel = this.createGoalLabel(chart, options);
|
464
|
+
}
|
366
465
|
};
|
367
466
|
|
368
467
|
this.updateCustomElements = function (chart, options) {
|
@@ -370,6 +469,10 @@ function DrGaugeChart(pivotData, opts) {
|
|
370
469
|
chart.endBorder.attr(DrGaugeChart.getBorderPosition(chart, options, "end"));
|
371
470
|
chart.goalIcon.attr(this.getGoalIconPosition(chart, options));
|
372
471
|
chart.label.attr(DrGaugeChart.getValueLabelPosition(chart, options));
|
472
|
+
|
473
|
+
if (chart.goalLabel) {
|
474
|
+
chart.goalLabel.attr(this.getGoalLabelPosition(chart, options, chart.goalLabel));
|
475
|
+
}
|
373
476
|
};
|
374
477
|
|
375
478
|
this.createPlotBands = function (options) {
|
@@ -380,10 +483,22 @@ function DrGaugeChart(pivotData, opts) {
|
|
380
483
|
gauge: { thickness },
|
381
484
|
} = options;
|
382
485
|
|
486
|
+
// If goal is not positive in percentage mode, scale segments by the current needle magnitude
|
487
|
+
const scaleBase = !isAbsoluteValue && (!helpers.isNumber(goalValue) || goalValue === 0)
|
488
|
+
? (helpers.isNumber(this.value) && Math.abs(this.value)) || 1
|
489
|
+
: goalValue;
|
490
|
+
|
383
491
|
const bands = segments.map((item) => {
|
492
|
+
const fromValue = isAbsoluteValue ? item.from : (item.from * scaleBase) / 100;
|
493
|
+
const toValue = isAbsoluteValue ? item.to : (item.to * scaleBase) / 100;
|
494
|
+
|
495
|
+
// Ensure a valid interval for Highcharts plotBands even when goal is negative
|
496
|
+
const normalizedFrom = Math.min(fromValue, toValue);
|
497
|
+
const normalizedTo = Math.max(fromValue, toValue);
|
498
|
+
|
384
499
|
return {
|
385
|
-
from:
|
386
|
-
to:
|
500
|
+
from: normalizedFrom,
|
501
|
+
to: normalizedTo,
|
387
502
|
color: item.color,
|
388
503
|
thickness: thickness,
|
389
504
|
title: item.title,
|
@@ -391,7 +506,9 @@ function DrGaugeChart(pivotData, opts) {
|
|
391
506
|
});
|
392
507
|
|
393
508
|
// clamp last segment
|
394
|
-
|
509
|
+
if (!DrGaugeChart.dynamicGoalFeatureEnabled()) {
|
510
|
+
bands[bands.length - 1].to = Math.max(bands[bands.length - 1].to, goalValue);
|
511
|
+
}
|
395
512
|
|
396
513
|
return bands;
|
397
514
|
};
|
@@ -400,6 +517,10 @@ function DrGaugeChart(pivotData, opts) {
|
|
400
517
|
chart.startBorder.toFront();
|
401
518
|
chart.endBorder.toFront();
|
402
519
|
chart.goalIcon.toFront();
|
520
|
+
|
521
|
+
if (chart.goalLabel) {
|
522
|
+
chart.goalLabel.toFront();
|
523
|
+
}
|
403
524
|
};
|
404
525
|
|
405
526
|
this.clampValueToPane = function (value, max = this.max, min = this.min) {
|
@@ -407,6 +528,16 @@ function DrGaugeChart(pivotData, opts) {
|
|
407
528
|
return helpers.clamp(min - correction, value, max + correction);
|
408
529
|
};
|
409
530
|
|
531
|
+
this.setGoal = function (pivotData, opts) {
|
532
|
+
if (isDynamicGoal) {
|
533
|
+
this.options.goal = {
|
534
|
+
title: DrGaugeChart.getGoalTitleText(this.options),
|
535
|
+
value: DrGaugeChart.getValue(pivotData, opts, true, true),
|
536
|
+
};
|
537
|
+
}
|
538
|
+
this.goal = this.options.goal;
|
539
|
+
};
|
540
|
+
|
410
541
|
this.configChart = function () {
|
411
542
|
return {
|
412
543
|
title: {
|
@@ -513,18 +644,25 @@ function DrGaugeChart(pivotData, opts) {
|
|
513
644
|
|
514
645
|
this.originalOptions = opts;
|
515
646
|
this.options = this.mergeOptions(opts.chartOptions);
|
516
|
-
this.aggregation =
|
647
|
+
this.aggregation = DrGaugeChart.getAggregation(pivotData, opts.chartOptions);
|
517
648
|
this.format = this.aggregation.widget_values_format;
|
518
|
-
this.
|
649
|
+
this.value = DrGaugeChart.getValue(pivotData, opts, isDynamicGoal);
|
650
|
+
this.setGoal(pivotData, opts);
|
519
651
|
this.plotBands = this.createPlotBands(this.options);
|
520
652
|
this.ticks = this.createTicks(this.plotBands, this.options);
|
521
|
-
this.value = DrGaugeChart.getValue(pivotData, opts);
|
522
653
|
this.max = this.ticks[this.ticks.length - 1];
|
523
654
|
this.min = this.ticks[0];
|
524
655
|
}
|
525
656
|
|
526
657
|
DrGaugeChart.createTicks = function (plotBands, options) {
|
527
|
-
|
658
|
+
const goal = options.goal.value;
|
659
|
+
const ticks = [plotBands[0].from || 0, ...plotBands.map((b) => b.to)];
|
660
|
+
|
661
|
+
if (!DrGaugeChart.dynamicGoalFeatureEnabled() || goal < Math.max(...ticks) && goal > Math.min(...ticks)) {
|
662
|
+
ticks.push(options.goal.value);
|
663
|
+
}
|
664
|
+
|
665
|
+
return _.uniq(ticks.sort((a, b) => a - b));
|
528
666
|
};
|
529
667
|
|
530
668
|
DrGaugeChart.getBorderPosition = function (chart, options, position) {
|
@@ -583,33 +721,57 @@ DrGaugeChart.getSingleValueAgg = function (opts, aggfunc, base) {
|
|
583
721
|
return DrGaugeChart.highchartsRenderer.getSingleValueAgg(opts, aggfunc, base);
|
584
722
|
};
|
585
723
|
|
586
|
-
DrGaugeChart.
|
587
|
-
|
724
|
+
DrGaugeChart.getAggregation = function(pivotData, options, isForGoal = false) {
|
725
|
+
if (_.get(options, 'dynamicGaugeConfig')) {
|
726
|
+
return pivotData.getAggregator([], [isForGoal ? options.dynamicGaugeConfig.goal : options.dynamicGaugeConfig.needle]);
|
727
|
+
}
|
728
|
+
return pivotData.getAggregator([], []);
|
729
|
+
}
|
588
730
|
|
589
|
-
let total = _.flatten(lineSeries
|
590
|
-
.map((s) => s.data.map((v) => v))
|
591
|
-
.filter((v) => !_.isNaN(v))
|
592
|
-
);
|
593
731
|
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
732
|
+
DrGaugeChart.getValue = function (pivotData, opts, isDynamicGoal = false, isForGoal = false) {
|
733
|
+
const aggregator = DrGaugeChart.getAggregation(pivotData, opts.chartOptions, isForGoal)
|
734
|
+
|
735
|
+
let total;
|
736
|
+
if (!isDynamicGoal) {
|
737
|
+
const lineSeries = DrGaugeChart.ptCreateBasicLineSeries(pivotData, null, true, null, null, opts, {});
|
738
|
+
|
739
|
+
total = _.flatten(lineSeries
|
740
|
+
.map((s) => s.data.map((v) => v))
|
741
|
+
.filter((v) => !_.isNaN(v))
|
742
|
+
);
|
743
|
+
|
744
|
+
let aggfunc = (a, b) => a + b;
|
745
|
+
let base = 0;
|
746
|
+
let singleValueAgg = DrGaugeChart.getSingleValueAgg(
|
747
|
+
{
|
748
|
+
value: {
|
749
|
+
value: "Sum",
|
750
|
+
},
|
600
751
|
},
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
);
|
752
|
+
aggfunc,
|
753
|
+
base
|
754
|
+
);
|
605
755
|
|
606
|
-
|
607
|
-
|
756
|
+
aggfunc = singleValueAgg.aggfunc;
|
757
|
+
base = singleValueAgg.base;
|
608
758
|
|
609
|
-
|
610
|
-
|
759
|
+
if (total.length > 0) {
|
760
|
+
return total.reduce(aggfunc, base);
|
761
|
+
}
|
762
|
+
}
|
611
763
|
|
612
|
-
return value;
|
764
|
+
return aggregator.value();
|
613
765
|
};
|
614
766
|
|
767
|
+
DrGaugeChart.getGoalTitleText = function(options) {
|
768
|
+
return DrGaugeChart.dynamicGoalFeatureEnabled()
|
769
|
+
? _.get(options, 'label.goal_name') || options.goal.title
|
770
|
+
: options.goal.title;
|
771
|
+
}
|
772
|
+
|
773
|
+
DrGaugeChart.dynamicGoalFeatureEnabled = function() {
|
774
|
+
return DrGaugeChart.highchartsRenderer.hasFeature(helpers.FEATURES.ENABLE_GAUGE_DYNAMIC_GOAL);
|
775
|
+
}
|
776
|
+
|
615
777
|
module.exports = { DrGaugeChart, GAUGE_OPTIONS_DEFAULT };
|
@@ -18,25 +18,32 @@ function isNumber(n) {
|
|
18
18
|
}
|
19
19
|
|
20
20
|
function mergeDeep(target, ...sources) {
|
21
|
-
const
|
21
|
+
const deepClone = (val) => {
|
22
|
+
if (Array.isArray(val)) return val.map(deepClone);
|
23
|
+
if (_.isPlainObject(val)) {
|
24
|
+
const out = {};
|
25
|
+
for (const k of Object.keys(val)) out[k] = deepClone(val[k]);
|
26
|
+
return out;
|
27
|
+
}
|
28
|
+
return val;
|
29
|
+
};
|
22
30
|
|
23
|
-
if (!
|
31
|
+
if (!_.isPlainObject(target)) return target;
|
24
32
|
|
25
|
-
|
26
|
-
if (!
|
33
|
+
for (const source of sources) {
|
34
|
+
if (!_.isPlainObject(source)) continue;
|
27
35
|
|
28
|
-
Object.keys(source)
|
29
|
-
const
|
30
|
-
const
|
36
|
+
for (const key of Object.keys(source)) {
|
37
|
+
const tVal = target[key];
|
38
|
+
const sVal = source[key];
|
31
39
|
|
32
|
-
if (
|
33
|
-
target[key] = mergeDeep(
|
40
|
+
if (_.isPlainObject(tVal) && _.isPlainObject(sVal)) {
|
41
|
+
target[key] = mergeDeep({}, tVal, sVal);
|
34
42
|
} else {
|
35
|
-
target[key] =
|
43
|
+
target[key] = deepClone(sVal);
|
36
44
|
}
|
37
|
-
}
|
38
|
-
}
|
39
|
-
|
45
|
+
}
|
46
|
+
}
|
40
47
|
return target;
|
41
48
|
}
|
42
49
|
|
@@ -66,6 +73,15 @@ function isShowingEmptyValues(additionOptions) {
|
|
66
73
|
return !additionOptions || !additionOptions.chart || additionOptions.chart.dislay_empty_values !== false;
|
67
74
|
}
|
68
75
|
|
76
|
+
const FEATURES = {
|
77
|
+
ENABLE_NEW_WIDGET_VALUE_FORMATTING: 'enable_new_widget_value_formatting',
|
78
|
+
FORMAT_DATES_AS_OTHER_AXIS_TYPES: 'format_dates_as_other_axis_types',
|
79
|
+
MULTIPLE_DIMENSION_TAGS: 'multiple_dimension_tags',
|
80
|
+
USE_NEW_SCENARIO_TAG: 'use_new_scenario_tag',
|
81
|
+
ENABLE_SERVER_WIDGET_DATA_SORTING: 'enable_server_widget_data_sorting',
|
82
|
+
ENABLE_GAUGE_DYNAMIC_GOAL: 'enable_gauge_dynamic_goal',
|
83
|
+
}
|
84
|
+
|
69
85
|
module.exports = {
|
70
86
|
backendSortingKeysAreNotEmpty,
|
71
87
|
capitalize,
|
@@ -75,4 +91,5 @@ module.exports = {
|
|
75
91
|
removeSVGTextCorrection,
|
76
92
|
disableLegendInteractionIfRequired,
|
77
93
|
isShowingEmptyValues,
|
94
|
+
FEATURES
|
78
95
|
}
|
package/src/dr_pivottable.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
const { DR_SCENARIO } = require('./smart_queries_helper');
|
2
|
-
|
2
|
+
const { TooMuchDataError } = require('./errors');
|
3
3
|
|
4
4
|
let initDRPivotTable = function($, window, document) {
|
5
5
|
var hasProp = {}.hasOwnProperty;
|
@@ -177,7 +177,7 @@ let initDRPivotTable = function($, window, document) {
|
|
177
177
|
return keys.join(delim);
|
178
178
|
}
|
179
179
|
|
180
|
-
DRPivotData.prototype.processRecord = function(record) {
|
180
|
+
DRPivotData.prototype.processRecord = function(record, isSmartQueriesEnabled) {
|
181
181
|
if (!this.notFirst) {
|
182
182
|
this.keysLength = _.filter(_.keys(record), key => !_.includes(['data_types', 'formats', 'values_formats'], key)).length - 1;
|
183
183
|
this.notFirst = true;
|
@@ -211,7 +211,7 @@ let initDRPivotTable = function($, window, document) {
|
|
211
211
|
if (!colKey.length && !rowKey.length) {
|
212
212
|
this.allTotal.push(record);
|
213
213
|
} else if (!colKey.length && rowKey.length) {
|
214
|
-
if (!this.rowTotals[flatRowKey]) {
|
214
|
+
if (!this.rowTotals[flatRowKey] || isSmartQueriesEnabled) {
|
215
215
|
this.rowTotals[flatRowKey] = getRowAggregator(rowKey.slice());
|
216
216
|
this.rowTotals[flatRowKey].push(record);
|
217
217
|
}
|
@@ -437,7 +437,6 @@ let initDRPivotTable = function($, window, document) {
|
|
437
437
|
|
438
438
|
return resultsArr;
|
439
439
|
} else {
|
440
|
-
let tooMuch = false;
|
441
440
|
const show_more_than_thousand_rows = _.get(opts, 'chartOptions.table_options.show_more_than_thousand_rows', false);
|
442
441
|
if (pvtData &&
|
443
442
|
(pvtData.rowKeys.length > 1000 || pvtData.colKeys.length > 500) &&
|
@@ -445,15 +444,16 @@ let initDRPivotTable = function($, window, document) {
|
|
445
444
|
!show_more_than_thousand_rows) {
|
446
445
|
pvtData.rowKeys = [];
|
447
446
|
pvtData.colKeys = [];
|
448
|
-
|
449
|
-
|
450
|
-
|
447
|
+
|
448
|
+
const tooMuchDataError = new TooMuchDataError();
|
449
|
+
console.error(tooMuchDataError.title);
|
450
|
+
throw tooMuchDataError;
|
451
451
|
}
|
452
|
-
return SubtotalRenderer(pvtData, opts, charttype
|
452
|
+
return SubtotalRenderer(pvtData, opts, charttype);
|
453
453
|
}
|
454
454
|
}
|
455
455
|
|
456
|
-
SubtotalRenderer = function(pivotData, opts, charttype
|
456
|
+
SubtotalRenderer = function(pivotData, opts, charttype) {
|
457
457
|
var addClass, allTotal, arrowCollapsed, arrowExpanded, buildColHeaderHeader, buildColHeaderHeaders, buildColHeaderHeadersClickEvents, buildColHeaders, buildColTotals, buildColTotalsHeader, buildGrandTotal, buildRowHeaderHeaders, buildRowHeaderHeadersClickEvents, buildRowHeaders, buildRowTotalsHeader, buildValues, classColCollapsed, classColExpanded, classColHide, classColShow, classCollapsed, classExpanded, classRowCollapsed, classRowExpanded, classRowHide, classRowShow, clickStatusCollapsed, clickStatusExpanded, colAttrs, colDisableAfter, colKeys, colTotals, collapseCol, collapseColsAt, collapseHideDescendantRow, collapseRow, collapseRowsAt, collapseShowColSubtotal, collapseShowRowSubtotal, applyInlineStyles, createElement, defaults, expandChildCol, expandChildRow, expandCol, expandColsAt, expandHideColSubtotal, expandHideRowSubtotal, expandRow, expandRowsAt, expandShowColSubtotal, expandShowRowSubtotal, getTableEventHandlers, hasClass, hideDescendantCol, isColDisable, isColDisableExpandCollapse, isColHideOnExpand, isRowDisable, isRowDisableExpandCollapse, isRowHideOnExpand, main, getSubtotalInBrackets, processKeys, encodeHtmlEntities, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, removeClass, replaceClass, rowAttrs, rowDisableAfter, rowKeys, rowTotals, setAttributes, showChildCol, showChildRow, toggleCol, toggleColHeaderHeader, toggleRow, toggleRowHeaderHeader, tree, subscribeToClick;
|
458
458
|
var createTotalValsBolder, createGrandTotalBolder, getHeaderColorProperties, colorizeRowLabelHeaders, colorizeTableIfNeed, valueNoDashes, getColorsWithOffsetForTable, offsetColors, handleFreezePanesScroll, selectFreezableElements, removeRowHeaderNullValue;
|
459
459
|
var getAdditionalAggregation, buildAdditionalHeaderCols, buildAdditionalHeaderRows, buildAdditionalColValues, buildAdditionalRowValues, buildAdditionalRowTotals, buildAdditionalColTotals;
|
@@ -1526,7 +1526,7 @@ let initDRPivotTable = function($, window, document) {
|
|
1526
1526
|
if (opts.chartOptions.isSmartQueriesEnabled && flatRowKey.split(' , ').includes(DR_SCENARIO.Forecast)) {
|
1527
1527
|
const actualsRow = tree[flatRowKey.replace(DR_SCENARIO.Forecast, DR_SCENARIO.SQ_Actuals)] || {};
|
1528
1528
|
if (actualsRow && actualsRow[flatColKey]) {
|
1529
|
-
val += actualsRow[flatColKey]
|
1529
|
+
val += (actualsRow[flatColKey] && actualsRow[flatColKey].value()) || 0;
|
1530
1530
|
}
|
1531
1531
|
}
|
1532
1532
|
isColSubtotal = colHeader.children.length !== 0;
|
@@ -1572,7 +1572,7 @@ let initDRPivotTable = function($, window, document) {
|
|
1572
1572
|
|
1573
1573
|
val = totalAggregator.value();
|
1574
1574
|
if (opts.chartOptions.isSmartQueriesEnabled && flatRowKey.split(' , ').includes(DR_SCENARIO.Forecast)) {
|
1575
|
-
val += rowTotals[flatRowKey.replace(DR_SCENARIO.Forecast, DR_SCENARIO.SQ_Actuals)]
|
1575
|
+
val += _.get(rowTotals[flatRowKey.replace(DR_SCENARIO.Forecast, DR_SCENARIO.SQ_Actuals)], 'value', () => null)() || 0;
|
1576
1576
|
}
|
1577
1577
|
style = "pvtTotal rowTotal";
|
1578
1578
|
if (isRowSubtotal) {
|
@@ -2356,6 +2356,9 @@ let initDRPivotTable = function($, window, document) {
|
|
2356
2356
|
main = function(rowAttrs, rowKeys, colAttrs, colKeys, pivotData) {
|
2357
2357
|
if (opts.chartOptions.isSmartQueriesEnabled) {
|
2358
2358
|
rowKeys = rowKeys.filter(rowKey => !rowKey.includes(DR_SCENARIO.SQ_Actuals));
|
2359
|
+
rowKeys = Array.from(
|
2360
|
+
new Set(rowKeys.map(JSON.stringify))
|
2361
|
+
).map(JSON.parse);
|
2359
2362
|
}
|
2360
2363
|
var c,rowspan, colHeaderCols, colHeaderHeaders, colHeaders, h, k, l, len, len1, result, rowHeaderHeaders, rowHeaderRows, rowHeaders, tbody, thead, tr;
|
2361
2364
|
rowHeaders = [];
|
@@ -2494,24 +2497,13 @@ let initDRPivotTable = function($, window, document) {
|
|
2494
2497
|
resultsArr.push(subTitle);
|
2495
2498
|
}
|
2496
2499
|
|
2497
|
-
|
2498
|
-
|
2499
|
-
|
2500
|
-
|
2501
|
-
|
2502
|
-
</div>
|
2503
|
-
`);
|
2504
|
-
|
2505
|
-
resultsArr.push($.pivotUtilities.errorHandling.getErrorPlaceholder(error_params) || defaultPlaceholder);
|
2506
|
-
} else {
|
2507
|
-
var tableContainer = document.createElement("div");
|
2508
|
-
tableContainer.className = "pivot-div";
|
2509
|
-
tableContainer.appendChild(result);
|
2510
|
-
if (opts.chartOptions.table_options.freeze_panes) {
|
2511
|
-
tableContainer.onscroll = handleFreezePanesScroll(selectFreezableElements(tableContainer));
|
2512
|
-
}
|
2513
|
-
resultsArr.push(tableContainer);
|
2500
|
+
var tableContainer = document.createElement("div");
|
2501
|
+
tableContainer.className = "pivot-div";
|
2502
|
+
tableContainer.appendChild(result);
|
2503
|
+
if (opts.chartOptions.table_options.freeze_panes) {
|
2504
|
+
tableContainer.onscroll = handleFreezePanesScroll(selectFreezableElements(tableContainer));
|
2514
2505
|
}
|
2506
|
+
resultsArr.push(tableContainer);
|
2515
2507
|
|
2516
2508
|
var wrapper = document.createElement("div");
|
2517
2509
|
wrapper.className = "pivot-wrapper";
|
@@ -2522,7 +2514,7 @@ let initDRPivotTable = function($, window, document) {
|
|
2522
2514
|
};
|
2523
2515
|
return main(rowAttrs, rowKeys, colAttrs, colKeys, pivotData);
|
2524
2516
|
};
|
2525
|
-
|
2517
|
+
|
2526
2518
|
$.pivotUtilities.subtotal_renderers = NovixRenderer;
|
2527
2519
|
$.pivotUtilities.delim = delim;
|
2528
2520
|
|