@datarailsshared/dr_renderer 1.2.37-beta → 1.2.37

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.
@@ -1,899 +1,901 @@
1
- let initNovixRenderer = function($, window, document, Handsontable){
2
- //register custom editor for format numeric editor
3
- (function (Handsontable) {
4
-
5
- var GenericEditor = Handsontable.editors.NumericEditor.prototype.extend();
6
-
7
- GenericEditor.prototype.beginEditing = function (initialValue) {
8
-
9
- var BaseEditor = Handsontable.editors.NumericEditor.prototype;
10
-
11
- if (typeof (initialValue) === 'undefined' && this.originalValue) {
12
-
13
- var value = '' + this.originalValue;
14
- if (!isNaN(parseFloat(value))) {
15
- value = value.replace(",", "");
16
- value = parseFloat(value).toFixed(10);
17
- }
18
- BaseEditor.beginEditing.apply(this, [value]);
19
- } else {
20
- BaseEditor.beginEditing.apply(this, arguments);
21
- }
22
- BaseEditor.beginEditing.apply(this, [initialValue]);
23
- };
24
- Handsontable.editors.GenericEditor = GenericEditor;
25
-
26
- }(Handsontable));
27
-
28
- const delim = " , ";
29
- const subtotal = "subtotalDatarailsPlaceholder";
30
- const replaceValue = "SubTotals";
31
- const useNewUx = document.ReportHippo && document.ReportHippo && document.ReportHippo.user &&
32
- document.ReportHippo.user.organization.settings && document.ReportHippo.user.organization.settings.use_new_ux;
33
-
34
- $.pivotUtilities.novix_renderers = {
35
-
36
- "Pivot Table": function (pvtData, opts) {
37
- return $.pivotUtilities.novix_renderers["Input Table"](pvtData, $.extend({}, opts, { readOnly: true }));
38
- },
39
-
40
- "Input Table": function (pvtData, opts) {
41
-
42
- // for (let i in pvtData.input) {
43
- // pvtData.input[i].value = pvtData.processRecord(pvtData.input[i]);
44
- // }
45
-
46
- var table;
47
- var def = {
48
- $el: $(document),
49
- showTotals: true,
50
- header: {
51
- className: "header"
52
- },
53
- total: {
54
- className: "total",
55
- format: "0,0.00"
56
- },
57
- subTotal: {
58
- className: "subTotal",
59
- format: "0,0.00"
60
- },
61
- data: {
62
- className: "data",
63
- format: "0,0.00"
64
- },
65
- getIndexContent: function (indexName) {
66
- // to customize content index on table. For pivot implementation
67
- return indexName;
68
- }
69
- };
70
-
71
- var minColWidth = 50;
72
- var maxColWidth = 250;
73
-
74
- var calculateMaxWidths = function(ds) {
75
- const mc = findMergeCols(ds);
76
- return ds.data
77
- .reduce((acc, row, index) => {
78
- for (let [col, value] of row.entries()) {
79
- if (value === subtotal) value = "SubTotals";
80
- if (
81
- typeof value !== "undefined" &&
82
- (!acc[col] || acc[col].len < value.length) &&
83
- !(index === ds.totalRows - 1 && col < ds.fixedColumns)
84
- ) {
85
- acc[col] = { str: value, len: value.length || 0 };
86
- }
87
- };
88
- return acc;
89
- }, new Array(ds.totalColumns).fill(null))
90
- .map((item) => getTdWidth(item.str))
91
- .reduce((acc, width, col, arr) => {
92
- acc[col] = mc[col] ? getMergeColsWidth(arr, col, mc[col]) : width;
93
- return acc;
94
- }, {});
95
- };
96
-
97
- var getTdWidth = function(str) {
98
- let tdStyles = {
99
- borderLeft: 'solid 1px',
100
- borderRight: 'solid 1px',
101
- fontSize: '11px',
102
- fontFamily: '"Open Sans",sans-serif',
103
- paddingRight: '4px',
104
- paddingLeft: '4px',
105
- wrap: 'nowrap',
106
- visibility: 'hidden',
107
- };
108
- let td = document.createElement('td');
109
- for (let [key, value] of Object.entries(tdStyles)) {
110
- td.style[key] = value;
111
- };
112
- td.innerHTML = str;
113
- document.body.appendChild(td);
114
- let width = Math.min(Math.max(td.offsetWidth, minColWidth), maxColWidth);
115
- document.body.removeChild(td);
116
- return width;
117
- };
118
-
119
- var findMergeCols = function(ds) {
120
- return ds.mergeCells
121
- .filter(cell => cell.row === ds.fixedRows - 1)
122
- .reduce((acc, val) => {
123
- if (!acc[val.col] && val.colspan > 1) acc[val.col] = val.colspan - 1;
124
- return acc;
125
- }, {});
126
- };
127
-
128
- var getMergeColsWidth = function(cw, col, m) {
129
- let rightColsWidth = 0;
130
- for (let _col = col + 1; _col <= col + m; _col++) {
131
- rightColsWidth += cw[_col];
132
- };
133
- return rightColsWidth >= cw[col] ? 0 : cw[col] - rightColsWidth;
134
- };
135
-
136
- opts = $.extend(def, opts, true);
137
-
138
- var headerRenderer = function (cellProperties) {
139
- cellProperties.readOnly = true;
140
- cellProperties.className = opts.header.className;
141
- };
142
- var totalRenderer = function (cellProperties) {
143
- cellProperties.readOnly = opts.showTotals;
144
- cellProperties.format = opts.total.format;
145
- cellProperties.className = opts.total.className;
146
- };
147
- var subTotalRenderer = function (cellProperties) {
148
- cellProperties.readOnly = true;
149
- cellProperties.format = opts.subTotal.format;
150
- cellProperties.className = opts.subTotal.className;
151
- };
152
- var dataRenderer = function (cellProperties) {
153
- cellProperties.readOnly = opts.readOnly;
154
- cellProperties.className = opts.data.className;
155
- cellProperties.format = opts.data.format;
156
- };
157
-
158
- // get changes on pivot table
159
- var getPivotChange = function (change, pvtData, dataSource) {
160
- var rowIdx = change[0] - dataSource.fixedRows;
161
- var colIdx = change[1] - dataSource.fixedColumns;
162
- var dataFilter = {
163
- filterList: [],
164
- oldValue: change[2],
165
- newValue: change[3]
166
- };
167
- if (colIdx >= 0) {
168
- var colKeys = pvtData.getColKeys();
169
- for (var cAttrIdx = 0; cAttrIdx < pvtData.colAttrs.length; cAttrIdx++) {
170
- if (colIdx < colKeys.length) {
171
- var cValues = colKeys[colIdx];
172
- dataFilter.filterList.push({
173
- Key: pvtData.colAttrs[cAttrIdx],
174
- Value: cValues[cAttrIdx]
175
- });
176
- }
177
- }
178
- }
179
- if (rowIdx >= 0) {
180
- var rowKeys = pvtData.getRowKeys();
181
- for (var rAttrIdx = 0; rAttrIdx < pvtData.rowAttrs.length; rAttrIdx++) {
182
- if (rowIdx < rowKeys.length) {
183
- var rValues = rowKeys[rowIdx];
184
- dataFilter.filterList.push({
185
- Key: pvtData.rowAttrs[rAttrIdx],
186
- Value: rValues[rAttrIdx]
187
- });
188
- }
189
- }
190
- }
191
- return dataFilter;
192
- }
193
-
194
- // Parse the pvtData and create datasource to handsontable
195
- var parsePivotData = function (pvtData) {
196
- var dataSource = {
197
- data: [],
198
- columns: [],
199
- fixedColumns: 0,
200
- fixedRows: 0,
201
- mergeCells: [],
202
- totalColumns: 0,
203
- totalRows: 0,
204
- };
205
-
206
- // add rows subtotals
207
- var addRowSubTotals = function (pvtData) {
208
-
209
- const tmpNewRows = [];
210
- const newRowsKeys = [];
211
- for (let i = 1; i < pvtData.rowAttrs.length; i++) {
212
- for (let rowKeyArr of pvtData.rowKeys) {
213
-
214
- let tmpRowKeyArr = rowKeyArr.slice(0, i);
215
- let tmpRowKey = tmpRowKeyArr.join(delim);
216
-
217
- let newKeyArr = tmpRowKeyArr.concat(subtotal);
218
- let newKey = newKeyArr.join(delim);
219
-
220
- if (!pvtData.rowTotals[newKey]) {
221
- pvtData.rowTotals[newKey] = pvtData.rowTotals[tmpRowKey];
222
- newRowsKeys.push(newKeyArr);
223
-
224
- pvtData.tree[newKey] = {};
225
- for (let colKeyArr of pvtData.colKeys) {
226
- let colKey = colKeyArr.join(delim);
227
- if (pvtData.tree[tmpRowKey][colKey]) {
228
- pvtData.tree[newKey][colKey] = pvtData.tree[tmpRowKey][colKey];
229
- }
230
-
231
- for (let j = 1; j < pvtData.colAttrs.length; j++) {
232
- let tmpColKeyArr = colKeyArr.slice(0, j);
233
- let tmpColKeyStr = tmpColKeyArr.join(delim);
234
-
235
- let grandSubTotal = pvtData.tree[tmpRowKey][tmpColKeyStr];
236
- pvtData.tree[newKey][tmpColKeyStr + delim + subtotal] = grandSubTotal;
237
-
238
- }
239
- }
240
- }
241
- }
242
- }
243
- pvtData.rowKeys = pvtData.rowKeys.concat(newRowsKeys);
244
- return pvtData;
245
- };
246
-
247
- // add cols subtotals
248
- var addColSubTotals = function (pvtData) {
249
- // console.log("handson col data", pvtData);
250
- const tmpNewColumns = [];
251
- const newColumnKeys = [];
252
- for (let i = 1; i < pvtData.colAttrs.length; i++) {
253
- for (let colKeyArr of pvtData.colKeys) {
254
-
255
- let tmpColKeyArr = colKeyArr.slice(0, i);
256
- let tmpColKey = tmpColKeyArr.join(delim);
257
-
258
- let newKeyArr = tmpColKeyArr.concat(subtotal);
259
- let newKey = newKeyArr.join(delim);
260
-
261
- if (!pvtData.colTotals[newKey]) {
262
- pvtData.colTotals[newKey] = pvtData.colTotals[tmpColKey];
263
- newColumnKeys.push(newKeyArr);
264
-
265
- for (let rowKeyArr of pvtData.rowKeys) {
266
- let rowKey = rowKeyArr.join(delim);
267
- if (pvtData.tree[rowKey][tmpColKey]) {
268
- pvtData.tree[rowKey][newKey] = pvtData.tree[rowKey][tmpColKey];
269
- }
270
- }
271
- }
272
- }
273
- }
274
- pvtData.colKeys = pvtData.colKeys.concat(newColumnKeys);
275
- // console.log("handson data2", pvtData);
276
- return pvtData;
277
- };
278
-
279
- if (opts.chartOptions.table_options.show_subtotals_for_rows) {
280
- pvtData = addRowSubTotals(pvtData);
281
- }
282
- if (opts.chartOptions.table_options.show_subtotals_for_columns) {
283
- pvtData = addColSubTotals(pvtData);
284
- }
285
-
286
-
287
- var colKeys = pvtData.getColKeys();
288
- var rowKeys = pvtData.getRowKeys();
289
- var hasColumnAttr = (pvtData.colAttrs.length > 0 ? true : false);
290
- var hasRowAttr = (pvtData.rowAttrs.length > 0 ? true : false);
291
-
292
- var addMergeCell = function (row, col, rows, columns, noHAlign, noVAlign) {
293
- dataSource.mergeCells.push({
294
- row: row,
295
- col: col,
296
- rowspan: rows,
297
- colspan: columns
298
- });
299
- }
300
-
301
- //fixed columns and rows
302
- dataSource.fixedColumns = pvtData.rowAttrs.length + (hasColumnAttr ? 1 : 0);
303
- dataSource.fixedRows = pvtData.colAttrs.length + (hasRowAttr ? 1 : 0);
304
-
305
- for (i = 0; i < pvtData.rowAttrs.length; i++) {
306
- rowKeys.sort((a,b) => {
307
- if (_.isEqual(a.slice(0, i), b.slice(0,i)) && a[i] && a[i] === subtotal) return -1;
308
- if (_.isEqual(a.slice(0, i), b.slice(0,i)) && b[i] && b[i] === subtotal) return 1;
309
- return 0;
310
- });
311
- };
312
-
313
- // for extra rows on edit mode. Where show only one dimension on row o column.
314
- var extraColumnLabel = "Grand Totals";
315
- var extraRowLabel = "";
316
- if (opts.totalFilterElements && opts.totalFilterElements.row_total) {
317
- extraColumnLabel = opts.totalFilterElements.row_total.innerHTML;
318
- }
319
- if (opts.totalFilterElements && opts.totalFilterElements.col_total) {
320
- extraRowLabel = opts.totalFilterElements.col_total.innerHTML;
321
- }
322
-
323
- var addExtraColumn = false;
324
- var addExtraRow = false;
325
- if (pvtData.colKeys.length == 0) {
326
- addExtraColumn = true;
327
- }
328
- if (pvtData.rowKeys.length == 0) {
329
- addExtraRow = true;
330
- }
331
-
332
- //columns
333
- var totalColumns = dataSource.totalColumns = pvtData.colKeys.length + pvtData.rowAttrs.length +
334
- (pvtData.colAttrs.length > 0 ? 1 : 0) +
335
- (opts.showTotals || addExtraColumn ? 1 : 0);
336
-
337
- if (!opts.chartOptions.table_options.show_column_total) {
338
- totalColumns--;
339
- }
340
- for (var cc = 0; cc < totalColumns; cc++) {
341
-
342
- if (cc < dataSource.fixedColumns) {
343
- dataSource.columns.push({
344
- type: 'text',
345
- });
346
- }
347
- else {
348
- dataSource.columns.push({
349
- type: 'text',
350
- editor: Handsontable.editors.GenericEditor
351
- });
352
- }
353
- }
354
-
355
- //first merge cells
356
- if (hasRowAttr && hasColumnAttr) {
357
- addMergeCell(0, 0, hasColumnAttr ? pvtData.colAttrs.length : 1, (hasRowAttr ? pvtData.rowAttrs.length : 1));
358
- }
359
-
360
- // ##
361
- // HEADERS (columns)
362
- for (var nn = 0; nn < pvtData.colAttrs.length + (hasRowAttr ? 1 : 0) ; nn++) {
363
- var rowData = [];
364
-
365
- // rows with dimensions on columns
366
- if (nn < pvtData.colAttrs.length) {
367
-
368
- // columns for row attrs
369
- for (var cc = 0; cc < pvtData.rowAttrs.length; cc++) {
370
- rowData.push("");
371
- }
372
-
373
- //column for colum attr,
374
- rowData.push(opts.getIndexContent(pvtData.colAttrs[nn]));
375
-
376
- //data columns
377
- if (pvtData.colKeys.length > 0) {
378
-
379
- var aux = rowData.length;
380
- var startCol = aux;
381
- var prior = colKeys[0][nn];
382
- var toMerge = 0;
383
- for (var cc = 0; cc < colKeys.length; cc++) {
384
-
385
- var textHeader = colKeys[cc][nn];
386
-
387
- if (nn < pvtData.colAttrs.length - 1 && prior != textHeader) {
388
- rowData.push(textHeader);
389
- prior = textHeader;
390
- // merge cell
391
- addMergeCell(nn, aux, 1, toMerge);
392
- aux = aux + toMerge;
393
- toMerge = 1;
394
- }
395
- else {
396
- toMerge++;
397
- rowData.push(textHeader);
398
-
399
- // vertical merge on last row of header columns. Disabled for performance analysis
400
- //if (nn == pvtData.colAttrs.length - 1 && hasRowAttr) {
401
- //addMergeCell(nn,startCol+cc ,2,1);
402
- //}
403
- }
404
- }
405
-
406
- //merge last cell
407
- if (nn < pvtData.colAttrs.length - 1) {
408
- addMergeCell(nn, aux, 1, toMerge);
409
- }
410
-
411
- }
412
-
413
- // total column
414
- if (opts.showTotals || addExtraColumn) {
415
- rowData.push(extraColumnLabel);
416
- }
417
- }
418
- else { // rows with dimensions on columns
419
-
420
- // columns for row attrs
421
- for (var cc = 0; cc < pvtData.rowAttrs.length; cc++) {
422
-
423
- rowData.push(opts.getIndexContent(pvtData.rowAttrs[cc]));
424
- //merge cell
425
- if (cc == pvtData.rowAttrs.length - 1 && hasColumnAttr) {
426
- addMergeCell(nn, cc, 1, 2);
427
- }
428
-
429
- }
430
-
431
- //empty column for colum attr,
432
- if (hasColumnAttr > 0) {
433
- rowData.push("");
434
- }
435
-
436
- //data columns (empty)
437
- for (var cc = 0; cc < colKeys.length; cc++) {
438
- rowData.push("");
439
- }
440
-
441
- // total column
442
- if (opts.showTotals || addExtraColumn) {
443
- rowData.push(extraColumnLabel);
444
- }
445
-
446
- }
447
-
448
- dataSource.data.push(rowData);
449
- }
450
- // END HEADER
451
- // ######
452
-
453
-
454
-
455
- // ######
456
- // DATA
457
-
458
- var mergeDic = {};
459
-
460
- for (var rr = 0; rr < rowKeys.length; rr++) {
461
-
462
- var rowData = [];
463
-
464
- if (rr == 0) {
465
- for (var cc = 0; cc < dataSource.fixedColumns; cc++) {
466
- mergeDic[cc] = {
467
- toMerge: 1,
468
- row: 0,
469
- priorText: rowKeys[rr][cc]
470
- };
471
- }
472
- }
473
-
474
- //column for row atts
475
- for (var cc = 0; cc < pvtData.rowAttrs.length; cc++) {
476
- rowData.push(rowKeys[rr][cc]);
477
- if (rowKeys[rr][cc] === subtotal) {
478
- addMergeCell(rr + pvtData.colAttrs.length + 1, cc, 1, dataSource.fixedColumns - cc, true, true);
479
- } else if (cc === rowKeys[rr].length - 1 && hasColumnAttr) {
480
- addMergeCell(rr + pvtData.colAttrs.length + 1, cc, 1, 2, true, true);
481
- }
482
- // merge cell (last column)
483
- if (opts.chartOptions.table_options.show_column_total && rr != 0 && mergeDic[cc]) { // check for merge dic
484
- if (rowKeys[rr][cc] == mergeDic[cc].priorText) {
485
- mergeDic[cc].toMerge++;
486
- } else if (cc < rowKeys[rr].length - 1) {
487
- //create merge cell for this column
488
- addMergeCell(mergeDic[cc].row + pvtData.colAttrs.length + 1, cc, mergeDic[cc].toMerge, 1);
489
- mergeDic[cc].row = rr;
490
- mergeDic[cc].toMerge = 1;
491
- mergeDic[cc].priorText = rowKeys[rr][cc];
492
- }
493
- }
494
- }
495
-
496
- // empty column (for colum atts)
497
- if (hasColumnAttr) {
498
- rowData.push("");
499
- }
500
-
501
- // columns data
502
- var agg;
503
- for (var cc = 0; cc < colKeys.length; cc++) {
504
- agg = pvtData.getAggregator(rowKeys[rr], colKeys[cc])
505
-
506
- var cellValue = $.pivotUtilities.getFormattedNumber(agg.value(), agg, opts);
507
- // var cellValue = agg.value();
508
-
509
- if (cellValue) {
510
- rowData.push(cellValue);
511
- }
512
- else if (cellValue === 0) {
513
- rowData.push("0");
514
- }
515
- else {
516
- rowData.push("");
517
- }
518
-
519
- }
520
-
521
- // column total
522
- if (opts.showTotals || addExtraColumn) {
523
- // var rowKeyAtt = rowKeys[rr].join(String.fromCharCode(0));
524
- var rowKeyAtt = rowKeys[rr].join(delim);
525
- if (pvtData.rowTotals[rowKeyAtt]) {
526
- let agg = pvtData.getAggregator(rowKeys[rr], []);
527
- let preValue = pvtData.rowTotals[rowKeyAtt].value();
528
- let cellValue = $.pivotUtilities.getFormattedNumber(preValue, agg, opts);
529
- rowData.push(cellValue);
530
- // rowData.push(pvtData.rowTotals[rowKeyAtt].value());
531
- }
532
- else {
533
- rowData.push("");
534
- // rowData.push(0);
535
- }
536
- }
537
-
538
- dataSource.data.push(rowData);
539
-
540
- }
541
-
542
- // add last rows merge cells for each column
543
- if (opts.chartOptions.table_options.show_column_total) {
544
-
545
- for (var cc = 0; cc < pvtData.rowAttrs.length - 1; cc++) {
546
-
547
- if (mergeDic[cc] && mergeDic[cc].toMerge > 1) {
548
- addMergeCell(mergeDic[cc].row + pvtData.colAttrs.length + 1, cc, mergeDic[cc].toMerge, 1);
549
- }
550
- }
551
- }
552
-
553
- // END DATA
554
- // ######
555
-
556
- // ######
557
- // TOTAL
558
- // colums totals area
559
- if (opts.showTotals || addExtraRow) {
560
-
561
- var rowData = [];
562
-
563
- // columns for row attrs
564
- for (var cc = 0; cc < pvtData.rowAttrs.length; cc++) {
565
- rowData.push(extraRowLabel);
566
- }
567
-
568
- //empty column for colum attr,
569
- if (hasColumnAttr) {
570
- rowData.push(extraRowLabel);
571
- }
572
-
573
-
574
- //column totals
575
- if (opts.chartOptions.table_options.show_row_total) {
576
- for (var cc = 0; cc < colKeys.length; cc++) {
577
-
578
- var colKeyAtt = colKeys[cc].join(delim);
579
- if (pvtData.colTotals[colKeyAtt]) {
580
- let agg = pvtData.getAggregator([], colKeys[cc]);
581
- let preValue = pvtData.colTotals[colKeyAtt].value();
582
- let cellValue = $.pivotUtilities.getFormattedNumber(preValue, agg, opts);
583
- rowData.push(cellValue);
584
- }
585
- else {
586
- rowData.push(0);
587
- }
588
- }
589
- }
590
-
591
- //all total column
592
- rowData.push($.pivotUtilities.getFormattedNumber(pvtData.allTotal.value(), pvtData.allTotal, opts));
593
-
594
- // END TOTAL
595
- // ######
596
-
597
- if (opts.chartOptions.table_options.show_row_total) {
598
-
599
- dataSource.data.push(rowData);
600
- }
601
- // end total columns
602
- }
603
- dataSource.totalRows = dataSource.data.length;
604
-
605
- if (opts.showTotals || addExtraRow) {
606
-
607
- // columns total merge cell
608
- if (opts.chartOptions.table_options.show_row_total) {
609
- if (pvtData.rowAttrs.length > 0) {
610
- addMergeCell(dataSource.totalRows - 1, 0, 1, pvtData.rowAttrs.length + (hasColumnAttr ? 1 : 0));
611
- }
612
- }
613
-
614
- if (opts.chartOptions.table_options.show_column_total) {
615
- // rows total merge cell
616
- if (pvtData.colAttrs.length > 0) {
617
- addMergeCell(0, totalColumns - 1, pvtData.colAttrs.length + (hasRowAttr ? 1 : 0), 1);
618
- }
619
- }
620
- }
621
- return dataSource;
622
- }
623
-
624
- // render the table
625
- var renderTable = function (pvtData, opts) {
626
- var dataSource = parsePivotData(pvtData);
627
-
628
- // function to data render
629
- var genericRenderer = function (instance, td, row, col, prop, value, cellProperties) {
630
-
631
- var newValue = '' + value;
632
- td.innerHTML = opts.labelsConvertFunction(newValue);
633
-
634
- if (row < dataSource.fixedRows || col < dataSource.fixedColumns) {
635
- // header
636
- td.className = opts.header.className;
637
-
638
- if (opts.chartOptions.table_options.colorize_headers == true && opts.defaults_colors) {
639
- let color_to_set;
640
- if (row < dataSource.fixedRows) {
641
- if (row < 1) {
642
- color_to_set = opts.defaults_colors[row];
643
- } else {
644
- color_to_set = opts.defaults_colors[1];
645
- }
646
- }
647
- if (col < dataSource.fixedColumns) {
648
- td.className = opts.header.className + " sideHeader";
649
- if (row < dataSource.fixedRows) {
650
- color_to_set = opts.defaults_colors[row];
651
- } else {
652
- // color_to_set = "#fff";
653
- }
654
- }
655
-
656
- if(color_to_set){
657
- td.style.setProperty("background-color", color_to_set, "important");
658
- // td.style.setProperty("border-color", color_to_set, "important");
659
- td.style.color = "#FFFFFF";
660
- // td.style.fontWeight = "bold";
661
- } else {
662
- td.style.setProperty("background-color", "#fff", "important");
663
- }
664
- }
665
- }
666
-
667
- else if (col < dataSource.fixedColumns) {
668
- if ((dataSource.data[0] && dataSource.data[0][col] == subtotal) ||
669
- (dataSource.data[1] && dataSource.data[1][col] == subtotal)) {
670
- td.className = opts.subTotal.className;
671
- } else if (dataSource.data[row] && dataSource.data[row].indexOf(subtotal) !== -1 &&
672
- dataSource.data[row].indexOf(subtotal) < 3) {
673
- td.className = opts.subTotal.className;
674
- }
675
- if (newValue === subtotal) {
676
- td.innerHTML = replaceValue;
677
- } else if (opts.chartOptions.table_options.remove_underscores == true) {
678
- td.innerHTML = newValue.replace("_", " ");
679
- }
680
- } else if (opts.chartOptions.table_options.show_row_total && opts.showTotals && row == dataSource.totalRows - 1) {
681
- //total row
682
- td.className = opts.total.className;
683
- } else if (opts.chartOptions.table_options.show_column_total && opts.showTotals && col == dataSource.totalColumns - 1) {
684
- //total col
685
- td.className = opts.total.className;
686
- } else if (dataSource.data[row] && dataSource.data[row].includes(subtotal)) {
687
- //subTotal row class
688
- td.className = opts.subTotal.className;
689
- } else if ((dataSource.data[0] && dataSource.data[0][col] == subtotal) ||
690
- (dataSource.data[1] && dataSource.data[1][col] == subtotal)) {
691
- //subTotal col class
692
- td.className = opts.subTotal.className;
693
- } else {
694
- //data
695
- td.className = opts.data.className;
696
- }
697
- td.className += " __" + row + "," + col + "__";
698
-
699
- if (opts.chartOptions.table_options.colorize_headers == true) {
700
- td.className += " colorized";
701
- }
702
-
703
- if (opts.chartOptions.table_options.show_row_total && row == dataSource.totalRows-1) {
704
- td.className += " withTopBorder";
705
- }
706
-
707
- if (td.innerHTML === subtotal) {
708
- td.innerHTML = replaceValue;
709
- }
710
- if (td.innerHTML === "undefined") {
711
- td.innerHTML = "";
712
- }
713
-
714
- if (opts.chartOptions.table_options.hide_nulls_in_headers && td.innerHTML === '[null]') {
715
- td.innerHTML = '';
716
- }
717
-
718
- if (opts.chartOptions.table_options.styles) {
719
- for (let rule of opts.chartOptions.table_options.styles) {
720
-
721
- if (!rule.styles || rule.styles.length === 0) {
722
- continue;
723
- }
724
-
725
- if (rule.row && rule.col) {
726
- if (row === parseInt(rule.row) && col === parseInt(rule.col)) {
727
- for (let style of rule.styles) {
728
- td.style.setProperty(style.name, style.val, "important");
729
- }
730
- }
731
- } else if (rule.row && row !== 0 && col !== 0) {
732
- if (rule.repeat) {
733
- const offset = rule.offset || 0;
734
- if (row > offset && (row - offset) % rule.row === 0) {
735
- for (let style of rule.styles) {
736
- td.style.setProperty(style.name, style.val, "important");
737
- }
738
- }
739
- } else if (row === parseInt(rule.row)) {
740
- for (let style of rule.styles) {
741
- td.style.setProperty(style.name, style.val, "important");
742
- }
743
- }
744
- } else if (rule.col && col !== 0 && row !== 0) {
745
- if (rule.repeat) {
746
- const offset = rule.offset || 0;
747
- if (col > offset && (col - offset) % rule.col === 0) {
748
- for (let style of rule.styles) {
749
- td.style.setProperty(style.name, style.val, "important");
750
- }
751
- }
752
- } else if (col === parseInt(rule.col)) {
753
- for (let style of rule.styles) {
754
- td.style.setProperty(style.name, style.val, "important");
755
- }
756
- }
757
- }
758
- }
759
- }
760
- return td;
761
- };
762
-
763
- var _this = this;
764
- if (table) {
765
- table.destroy();
766
- }
767
-
768
- var contextMenu = null;
769
-
770
- if(opts.value_drill_down_fn){
771
- let calBackFn = function(key, selection, clickEvent) {
772
- let row = selection[0].start.row;
773
- let col = selection[0].start.col;
774
- if (row < dataSource.fixedRows || col < dataSource.fixedColumns) {
775
- return;
776
- }
777
- else{
778
- let cols = [];
779
- let rows = [];
780
-
781
- for(let i=0; i< pvtData.rowAttrs.length; i++){
782
- rows.push(dataSource.data[row][i]);
783
- }
784
- for(let i=0; i< pvtData.colAttrs.length; i++){
785
- cols.push(dataSource.data[i][col]);
786
- }
787
-
788
- if (opts.showTotals && row == dataSource.totalRows - 1) {
789
- rows = [];
790
- }
791
-
792
- if (opts.showTotals && col == dataSource.totalColumns - 1) {
793
- cols = [];
794
- }
795
-
796
- opts.value_drill_down_fn(clickEvent, rows, cols, key);
797
- }
798
- };
799
-
800
- let disableFn = function () {
801
- let selection = this.getSelectedLast();
802
- if (selection[0] < dataSource.fixedRows || selection[1] < dataSource.fixedColumns) {
803
- return true;
804
- }
805
- return false;
806
- };
807
-
808
- contextMenu = {
809
- items: {
810
- "open_drill_down_view": {
811
- name: 'Open drill down view',
812
- callback: calBackFn,
813
- disabled: disableFn
814
- },
815
- "export_drill_down": {
816
- name: 'Export drill down to excel',
817
- callback: calBackFn,
818
- disabled: disableFn
819
- }
820
- }
821
- };
822
- }
823
-
824
- var $tableArea = opts.$el.find(".widget-id-" + opts.widgetId);
825
- $tableArea.empty();
826
- console.log('Handsontable data', dataSource);
827
- var maxWidths = calculateMaxWidths(dataSource);
828
- table = new Handsontable($tableArea.get(0), {
829
- licenseKey: 'b0eda-7220b-32d15-e4128-c2f4c', //98463-b132b-fcea0-24f22-da020
830
- data: dataSource.data,
831
- contextMenu: contextMenu,
832
- selectionMode: "single",
833
- colHeaders: false,
834
- allowInsertColumn: false,
835
- allowInsertRow: false,
836
- columns: dataSource.columns,
837
- fixedColumnsLeft: dataSource.fixedColumns,
838
- fixedRowsTop: dataSource.fixedRows,
839
- mergeCells: dataSource.mergeCells,
840
- colWidths: function(index) {
841
- return maxWidths[index];
842
- },
843
- cells: function (row, col, prop) {
844
- var cellProperties = {};
845
- cellProperties.renderer = genericRenderer;
846
- if (row < dataSource.fixedRows || col < dataSource.fixedColumns) {
847
- headerRenderer(cellProperties);
848
- } else {
849
- if (opts.showTotals && (row == dataSource.totalRows - 1 || col == dataSource.totalColumns - 1)) {
850
- totalRenderer(cellProperties);
851
- } else {
852
- dataRenderer(cellProperties);
853
- }
854
- }
855
- return cellProperties;
856
- }
857
- });
858
-
859
- setTimeout(function () {
860
-
861
- var currentState = opts.$el.data("currentState");
862
-
863
- if (currentState) {
864
- if (currentState && currentState.lastRowChanged) {
865
- table.selectCell(currentState.lastRowChanged + 1, currentState.lasColChanged, currentState.lastRowChanged + 1, currentState.lasColChanged);
866
- currentState.lastRowChanged = null;
867
- if (currentState.scrollX && currentState.scrollX > 0) {
868
- opts.$el.scrollLeft(currentState.scrollX);
869
- }
870
- if (currentState.scrollY && currentState.scrollY > 0) {
871
- opts.$el.scrollTop(currentState.scrollY);
872
- }
873
-
874
- currentState = null;
875
- opts.$el.data("currentState", null);
876
- }
877
- }
878
-
879
- }, 5);
880
- return false;
881
- };
882
-
883
- var _this = this;
884
- setTimeout(function () {
885
- renderTable(pvtData, opts);
886
- }, 10);
887
-
888
- // inject the widgetId to the class name so we can separate the tables by it
889
- // look for the search side on line 653 "opts.$el.find(".widget-id-" + opts.widgetId);"
890
- return `<div class='novixPivot widget-id-${opts.widgetId} ${
891
- useNewUx && opts.chartOptions.table_options.use_new_table_design ? 'handsontable-new' : ''
892
- }' style='overflow:auto'></div>`;
893
- }
894
-
895
- };
896
-
897
- }
898
-
899
- module.exports = initNovixRenderer;
1
+ let initNovixRenderer = function($, window, document, Handsontable){
2
+ //register custom editor for format numeric editor
3
+ (function (Handsontable) {
4
+
5
+ var GenericEditor = Handsontable.editors.NumericEditor.prototype.extend();
6
+
7
+ GenericEditor.prototype.beginEditing = function (initialValue) {
8
+
9
+ var BaseEditor = Handsontable.editors.NumericEditor.prototype;
10
+
11
+ if (typeof (initialValue) === 'undefined' && this.originalValue) {
12
+
13
+ var value = '' + this.originalValue;
14
+ if (!isNaN(parseFloat(value))) {
15
+ value = value.replace(",", "");
16
+ value = parseFloat(value).toFixed(10);
17
+ }
18
+ BaseEditor.beginEditing.apply(this, [value]);
19
+ } else {
20
+ BaseEditor.beginEditing.apply(this, arguments);
21
+ }
22
+ BaseEditor.beginEditing.apply(this, [initialValue]);
23
+ };
24
+ Handsontable.editors.GenericEditor = GenericEditor;
25
+
26
+ }(Handsontable));
27
+
28
+ const delim = " , ";
29
+ const subtotal = "subtotalDatarailsPlaceholder";
30
+ const replaceValue = "SubTotals";
31
+ const useNewUx = document.ReportHippo && document.ReportHippo && document.ReportHippo.user &&
32
+ document.ReportHippo.user.organization.settings && document.ReportHippo.user.organization.settings.use_new_ux;
33
+
34
+ $.pivotUtilities.novix_renderers = {
35
+
36
+ "Pivot Table": function (pvtData, opts) {
37
+ return $.pivotUtilities.novix_renderers["Input Table"](pvtData, $.extend({}, opts, { readOnly: true }));
38
+ },
39
+
40
+ "Input Table": function (pvtData, opts) {
41
+
42
+ // for (let i in pvtData.input) {
43
+ // pvtData.input[i].value = pvtData.processRecord(pvtData.input[i]);
44
+ // }
45
+
46
+ var table;
47
+ var def = {
48
+ $el: $(document),
49
+ showTotals: true,
50
+ header: {
51
+ className: "header"
52
+ },
53
+ total: {
54
+ className: "total",
55
+ format: "0,0.00"
56
+ },
57
+ subTotal: {
58
+ className: "subTotal",
59
+ format: "0,0.00"
60
+ },
61
+ data: {
62
+ className: "data",
63
+ format: "0,0.00"
64
+ },
65
+ getIndexContent: function (indexName) {
66
+ // to customize content index on table. For pivot implementation
67
+ return indexName;
68
+ }
69
+ };
70
+
71
+ var minColWidth = 50;
72
+ var maxColWidth = 250;
73
+
74
+ var calculateMaxWidths = function(ds) {
75
+ const mc = findMergeCols(ds);
76
+ return ds.data
77
+ .reduce((acc, row, index) => {
78
+ for (let [col, value] of row.entries()) {
79
+ if (value === subtotal) value = "SubTotals";
80
+ value = typeof value === 'number' ? String(value) : value;
81
+ if (
82
+ typeof value !== "undefined" &&
83
+ (!acc[col] || acc[col].len <= value.length) &&
84
+ !(index === ds.totalRows - 1 && col < ds.fixedColumns)
85
+ ) {
86
+ acc[col] = { str: value, len: value.length || 0, lastRow: index === ds.totalRows - 1 };
87
+ }
88
+ };
89
+ return acc;
90
+ }, new Array(ds.totalColumns).fill(null))
91
+ .map((item) => getTdWidth(item))
92
+ .reduce((acc, width, col, arr) => {
93
+ acc[col] = mc[col] ? getMergeColsWidth(arr, col, mc[col]) : width;
94
+ return acc;
95
+ }, {});
96
+ };
97
+
98
+ var getTdWidth = function(item) {
99
+ let tdStyles = {
100
+ borderLeft: 'solid 1px',
101
+ borderRight: 'solid 1px',
102
+ fontSize: '11px',
103
+ fontFamily: '"Open Sans",sans-serif',
104
+ fontWeight: item.lastRow && opts.chartOptions.table_options.show_row_total ? '700' : '400',
105
+ paddingRight: '4px',
106
+ paddingLeft: '4px',
107
+ wrap: 'nowrap',
108
+ visibility: 'hidden',
109
+ };
110
+ let td = document.createElement('td');
111
+ for (let [key, value] of Object.entries(tdStyles)) {
112
+ td.style[key] = value;
113
+ };
114
+ td.innerHTML = item.str;
115
+ document.body.appendChild(td);
116
+ let width = Math.min(Math.max(td.offsetWidth, minColWidth), maxColWidth);
117
+ document.body.removeChild(td);
118
+ return width;
119
+ };
120
+
121
+ var findMergeCols = function(ds) {
122
+ return ds.mergeCells
123
+ .filter(cell => cell.row === ds.fixedRows - 1)
124
+ .reduce((acc, val) => {
125
+ if (!acc[val.col] && val.colspan > 1) acc[val.col] = val.colspan - 1;
126
+ return acc;
127
+ }, {});
128
+ };
129
+
130
+ var getMergeColsWidth = function(cw, col, m) {
131
+ let rightColsWidth = 0;
132
+ for (let _col = col + 1; _col <= col + m; _col++) {
133
+ rightColsWidth += cw[_col];
134
+ };
135
+ return rightColsWidth >= cw[col] ? 0 : cw[col] - rightColsWidth;
136
+ };
137
+
138
+ opts = $.extend(def, opts, true);
139
+
140
+ var headerRenderer = function (cellProperties) {
141
+ cellProperties.readOnly = true;
142
+ cellProperties.className = opts.header.className;
143
+ };
144
+ var totalRenderer = function (cellProperties) {
145
+ cellProperties.readOnly = opts.showTotals;
146
+ cellProperties.format = opts.total.format;
147
+ cellProperties.className = opts.total.className;
148
+ };
149
+ var subTotalRenderer = function (cellProperties) {
150
+ cellProperties.readOnly = true;
151
+ cellProperties.format = opts.subTotal.format;
152
+ cellProperties.className = opts.subTotal.className;
153
+ };
154
+ var dataRenderer = function (cellProperties) {
155
+ cellProperties.readOnly = opts.readOnly;
156
+ cellProperties.className = opts.data.className;
157
+ cellProperties.format = opts.data.format;
158
+ };
159
+
160
+ // get changes on pivot table
161
+ var getPivotChange = function (change, pvtData, dataSource) {
162
+ var rowIdx = change[0] - dataSource.fixedRows;
163
+ var colIdx = change[1] - dataSource.fixedColumns;
164
+ var dataFilter = {
165
+ filterList: [],
166
+ oldValue: change[2],
167
+ newValue: change[3]
168
+ };
169
+ if (colIdx >= 0) {
170
+ var colKeys = pvtData.getColKeys();
171
+ for (var cAttrIdx = 0; cAttrIdx < pvtData.colAttrs.length; cAttrIdx++) {
172
+ if (colIdx < colKeys.length) {
173
+ var cValues = colKeys[colIdx];
174
+ dataFilter.filterList.push({
175
+ Key: pvtData.colAttrs[cAttrIdx],
176
+ Value: cValues[cAttrIdx]
177
+ });
178
+ }
179
+ }
180
+ }
181
+ if (rowIdx >= 0) {
182
+ var rowKeys = pvtData.getRowKeys();
183
+ for (var rAttrIdx = 0; rAttrIdx < pvtData.rowAttrs.length; rAttrIdx++) {
184
+ if (rowIdx < rowKeys.length) {
185
+ var rValues = rowKeys[rowIdx];
186
+ dataFilter.filterList.push({
187
+ Key: pvtData.rowAttrs[rAttrIdx],
188
+ Value: rValues[rAttrIdx]
189
+ });
190
+ }
191
+ }
192
+ }
193
+ return dataFilter;
194
+ }
195
+
196
+ // Parse the pvtData and create datasource to handsontable
197
+ var parsePivotData = function (pvtData) {
198
+ var dataSource = {
199
+ data: [],
200
+ columns: [],
201
+ fixedColumns: 0,
202
+ fixedRows: 0,
203
+ mergeCells: [],
204
+ totalColumns: 0,
205
+ totalRows: 0,
206
+ };
207
+
208
+ // add rows subtotals
209
+ var addRowSubTotals = function (pvtData) {
210
+
211
+ const tmpNewRows = [];
212
+ const newRowsKeys = [];
213
+ for (let i = 1; i < pvtData.rowAttrs.length; i++) {
214
+ for (let rowKeyArr of pvtData.rowKeys) {
215
+
216
+ let tmpRowKeyArr = rowKeyArr.slice(0, i);
217
+ let tmpRowKey = tmpRowKeyArr.join(delim);
218
+
219
+ let newKeyArr = tmpRowKeyArr.concat(subtotal);
220
+ let newKey = newKeyArr.join(delim);
221
+
222
+ if (!pvtData.rowTotals[newKey]) {
223
+ pvtData.rowTotals[newKey] = pvtData.rowTotals[tmpRowKey];
224
+ newRowsKeys.push(newKeyArr);
225
+
226
+ pvtData.tree[newKey] = {};
227
+ for (let colKeyArr of pvtData.colKeys) {
228
+ let colKey = colKeyArr.join(delim);
229
+ if (pvtData.tree[tmpRowKey][colKey]) {
230
+ pvtData.tree[newKey][colKey] = pvtData.tree[tmpRowKey][colKey];
231
+ }
232
+
233
+ for (let j = 1; j < pvtData.colAttrs.length; j++) {
234
+ let tmpColKeyArr = colKeyArr.slice(0, j);
235
+ let tmpColKeyStr = tmpColKeyArr.join(delim);
236
+
237
+ let grandSubTotal = pvtData.tree[tmpRowKey][tmpColKeyStr];
238
+ pvtData.tree[newKey][tmpColKeyStr + delim + subtotal] = grandSubTotal;
239
+
240
+ }
241
+ }
242
+ }
243
+ }
244
+ }
245
+ pvtData.rowKeys = pvtData.rowKeys.concat(newRowsKeys);
246
+ return pvtData;
247
+ };
248
+
249
+ // add cols subtotals
250
+ var addColSubTotals = function (pvtData) {
251
+ // console.log("handson col data", pvtData);
252
+ const tmpNewColumns = [];
253
+ const newColumnKeys = [];
254
+ for (let i = 1; i < pvtData.colAttrs.length; i++) {
255
+ for (let colKeyArr of pvtData.colKeys) {
256
+
257
+ let tmpColKeyArr = colKeyArr.slice(0, i);
258
+ let tmpColKey = tmpColKeyArr.join(delim);
259
+
260
+ let newKeyArr = tmpColKeyArr.concat(subtotal);
261
+ let newKey = newKeyArr.join(delim);
262
+
263
+ if (!pvtData.colTotals[newKey]) {
264
+ pvtData.colTotals[newKey] = pvtData.colTotals[tmpColKey];
265
+ newColumnKeys.push(newKeyArr);
266
+
267
+ for (let rowKeyArr of pvtData.rowKeys) {
268
+ let rowKey = rowKeyArr.join(delim);
269
+ if (pvtData.tree[rowKey][tmpColKey]) {
270
+ pvtData.tree[rowKey][newKey] = pvtData.tree[rowKey][tmpColKey];
271
+ }
272
+ }
273
+ }
274
+ }
275
+ }
276
+ pvtData.colKeys = pvtData.colKeys.concat(newColumnKeys);
277
+ // console.log("handson data2", pvtData);
278
+ return pvtData;
279
+ };
280
+
281
+ if (opts.chartOptions.table_options.show_subtotals_for_rows) {
282
+ pvtData = addRowSubTotals(pvtData);
283
+ }
284
+ if (opts.chartOptions.table_options.show_subtotals_for_columns) {
285
+ pvtData = addColSubTotals(pvtData);
286
+ }
287
+
288
+
289
+ var colKeys = pvtData.getColKeys();
290
+ var rowKeys = pvtData.getRowKeys();
291
+ var hasColumnAttr = (pvtData.colAttrs.length > 0 ? true : false);
292
+ var hasRowAttr = (pvtData.rowAttrs.length > 0 ? true : false);
293
+
294
+ var addMergeCell = function (row, col, rows, columns, noHAlign, noVAlign) {
295
+ dataSource.mergeCells.push({
296
+ row: row,
297
+ col: col,
298
+ rowspan: rows,
299
+ colspan: columns
300
+ });
301
+ }
302
+
303
+ //fixed columns and rows
304
+ dataSource.fixedColumns = pvtData.rowAttrs.length + (hasColumnAttr ? 1 : 0);
305
+ dataSource.fixedRows = pvtData.colAttrs.length + (hasRowAttr ? 1 : 0);
306
+
307
+ for (i = 0; i < pvtData.rowAttrs.length; i++) {
308
+ rowKeys.sort((a,b) => {
309
+ if (_.isEqual(a.slice(0, i), b.slice(0,i)) && a[i] && a[i] === subtotal) return -1;
310
+ if (_.isEqual(a.slice(0, i), b.slice(0,i)) && b[i] && b[i] === subtotal) return 1;
311
+ return 0;
312
+ });
313
+ };
314
+
315
+ // for extra rows on edit mode. Where show only one dimension on row o column.
316
+ var extraColumnLabel = "Grand Totals";
317
+ var extraRowLabel = "Grand Totals";
318
+ if (opts.totalFilterElements && opts.totalFilterElements.row_total) {
319
+ extraColumnLabel = opts.totalFilterElements.row_total.innerHTML;
320
+ }
321
+ if (opts.totalFilterElements && opts.totalFilterElements.col_total) {
322
+ extraRowLabel = opts.totalFilterElements.col_total.innerHTML;
323
+ }
324
+
325
+ var addExtraColumn = false;
326
+ var addExtraRow = false;
327
+ if (pvtData.colKeys.length == 0) {
328
+ addExtraColumn = true;
329
+ }
330
+ if (pvtData.rowKeys.length == 0) {
331
+ addExtraRow = true;
332
+ }
333
+
334
+ //columns
335
+ var totalColumns = dataSource.totalColumns = pvtData.colKeys.length + pvtData.rowAttrs.length +
336
+ (pvtData.colAttrs.length > 0 ? 1 : 0) +
337
+ (opts.showTotals || addExtraColumn ? 1 : 0);
338
+
339
+ if (!opts.chartOptions.table_options.show_column_total) {
340
+ totalColumns--;
341
+ }
342
+ for (var cc = 0; cc < totalColumns; cc++) {
343
+
344
+ if (cc < dataSource.fixedColumns) {
345
+ dataSource.columns.push({
346
+ type: 'text',
347
+ });
348
+ }
349
+ else {
350
+ dataSource.columns.push({
351
+ type: 'text',
352
+ editor: Handsontable.editors.GenericEditor
353
+ });
354
+ }
355
+ }
356
+
357
+ //first merge cells
358
+ if (hasRowAttr && hasColumnAttr) {
359
+ addMergeCell(0, 0, hasColumnAttr ? pvtData.colAttrs.length : 1, (hasRowAttr ? pvtData.rowAttrs.length : 1));
360
+ }
361
+
362
+ // ##
363
+ // HEADERS (columns)
364
+ for (var nn = 0; nn < pvtData.colAttrs.length + (hasRowAttr ? 1 : 0) ; nn++) {
365
+ var rowData = [];
366
+
367
+ // rows with dimensions on columns
368
+ if (nn < pvtData.colAttrs.length) {
369
+
370
+ // columns for row attrs
371
+ for (var cc = 0; cc < pvtData.rowAttrs.length; cc++) {
372
+ rowData.push("");
373
+ }
374
+
375
+ //column for colum attr,
376
+ rowData.push(opts.getIndexContent(pvtData.colAttrs[nn]));
377
+
378
+ //data columns
379
+ if (pvtData.colKeys.length > 0) {
380
+
381
+ var aux = rowData.length;
382
+ var startCol = aux;
383
+ var prior = colKeys[0][nn];
384
+ var toMerge = 0;
385
+ for (var cc = 0; cc < colKeys.length; cc++) {
386
+
387
+ var textHeader = colKeys[cc][nn];
388
+
389
+ if (nn < pvtData.colAttrs.length - 1 && prior != textHeader) {
390
+ rowData.push(textHeader);
391
+ prior = textHeader;
392
+ // merge cell
393
+ addMergeCell(nn, aux, 1, toMerge);
394
+ aux = aux + toMerge;
395
+ toMerge = 1;
396
+ }
397
+ else {
398
+ toMerge++;
399
+ rowData.push(textHeader);
400
+
401
+ // vertical merge on last row of header columns. Disabled for performance analysis
402
+ //if (nn == pvtData.colAttrs.length - 1 && hasRowAttr) {
403
+ //addMergeCell(nn,startCol+cc ,2,1);
404
+ //}
405
+ }
406
+ }
407
+
408
+ //merge last cell
409
+ if (nn < pvtData.colAttrs.length - 1) {
410
+ addMergeCell(nn, aux, 1, toMerge);
411
+ }
412
+
413
+ }
414
+
415
+ // total column
416
+ if (opts.showTotals || addExtraColumn) {
417
+ rowData.push(extraColumnLabel);
418
+ }
419
+ }
420
+ else { // rows with dimensions on columns
421
+
422
+ // columns for row attrs
423
+ for (var cc = 0; cc < pvtData.rowAttrs.length; cc++) {
424
+
425
+ rowData.push(opts.getIndexContent(pvtData.rowAttrs[cc]));
426
+ //merge cell
427
+ if (cc == pvtData.rowAttrs.length - 1 && hasColumnAttr) {
428
+ addMergeCell(nn, cc, 1, 2);
429
+ }
430
+
431
+ }
432
+
433
+ //empty column for colum attr,
434
+ if (hasColumnAttr > 0) {
435
+ rowData.push("");
436
+ }
437
+
438
+ //data columns (empty)
439
+ for (var cc = 0; cc < colKeys.length; cc++) {
440
+ rowData.push("");
441
+ }
442
+
443
+ // total column
444
+ if (opts.showTotals || addExtraColumn) {
445
+ rowData.push(extraColumnLabel);
446
+ }
447
+
448
+ }
449
+
450
+ dataSource.data.push(rowData);
451
+ }
452
+ // END HEADER
453
+ // ######
454
+
455
+
456
+
457
+ // ######
458
+ // DATA
459
+
460
+ var mergeDic = {};
461
+
462
+ for (var rr = 0; rr < rowKeys.length; rr++) {
463
+
464
+ var rowData = [];
465
+
466
+ if (rr == 0) {
467
+ for (var cc = 0; cc < dataSource.fixedColumns; cc++) {
468
+ mergeDic[cc] = {
469
+ toMerge: 1,
470
+ row: 0,
471
+ priorText: rowKeys[rr][cc]
472
+ };
473
+ }
474
+ }
475
+
476
+ //column for row atts
477
+ for (var cc = 0; cc < pvtData.rowAttrs.length; cc++) {
478
+ rowData.push(rowKeys[rr][cc]);
479
+ if (rowKeys[rr][cc] === subtotal) {
480
+ addMergeCell(rr + pvtData.colAttrs.length + 1, cc, 1, dataSource.fixedColumns - cc, true, true);
481
+ } else if (cc === rowKeys[rr].length - 1 && hasColumnAttr) {
482
+ addMergeCell(rr + pvtData.colAttrs.length + 1, cc, 1, 2, true, true);
483
+ }
484
+ // merge cell (last column)
485
+ if (opts.chartOptions.table_options.show_column_total && rr != 0 && mergeDic[cc]) { // check for merge dic
486
+ if (rowKeys[rr][cc] == mergeDic[cc].priorText) {
487
+ mergeDic[cc].toMerge++;
488
+ } else if (cc < rowKeys[rr].length - 1) {
489
+ //create merge cell for this column
490
+ addMergeCell(mergeDic[cc].row + pvtData.colAttrs.length + 1, cc, mergeDic[cc].toMerge, 1);
491
+ mergeDic[cc].row = rr;
492
+ mergeDic[cc].toMerge = 1;
493
+ mergeDic[cc].priorText = rowKeys[rr][cc];
494
+ }
495
+ }
496
+ }
497
+
498
+ // empty column (for colum atts)
499
+ if (hasColumnAttr) {
500
+ rowData.push("");
501
+ }
502
+
503
+ // columns data
504
+ var agg;
505
+ for (var cc = 0; cc < colKeys.length; cc++) {
506
+ agg = pvtData.getAggregator(rowKeys[rr], colKeys[cc])
507
+
508
+ var cellValue = $.pivotUtilities.getFormattedNumber(agg.value(), agg, opts);
509
+ // var cellValue = agg.value();
510
+
511
+ if (cellValue) {
512
+ rowData.push(cellValue);
513
+ }
514
+ else if (cellValue === 0) {
515
+ rowData.push("0");
516
+ }
517
+ else {
518
+ rowData.push("");
519
+ }
520
+
521
+ }
522
+
523
+ // column total
524
+ if (opts.showTotals || addExtraColumn) {
525
+ // var rowKeyAtt = rowKeys[rr].join(String.fromCharCode(0));
526
+ var rowKeyAtt = rowKeys[rr].join(delim);
527
+ if (pvtData.rowTotals[rowKeyAtt]) {
528
+ let agg = pvtData.getAggregator(rowKeys[rr], []);
529
+ let preValue = pvtData.rowTotals[rowKeyAtt].value();
530
+ let cellValue = $.pivotUtilities.getFormattedNumber(preValue, agg, opts);
531
+ rowData.push(cellValue);
532
+ // rowData.push(pvtData.rowTotals[rowKeyAtt].value());
533
+ }
534
+ else {
535
+ rowData.push("");
536
+ // rowData.push(0);
537
+ }
538
+ }
539
+
540
+ dataSource.data.push(rowData);
541
+
542
+ }
543
+
544
+ // add last rows merge cells for each column
545
+ if (opts.chartOptions.table_options.show_column_total) {
546
+
547
+ for (var cc = 0; cc < pvtData.rowAttrs.length - 1; cc++) {
548
+
549
+ if (mergeDic[cc] && mergeDic[cc].toMerge > 1) {
550
+ addMergeCell(mergeDic[cc].row + pvtData.colAttrs.length + 1, cc, mergeDic[cc].toMerge, 1);
551
+ }
552
+ }
553
+ }
554
+
555
+ // END DATA
556
+ // ######
557
+
558
+ // ######
559
+ // TOTAL
560
+ // colums totals area
561
+ if (opts.showTotals || addExtraRow) {
562
+
563
+ var rowData = [];
564
+
565
+ // columns for row attrs
566
+ for (var cc = 0; cc < pvtData.rowAttrs.length; cc++) {
567
+ rowData.push(extraRowLabel);
568
+ }
569
+
570
+ //empty column for colum attr,
571
+ if (hasColumnAttr) {
572
+ rowData.push(extraRowLabel);
573
+ }
574
+
575
+
576
+ //column totals
577
+ if (opts.chartOptions.table_options.show_row_total) {
578
+ for (var cc = 0; cc < colKeys.length; cc++) {
579
+
580
+ var colKeyAtt = colKeys[cc].join(delim);
581
+ if (pvtData.colTotals[colKeyAtt]) {
582
+ let agg = pvtData.getAggregator([], colKeys[cc]);
583
+ let preValue = pvtData.colTotals[colKeyAtt].value();
584
+ let cellValue = $.pivotUtilities.getFormattedNumber(preValue, agg, opts);
585
+ rowData.push(cellValue);
586
+ }
587
+ else {
588
+ rowData.push(0);
589
+ }
590
+ }
591
+ }
592
+
593
+ //all total column
594
+ rowData.push($.pivotUtilities.getFormattedNumber(pvtData.allTotal.value(), pvtData.allTotal, opts));
595
+
596
+ // END TOTAL
597
+ // ######
598
+
599
+ if (opts.chartOptions.table_options.show_row_total) {
600
+
601
+ dataSource.data.push(rowData);
602
+ }
603
+ // end total columns
604
+ }
605
+ dataSource.totalRows = dataSource.data.length;
606
+
607
+ if (opts.showTotals || addExtraRow) {
608
+
609
+ // columns total merge cell
610
+ if (opts.chartOptions.table_options.show_row_total) {
611
+ if (pvtData.rowAttrs.length > 0) {
612
+ addMergeCell(dataSource.totalRows - 1, 0, 1, pvtData.rowAttrs.length + (hasColumnAttr ? 1 : 0));
613
+ }
614
+ }
615
+
616
+ if (opts.chartOptions.table_options.show_column_total) {
617
+ // rows total merge cell
618
+ if (pvtData.colAttrs.length > 0) {
619
+ addMergeCell(0, totalColumns - 1, pvtData.colAttrs.length + (hasRowAttr ? 1 : 0), 1);
620
+ }
621
+ }
622
+ }
623
+ return dataSource;
624
+ }
625
+
626
+ // render the table
627
+ var renderTable = function (pvtData, opts) {
628
+ var dataSource = parsePivotData(pvtData);
629
+
630
+ // function to data render
631
+ var genericRenderer = function (instance, td, row, col, prop, value, cellProperties) {
632
+
633
+ var newValue = '' + value;
634
+ td.innerHTML = opts.labelsConvertFunction(newValue);
635
+
636
+ if (row < dataSource.fixedRows || col < dataSource.fixedColumns) {
637
+ // header
638
+ td.className = opts.header.className;
639
+
640
+ if (opts.chartOptions.table_options.colorize_headers == true && opts.defaults_colors) {
641
+ let color_to_set;
642
+ if (row < dataSource.fixedRows) {
643
+ if (row < 1) {
644
+ color_to_set = opts.defaults_colors[row];
645
+ } else {
646
+ color_to_set = opts.defaults_colors[1];
647
+ }
648
+ }
649
+ if (col < dataSource.fixedColumns) {
650
+ td.className = opts.header.className + " sideHeader";
651
+ if (row < dataSource.fixedRows) {
652
+ color_to_set = opts.defaults_colors[row];
653
+ } else {
654
+ // color_to_set = "#fff";
655
+ }
656
+ }
657
+
658
+ if(color_to_set){
659
+ td.style.setProperty("background-color", color_to_set, "important");
660
+ // td.style.setProperty("border-color", color_to_set, "important");
661
+ td.style.color = "#FFFFFF";
662
+ // td.style.fontWeight = "bold";
663
+ } else {
664
+ td.style.setProperty("background-color", "#fff", "important");
665
+ }
666
+ }
667
+ }
668
+
669
+ else if (col < dataSource.fixedColumns) {
670
+ if ((dataSource.data[0] && dataSource.data[0][col] == subtotal) ||
671
+ (dataSource.data[1] && dataSource.data[1][col] == subtotal)) {
672
+ td.className = opts.subTotal.className;
673
+ } else if (dataSource.data[row] && dataSource.data[row].indexOf(subtotal) !== -1 &&
674
+ dataSource.data[row].indexOf(subtotal) < 3) {
675
+ td.className = opts.subTotal.className;
676
+ }
677
+ if (newValue === subtotal) {
678
+ td.innerHTML = replaceValue;
679
+ } else if (opts.chartOptions.table_options.remove_underscores == true) {
680
+ td.innerHTML = newValue.replace("_", " ");
681
+ }
682
+ } else if (opts.chartOptions.table_options.show_row_total && opts.showTotals && row == dataSource.totalRows - 1) {
683
+ //total row
684
+ td.className = opts.total.className;
685
+ } else if (opts.chartOptions.table_options.show_column_total && opts.showTotals && col == dataSource.totalColumns - 1) {
686
+ //total col
687
+ td.className = opts.total.className;
688
+ } else if (dataSource.data[row] && dataSource.data[row].includes(subtotal)) {
689
+ //subTotal row class
690
+ td.className = opts.subTotal.className;
691
+ } else if ((dataSource.data[0] && dataSource.data[0][col] == subtotal) ||
692
+ (dataSource.data[1] && dataSource.data[1][col] == subtotal)) {
693
+ //subTotal col class
694
+ td.className = opts.subTotal.className;
695
+ } else {
696
+ //data
697
+ td.className = opts.data.className;
698
+ }
699
+ td.className += " __" + row + "," + col + "__";
700
+
701
+ if (opts.chartOptions.table_options.colorize_headers == true) {
702
+ td.className += " colorized";
703
+ }
704
+
705
+ if (opts.chartOptions.table_options.show_row_total && row == dataSource.totalRows-1) {
706
+ td.className += " withTopBorder";
707
+ }
708
+
709
+ if (td.innerHTML === subtotal) {
710
+ td.innerHTML = replaceValue;
711
+ }
712
+ if (td.innerHTML === "undefined") {
713
+ td.innerHTML = "";
714
+ }
715
+
716
+ if (opts.chartOptions.table_options.hide_nulls_in_headers && td.innerHTML === '[null]') {
717
+ td.innerHTML = '';
718
+ }
719
+
720
+ if (opts.chartOptions.table_options.styles) {
721
+ for (let rule of opts.chartOptions.table_options.styles) {
722
+
723
+ if (!rule.styles || rule.styles.length === 0) {
724
+ continue;
725
+ }
726
+
727
+ if (rule.row && rule.col) {
728
+ if (row === parseInt(rule.row) && col === parseInt(rule.col)) {
729
+ for (let style of rule.styles) {
730
+ td.style.setProperty(style.name, style.val, "important");
731
+ }
732
+ }
733
+ } else if (rule.row && row !== 0 && col !== 0) {
734
+ if (rule.repeat) {
735
+ const offset = rule.offset || 0;
736
+ if (row > offset && (row - offset) % rule.row === 0) {
737
+ for (let style of rule.styles) {
738
+ td.style.setProperty(style.name, style.val, "important");
739
+ }
740
+ }
741
+ } else if (row === parseInt(rule.row)) {
742
+ for (let style of rule.styles) {
743
+ td.style.setProperty(style.name, style.val, "important");
744
+ }
745
+ }
746
+ } else if (rule.col && col !== 0 && row !== 0) {
747
+ if (rule.repeat) {
748
+ const offset = rule.offset || 0;
749
+ if (col > offset && (col - offset) % rule.col === 0) {
750
+ for (let style of rule.styles) {
751
+ td.style.setProperty(style.name, style.val, "important");
752
+ }
753
+ }
754
+ } else if (col === parseInt(rule.col)) {
755
+ for (let style of rule.styles) {
756
+ td.style.setProperty(style.name, style.val, "important");
757
+ }
758
+ }
759
+ }
760
+ }
761
+ }
762
+ return td;
763
+ };
764
+
765
+ var _this = this;
766
+ if (table) {
767
+ table.destroy();
768
+ }
769
+
770
+ var contextMenu = null;
771
+
772
+ if(opts.value_drill_down_fn){
773
+ let calBackFn = function(key, selection, clickEvent) {
774
+ let row = selection[0].start.row;
775
+ let col = selection[0].start.col;
776
+ if (row < dataSource.fixedRows || col < dataSource.fixedColumns) {
777
+ return;
778
+ }
779
+ else{
780
+ let cols = [];
781
+ let rows = [];
782
+
783
+ for(let i=0; i< pvtData.rowAttrs.length; i++){
784
+ rows.push(dataSource.data[row][i]);
785
+ }
786
+ for(let i=0; i< pvtData.colAttrs.length; i++){
787
+ cols.push(dataSource.data[i][col]);
788
+ }
789
+
790
+ if (opts.showTotals && row == dataSource.totalRows - 1) {
791
+ rows = [];
792
+ }
793
+
794
+ if (opts.showTotals && col == dataSource.totalColumns - 1) {
795
+ cols = [];
796
+ }
797
+
798
+ opts.value_drill_down_fn(clickEvent, rows, cols, key);
799
+ }
800
+ };
801
+
802
+ let disableFn = function () {
803
+ let selection = this.getSelectedLast();
804
+ if (selection[0] < dataSource.fixedRows || selection[1] < dataSource.fixedColumns) {
805
+ return true;
806
+ }
807
+ return false;
808
+ };
809
+
810
+ contextMenu = {
811
+ items: {
812
+ "open_drill_down_view": {
813
+ name: 'Open drill down view',
814
+ callback: calBackFn,
815
+ disabled: disableFn
816
+ },
817
+ "export_drill_down": {
818
+ name: 'Export drill down to excel',
819
+ callback: calBackFn,
820
+ disabled: disableFn
821
+ }
822
+ }
823
+ };
824
+ }
825
+
826
+ var $tableArea = opts.$el.find(".widget-id-" + opts.widgetId);
827
+ $tableArea.empty();
828
+ console.log('Handsontable data', dataSource);
829
+ var maxWidths = calculateMaxWidths(dataSource);
830
+ table = new Handsontable($tableArea.get(0), {
831
+ licenseKey: 'b0eda-7220b-32d15-e4128-c2f4c', //98463-b132b-fcea0-24f22-da020
832
+ data: dataSource.data,
833
+ contextMenu: contextMenu,
834
+ selectionMode: "single",
835
+ colHeaders: false,
836
+ allowInsertColumn: false,
837
+ allowInsertRow: false,
838
+ columns: dataSource.columns,
839
+ fixedColumnsLeft: dataSource.fixedColumns,
840
+ fixedRowsTop: dataSource.fixedRows,
841
+ mergeCells: dataSource.mergeCells,
842
+ colWidths: function(index) {
843
+ return maxWidths[index];
844
+ },
845
+ cells: function (row, col, prop) {
846
+ var cellProperties = {};
847
+ cellProperties.renderer = genericRenderer;
848
+ if (row < dataSource.fixedRows || col < dataSource.fixedColumns) {
849
+ headerRenderer(cellProperties);
850
+ } else {
851
+ if (opts.showTotals && (row == dataSource.totalRows - 1 || col == dataSource.totalColumns - 1)) {
852
+ totalRenderer(cellProperties);
853
+ } else {
854
+ dataRenderer(cellProperties);
855
+ }
856
+ }
857
+ return cellProperties;
858
+ }
859
+ });
860
+
861
+ setTimeout(function () {
862
+
863
+ var currentState = opts.$el.data("currentState");
864
+
865
+ if (currentState) {
866
+ if (currentState && currentState.lastRowChanged) {
867
+ table.selectCell(currentState.lastRowChanged + 1, currentState.lasColChanged, currentState.lastRowChanged + 1, currentState.lasColChanged);
868
+ currentState.lastRowChanged = null;
869
+ if (currentState.scrollX && currentState.scrollX > 0) {
870
+ opts.$el.scrollLeft(currentState.scrollX);
871
+ }
872
+ if (currentState.scrollY && currentState.scrollY > 0) {
873
+ opts.$el.scrollTop(currentState.scrollY);
874
+ }
875
+
876
+ currentState = null;
877
+ opts.$el.data("currentState", null);
878
+ }
879
+ }
880
+
881
+ }, 5);
882
+ return false;
883
+ };
884
+
885
+ var _this = this;
886
+ setTimeout(function () {
887
+ renderTable(pvtData, opts);
888
+ }, 10);
889
+
890
+ // inject the widgetId to the class name so we can separate the tables by it
891
+ // look for the search side on line 653 "opts.$el.find(".widget-id-" + opts.widgetId);"
892
+ return `<div class='novixPivot widget-id-${opts.widgetId} ${
893
+ useNewUx && opts.chartOptions.table_options.use_new_table_design ? 'handsontable-new' : ''
894
+ }' style='overflow:auto'></div>`;
895
+ }
896
+
897
+ };
898
+
899
+ }
900
+
901
+ module.exports = initNovixRenderer;