@datarailsshared/dr_renderer 1.4.121 → 1.4.129

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datarailsshared/dr_renderer",
3
- "version": "1.4.121",
3
+ "version": "1.4.129",
4
4
  "description": "DataRails charts and tables renderer",
5
5
  "keywords": [
6
6
  "datarails",
@@ -483,10 +483,22 @@ function DrGaugeChart(pivotData, opts, isDynamicGoal) {
483
483
  gauge: { thickness },
484
484
  } = options;
485
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
+
486
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
+
487
499
  return {
488
- from: isAbsoluteValue ? item.from : (item.from * goalValue) / 100,
489
- to: isAbsoluteValue ? item.to : (item.to * goalValue) / 100,
500
+ from: normalizedFrom,
501
+ to: normalizedTo,
490
502
  color: item.color,
491
503
  thickness: thickness,
492
504
  title: item.title,
@@ -634,10 +646,10 @@ function DrGaugeChart(pivotData, opts, isDynamicGoal) {
634
646
  this.options = this.mergeOptions(opts.chartOptions);
635
647
  this.aggregation = DrGaugeChart.getAggregation(pivotData, opts.chartOptions);
636
648
  this.format = this.aggregation.widget_values_format;
649
+ this.value = DrGaugeChart.getValue(pivotData, opts, isDynamicGoal);
637
650
  this.setGoal(pivotData, opts);
638
651
  this.plotBands = this.createPlotBands(this.options);
639
652
  this.ticks = this.createTicks(this.plotBands, this.options);
640
- this.value = DrGaugeChart.getValue(pivotData, opts, isDynamicGoal);
641
653
  this.max = this.ticks[this.ticks.length - 1];
642
654
  this.min = this.ticks[0];
643
655
  }
@@ -31,7 +31,7 @@ function isAbsoluteValue(formula) {
31
31
  if (!formula)
32
32
  return false;
33
33
 
34
- return lodash.includes(formula.replace(/\s+/g, ''), 'x2-x1');
34
+ return !lodash.includes(formula.replace(/\s+/g, ''), '/');
35
35
  };
36
36
 
37
37
  module.exports = {
@@ -310,6 +310,93 @@ describe("DrGaugeChart", () => {
310
310
  },
311
311
  ]);
312
312
  });
313
+
314
+ it("scales by needle magnitude when goal is 0 in percentage mode", () => {
315
+ chart.value = 250;
316
+ expect(
317
+ chart.createPlotBands({
318
+ isAbsoluteValue: false,
319
+ gauge: { thickness: 10 },
320
+ goal: { value: 0 },
321
+ segments: [
322
+ { from: 0, to: 50, color: "red", title: "Title 1" },
323
+ { from: 50, to: 100, color: "blue", title: "Title 2" },
324
+ ],
325
+ })
326
+ ).toEqual([
327
+ { from: 0, to: 125, color: "red", thickness: 10, title: "Title 1" },
328
+ { from: 125, to: 250, color: "blue", thickness: 10, title: "Title 2" },
329
+ ]);
330
+ });
331
+
332
+ it("scales by absolute needle magnitude when goal is not a number", () => {
333
+ const featureSpy = jest
334
+ .spyOn(DrGaugeChart.highchartsRenderer, "hasFeature")
335
+ .mockReturnValue(true);
336
+
337
+ chart.value = -300;
338
+ const res = chart.createPlotBands({
339
+ isAbsoluteValue: false,
340
+ gauge: { thickness: 8 },
341
+ goal: { value: undefined },
342
+ segments: [
343
+ { from: 0, to: 50, color: "#1", title: "A" },
344
+ { from: 50, to: 100, color: "#2", title: "B" },
345
+ ],
346
+ });
347
+
348
+ expect(res).toEqual([
349
+ { from: 0, to: 150, color: "#1", thickness: 8, title: "A" },
350
+ { from: 150, to: 300, color: "#2", thickness: 8, title: "B" },
351
+ ]);
352
+
353
+ featureSpy.mockRestore();
354
+ });
355
+
356
+ it("normalizes bands when goal is negative in percentage mode", () => {
357
+ const res = chart.createPlotBands({
358
+ isAbsoluteValue: false,
359
+ gauge: { thickness: 12 },
360
+ goal: { value: -1000 },
361
+ segments: [
362
+ { from: 0, to: 50, color: "r", title: "S1" },
363
+ { from: 50, to: 100, color: "b", title: "S2" },
364
+ ],
365
+ });
366
+
367
+ expect(res[0].from).toBe(-500);
368
+ expect(Math.abs(res[0].to)).toBe(0);
369
+ expect(res[0].color).toBe("r");
370
+ expect(res[0].thickness).toBe(12);
371
+ expect(res[0].title).toBe("S1");
372
+
373
+ expect(res[1]).toEqual({ from: -1000, to: -500, color: "b", thickness: 12, title: "S2" });
374
+ });
375
+
376
+ it("does not clamp last segment when dynamic goal feature is enabled", () => {
377
+ const featureSpy = jest
378
+ .spyOn(DrGaugeChart.highchartsRenderer, "hasFeature")
379
+ .mockReturnValue(true);
380
+
381
+ const res = chart.createPlotBands({
382
+ isAbsoluteValue: true,
383
+ gauge: { thickness: 10 },
384
+ goal: { value: 1800 },
385
+ segments: [
386
+ { from: 100, to: 200, color: "red", title: "Title 1" },
387
+ { from: 200, to: 400, color: "blue", title: "Title 2" },
388
+ { from: 400, to: 800, color: "green", title: "Title 3" },
389
+ ],
390
+ });
391
+
392
+ expect(res).toEqual([
393
+ { from: 100, to: 200, color: "red", thickness: 10, title: "Title 1" },
394
+ { from: 200, to: 400, color: "blue", thickness: 10, title: "Title 2" },
395
+ { from: 400, to: 800, color: "green", thickness: 10, title: "Title 3" },
396
+ ]);
397
+
398
+ featureSpy.mockRestore();
399
+ });
313
400
  });
