@datarailsshared/dr_renderer 1.2.419 → 1.2.421

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.2.419",
3
+ "version": "1.2.421",
4
4
  "description": "DataRails charts and tables renderer",
5
5
  "keywords": [
6
6
  "datarails",
@@ -346,7 +346,24 @@ let getHighchartsRenderer = function ($, document, Highcharts, default_colors, h
346
346
  },
347
347
  exporting: {
348
348
  enabled: false,
349
- sourceWidth: 900
349
+ sourceWidth: 900,
350
+ chartOptions: {
351
+ chart: {
352
+ events: {
353
+ load: function () {
354
+ const chart = this;
355
+ chart.renderer.definition({
356
+ tagName: 'style',
357
+ textContent: `
358
+ .highcharts-xaxis-grid > .highcharts-grid-line {
359
+ stroke: none;
360
+ }
361
+ `,
362
+ });
363
+ },
364
+ },
365
+ },
366
+ },
350
367
  },
351
368
  drilldown: {
352
369
  activeAxisLabelStyle: {
@@ -1024,8 +1041,8 @@ let getHighchartsRenderer = function ($, document, Highcharts, default_colors, h
1024
1041
  };
1025
1042
  if (isNewAngular) {
1026
1043
  const isPieChart = chartOptions.chart && chartOptions.chart.type === 'pie';
1027
- const x = isPieChart ? 13 : 12
1028
- const y = isPieChart ? -9 : 6
1044
+ const x = isPieChart ? 13 : 12;
1045
+ const y = isPieChart ? -9 : 6;
1029
1046
  chartOptions.chart.spacingBottom = lodash.get(chartOptions, 'xAxis.title') ? 34 : 30;
1030
1047
  chartOptions.drilldown.breadcrumbs = {
1031
1048
  formatter: () => '< &nbsp;Back',
@@ -1831,7 +1848,6 @@ let getHighchartsRenderer = function ($, document, Highcharts, default_colors, h
1831
1848
  var col_n_keys = pivotData.getColKeys();
1832
1849
  var row_n_keys = pivotData.getRowKeys();
1833
1850
 
1834
- var num_cols = col_n_keys.length;
1835
1851
  var num_rows = row_n_keys.length;
1836
1852
 
1837
1853
  const isOthersIncludedInRow = num_rows === 1 && lodash.includes(row_n_keys[0], highchartsRenderer.DR_OTHERS_KEY);
@@ -1850,9 +1866,6 @@ let getHighchartsRenderer = function ($, document, Highcharts, default_colors, h
1850
1866
  var ob = {};
1851
1867
  // check string contains hebrew
1852
1868
  ob.initialName = (/[\u0590-\u05FF]/).test(key) ? ('\u200E' + key) : key;
1853
- if (lodash.isEmpty(String(ob.name))) {
1854
- ob.initialName = "[blank]";
1855
- }
1856
1869
 
1857
1870
  if (ob.initialName === highchartsRenderer.DR_OTHERS_KEY) {
1858
1871
  ob.initialName = othersName;
@@ -5067,10 +5080,28 @@ let getHighchartsRenderer = function ($, document, Highcharts, default_colors, h
5067
5080
 
5068
5081
  const timeframe = highchartsRenderer.getTimeframeByFormat(format);
5069
5082
  const fiscalYearMonthsModifier = highchartsRenderer.getFiscalYearMonthModifier();
5083
+ const isFiscalYearBackEnabled = highchartsRenderer.isFiscalYearBackEnabled();
5070
5084
 
5071
5085
  let date = moment_lib(tryParse).utcOffset(0);
5072
- if (lodash.includes(['quarter', 'year'], timeframe)) {
5086
+ const originalDateYear = date.year()
5087
+ const originalDateMonth = date.month();
5088
+
5089
+ if (lodash.includes(['quarter'], timeframe)){
5073
5090
  date = date.subtract(fiscalYearMonthsModifier, 'M');
5091
+ if (fiscalYearMonthsModifier > 0 && !isFiscalYearBackEnabled) {
5092
+ let fiscalYear = originalDateYear;
5093
+ if ((originalDateMonth - fiscalYearMonthsModifier) >= 0) {
5094
+ fiscalYear += 1;
5095
+ }
5096
+ date = date.set('year', fiscalYear);
5097
+ }
5098
+ }
5099
+
5100
+ if (lodash.includes(['year'], timeframe)) {
5101
+ if (fiscalYearMonthsModifier > 0 && isFiscalYearBackEnabled) {
5102
+ let fiscalYear = originalDateYear - 1;
5103
+ date = date.set('year', fiscalYear);
5104
+ }
5074
5105
  }
5075
5106
 
5076
5107
  return date.format(format) + "";
@@ -6248,7 +6279,7 @@ let getHighchartsRenderer = function ($, document, Highcharts, default_colors, h
6248
6279
  element_type: 'checkbox',
6249
6280
  element_label: 'Freeze panes <small>(old table only)</small>',
6250
6281
  value_name: 'freeze_panes',
6251
- default_value: true
6282
+ default_value: false
6252
6283
  },
6253
6284
  {
6254
6285
  element_type: 'checkbox',
@@ -6474,7 +6505,7 @@ let getHighchartsRenderer = function ($, document, Highcharts, default_colors, h
6474
6505
  element_type: 'checkbox',
6475
6506
  element_label: 'Freeze panes <small>(old table only)</small>',
6476
6507
  value_name: 'freeze_panes',
6477
- default_value: true
6508
+ default_value: false
6478
6509
  },
6479
6510
  {
6480
6511
  element_type: 'checkbox',
@@ -8503,18 +8534,27 @@ let getHighchartsRenderer = function ($, document, Highcharts, default_colors, h
8503
8534
  lastDay2.getMonth(),
8504
8535
  lastDay2.getDate(),
8505
8536
  23, 59, 59
8506
- ) / 1000)
8537
+ ) / 1000);
8507
8538
  return range;
8508
8539
  case 'quarter':
8509
8540
  const utcDate = moment_lib.utc(initialDateString, format, true);
8510
- range.val.fromdate = lodash.cloneDeep(utcDate).startOf(timeframe).add(fiscalYearMonthsModifier, 'M').unix();
8511
- range.val.todate = lodash.cloneDeep(utcDate).endOf(timeframe).add(fiscalYearMonthsModifier, 'M').endOf('M').unix();
8541
+ range.val.fromdate = lodash.cloneDeep(utcDate).startOf(timeframe).add(fiscalYearMonthsModifier, 'M');
8542
+ range.val.todate = lodash.cloneDeep(utcDate).endOf(timeframe).add(fiscalYearMonthsModifier, 'M').endOf('M');
8543
+ if (fiscalYearMonthsModifier > 0 && !highchartsRenderer.isFiscalYearBackEnabled()) {
8544
+ range.val.fromdate = moment_lib(range.val.fromdate.subtract(1, 'Y'));
8545
+ range.val.todate = moment_lib(range.val.todate.subtract(1, 'Y'));
8546
+ }
8547
+ range.val.fromdate = range.val.fromdate.unix();
8548
+ range.val.todate = range.val.todate.unix();
8512
8549
  return range;
8513
8550
  default:
8514
8551
  return "";
8515
8552
  }
8516
8553
  } else if (!lodash.isNaN(fieldnametoFilter)) {
8517
- const utcDate = moment_lib.unix(fieldnametoFilter).utc();
8554
+ let utcDate = moment_lib.unix(fieldnametoFilter).utc();
8555
+ if (lodash.includes(['year', 'quarter'], timeframe)) {
8556
+ utcDate = moment_lib(utcDate).subtract(fiscalYearMonthsModifier, 'M');
8557
+ }
8518
8558
  const fromDateMoment = lodash.cloneDeep(utcDate).startOf(timeframe);
8519
8559
  const toDateMoment = lodash.cloneDeep(utcDate).endOf(timeframe);
8520
8560
 
@@ -9480,6 +9520,10 @@ let getHighchartsRenderer = function ($, document, Highcharts, default_colors, h
9480
9520
  return lodash.get(document, 'ReportHippo.user.organization.fiscal_year_starts_from', 1) - 1;
9481
9521
  }
9482
9522
 
9523
+ highchartsRenderer.isFiscalYearBackEnabled = function() {
9524
+ return lodash.get(document, 'ReportHippo.user.organization.fiscal_year_back');
9525
+ }
9526
+
9483
9527
  highchartsRenderer.getTimeframeByFormat = function(format) {
9484
9528
  if (format && highchartsRenderer.containsIgnoreCase(format, 'q'))
9485
9529
  return 'quarter';
@@ -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();
@@ -30,16 +31,23 @@ let getPublishedItemsRenderer = function (publishedItemsRenderer) {
30
31
  publishedItemsRenderer.resizePublishedImage(publish_item_image, iframeWindow, body);
31
32
  }
32
33
 
33
- publishedItemsRenderer.zoomTable = function(iframeWindow, table, body) {
34
+ publishedItemsRenderer.zoomTable = function (iframeWindow, table, body) {
34
35
  const bodyZoom = parseFloat(body.style.zoom) || 1;
36
+ const SCROLL_OFFSET = 16;
37
+
38
+ const tableWidth = table.getBoundingClientRect().width * bodyZoom;
39
+ const tableHeight = table.getBoundingClientRect().height * bodyZoom;
40
+ const root = iframeWindow.document.documentElement;
41
+
42
+ let requiredZoom = (root.clientWidth - SCROLL_OFFSET) / tableWidth;
43
+ if (this.settings.resizeTableUsingBothDimensions) {
44
+ requiredZoom = Math.min(requiredZoom, (root.clientHeight - SCROLL_OFFSET) / tableHeight);
45
+ }
35
46
 
36
- const tableWidth = (table.getBoundingClientRect().width + (iframeWindow.innerWidth - body.offsetWidth)) * bodyZoom;
37
- const requiredZoom = iframeWindow.innerWidth / tableWidth;
38
-
39
47
  table.style.zoom = requiredZoom;
40
48
  };
41
49
 
42
- publishedItemsRenderer.resizePublishedImage = function(publish_item_image, iframeWindow, body) {
50
+ publishedItemsRenderer.resizePublishedImage = function (publish_item_image, iframeWindow, body) {
43
51
  if (!publish_item_image) return;
44
52
 
45
53
  let body_zoom = body.style.zoom;
@@ -188,7 +196,7 @@ let getPublishedItemsRenderer = function (publishedItemsRenderer) {
188
196
  const format = inputMetaData.format ? inputMetaData.format.toUpperCase() : 'MM/DD/YYYY';
189
197
  const formattedDate = formatValue('d', format, inputMetaData.value).value
190
198
  if (_this.isScenarioMode) {
191
- 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>';
192
200
  } else {
193
201
  dateEl.innerHTML = '<label class="value dateInput" style="cursor: pointer;">' + formattedDate + '</label>';
194
202
  }
@@ -299,7 +307,7 @@ let getPublishedItemsRenderer = function (publishedItemsRenderer) {
299
307
  if (resizeTimeout) {
300
308
  cancelAnimationFrame(resizeTimeout);
301
309
  }
302
-
310
+
303
311
  resizeTimeout = requestAnimationFrame(() => {
304
312
  publishedItemsRenderer.resizeTable(iframeWindow.__options__, iframeWindow);
305
313
  });
@@ -342,7 +350,7 @@ let getPublishedItemsRenderer = function (publishedItemsRenderer) {
342
350
  }, 500);
343
351
  }
344
352
 
345
- publishedItemsRenderer.applyInitDocumentStyles = function(document, iframeWindow) {
353
+ publishedItemsRenderer.applyInitDocumentStyles = function (document, iframeWindow) {
346
354
  const table = document.getElementsByTagName('table')[0];
347
355
  if (table) {
348
356
  table.style.overflow = 'hidden';
@@ -39,6 +39,7 @@ describe('highcharts_renderer', () => {
39
39
  getOptions: function() { return Highcharts.opt; },
40
40
  Tooltip: {},
41
41
  wrap: () => {},
42
+ chart: () => {},
42
43
  };
43
44
  _window.DataFormatter = DataFormatter;
44
45
  initPivotTable($, _window, _document);
@@ -7375,6 +7376,124 @@ describe('highcharts_renderer', () => {
7375
7376
  })
7376
7377
  });
7377
7378
 
7379
+ describe('Function ptCreateElementAndDraw', () => {
7380
+ beforeEach(() => {
7381
+ jest.clearAllMocks();
7382
+ });
7383
+
7384
+ afterAll(() => {
7385
+ jest.restoreAllMocks();
7386
+ });
7387
+
7388
+ it('should set chart colors palette using widget or dashboard colors palette', () => {
7389
+ const chartOptions = {
7390
+ colors: [],
7391
+ chart: {
7392
+ },
7393
+ };
7394
+ const optionsWidgetPalette = {
7395
+ paletteOptions: {
7396
+ widgetPalette: ['#ff0202', '#b3060e', '#70000a'],
7397
+ dashboardPalette: {
7398
+ colors: ['#ffffff', '#000000']
7399
+ },
7400
+ },
7401
+ onlyOptions: true,
7402
+ };
7403
+
7404
+ const res = highchartsRenderer.ptCreateElementAndDraw(chartOptions, optionsWidgetPalette);
7405
+ expect(res.colors).toEqual(optionsWidgetPalette.paletteOptions.widgetPalette);
7406
+
7407
+ const optionsDashboardPalette = {
7408
+ paletteOptions: {
7409
+ dashboardPalette: {
7410
+ colors: ['#ffffff', '#000000']
7411
+ },
7412
+ },
7413
+ onlyOptions: true,
7414
+ };
7415
+
7416
+ const res2 = highchartsRenderer.ptCreateElementAndDraw(chartOptions, optionsDashboardPalette);
7417
+ expect(res2.colors).toEqual(optionsDashboardPalette.paletteOptions.dashboardPalette.colors);
7418
+ });
7419
+
7420
+ it('should set drilldown options on drilldown chart', () => {
7421
+ jest.useFakeTimers();
7422
+ highchartsRenderer.isNewAngular = true;
7423
+ const chartSpy = jest.spyOn(Highcharts, 'chart').mockImplementation(() => {});
7424
+
7425
+ const chartOptions = {
7426
+ colors: [],
7427
+ chart: {
7428
+ },
7429
+ onlyText: true,
7430
+ drilldown: {
7431
+ },
7432
+ };
7433
+ const options = {};
7434
+
7435
+ highchartsRenderer.ptCreateElementAndDraw(chartOptions, options);
7436
+
7437
+ jest.runAllTimers();
7438
+
7439
+ expect(chartSpy).toHaveBeenCalledWith(
7440
+ expect.any(Object),
7441
+ expect.objectContaining({
7442
+ drilldown: expect.objectContaining({
7443
+ drillUpButton: expect.any(Object),
7444
+ breadcrumbs: expect.any(Object),
7445
+ }),
7446
+ }),
7447
+ );
7448
+ });
7449
+
7450
+ it('should return no data result if series is empty', () => {
7451
+ const chartOptions = {
7452
+ chart: {},
7453
+ series: [{ data: [] }, { data: [] }, {}],
7454
+ };
7455
+ const options = {};
7456
+ const noDataFnSpy = jest.spyOn(highchartsRenderer, 'getNoDataResult').mockImplementation(() => {});
7457
+
7458
+ highchartsRenderer.ptCreateElementAndDraw(chartOptions, options);
7459
+
7460
+ expect(noDataFnSpy).toHaveBeenCalled();
7461
+ expect(options.error_has_occurred).toBeTruthy();
7462
+ expect(options.error_params).toBe(highchartsRenderer.widgetPlaceholders.nodata);
7463
+ });
7464
+
7465
+ it('should return too much data result if series is too long', () => {
7466
+ const chartOptions = {
7467
+ chart: {},
7468
+ series: [{ data: new Array(1000) }, { data: new Array(1000) }, {}],
7469
+ };
7470
+ const options = {};
7471
+ const noDataFnSpy = jest.spyOn(highchartsRenderer, 'getNoDataResult').mockImplementation(() => {});
7472
+
7473
+ highchartsRenderer.ptCreateElementAndDraw(chartOptions, options);
7474
+
7475
+ expect(noDataFnSpy).toHaveBeenCalled();
7476
+ expect(options.error_has_occurred).toBeTruthy();
7477
+ expect(options.error_params).toBe(highchartsRenderer.widgetPlaceholders.tooMuchData);
7478
+ });
7479
+
7480
+ it('should set hcInstance on options with chart object for graph table renderer to use', () => {
7481
+ jest.useFakeTimers();
7482
+ jest.spyOn(Highcharts, 'chart').mockImplementation(() => ({ chart: true }));
7483
+
7484
+ const chartOptions = {
7485
+ chart: {},
7486
+ onlyText: true,
7487
+ };
7488
+ const options = {};
7489
+
7490
+ highchartsRenderer.ptCreateElementAndDraw(chartOptions, options);
7491
+ jest.runAllTimers();
7492
+
7493
+ expect(options.hcInstance).toBeDefined();
7494
+ });
7495
+ });
7496
+
7378
7497
  describe('Function getNoDataResult', () => {
7379
7498
  const container = $('<div class="noData-box"></div>');
7380
7499
 
@@ -8739,4 +8858,77 @@ describe('highcharts_renderer', () => {
8739
8858
  });
8740
8859
  });
8741
8860
 
8861
+
8862
+ describe('Function ptCreateSeriesToDrillDownChart', () => {
8863
+ let pivotData, chartOptions, additionOptions, opts;
8864
+
8865
+ beforeEach(() => {
8866
+ pivotData = {
8867
+ getColKeys: jest.fn(),
8868
+ getRowKeys: jest.fn(),
8869
+ getAggregator: jest.fn().mockReturnValue({
8870
+ value: jest.fn()
8871
+ })
8872
+ };
8873
+
8874
+ chartOptions = {
8875
+ chart: {
8876
+ type: 'pie'
8877
+ }
8878
+ };
8879
+
8880
+ additionOptions = {};
8881
+ opts = {};
8882
+
8883
+ highchartsRenderer.getOthersName = jest.fn();
8884
+ highchartsRenderer.getFormattedColKey = jest.fn();
8885
+ highchartsRenderer.moveSeriesToSecondYAxisIfNeeded = jest.fn();
8886
+ });
8887
+
8888
+ it('should handle Hebrew characters in key', () => {
8889
+ pivotData.getColKeys.mockReturnValue(['שלום']);
8890
+ pivotData.getRowKeys.mockReturnValue(['row1']);
8891
+ pivotData.getAggregator().value.mockReturnValue(10);
8892
+ highchartsRenderer.getOthersName.mockReturnValue('Others');
8893
+ highchartsRenderer.getFormattedColKey.mockReturnValue('FormattedKey');
8894
+
8895
+ const result = highchartsRenderer.ptCreateSeriesToDrillDownChart(pivotData, chartOptions, additionOptions, opts);
8896
+ expect(result[0].data[0].initialName).toEqual('\u200Eשלום');
8897
+ });
8898
+
8899
+ it('should handle DR_OTHERS_KEY', () => {
8900
+ pivotData.getColKeys.mockReturnValue([highchartsRenderer.DR_OTHERS_KEY]);
8901
+ pivotData.getRowKeys.mockReturnValue(['row1']);
8902
+ pivotData.getAggregator().value.mockReturnValue(10);
8903
+ highchartsRenderer.getOthersName.mockReturnValue('Others');
8904
+ highchartsRenderer.getFormattedColKey.mockReturnValue('FormattedKey');
8905
+
8906
+ const result = highchartsRenderer.ptCreateSeriesToDrillDownChart(pivotData, chartOptions, additionOptions, opts);
8907
+ expect(result[0].data[0].initialName).toEqual('Others');
8908
+ });
8909
+
8910
+ it('should handle negative values when chart type is not pie', () => {
8911
+ chartOptions.chart.type = 'notPie';
8912
+ pivotData.getColKeys.mockReturnValue(['key1']);
8913
+ pivotData.getRowKeys.mockReturnValue(['row1']);
8914
+ pivotData.getAggregator().value.mockReturnValue(-10);
8915
+ highchartsRenderer.getOthersName.mockReturnValue('Others');
8916
+ highchartsRenderer.getFormattedColKey.mockReturnValue('FormattedKey');
8917
+
8918
+ const result = highchartsRenderer.ptCreateSeriesToDrillDownChart(pivotData, chartOptions, additionOptions, opts);
8919
+ expect(result[0].data[0].y).toEqual(-10);
8920
+ });
8921
+
8922
+ it('should handle numeric keys', () => {
8923
+ pivotData.getColKeys.mockReturnValue(['123']);
8924
+ pivotData.getRowKeys.mockReturnValue(['row1']);
8925
+ pivotData.getAggregator().value.mockReturnValue(10);
8926
+ highchartsRenderer.getOthersName.mockReturnValue('Others');
8927
+ highchartsRenderer.getFormattedColKey.mockReturnValue('FormattedKey');
8928
+
8929
+ const result = highchartsRenderer.ptCreateSeriesToDrillDownChart(pivotData, chartOptions, additionOptions, opts);
8930
+ expect(result[0].data[0].drilldown).toEqual(123);
8931
+ });
8932
+ });
8933
+
8742
8934
  });