@datarailsshared/dr_renderer 1.2.101 → 1.2.102-dev

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,901 +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
- 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 _.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 (let 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;
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 _.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 (let 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;