@datarailsshared/dr_renderer 1.4.67 → 1.4.80

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -23,4 +23,42 @@ To compile types for the project use: `npm run build:types`
23
23
 
24
24
  Just merge to master branch
25
25
 
26
+ ## Error Handling
27
+
28
+ The renderer includes a comprehensive error handling system with specific error types for different scenarios:
29
+
30
+ ### Error Codes
31
+
32
+ The following error codes are available via `RendererErrorCodes`:
33
+
34
+ - `NoDataError` (1) - No data is available for rendering
35
+ - `TooMuchDataError` (3) - Dataset exceeds capacity
36
+ - `DataConflictError` (5) - Conflicts detected in data being processed
37
+ - `GaugeConfigurationError` (6) - Gauge chart missing required data
38
+ - `GenericRenderingError` (7) - Generic rendering failure in PivotTable components
39
+ - `GenericComputationalError` (8) - Generic computational failure in PivotTable components
40
+
41
+ ### Error Classes
42
+
43
+ All errors extend the `BaseRendererError` class which includes:
44
+ - `code` - Unique error code for identification
45
+ - `title` - Human-readable error message
46
+ - `options` - Additional context or configuration
47
+
48
+ ### Usage Example
49
+
50
+ ```javascript
51
+ const { RendererErrorCodes, NoDataError, TooMuchDataError } = require('@datarailsshared/dr_renderer');
52
+
53
+ try {
54
+ // Your rendering code here
55
+ } catch (error) {
56
+ if (error instanceof NoDataError) {
57
+ console.log('No data available:', error.title);
58
+ } else if (error.code === RendererErrorCodes.TooMuchDataError) {
59
+ console.log('Too much data:', error.title);
60
+ }
61
+ }
62
+ ```
63
+
26
64
  ###
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datarailsshared/dr_renderer",
3
- "version": "1.4.67",
3
+ "version": "1.4.80",
4
4
  "description": "DataRails charts and tables renderer",