314
401
 
315
402
  describe("createTicks", () => {
@@ -9,7 +9,8 @@ describe('Function getAggregatorPercentageValueIfRequired', () => {
9
9
  chartOptions: {
10
10
  delta_column: {
11
11
  name: 'Variance',
12
- formula: 'x2-x1'
12
+ formula: 'x2-x1',
13
+ is_percentage: false
13
14
  }
14
15
  }
15
16
  };
@@ -17,7 +18,7 @@ describe('Function getAggregatorPercentageValueIfRequired', () => {
17
18
  colKey = ['SomeCol'];
18
19
  });
19
20
 
20
- it('should return percentage string when all conditions are met', () => {
21
+ it('should return percentage string when secondaryAxisSettings.is_percentage is true but delta_column.is_percentage is false', () => {
21
22
  const data = {
22
23
  rowKeys: ['Variance'],
23
24
  getAggregator: jest.fn(() => ({
@@ -28,6 +29,19 @@ describe('Function getAggregatorPercentageValueIfRequired', () => {
28
29
  expect(result).toBe('25%');
29
30
  });
30
31
 
32
+ it('should return percentage string when secondaryAxisSettings.is_percentage is false but delta_column.is_percentage is true', () => {
33
+ const data = {
34
+ rowKeys: ['Variance'],
35
+ getAggregator: jest.fn(() => ({
36
+ value: () => 200
37
+ }))
38
+ };
39
+ render_options.comboOptions.secondaryAxisSettings.is_percentage = false;
40
+ render_options.chartOptions.delta_column.is_percentage = true;
41
+ const result = getAggregatorPercentageValueIfRequired(50, render_options, data, rowKey, colKey);
42
+ expect(result).toBe('25%');
43
+ });
44
+
31
45
  it('should return null if is_percentage is false', () => {
32
46
  const data = {
33
47
  rowKeys: ['Variance'],
@@ -111,20 +125,19 @@ describe('Function isAbsoluteValue', () => {
111
125
  expect(isAbsoluteValue(null)).toBe(false);
112
126
  });
113
127
 
114
- it('should return false if formula does not contain "x2-x1"', () => {
115
- expect(isAbsoluteValue('x2 + x1')).toBe(false);
116
- expect(isAbsoluteValue('x1-x2')).toBe(false);
117
- expect(isAbsoluteValue('')).toBe(false);
128
+ it('should return false if formula contains "/"', () => {
129
+ expect(isAbsoluteValue('/')).toBe(false);
130
+ expect(isAbsoluteValue(' / ')).toBe(false);
118
131
  });
119
132
 
120
- it('should return true if formula contains "x2-x1"', () => {
133
+ it('should return true if formula does not contain "/"', () => {
121
134
  expect(isAbsoluteValue('x2-x1')).toBe(true);
122
- expect(isAbsoluteValue(' x2 - x1 ')).toBe(true);
135
+ expect(isAbsoluteValue(' x1 - x2 ')).toBe(true);
123
136
  expect(isAbsoluteValue('some text x2-x1 more text')).toBe(true);
124
137
  });
125
138
 
126
139
  it('should ignore spaces in formula', () => {
127
140
  expect(isAbsoluteValue('x2 - x1')).toBe(true);
128
- expect(isAbsoluteValue(' x2 - x1 ')).toBe(true);
141
+ expect(isAbsoluteValue(' x1 - x2 ')).toBe(true);
129
142
  });
130
143
  });