@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.
@@ -376,13 +376,14 @@ let initNovixRenderer = function($, window, document, Handsontable){
376
376
  //data columns
377
377
  if (pvtData.colKeys.length > 0) {
378
378
 
379
+ const formattedColKeys = pvtData.getFormattedColKeys(colKeys);
379
380
  var aux = rowData.length;
380
381
  var startCol = aux;
381
- var prior = colKeys[0][nn];
382
+ var prior = formattedColKeys[0][nn];
382
383
  var toMerge = 0;
383
- for (var cc = 0; cc < colKeys.length; cc++) {
384
+ for (var cc = 0; cc < formattedColKeys.length; cc++) {
384
385
 
385
- var textHeader = colKeys[cc][nn];
386
+ var textHeader = formattedColKeys[cc][nn];
386
387
 
387
388
  if (nn < pvtData.colAttrs.length - 1 && prior != textHeader) {
388
389
  rowData.push(textHeader);
@@ -456,8 +457,9 @@ let initNovixRenderer = function($, window, document, Handsontable){
456
457
  // DATA
457
458
 
458
459
  var mergeDic = {};
460
+ const formattedRowKeys = pvtData.getFormattedRowKeys(rowKeys);
459
461
 
460
- for (var rr = 0; rr < rowKeys.length; rr++) {
462
+ for (var rr = 0; rr < formattedRowKeys.length; rr++) {
461
463
 
462
464
  var rowData = [];
463
465
 
@@ -466,29 +468,29 @@ let initNovixRenderer = function($, window, document, Handsontable){
466
468
  mergeDic[cc] = {
467
469
  toMerge: 1,
468
470
  row: 0,
469
- priorText: rowKeys[rr][cc]
471
+ priorText: formattedRowKeys[rr][cc]
470
472
  };
471
473
  }
472
474
  }
473
475
 
474
476
  //column for row atts
475
477
  for (var cc = 0; cc < pvtData.rowAttrs.length; cc++) {
476
- rowData.push(rowKeys[rr][cc]);
477
- if (rowKeys[rr][cc] === subtotal) {
478
+ rowData.push(formattedRowKeys[rr][cc]);
479
+ if (formattedRowKeys[rr][cc] === subtotal) {
478
480
  addMergeCell(rr + pvtData.colAttrs.length + 1, cc, 1, dataSource.fixedColumns - cc, true, true);
479
- } else if (cc === rowKeys[rr].length - 1 && hasColumnAttr) {
481
+ } else if (cc === formattedRowKeys[rr].length - 1 && hasColumnAttr) {
480
482
  addMergeCell(rr + pvtData.colAttrs.length + 1, cc, 1, 2, true, true);
481
483
  }
482
484
  // merge cell (last column)
483
485
  if (opts.chartOptions.table_options.show_column_total && rr != 0 && mergeDic[cc]) { // check for merge dic
484
- if (rowKeys[rr][cc] == mergeDic[cc].priorText) {
486
+ if (formattedRowKeys[rr][cc] == mergeDic[cc].priorText) {
485
487
  mergeDic[cc].toMerge++;
486
- } else if (cc < rowKeys[rr].length - 1) {
488
+ } else if (cc < formattedRowKeys[rr].length - 1) {
487
489
  //create merge cell for this column
488
490
  addMergeCell(mergeDic[cc].row + pvtData.colAttrs.length + 1, cc, mergeDic[cc].toMerge, 1);
489
491
  mergeDic[cc].row = rr;
490
492
  mergeDic[cc].toMerge = 1;
491
- mergeDic[cc].priorText = rowKeys[rr][cc];
493
+ mergeDic[cc].priorText = formattedRowKeys[rr][cc];
492
494
  }
493
495
  }
494
496
  }
package/src/pivottable.js CHANGED
@@ -1,3 +1,5 @@
1
+ const helpers = require('./dr-renderer-helpers');
2
+
1
3
  // from pivottable@2.23.0
2
4
  let initPivotTable = function($, window, document) {
3
5
  var indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
@@ -20,10 +22,7 @@ let initPivotTable = function($, window, document) {
20
22
  }
21
23
  return x1 + x2;
22
24
  };
23
- let useTotalsCalculation = false;
24
- if (document.ReportHippo && document.ReportHippo && document.ReportHippo.user) {
25
- useTotalsCalculation = _.includes(document.ReportHippo.user.features, 'enable_server_totals_calculation');
26
- }
25
+
27
26
  numberFormat = function(opts) {
28
27
  var defaults;
29
28
  defaults = {
@@ -577,6 +576,7 @@ let initPivotTable = function($, window, document) {
577
576
  l_mapping = {};
578
577
  for (i in order) {
579
578
  x = order[i];
579
+ if (order[i] === null) x = '[null]';
580
580
  mapping[x] = i;
581
581
  if (typeof x === "string") {
582
582
  l_mapping[x.toLowerCase()] = i;
@@ -668,6 +668,7 @@ let initPivotTable = function($, window, document) {
668
668
  this.getAggregator = bind(this.getAggregator, this);
669
669
  this.getRowKeys = bind(this.getRowKeys, this);
670
670
  this.getColKeys = bind(this.getColKeys, this);
671
+ this.getRowKeysByCols = bind(this.getRowKeysByCols, this);
671
672
  this.sortKeys = bind(this.sortKeys, this);
672
673
  this.arrSort = bind(this.arrSort, this);
673
674
  this.input = input;
@@ -684,17 +685,34 @@ let initPivotTable = function($, window, document) {
684
685
  return true;
685
686
  });
686
687
  this.tree = {};
687
- this.rowKeys = [];
688
- this.colKeys = [];
688
+
689
+ this.isKeysSortingDoneOnBackendSide = opts.keysObject && typeof opts.keysObject === 'object' && helpers.backendSortingKeysAreNotEmpty(opts.keysObject);
690
+ if (this.isKeysSortingDoneOnBackendSide) {
691
+ this.rowKeys = opts.keysObject.row_keys;
692
+ this.colKeys = opts.keysObject.col_keys;
693
+ this.rowKeysByCols = opts.keysObject.row_keys_by_cols;
694
+ } else {
695
+ this.rowKeys = [];
696
+ this.colKeys = [];
697
+ }
698
+
689
699
  this.rowTotals = {};
690
700
  this.colTotals = {};
691
701
  this.allTotal = this.aggregator(this, [], []);
692
702
  this.sorted = false;
693
703
  this.dateValuesDictionary = opts.dateValuesDictionary;
704
+ this.sortByValueAttrs = opts.sortByValueAttrs || [];
705
+ this.colFormats = opts.colFormats || [];
706
+ this.rowFormats = opts.rowFormats || [];
707
+ this.isFormattingAxisLabels = opts.rendererOptions && opts.rendererOptions.isFormattingAxisLabels;
708
+ this.getFormattedColKeys = (keys) => opts.getFormattedColKeys(this, keys);
709
+ this.getFormattedRowKeys = (keys) => opts.getFormattedRowKeys(this, keys);
710
+ this.isDrillDownDisabled = opts.isDrillDownDisabled;
711
+
694
712
  PivotData.forEachRecord(this.input, this.derivedAttributes, (function(_this) {
695
713
  return function(record) {
696
714
  if (_this.filter(record)) {
697
- return _this.processRecord(record, useTotalsCalculation);
715
+ return _this.processRecord(record);
698
716
  }
699
717
  };
700
718
  })(this));
@@ -850,15 +868,23 @@ let initPivotTable = function($, window, document) {
850
868
  };
851
869
 
852
870
  PivotData.prototype.getColKeys = function() {
853
- this.sortKeys();
871
+ if (!this.isKeysSortingDoneOnBackendSide) {
872
+ this.sortKeys();
873
+ }
854
874
  return this.colKeys;
855
875
  };
856
876
 
857
877
  PivotData.prototype.getRowKeys = function() {
858
- this.sortKeys();
878
+ if (!this.isKeysSortingDoneOnBackendSide) {
879
+ this.sortKeys();
880
+ }
859
881
  return this.rowKeys;
860
882
  };
861
883
 
884
+ PivotData.prototype.getRowKeysByCols = function() {
885
+ return this.rowKeysByCols;
886
+ };
887
+
862
888
  PivotData.prototype.processRecord = function(record) {
863
889
  var colKey, flatColKey, flatRowKey, l, len1, len2, n, ref, ref1, ref2, ref3, rowKey, x;
864
890
  colKey = [];
@@ -4,6 +4,7 @@ let getPublishedItemsRenderer = function (publishedItemsRenderer) {
4
4
  this.scope = {};
5
5
  this.options = {};
6
6
  this.isScenarioMode = null;
7
+ this.settings = {};
7
8
 
8
9
  publishedItemsRenderer.formulaCellClicked = function (event, scope, options, window) {
9
10
  event.stopPropagation();
@@ -19,7 +20,6 @@ let getPublishedItemsRenderer = function (publishedItemsRenderer) {
19
20
  }
20
21
 
21
22
  publishedItemsRenderer.resizeTable = function (options, iframeWindow) {
22
- options.alreadySetTimeout = null;
23
23
  const publish_item_image = iframeWindow.document.getElementById('publish_item_image');
24
24
  const table = iframeWindow.document.getElementsByTagName("table")[0];
25
25
  const body = iframeWindow.document.getElementsByTagName("body")[0];
@@ -31,40 +31,23 @@ let getPublishedItemsRenderer = function (publishedItemsRenderer) {
31
31
  publishedItemsRenderer.resizePublishedImage(publish_item_image, iframeWindow, body);
32
32
  }
33
33
 
34
- publishedItemsRenderer.zoomTable = function(iframeWindow, table, body) {
35
- let body_zoom = body.style.zoom;
36
- body_zoom = parseFloat(body_zoom) || 1;
37
-
38
- let zoom = table.style.zoom;
39
- zoom = parseFloat(zoom) || 1;
40
-
41
- const positionInfo = table.getBoundingClientRect();
42
- let width = Math.ceil((positionInfo.width + iframeWindow.innerWidth - iframeWindow.document.body.offsetWidth) * zoom * body_zoom);
34
+ publishedItemsRenderer.zoomTable = function (iframeWindow, table, body) {
35
+ const bodyZoom = parseFloat(body.style.zoom) || 1;
36
+ const SCROLL_OFFSET = 16;
43
37
 
44
- if (width < iframeWindow.innerWidth) {
45
- zoom += 0.05;
38
+ const tableWidth = table.getBoundingClientRect().width * bodyZoom;
39
+ const tableHeight = table.getBoundingClientRect().height * bodyZoom;
40
+ const root = iframeWindow.document.documentElement;
46
41
 
47
- width = Math.ceil((positionInfo.width + iframeWindow.innerWidth - iframeWindow.document.body.offsetWidth) * zoom * body_zoom);
48
- if (width < iframeWindow.innerWidth) {
49
- table.style.zoom = zoom;
50
- setTimeout(function () {
51
- publishedItemsRenderer.zoomTable(iframeWindow, table, body);
52
- }, 10);
53
- }
54
- } else if (width >= iframeWindow.innerWidth) {
55
- zoom -= 0.05;
56
-
57
- width = Math.ceil((positionInfo.width + iframeWindow.innerWidth - iframeWindow.document.body.offsetWidth) * zoom * body_zoom);
58
- table.style.zoom = zoom;
59
- if (width >= iframeWindow.innerWidth) {
60
- setTimeout(function () {
61
- publishedItemsRenderer.zoomTable(iframeWindow, table, body);
62
- }, 10);
63
- }
42
+ let requiredZoom = (root.clientWidth - SCROLL_OFFSET) / tableWidth;
43
+ if (this.settings.resizeTableUsingBothDimensions) {
44
+ requiredZoom = Math.min(requiredZoom, (root.clientHeight - SCROLL_OFFSET) / tableHeight);
64
45
  }
65
- }
66
46
 
67
- publishedItemsRenderer.resizePublishedImage = function(publish_item_image, iframeWindow, body) {
47
+ table.style.zoom = requiredZoom;
48
+ };
49
+
50
+ publishedItemsRenderer.resizePublishedImage = function (publish_item_image, iframeWindow, body) {
68
51
  if (!publish_item_image) return;
69
52
 
70
53
  let body_zoom = body.style.zoom;
@@ -107,11 +90,7 @@ let getPublishedItemsRenderer = function (publishedItemsRenderer) {
107
90
  if (!options.responsive) {
108
91
  publishedItemsRenderer.resetTableZoom(document);
109
92
  } else {
110
- if (!options.alreadySetTimeout) {
111
- options.alreadySetTimeout = setTimeout(function () {
112
- publishedItemsRenderer.resizeTable(options, iframeWindow);
113
- }, 100);
114
- }
93
+ publishedItemsRenderer.resizeTable(options, iframeWindow);
115
94
  }
116
95
  }
117
96
 
@@ -217,7 +196,7 @@ let getPublishedItemsRenderer = function (publishedItemsRenderer) {
217
196
  const format = inputMetaData.format ? inputMetaData.format.toUpperCase() : 'MM/DD/YYYY';
218
197
  const formattedDate = formatValue('d', format, inputMetaData.value).value
219
198
  if (_this.isScenarioMode) {
220
- dateEl.innerHTML = '<label class="value dateInput" style="background: #FFEDBF;padding: 2px 1px 2px 6px;border: 1px solid #FABC5F;border-radius: 6px;cursor:pointer;">' + formattedDate + '</label>';
199
+ dateEl.innerHTML = '<label class="value dateInput" style="background: #FFEDBF;padding: 2px 1px 2px 6px;border: 1px solid #FABC5F;border-radius: 6px;cursor:pointer;">' + formattedDate + '</label>';
221
200
  } else {
222
201
  dateEl.innerHTML = '<label class="value dateInput" style="cursor: pointer;">' + formattedDate + '</label>';
223
202
  }
@@ -323,20 +302,19 @@ let getPublishedItemsRenderer = function (publishedItemsRenderer) {
323
302
  }
324
303
 
325
304
  publishedItemsRenderer.addEventListeners = function (document, iframeWindow, scope, options) {
326
- document.addEventListener("DOMContentLoaded", function () {
327
- if (!options.alreadySetTimeout) {
328
- options.alreadySetTimeout = setTimeout(function () {
329
- publishedItemsRenderer.resizeTable(options, iframeWindow);
330
- }, 50);
305
+ let resizeTimeout;
306
+ const handleDimensionChange = () => {
307
+ if (resizeTimeout) {
308
+ cancelAnimationFrame(resizeTimeout);
331
309
  }
332
- });
333
- iframeWindow.addEventListener("resize", function () {
334
- if (!options.alreadySetTimeout) {
335
- options.alreadySetTimeout = setTimeout(function () {
336
- publishedItemsRenderer.resizeTable(iframeWindow.__options__, iframeWindow);
337
- }, 100);
338
- }
339
- });
310
+
311
+ resizeTimeout = requestAnimationFrame(() => {
312
+ publishedItemsRenderer.resizeTable(iframeWindow.__options__, iframeWindow);
313
+ });
314
+ }
315
+
316
+ document.addEventListener("DOMContentLoaded", handleDimensionChange);
317
+ iframeWindow.addEventListener("resize", handleDimensionChange);
340
318
 
341
319
  // Add click event to cell with formula
342
320
  let all_a_hrefs = document.querySelectorAll('td a[location_id]');
@@ -372,7 +350,7 @@ let getPublishedItemsRenderer = function (publishedItemsRenderer) {
372
350
  }, 500);
373
351
  }
374
352
 
375
- publishedItemsRenderer.applyInitDocumentStyles = function(document, iframeWindow) {
353
+ publishedItemsRenderer.applyInitDocumentStyles = function (document, iframeWindow) {
376
354
  const table = document.getElementsByTagName('table')[0];
377
355
  if (table) {
378
356
  table.style.overflow = 'hidden';
@@ -0,0 +1,43 @@
1
+ function getSeriesPointStyles(isSelected) {
2
+ return {
3
+ opacity: isSelected ? 1 : 0.1,
4
+ marker: {
5
+ enabled: true,
6
+ radius: isSelected ? 8 : 3,
7
+ },
8
+ dataLabels: {
9
+ style: {
10
+ fontWeight: isSelected ? "bold" : "normal",
11
+ },
12
+ },
13
+ };
14
+ }
15
+
16
+ function setSeriesPointStylesOnClick(e) {
17
+ const selectedPoint = e.point;
18
+ e.point.series.chart.series.forEach((series) =>
19
+ series.points.forEach((point) => {
20
+ point.update(getSeriesPointStyles(point === selectedPoint), false);
21
+ })
22
+ );
23
+ e.point.series.chart.redraw();
24
+ }
25
+
26
+ function setInitialPointStyles(opts, series) {
27
+ series.forEach((series) => {
28
+ if (Array.isArray(series.data)) {
29
+ series.data.forEach((item) => {
30
+ const isSelected =
31
+ item && opts.selectedPoint &&
32
+ item.initialName === opts.selectedPoint.initialName &&
33
+ item.y.toFixed(2) === opts.selectedPoint.y.toFixed(2);
34
+ item = Object.assign(item, getSeriesPointStyles(isSelected));
35
+ });
36
+ }
37
+ });
38
+ }
39
+
40
+ module.exports = {
41
+ setSeriesPointStylesOnClick,
42
+ setInitialPointStyles,
43
+ };
@@ -0,0 +1,150 @@
1
+ import drRendererHelpers from '../src/dr-renderer-helpers';
2
+
3
+ describe('dr-renderer-helpers', () => {
4
+
5
+ describe('backendSortingKeysAreNotEmpty', () => {
6
+ it('should return true if keys are not empty', () => {
7
+ const keys = {
8
+ row_keys: [1, 2, 3],
9
+ col_keys: [1, 2, 3]
10
+ };
11
+ expect(drRendererHelpers.backendSortingKeysAreNotEmpty(keys)).toBe(true);
12
+ });
13
+
14
+ it('should return true if one of the keys is not empty', () => {
15
+ const keys = {
16
+ row_keys: [1, 2, 3],
17
+ col_keys: []
18
+ };
19
+ expect(drRendererHelpers.backendSortingKeysAreNotEmpty(keys)).toBe(true);
20
+ });
21
+
22
+ it('should return false if keys are empty', () => {
23
+ const keys = {
24
+ row_keys: [],
25
+ col_keys: [],
26
+ };
27
+ expect(drRendererHelpers.backendSortingKeysAreNotEmpty(keys)).toBe(false);
28
+ });
29
+
30
+ it('should return false if keys are null', () => {
31
+ const keys = null;
32
+ expect(drRendererHelpers.backendSortingKeysAreNotEmpty(keys)).toBe(false);
33
+ });
34
+ });
35
+
36
+ describe('capitalize', () => {
37
+ it('should capitalize a string', () => {
38
+ const string = 'test';
39
+ expect(drRendererHelpers.capitalize(string)).toBe('Test');
40
+ });
41
+
42
+ it('should not capitalize a string when it was not trimmed', () => {
43
+ const string = ' test';
44
+ expect(drRendererHelpers.capitalize(string)).toBe(' test');
45
+ });
46
+
47
+ it('should return an empty string if string is null', () => {
48
+ const string = null;
49
+ expect(drRendererHelpers.capitalize(string)).toBe('');
50
+ });
51
+ });
52
+
53
+ describe('clamp', () => {
54
+ it('should clamp value between teh boundaries', () => {
55
+ expect(drRendererHelpers.clamp(10, 5, 20)).toBe(10);
56
+ expect(drRendererHelpers.clamp(10, 25, 20)).toBe(20);
57
+ expect(drRendererHelpers.clamp(10, 15, 20)).toBe(15);
58
+ });
59
+ });
60
+
61
+ describe('isNumber', () => {
62
+ it('should check whether the value is a finity number', () => {
63
+ expect(drRendererHelpers.isNumber('number')).toBeFalsy();
64
+ expect(drRendererHelpers.isNumber(Infinity)).toBeFalsy();
65
+ expect(drRendererHelpers.isNumber(12)).toBeTruthy();
66
+ });
67
+ });
68
+
69
+ describe('mergeDeep', () => {
70
+ it('should handle the wrong data', () => {
71
+ expect(drRendererHelpers.mergeDeep([1, 2, 3], { a: 1, b: 2})).toEqual([1, 2, 3]);
72
+ expect(drRendererHelpers.mergeDeep('string', { a: 1, b: 2})).toEqual('string');
73
+ expect(drRendererHelpers.mergeDeep({ a: 1 }, 'string')).toEqual({ a: 1 });
74
+ });
75
+
76
+ it('should not merge arrays and replace instead', () => {
77
+ expect(drRendererHelpers.mergeDeep({
78
+ a: [1, 2, 3]
79
+ }, {
80
+ a: [2, 3, 4]
81
+ })).toEqual({
82
+ a: [2, 3, 4]
83
+ });
84
+ });
85
+
86
+ it('should merge nested objects', () => {
87
+ expect(drRendererHelpers.mergeDeep({
88
+ a: 1,
89
+ b: {
90
+ c: 3,
91
+ d: 4
92
+ }
93
+ },
94
+ {
95
+ b: {
96
+ d: 5,
97
+ e: 6
98
+ },
99
+ c: 7
100
+ })).toEqual({
101
+ a: 1,
102
+ b: {
103
+ c: 3,
104
+ d: 5,
105
+ e: 6,
106
+ },
107
+ c: 7,
108
+ });
109
+ });
110
+
111
+ it('should merge more than 2 objects', () => {
112
+ expect(drRendererHelpers.mergeDeep({
113
+ a: 1,
114
+ b: 2
115
+ },
116
+ {
117
+ b: 3,
118
+ c: 4
119
+ },
120
+ {
121
+ a: 5,
122
+ e: 6
123
+ })).toEqual({
124
+ a: 5,
125
+ b: 3,
126
+ c: 4,
127
+ e: 6
128
+ });
129
+ });
130
+ });
131
+
132
+ describe('removeSVGTextCorrection', () => {
133
+ it('should remove yCorr by default', () => {
134
+ const svg = {
135
+ yCorr: -12
136
+ };
137
+ drRendererHelpers.removeSVGTextCorrection(svg);
138
+ expect(svg.yCorr).toBe(0);
139
+ });
140
+
141
+ it('should remove yCorr by default', () => {
142
+ const svg = {
143
+ xCorr: -12
144
+ };
145
+ drRendererHelpers.removeSVGTextCorrection(svg, 'xCorr');
146
+ svg.xCorr = -20;
147
+ expect(svg.xCorr).toBe(0);
148
+ });
149
+ });
150
+ });