5
5
  "keywords": [
6
6
  "datarails",
@@ -1,5 +1,5 @@
1
1
  const { DR_SCENARIO } = require('./smart_queries_helper');
2
-
2
+ const { TooMuchDataError } = require('./errors');
3
3
 
4
4
  let initDRPivotTable = function($, window, document) {
5
5
  var hasProp = {}.hasOwnProperty;
@@ -437,7 +437,6 @@ let initDRPivotTable = function($, window, document) {
437
437
 
438
438
  return resultsArr;
439
439
  } else {
440
- let tooMuch = false;
441
440
  const show_more_than_thousand_rows = _.get(opts, 'chartOptions.table_options.show_more_than_thousand_rows', false);
442
441
  if (pvtData &&
443
442
  (pvtData.rowKeys.length > 1000 || pvtData.colKeys.length > 500) &&
@@ -445,15 +444,16 @@ let initDRPivotTable = function($, window, document) {
445
444
  !show_more_than_thousand_rows) {
446
445
  pvtData.rowKeys = [];
447
446
  pvtData.colKeys = [];
448
- tooMuch = true;
449
- opts.error_has_occurred = true;
450
- opts.error_params = $.pivotUtilities.errorHandling.placeholders.tooMuchData;
447
+
448
+ const tooMuchDataError = new TooMuchDataError();
449
+ console.error(tooMuchDataError.title);
450
+ throw tooMuchDataError;
451
451
  }
452
- return SubtotalRenderer(pvtData, opts, charttype, tooMuch, opts.error_params);
452
+ return SubtotalRenderer(pvtData, opts, charttype);
453
453
  }
454
454
  }
455
455
 
456
- SubtotalRenderer = function(pivotData, opts, charttype, tooMuch = false, error_params) {
456
+ SubtotalRenderer = function(pivotData, opts, charttype) {
457
457
  var addClass, allTotal, arrowCollapsed, arrowExpanded, buildColHeaderHeader, buildColHeaderHeaders, buildColHeaderHeadersClickEvents, buildColHeaders, buildColTotals, buildColTotalsHeader, buildGrandTotal, buildRowHeaderHeaders, buildRowHeaderHeadersClickEvents, buildRowHeaders, buildRowTotalsHeader, buildValues, classColCollapsed, classColExpanded, classColHide, classColShow, classCollapsed, classExpanded, classRowCollapsed, classRowExpanded, classRowHide, classRowShow, clickStatusCollapsed, clickStatusExpanded, colAttrs, colDisableAfter, colKeys, colTotals, collapseCol, collapseColsAt, collapseHideDescendantRow, collapseRow, collapseRowsAt, collapseShowColSubtotal, collapseShowRowSubtotal, applyInlineStyles, createElement, defaults, expandChildCol, expandChildRow, expandCol, expandColsAt, expandHideColSubtotal, expandHideRowSubtotal, expandRow, expandRowsAt, expandShowColSubtotal, expandShowRowSubtotal, getTableEventHandlers, hasClass, hideDescendantCol, isColDisable, isColDisableExpandCollapse, isColHideOnExpand, isRowDisable, isRowDisableExpandCollapse, isRowHideOnExpand, main, getSubtotalInBrackets, processKeys, encodeHtmlEntities, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, removeClass, replaceClass, rowAttrs, rowDisableAfter, rowKeys, rowTotals, setAttributes, showChildCol, showChildRow, toggleCol, toggleColHeaderHeader, toggleRow, toggleRowHeaderHeader, tree, subscribeToClick;
458
458
  var createTotalValsBolder, createGrandTotalBolder, getHeaderColorProperties, colorizeRowLabelHeaders, colorizeTableIfNeed, valueNoDashes, getColorsWithOffsetForTable, offsetColors, handleFreezePanesScroll, selectFreezableElements, removeRowHeaderNullValue;
459
459
  var getAdditionalAggregation, buildAdditionalHeaderCols, buildAdditionalHeaderRows, buildAdditionalColValues, buildAdditionalRowValues, buildAdditionalRowTotals, buildAdditionalColTotals;
@@ -2356,6 +2356,9 @@ let initDRPivotTable = function($, window, document) {
2356
2356
  main = function(rowAttrs, rowKeys, colAttrs, colKeys, pivotData) {
2357
2357
  if (opts.chartOptions.isSmartQueriesEnabled) {
2358
2358
  rowKeys = rowKeys.filter(rowKey => !rowKey.includes(DR_SCENARIO.SQ_Actuals));
2359
+ rowKeys = Array.from(
2360
+ new Set(rowKeys.map(JSON.stringify))
2361
+ ).map(JSON.parse);
2359
2362
  }
2360
2363
  var c,rowspan, colHeaderCols, colHeaderHeaders, colHeaders, h, k, l, len, len1, result, rowHeaderHeaders, rowHeaderRows, rowHeaders, tbody, thead, tr;
2361
2364
  rowHeaders = [];
@@ -2494,24 +2497,13 @@ let initDRPivotTable = function($, window, document) {
2494
2497
  resultsArr.push(subTitle);
2495
2498
  }
2496
2499
 
2497
- if (tooMuch) {
2498
- const defaultPlaceholder = $(`
2499
- <div class="noData--table-many-rows">
2500
- <span><i class="noData-icon dr-icon-info"></i> There are too many rows to display in the table.</span>
2501
- <span>Please filter or change the table type in options.</span>
2502
- </div>
2503
- `);
2504
-
2505
- resultsArr.push($.pivotUtilities.errorHandling.getErrorPlaceholder(error_params) || defaultPlaceholder);
2506
- } else {
2507
- var tableContainer = document.createElement("div");
2508
- tableContainer.className = "pivot-div";
2509
- tableContainer.appendChild(result);
2510
- if (opts.chartOptions.table_options.freeze_panes) {
2511
- tableContainer.onscroll = handleFreezePanesScroll(selectFreezableElements(tableContainer));
2512
- }
2513
- resultsArr.push(tableContainer);
2500
+ var tableContainer = document.createElement("div");
2501
+ tableContainer.className = "pivot-div";
2502
+ tableContainer.appendChild(result);
2503
+ if (opts.chartOptions.table_options.freeze_panes) {
2504
+ tableContainer.onscroll = handleFreezePanesScroll(selectFreezableElements(tableContainer));
2514
2505
  }
2506
+ resultsArr.push(tableContainer);
2515
2507
 
2516
2508
  var wrapper = document.createElement("div");
2517
2509
  wrapper.className = "pivot-wrapper";
@@ -2522,7 +2514,7 @@ let initDRPivotTable = function($, window, document) {
2522
2514
  };
2523
2515
  return main(rowAttrs, rowKeys, colAttrs, colKeys, pivotData);
2524
2516
  };
2525
- // $.pivotUtilities.subtotal_renderers = SubtotalRenderer;
2517
+
2526
2518
  $.pivotUtilities.subtotal_renderers = NovixRenderer;
2527
2519
  $.pivotUtilities.delim = delim;
2528
2520
 
package/src/errors.js ADDED
@@ -0,0 +1,174 @@
1
+ /**
2
+ * Enum for dr renderer error codes.
3
+ * @readonly
4
+ * @enum {number}
5
+ */
6
+ const RendererErrorCodes = {
7
+ NoDataError: 1,
8
+ TooMuchDataError: 3,
9
+ DataConflictError: 5,
10
+ GaugeConfigurationError: 6,
11
+ GenericRenderingError: 7,
12
+ GenericComputationalError: 8
13
+ };
14
+
15
+ /**
16
+ * Base error class for all renderer-related errors.
17
+ * @class BaseRendererError
18
+ * @extends Error
19
+ */
20
+ class BaseRendererError extends Error {
21
+ /**
22
+ * Error code for identification purposes
23
+ * @type {number}
24
+ */
25
+ code = 0;
26
+
27
+ /**
28
+ * Human-readable error title
29
+ * @type {string}
30
+ */
31
+ title = '';
32
+
33
+ /**
34
+ * Additional options or context for the error
35
+ * @type {Object}
36
+ */
37
+ options = {};
38
+
39
+ /**
40
+ * Creates a new BaseRendererError instance.
41
+ * @param {Object} config - Error configuration object
42
+ * @param {number} config.code - Unique error code
43
+ * @param {string} config.title - Error title/message
44
+ * @param {Object} [config.options={}] - Additional error options or context
45
+ */
46
+ constructor({ code, title, options }) {
47
+ super();
48
+ this.code = code;
49
+ this.title = title;
50
+ this.options = options || {};
51
+ }
52
+ }
53
+
54
+ /**
55
+ * Error thrown when no data is available.
56
+ * @class NoDataError
57
+ * @extends BaseRendererError
58
+ */
59
+ class NoDataError extends BaseRendererError {
60
+ /**
61
+ * Creates a new NoDataError instance.
62
+ * This error is thrown when a widget or component has no available data.
63
+ */
64
+ constructor() {
65
+ super({
66
+ code: RendererErrorCodes.NoDataError,
67
+ title: 'No Data Available',
68
+ });
69
+ }
70
+ }
71
+
72
+ /**
73
+ * Error thrown when there is too much data to render efficiently.
74
+ * @class TooMuchDataError
75
+ * @extends BaseRendererError
76
+ */
77
+ class TooMuchDataError extends BaseRendererError {
78
+ /**
79
+ * Creates a new TooMuchDataError instance.
80
+ * This error is thrown when the dataset exceeds the renderer's capacity
81
+ * and requires the user to edit the widget.
82
+ */
83
+ constructor() {
84
+ super({
85
+ code: RendererErrorCodes.TooMuchDataError,
86
+ title: 'There is too much data. Please edit this widget',
87
+ });
88
+ }
89
+ }
90
+
91
+ /**
92
+ * Error thrown when there are conflicts in the data being processed.
93
+ * @class DataConflictError
94
+ * @extends BaseRendererError
95
+ */
96
+ class DataConflictError extends BaseRendererError {
97
+ /**
98
+ * Creates a new DataConflictError instance.
99
+ * @param {Object} [options] - Additional context about the data conflict.
100
+ */
101
+ constructor(options) {
102
+ super({
103
+ code: RendererErrorCodes.DataConflictError,
104
+ title: 'Data Conflict',
105
+ options
106
+ });
107
+ }
108
+ }
109
+
110
+ /**
111
+ * Error thrown when a gauge chart is missing required info.
112
+ * @class GaugeConfigurationError
113
+ * @extends BaseRendererError
114
+ */
115
+ class GaugeConfigurationError extends BaseRendererError {
116
+ /**
117
+ * Creates a new GaugeConfigurationError instance.
118
+ */
119
+ constructor() {
120
+ super({
121
+ code: RendererErrorCodes.GaugeConfigurationError,
122
+ title: 'Please configure goal and needle',
123
+ });
124
+ }
125
+ }
126
+
127
+ /**
128
+ * Generic error for rendering failures in PivotTable components.
129
+ * @class GenericRenderingError
130
+ * @extends BaseRendererError
131
+ */
132
+ class GenericRenderingError extends BaseRendererError {
133
+ /**
134
+ * Creates a new GenericRenderingError instance.
135
+ * This error is thrown when an unexpected error occurs during
136
+ * the rendering process of PivotTable results.
137
+ */
138
+ constructor() {
139
+ super({
140
+ code: RendererErrorCodes.GenericRenderingError,
141
+ title: 'An error occurred rendering the PivotTable results.',
142
+ });
143
+ }
144
+ }
145
+
146
+ /**
147
+ * Generic error for computational failures in PivotTable components.
148
+ * @class GenericComputationalError
149
+ * @extends BaseRendererError
150
+ */
151
+ class GenericComputationalError extends BaseRendererError {
152
+ /**
153
+ * Creates a new GenericComputationalError instance.
154
+ * This error is thrown when an unexpected error occurs during
155
+ * the computation process of PivotTable results.
156
+ */
157
+ constructor() {
158
+ super({
159
+ code: RendererErrorCodes.GenericComputationalError,
160
+ title: 'An error occurred computing the PivotTable results.',
161
+ });
162
+ }
163
+ }
164
+
165
+ module.exports = {
166
+ RendererErrorCodes,
167
+ BaseRendererError,
168
+ TooMuchDataError,
169
+ NoDataError,
170
+ DataConflictError,
171
+ GaugeConfigurationError,
172
+ GenericRenderingError,
173
+ GenericComputationalError
174
+ };
@@ -4,6 +4,15 @@ const { DrDonutChart } = require('./charts/dr_donut_chart');
4
4
  const seriesPointStylesHelper= require('./seriesPointStyles-helper');
5
5
  const smartQueriesHelper = require('./smart_queries_helper');
6
6
  const {DrGaugeCategoriesSummaryChart} = require("./charts/dr_gauge_categories_summary_chart");
7
+ const {
8
+ TooMuchDataError,
9
+ NoDataError,
10
+ BaseRendererError,
11
+ DataConflictError,
12
+ GaugeConfigurationError,
13
+ GenericRenderingError,
14
+ GenericComputationalError
15
+ } = require('./errors');
7
16
 
8
17
  const mobileBrowserRegex = new RegExp([
9
18
  '(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)',
@@ -204,6 +213,34 @@ let getHighchartsRenderer = function ($, document, Highcharts, default_colors, h
204
213
  highchartsRenderer.enabledNewWidgetValueFormatting = false;
205
214
  let disableAnimation = false;
206
215
 
216
+ const _handleComputationalError = (err, onlyOptions) => {
217
+ if (err instanceof BaseRendererError) {
218
+ throw err;
219
+ }
220
+
221
+ const genericError = new GenericComputationalError();
222
+ if (onlyOptions) {
223
+ console.error(genericError.title);
224
+ return {};
225
+ } else {
226
+ throw genericError;
227
+ }
228
+ };
229
+
230
+ const _handleRenderingError = (err, onlyOptions) => {
231
+ if (err instanceof BaseRendererError) {
232
+ throw err;
233
+ }
234
+
235
+ const genericError = new GenericRenderingError();
236
+ console.error(genericError.title);
237
+ if (onlyOptions) {
238
+ return {};
239
+ } else {
240
+ throw genericError;
241
+ }
242
+ }
243
+
207
244
  highchartsRenderer.hasFeature = function(featureFlagKey) {
208
245
  return lodash.includes(lodash.get(document, 'ReportHippo.user.features', []), featureFlagKey);
209
246
  }
@@ -1039,26 +1076,6 @@ let getHighchartsRenderer = function ($, document, Highcharts, default_colors, h
1039
1076
  return forExport;
1040
1077
  };
1041
1078
 
1042
- highchartsRenderer.getNoDataResult = function (to_match) {
1043
- var temp_result = $('<div class="noData-box"></div>');
1044
- var resultsArr = [];
1045
-
1046
- if (to_match) {
1047
- resultsArr.push(highchartsRenderer.getWidgetPlaceholder(highchartsRenderer.widgetPlaceholders.tooMuchData));
1048
- } else {
1049
- resultsArr.push(highchartsRenderer.getWidgetPlaceholder(highchartsRenderer.widgetPlaceholders.nodata));
1050
- }
1051
-
1052
- temp_result.html(resultsArr);
1053
-
1054
- return temp_result;
1055
- };
1056
-
1057
- highchartsRenderer.getWidgetPlaceholder = function(placeholder) {
1058
- const defaultPlaceholder = $('<div class="noData"><i class="noData-image"></i> no data</div>');
1059
- return $.pivotUtilities.errorHandling.getErrorPlaceholder(placeholder) || defaultPlaceholder;
1060
- }
1061
-
1062
1079
  highchartsRenderer.ptCreateElementAndDraw = function (chartOptions, opts) {
1063
1080
  chartOptions = lodash.merge(highchartsRenderer.getCommonChartOptions(opts.chartOptions), chartOptions);
1064
1081
 
@@ -1159,13 +1176,13 @@ let getHighchartsRenderer = function ($, document, Highcharts, default_colors, h
1159
1176
  }
1160
1177
 
1161
1178
  if (!seriesDataLength && !chartOptions.onlyText) {
1162
- result = highchartsRenderer.getNoDataResult();
1163
- opts.error_has_occurred = true;
1164
- opts.error_params = highchartsRenderer.widgetPlaceholders.nodata;
1179
+ const noDataError = new NoDataError();
1180
+ console.error(noDataError.title);
1181
+ throw noDataError;
1165
1182
  } else if (!chartOptions.onlyText && chartOptions.series && toMatch) {
1166
- result = highchartsRenderer.getNoDataResult(toMatch);
1167
- opts.error_has_occurred = true;
1168
- opts.error_params = highchartsRenderer.widgetPlaceholders.tooMuchData;
1183
+ const tooMuchDataError = new TooMuchDataError();
1184
+ console.error(tooMuchDataError.title);
1185
+ throw tooMuchDataError;
1169
1186
  } else {
1170
1187
  chartOptions = highchartsRenderer.updateChartOptions(chartOptions, opts);
1171
1188
  chartOptions = highchartsRenderer.updateChartOptions(chartOptions, {credits: {enabled: false}});
@@ -1233,6 +1250,19 @@ let getHighchartsRenderer = function ($, document, Highcharts, default_colors, h
1233
1250
  var chart_series = [],
1234
1251
  row_n_keys = pivotData.getRowKeys(),
1235
1252
  col_n_keys = pivotData.getColKeys();
1253
+ const chartType = chartOptions && chartOptions.chart && chartOptions.chart.type ? chartOptions.chart.type : null;
1254
+ const isCombiLineForecastChart = opts.chartOptions.isSmartQueriesEnabled;
1255
+ const indexOfScenarioCycleFilter = lodash.findIndex(pivotData.rowAttrs, (rowAttr) => rowAttr === 'Scenario Cycle');
1256
+
1257
+ if (isChartTypeSupportedForSmartQuery(chartType) && pivotData.rowAttrs?.length < row_n_keys?.[0]?.length && indexOfScenarioCycleFilter > -1) {
1258
+ const indexOfScenarioFilter = row_n_keys[0].length - 1;
1259
+ for (let i = 0; i < row_n_keys?.length; i++) {
1260
+ row_n_keys[i].splice(indexOfScenarioFilter, 1);
1261
+ }
1262
+ row_n_keys = Array.from(
1263
+ new Set(row_n_keys.map(JSON.stringify))
1264
+ ).map(JSON.parse);
1265
+ }
1236
1266
 
1237
1267
  var has_delta = false;
1238
1268
  if (additionOptions && lodash.has(additionOptions, "delta_column.field") && additionOptions.delta_column.field == "series") {
@@ -1413,8 +1443,6 @@ let getHighchartsRenderer = function ($, document, Highcharts, default_colors, h
1413
1443
  chart_series = chart_series.concat(trendSerieses);
1414
1444
 
1415
1445
  highchartsRenderer.moveSeriesToSecondYAxisIfNeeded(chart_series, pivotData, chartOptions, additionOptions, opts, opts.total && opts.totalSeriesSettings && opts.totalSeriesSettings.secondaryAxis);
1416
- const chartType = chartOptions && chartOptions.chart && chartOptions.chart.type ? chartOptions.chart.type : null;
1417
- const isCombiLineForecastChart = opts.chartOptions.isSmartQueriesEnabled;
1418
1446
  const smartQuerySeries = isChartTypeSupportedForSmartQuery(chartType)
1419
1447
  ? smartQueriesHelper.createSingleDataSeriesForForecast(chart_series, opts.chartOptions, pivotData, isCombiLineForecastChart)
1420
1448
  : null;
@@ -4459,19 +4487,14 @@ let getHighchartsRenderer = function ($, document, Highcharts, default_colors, h
4459
4487
  }
4460
4488
  if (uniqueCategories && ((maxCategories && uniqueCategories.length > maxCategories)
4461
4489
  || (minCategories && uniqueCategories.length < minCategories))) {
4462
- options.error_has_occurred = true;
4463
- const breakdownText = `Please adjust your dashboard's reference date or filter selections as \
4464
- the quantity of data doesn't match the limit of at least ${ minCategories } values.`;
4465
- const walkthroughText = `Please adjust your dashboard's reference date and filter selections as \
4466
- the quantity of data doesn't match the chart's ${ minCategories }-${ maxCategories } value limit.`;
4467
-
4468
- options.error_params = {
4469
- title: 'Data Conflict',
4470
- text: isBreakdown ? breakdownText : walkthroughText,
4471
- class: uniqueCategories.length < minCategories ? 'waterfall-nodata' : 'waterfall-too-much-data',
4472
- }
4473
-
4474
- return highchartsRenderer.getNoDataResult(true);
4490
+ const dataConflictError = new DataConflictError({
4491
+ chartType: lodash.get(widget, 'chart_type'),
4492
+ uniqueCategories,
4493
+ minCategories,
4494
+ maxCategories
4495
+ });
4496
+ console.error(dataConflictError.title);
4497
+ throw dataConflictError;
4475
4498
  }
4476
4499
  }
4477
4500
 
@@ -4480,9 +4503,9 @@ let getHighchartsRenderer = function ($, document, Highcharts, default_colors, h
4480
4503
  return {};
4481
4504
  }
4482
4505
 
4483
- options.error_has_occurred = true;
4484
- options.error_params = highchartsRenderer.widgetPlaceholders.nodata;
4485
- return highchartsRenderer.getNoDataResult();
4506
+ const noDataError = new NoDataError();
4507
+ console.error(noDataError.title);
4508
+ throw noDataError;
4486
4509
  }
4487
4510
 
4488
4511
  if (rowData.length > highchartsRenderer.MAX_ROWS_FOR_SHOW_RESULTS) {
@@ -4490,9 +4513,9 @@ let getHighchartsRenderer = function ($, document, Highcharts, default_colors, h
4490
4513
  return {};
4491
4514
  }
4492
4515
 
4493
- options.error_has_occurred = true;
4494
- options.error_params = highchartsRenderer.widgetPlaceholders.tooMuchData;
4495
- return highchartsRenderer.getNoDataResult(true);
4516
+ const tooMuchDataError = new TooMuchDataError();
4517
+ console.error(tooMuchDataError.title);
4518
+ throw tooMuchDataError;
4496
4519
  }
4497
4520
 
4498
4521
  var tmp = $.pivotUtilities.aggregatorTemplates;
@@ -4554,28 +4577,14 @@ let getHighchartsRenderer = function ($, document, Highcharts, default_colors, h
4554
4577
 
4555
4578
  result = opts.renderer(pivotData, opts.rendererOptions);
4556
4579
  } catch (_error) {
4557
- e = _error;
4558
- if (typeof console !== "undefined" && console !== null) {
4559
- console.error(e.stack);
4560
- }
4561
- result = $("<span>").html(opts.localeStrings.renderError);
4562
- if (options.onlyOptions) {
4563
- result = {};
4564
- }
4580
+ result = _handleRenderingError(_error, options.onlyOptions);
4565
4581
  }
4566
4582
 
4567
4583
  if (lodash.isObject(lodash.get(widget, 'pivot'))) {
4568
4584
  widget.pivot.sortByValueAttrs = pivotData.sortByValueAttrs;
4569
4585
  }
4570
4586
  } catch (_error) {
4571
- e = _error;
4572
- if (typeof console !== "undefined" && console !== null) {
4573
- console.error(e.stack);
4574
- }
4575
- result = $("<span>").html(opts.localeStrings.computeError);
4576
- if (options.onlyOptions) {
4577
- result = {};
4578
- }
4587
+ result = _handleComputationalError(_error, options.onlyOptions);
4579
4588
  }
4580
4589
 
4581
4590
  return result;
@@ -4613,19 +4622,14 @@ let getHighchartsRenderer = function ($, document, Highcharts, default_colors, h
4613
4622
  }
4614
4623
  if (uniqueCategories && ((maxCategories && uniqueCategories.length > maxCategories)
4615
4624
  || (minCategories && uniqueCategories.length < minCategories))) {
4616
- options.error_has_occurred = true;
4617
- const breakdownText = `Please adjust your dashboard's reference date or filter selections as \
4618
- the quantity of data doesn't match the limit of at least ${ minCategories } values.`;
4619
- const walkthroughText = `Please adjust your dashboard's reference date and filter selections as \
4620
- the quantity of data doesn't match the chart's ${ minCategories }-${ maxCategories } value limit.`;
4621
-
4622
- options.error_params = {
4623
- title: 'Data Conflict',
4624
- text: isBreakdown ? breakdownText : walkthroughText,
4625
- class: uniqueCategories.length < minCategories ? 'waterfall-nodata' : 'waterfall-too-much-data',
4626
- }
4627
-
4628
- return highchartsRenderer.getNoDataResult(true);
4625
+ const dataConflictError = new DataConflictError({
4626
+ chartType: lodash.get(widget, 'chart_type'),
4627
+ uniqueCategories,
4628
+ minCategories,
4629
+ maxCategories
4630
+ });
4631
+ console.error(dataConflictError.title);
4632
+ throw dataConflictError;
4629
4633
  }
4630
4634
  }
4631
4635
 
@@ -4634,9 +4638,9 @@ let getHighchartsRenderer = function ($, document, Highcharts, default_colors, h
4634
4638
  return {};
4635
4639
  }
4636
4640
 
4637
- options.error_has_occurred = true;
4638
- options.error_params = highchartsRenderer.widgetPlaceholders.nodata;
4639
- return highchartsRenderer.getNoDataResult();
4641
+ const noDataError = new NoDataError();
4642
+ console.error(noDataError.title);
4643
+ throw noDataError;
4640
4644
  }
4641
4645
 
4642
4646
  if (rowData.length > highchartsRenderer.MAX_ROWS_FOR_SHOW_RESULTS) {
@@ -4644,9 +4648,9 @@ let getHighchartsRenderer = function ($, document, Highcharts, default_colors, h
4644
4648
  return {};
4645
4649
  }
4646
4650
 
4647
- options.error_has_occurred = true;
4648
- options.error_params = highchartsRenderer.widgetPlaceholders.tooMuchData;
4649
- return highchartsRenderer.getNoDataResult(true);
4651
+ const tooMuchDataError = new TooMuchDataError();
4652
+ console.error(tooMuchDataError.title);
4653
+ throw tooMuchDataError;
4650
4654
  }
4651
4655
 
4652
4656
  if (lodash.get(widget, 'chart_type') === highchartsRenderer.CHART_TYPES.GAUGE_CHART_DYNAMIC_GOAL) {
@@ -4655,14 +4659,9 @@ let getHighchartsRenderer = function ($, document, Highcharts, default_colors, h
4655
4659
  || !lodash.get(widget, 'options.chartOptions.dynamicGaugeConfig.needle');
4656
4660
 
4657
4661
  if (noNeedleOrGoalSelected) {
4658
- options.error_has_occurred = true;
4659
- options.error_params = {
4660
- title: 'Please configure goal and needle',
4661
- // TODO: add text
4662
- text: '',
4663
- class: 'configure-gauge-settings',
4664
- }
4665
- return highchartsRenderer.getNoDataResult(true);
4662
+ const gaugeError = new GaugeConfigurationError();
4663
+ console.error(gaugeError.title);
4664
+ throw gaugeError;
4666
4665
  }
4667
4666
  }
4668
4667
 
@@ -4724,28 +4723,14 @@ let getHighchartsRenderer = function ($, document, Highcharts, default_colors, h
4724
4723
 
4725
4724
  result = opts.renderer(pivotData, opts.rendererOptions);
4726
4725
  } catch (_error) {
4727
- e = _error;
4728
- if (typeof console !== "undefined" && console !== null) {
4729
- console.error(e.stack);
4730
- }
4731
- result = $("<span>").html(opts.localeStrings.renderError);
4732
- if (options.onlyOptions) {
4733
- result = {};
4734
- }
4726
+ result = _handleRenderingError(_error, options.onlyOptions);
4735
4727
  }
4736
4728
 
4737
4729
  if (lodash.isObject(lodash.get(widget, 'pivot'))) {
4738
4730
  widget.pivot.sortByValueAttrs = pivotData.sortByValueAttrs;
4739
4731
  }
4740
4732
  } catch (_error) {
4741
- e = _error;
4742
- if (typeof console !== "undefined" && console !== null) {
4743
- console.error(e.stack);
4744
- }
4745
- result = $("<span>").html(opts.localeStrings.computeError);
4746
- if (options.onlyOptions) {
4747
- result = {};
4748
- }
4733
+ result = _handleComputationalError(_error, options.onlyOptions);
4749
4734
  }
4750
4735
 
4751
4736
  return result;
@@ -6079,8 +6064,6 @@ let getHighchartsRenderer = function ($, document, Highcharts, default_colors, h
6079
6064
  return highchartsRenderer.chartsTypesInfo[type] ? highchartsRenderer.chartsTypesInfo[type].legendName : CHART_LEGEND_DEFAULT_LABEL;
6080
6065
  };
6081
6066
 
6082
- highchartsRenderer.widgetPlaceholders = lodash.assign({}, $.pivotUtilities.errorHandling.placeholders);
6083
-
6084
6067
  const suboptionsFontSizeValues = (lodash.map(lodash.fill(new Array(19), null), function (item, index) {
6085
6068
  const fontValue = index + 6;
6086
6069
  return { label: fontValue, value: fontValue }
@@ -10024,7 +10007,7 @@ let getHighchartsRenderer = function ($, document, Highcharts, default_colors, h
10024
10007
  e.point.name = e.point.initialName;
10025
10008
  e.point.series.name = lodash.get(e.point.series, 'userOptions.initialName', e.point.series.name);
10026
10009
  const seriesData = lodash.get(e.point.series, 'userOptions.data');
10027
- const initialNameForSmartQueries = seriesData
10010
+ const initialNameForSmartQueries = seriesData
10028
10011
  ? lodash.find(seriesData, obj => obj.name === e.point.name)
10029
10012
  : null;
10030
10013
  if (initialNameForSmartQueries && initialNameForSmartQueries.type) {
package/src/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from './types';
2
2
  import DataFormatterType = require('./dataformatter');
3
+ import * as ErrorTypes from './types/errors';
3
4
 
4
5
  declare module '*.css' {
5
6
  const content: { [className: string]: string };
@@ -45,6 +46,16 @@ declare namespace DrRenderFactory {
45
46
  getInitPublishedItemsRenderer(publishedItemsRenderer: any, bind?: any): any;
46
47
 
47
48
  DataFormatter: typeof DataFormatterType;
49
+
50
+ // Error types and classes
51
+ RendererErrorCodes: typeof ErrorTypes.RendererErrorCodes;
52
+ BaseRendererError: typeof ErrorTypes.BaseRendererError;
53
+ TooMuchDataError: typeof ErrorTypes.TooMuchDataError;
54
+ NoDataError: typeof ErrorTypes.NoDataError;
55
+ DataConflictError: typeof ErrorTypes.DataConflictError;
56
+ GaugeConfigurationError: typeof ErrorTypes.GaugeConfigurationError;
57
+ GenericRenderingError: typeof ErrorTypes.GenericRenderingError;
58
+ GenericComputationalError: typeof ErrorTypes.GenericComputationalError;
48
59
  }
49
60
  }
50
61