axidio-styleguide-library1-v2 0.2.27 → 0.2.28
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/esm2022/lib/horizontal-grouped-bar-with-scroll-zoom/horizontal-grouped-bar-with-scroll-zoom.component.mjs +1908 -982
- package/fesm2022/axidio-styleguide-library1-v2.mjs +1917 -991
- package/fesm2022/axidio-styleguide-library1-v2.mjs.map +1 -1
- package/lib/horizontal-grouped-bar-with-scroll-zoom/horizontal-grouped-bar-with-scroll-zoom.component.d.ts +34 -0
- package/package.json +1 -1
|
@@ -8187,352 +8187,1553 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
8187
8187
|
get isAlertEnabled() {
|
|
8188
8188
|
return this.chartConfiguration?.headerMenuOptions?.some((option) => option.id === 'editAlert');
|
|
8189
8189
|
}
|
|
8190
|
+
// initializegroupChart() {
|
|
8191
|
+
// var self = this;
|
|
8192
|
+
// let data = [];
|
|
8193
|
+
// let metaData: any = null;
|
|
8194
|
+
// let keyList = null;
|
|
8195
|
+
// let lineData = null;
|
|
8196
|
+
// let colorMap = {};
|
|
8197
|
+
// var formatFromBackend;
|
|
8198
|
+
// var formatForHugeNumbers;
|
|
8199
|
+
// const isMobile = window.innerWidth < 576;
|
|
8200
|
+
// const isTablet = window.innerWidth >= 576 && window.innerWidth < 992;
|
|
8201
|
+
// const isDesktop = window.innerWidth >= 992;
|
|
8202
|
+
// let isria = this.customChartConfiguration.isRia
|
|
8203
|
+
// var x: any;
|
|
8204
|
+
// var alternate_text = false;
|
|
8205
|
+
// var short_tick_length = 4;
|
|
8206
|
+
// var long_tick_length = 16;
|
|
8207
|
+
// /**
|
|
8208
|
+
// * longer tick length needed for weekly charts
|
|
8209
|
+
// */
|
|
8210
|
+
// var short_tick_length_bg = 5;
|
|
8211
|
+
// var long_tick_length_bg = 30;
|
|
8212
|
+
// var leftAndRightSpaces = 50;
|
|
8213
|
+
// var rightSvgWidth = 60;
|
|
8214
|
+
// var tempScale;
|
|
8215
|
+
// for (var i in this.defaultConfiguration) {
|
|
8216
|
+
// this.chartConfiguration[i] = ChartHelper.getValueByConfigurationType(
|
|
8217
|
+
// i,
|
|
8218
|
+
// this.defaultConfiguration,
|
|
8219
|
+
// this.customChartConfiguration
|
|
8220
|
+
// );
|
|
8221
|
+
// }
|
|
8222
|
+
// data = this.chartData.data;
|
|
8223
|
+
// metaData = this.chartData.metaData;
|
|
8224
|
+
// lineData = this.chartData.lineData;
|
|
8225
|
+
// // if (lineData || this.chartData.targetLineData) {
|
|
8226
|
+
// // rightSvgWidth = 60;
|
|
8227
|
+
// // }
|
|
8228
|
+
// if (!metaData.colorAboveTarget) {
|
|
8229
|
+
// metaData['colorAboveTarget'] = metaData.colors;
|
|
8230
|
+
// }
|
|
8231
|
+
// colorMap = metaData.colors;
|
|
8232
|
+
// keyList = metaData.keyList;
|
|
8233
|
+
// var chartContainer = d3.select(this.containerElt.nativeElement);
|
|
8234
|
+
// var verticalstackedcontainer = d3.select(
|
|
8235
|
+
// this.groupcontainerElt.nativeElement
|
|
8236
|
+
// );
|
|
8237
|
+
// var margin = this.chartConfiguration.margin;
|
|
8238
|
+
// const { width, height } = this.calculateChartDimensions(
|
|
8239
|
+
// chartContainer,
|
|
8240
|
+
// verticalstackedcontainer,
|
|
8241
|
+
// margin,
|
|
8242
|
+
// self
|
|
8243
|
+
// );
|
|
8244
|
+
// /**
|
|
8245
|
+
// * for hiding header
|
|
8246
|
+
// * used by weekly charts
|
|
8247
|
+
// */
|
|
8248
|
+
// if (this.chartConfiguration.isHeaderVisible != undefined)
|
|
8249
|
+
// this.isHeaderVisible = this.chartConfiguration.isHeaderVisible;
|
|
8250
|
+
// /**
|
|
8251
|
+
// * for hiding legends
|
|
8252
|
+
// * used by weekly charts
|
|
8253
|
+
// */
|
|
8254
|
+
// if (this.chartConfiguration.legendVisible != undefined) {
|
|
8255
|
+
// this.legendVisible = this.chartConfiguration.legendVisible;
|
|
8256
|
+
// }
|
|
8257
|
+
// /**
|
|
8258
|
+
// * for removing background color so that it can take parents color
|
|
8259
|
+
// *
|
|
8260
|
+
// */
|
|
8261
|
+
// if (this.chartConfiguration.isTransparentBackground != undefined) {
|
|
8262
|
+
// this.isTransparentBackground =
|
|
8263
|
+
// this.chartConfiguration.isTransparentBackground;
|
|
8264
|
+
// }
|
|
8265
|
+
// /**
|
|
8266
|
+
// * format data values based on configuration received
|
|
8267
|
+
// */
|
|
8268
|
+
// if (this.chartConfiguration.textFormatter != undefined) {
|
|
8269
|
+
// formatFromBackend = ChartHelper.dataValueFormatter(
|
|
8270
|
+
// this.chartConfiguration.textFormatter
|
|
8271
|
+
// );
|
|
8272
|
+
// formatForHugeNumbers = ChartHelper.dataValueFormatter('.2s');
|
|
8273
|
+
// }
|
|
8274
|
+
// const {
|
|
8275
|
+
// outerContainer,
|
|
8276
|
+
// svgYAxisLeft,
|
|
8277
|
+
// svgYAxisRight,
|
|
8278
|
+
// innerContainer,
|
|
8279
|
+
// svg
|
|
8280
|
+
// } = this.createChartContainers(chartContainer, margin, height, rightSvgWidth, self, width);
|
|
8281
|
+
// var subgroups: any = keyList;
|
|
8282
|
+
// var groups = d3
|
|
8283
|
+
// .map(data, function (d) {
|
|
8284
|
+
// return d.name;
|
|
8285
|
+
// })
|
|
8286
|
+
// .keys();
|
|
8287
|
+
// /**
|
|
8288
|
+
// * x axis range made similar to line chart or vertical stack so that all the charts will get aligned with each other.
|
|
8289
|
+
// */
|
|
8290
|
+
// if (this.chartConfiguration.isMultiChartGridLine != undefined) {
|
|
8291
|
+
// x = d3
|
|
8292
|
+
// .scaleBand()
|
|
8293
|
+
// .rangeRound([width, 0])
|
|
8294
|
+
// .align(0.5)
|
|
8295
|
+
// .padding([0.5])
|
|
8296
|
+
// .domain(
|
|
8297
|
+
// data.map(function (d: any) {
|
|
8298
|
+
// return d.name.toLowerCase();
|
|
8299
|
+
// })
|
|
8300
|
+
// );
|
|
8301
|
+
// } else {
|
|
8302
|
+
// x = d3
|
|
8303
|
+
// .scaleBand()
|
|
8304
|
+
// .domain(groups)
|
|
8305
|
+
// .range([leftAndRightSpaces, width - rightSvgWidth - leftAndRightSpaces])
|
|
8306
|
+
// .padding([0.3]);
|
|
8307
|
+
// }
|
|
8308
|
+
// // x.bandwidth(96);
|
|
8309
|
+
// var xScaleFromOrigin = d3
|
|
8310
|
+
// .scaleBand()
|
|
8311
|
+
// .domain(groups)
|
|
8312
|
+
// .range([0, width - rightSvgWidth]);
|
|
8313
|
+
// // .padding([0.2]);
|
|
8314
|
+
// if (this.chartConfiguration.isMultiChartGridLine == undefined) {
|
|
8315
|
+
// /**
|
|
8316
|
+
// * normal ticks for all dashboard charts
|
|
8317
|
+
// */
|
|
8318
|
+
// svg
|
|
8319
|
+
// .append('g')
|
|
8320
|
+
// .attr('class', 'x1 axis1')
|
|
8321
|
+
// .attr('transform', 'translate(0,' + height + ')')
|
|
8322
|
+
// .call(d3.axisBottom(x))
|
|
8323
|
+
// .call((g) => g.select('.domain').remove());
|
|
8324
|
+
// svg.selectAll('g.x1.axis1 g.tick line').remove();
|
|
8325
|
+
// // Only move x-axis labels further down for grouped charts if there is no xLabel
|
|
8326
|
+
// if (subgroups.length > 1 && !metaData.xLabel) {
|
|
8327
|
+
// svg
|
|
8328
|
+
// .selectAll('g.x1.axis1 g.tick text')
|
|
8329
|
+
// .attr('class', 'lib-xaxis-labels-texts-drilldown')
|
|
8330
|
+
// .style('fill', 'var(--chart-text-color)')
|
|
8331
|
+
// .attr('y', 32); // Increase distance from bars (default is ~9)
|
|
8332
|
+
// } else {
|
|
8333
|
+
// svg
|
|
8334
|
+
// .selectAll('g.x1.axis1 g.tick text')
|
|
8335
|
+
// .attr('class', 'lib-xaxis-labels-texts-drilldown')
|
|
8336
|
+
// .style('fill', 'var(--chart-text-color)');
|
|
8337
|
+
// }
|
|
8338
|
+
// }
|
|
8339
|
+
// else {
|
|
8340
|
+
// /**
|
|
8341
|
+
// * bigger ticks for weekly charts and more space from x axis to labels
|
|
8342
|
+
// */
|
|
8343
|
+
// /**
|
|
8344
|
+
// * draw x axis
|
|
8345
|
+
// */
|
|
8346
|
+
// svg
|
|
8347
|
+
// .append('g')
|
|
8348
|
+
// .attr('class', 'x1 axis1')
|
|
8349
|
+
// .attr('transform', 'translate(0,' + height + ')')
|
|
8350
|
+
// .call(d3.axisBottom(x).tickSize(0))
|
|
8351
|
+
// .call((g) => g.select('.domain').attr('fill', 'none'));
|
|
8352
|
+
// /**
|
|
8353
|
+
// * tick line size in alternate fashion
|
|
8354
|
+
// */
|
|
8355
|
+
// svg.selectAll('g.x1.axis1 g.tick line').attr('y2', function () {
|
|
8356
|
+
// if (
|
|
8357
|
+
// alternate_text &&
|
|
8358
|
+
// self.chartConfiguration.isNoAlternateXaxisText == undefined
|
|
8359
|
+
// ) {
|
|
8360
|
+
// alternate_text = false;
|
|
8361
|
+
// return long_tick_length_bg - 7;
|
|
8362
|
+
// } else {
|
|
8363
|
+
// alternate_text = true;
|
|
8364
|
+
// return short_tick_length_bg - 4;
|
|
8365
|
+
// }
|
|
8366
|
+
// });
|
|
8367
|
+
// /**
|
|
8368
|
+
// * reset the flag so that values can be shown in same alternate fashion
|
|
8369
|
+
// */
|
|
8370
|
+
// alternate_text = false;
|
|
8371
|
+
// /**
|
|
8372
|
+
// * print x-axis label texts
|
|
8373
|
+
// * used by weekly charts
|
|
8374
|
+
// */
|
|
8375
|
+
// svg
|
|
8376
|
+
// .selectAll('g.x1.axis1 g.tick text')
|
|
8377
|
+
// .attr('class', 'lib-xaxis-labels-texts-weeklycharts')
|
|
8378
|
+
// .attr('y', function () {
|
|
8379
|
+
// // Minimize gap in maximized (fullscreen) view for weekly charts
|
|
8380
|
+
// if (self.chartConfiguration.isFullScreen) {
|
|
8381
|
+
// return short_tick_length_bg;
|
|
8382
|
+
// }
|
|
8383
|
+
// if (alternate_text) {
|
|
8384
|
+
// alternate_text = false;
|
|
8385
|
+
// return long_tick_length_bg;
|
|
8386
|
+
// } else {
|
|
8387
|
+
// alternate_text = true;
|
|
8388
|
+
// return short_tick_length_bg;
|
|
8389
|
+
// }
|
|
8390
|
+
// });
|
|
8391
|
+
// }
|
|
8392
|
+
// if (self.chartConfiguration.xLabelsOnSameLine) {
|
|
8393
|
+
// const xAxisLabels = svg
|
|
8394
|
+
// .selectAll('g.x1.axis1 g.tick text')
|
|
8395
|
+
// .attr('class', 'lib-xaxis-labels-texts-drilldown')
|
|
8396
|
+
// .style('font-size', this.isHeaderVisible ? '18px' : '14px')
|
|
8397
|
+
// .attr('text-anchor', 'middle')
|
|
8398
|
+
// .attr('y', function(d) {
|
|
8399
|
+
// // For grouped bar charts with many bars and xLabel present, only add 5 if the label is a date
|
|
8400
|
+
// if (subgroups.length > 1 && data.length > 8 && metaData.xLabel) {
|
|
8401
|
+
// const isDateLabel = /\d{2,4}[-\/]/.test(d);
|
|
8402
|
+
// if (self.chartConfiguration.isFullScreen) {
|
|
8403
|
+
// return isDateLabel ? short_tick_length_bg + 14 : short_tick_length_bg;
|
|
8404
|
+
// }
|
|
8405
|
+
// return isDateLabel ? short_tick_length_bg + 14 : short_tick_length_bg;
|
|
8406
|
+
// }
|
|
8407
|
+
// // For grouped bar charts with many bars and NO xLabel, add space as before, but reduce in fullscreen
|
|
8408
|
+
// if (subgroups.length > 1 && data.length > 8 && !metaData.xLabel) {
|
|
8409
|
+
// const chartHasExtraBottom = (self.chartConfiguration.margin && self.chartConfiguration.margin.bottom >= 40);
|
|
8410
|
+
// if (self.chartConfiguration.isFullScreen) {
|
|
8411
|
+
// // Reduce extra gap in maximized view
|
|
8412
|
+
// return short_tick_length_bg + 2;
|
|
8413
|
+
// }
|
|
8414
|
+
// return chartHasExtraBottom ? short_tick_length_bg : short_tick_length_bg + 10;
|
|
8415
|
+
// }
|
|
8416
|
+
// // Default/fallback logic for other cases
|
|
8417
|
+
// let baseY = self.isHeaderVisible ? short_tick_length_bg + 25 : short_tick_length_bg;
|
|
8418
|
+
// if (
|
|
8419
|
+
// subgroups.length > 1 &&
|
|
8420
|
+
// !metaData.xLabel &&
|
|
8421
|
+
// (/\d{2,4}[-\/]\d{2}[-\/]\d{2,4}/.test(d) || /\d{2,4}[-\/]\d{2,4}/.test(d))
|
|
8422
|
+
// ) {
|
|
8423
|
+
// baseY = self.isHeaderVisible ? short_tick_length_bg + 15 : short_tick_length_bg + 25;
|
|
8424
|
+
// }
|
|
8425
|
+
// if (/\d{2,4}[-\/]\d{2,4}/.test(d) && d.indexOf(' ') > -1) {
|
|
8426
|
+
// baseY += 4;
|
|
8427
|
+
// }
|
|
8428
|
+
// // In maximized view, reduce baseY slightly for grouped bars
|
|
8429
|
+
// if (self.chartConfiguration.isFullScreen && subgroups.length > 1) {
|
|
8430
|
+
// baseY = Math.max(short_tick_length_bg, baseY - 10);
|
|
8431
|
+
// }
|
|
8432
|
+
// return baseY;
|
|
8433
|
+
// })
|
|
8434
|
+
// .attr('x', function (d) {
|
|
8435
|
+
// if (self.chartData.data.length > 8 && !self.isZoomedOut) {
|
|
8436
|
+
// return 1; // Move first line text slightly to the left in zoom-in view for better alignment
|
|
8437
|
+
// }
|
|
8438
|
+
// return 0; // Default position
|
|
8439
|
+
// })
|
|
8440
|
+
// .text(function (d) {
|
|
8441
|
+
// var isValueToBeIgnored = false;
|
|
8442
|
+
// if (isMobile && !self.isHeaderVisible) {
|
|
8443
|
+
// let firstPart = d.split(/[\s\-]+/)[0];
|
|
8444
|
+
// return firstPart.substring(0, 3).toLowerCase();
|
|
8445
|
+
// }
|
|
8446
|
+
// (data as any[]).map((indiv: any) => {
|
|
8447
|
+
// if (
|
|
8448
|
+
// indiv.name &&
|
|
8449
|
+
// indiv.name.toLowerCase() == d.trim().toLowerCase() &&
|
|
8450
|
+
// indiv[metaData.keyList[0]] == -1
|
|
8451
|
+
// ) {
|
|
8452
|
+
// isValueToBeIgnored = true;
|
|
8453
|
+
// }
|
|
8454
|
+
// });
|
|
8455
|
+
// if (isValueToBeIgnored) {
|
|
8456
|
+
// return '';
|
|
8457
|
+
// }
|
|
8458
|
+
// // Always add space before and after hyphen for date range labels, even when header is visible and label is single line
|
|
8459
|
+
// // Apply for grouped bar charts and single bar charts, header visible, single line
|
|
8460
|
+
// const dateRangeRegex = /(\d{2,4}[-\/]\d{2}[-\/]\d{2,4})\s*-\s*(\d{2,4}[-\/]\d{2}[-\/]\d{2,4})/;
|
|
8461
|
+
// if (dateRangeRegex.test(d.trim())) {
|
|
8462
|
+
// return d.trim().replace(dateRangeRegex, (m, d1, d2) => `${d1} - ${d2}`);
|
|
8463
|
+
// }
|
|
8464
|
+
// // Split date and week labels into two lines in grouped bar zoom-in view (and minimized view)
|
|
8465
|
+
// const isDateLabel = /\d{2,4}[-\/]/.test(d);
|
|
8466
|
+
// const isWeekLabel = /week|wk|w\d+/i.test(d);
|
|
8467
|
+
// if (
|
|
8468
|
+
// subgroups.length > 1 && !self.isZoomedOut && data.length > 8 && d.indexOf(' ') > -1 && (isDateLabel || isWeekLabel)
|
|
8469
|
+
// ) {
|
|
8470
|
+
// var first = d.substring(0, d.indexOf(' '));
|
|
8471
|
+
// var second = d.substring(d.indexOf(' ') + 1).trim();
|
|
8472
|
+
// return first + '\n' + second;
|
|
8473
|
+
// }
|
|
8474
|
+
// // Also keep previous logic for minimized view
|
|
8475
|
+
// if (isDateLabel) {
|
|
8476
|
+
// if (!self.isHeaderVisible && data.length > 8 && d.indexOf(' ') > -1) {
|
|
8477
|
+
// var first = d.substring(0, d.indexOf(' '));
|
|
8478
|
+
// var second = d.substring(d.indexOf(' ') + 1).trim();
|
|
8479
|
+
// return first + '\n' + second;
|
|
8480
|
+
// } else {
|
|
8481
|
+
// return d;
|
|
8482
|
+
// }
|
|
8483
|
+
// }
|
|
8484
|
+
// if (d.trim().indexOf(' ') > -1) {
|
|
8485
|
+
// return d.trim().substring(0, d.indexOf(' ')).toLowerCase();
|
|
8486
|
+
// }
|
|
8487
|
+
// return d.toLowerCase();
|
|
8488
|
+
// // If label looks like a date (contains digits and - or /)
|
|
8489
|
+
// const isDateLabel2 = /\d{2,4}[-\/]/.test(d);
|
|
8490
|
+
// // Only split date/week labels if there are many grouped bars and header is not visible
|
|
8491
|
+
// if (isDateLabel) {
|
|
8492
|
+
// if (!self.isHeaderVisible && data.length > 8 && d.indexOf(' ') > -1) {
|
|
8493
|
+
// var first = d.substring(0, d.indexOf(' '));
|
|
8494
|
+
// var second = d.substring(d.indexOf(' ') + 1).trim();
|
|
8495
|
+
// return first + '\n' + second;
|
|
8496
|
+
// } else {
|
|
8497
|
+
// return d;
|
|
8498
|
+
// }
|
|
8499
|
+
// }
|
|
8500
|
+
// if (d.trim().indexOf(' ') > -1) {
|
|
8501
|
+
// return d.trim().substring(0, d.indexOf(' ')).toLowerCase();
|
|
8502
|
+
// }
|
|
8503
|
+
// return d.toLowerCase();
|
|
8504
|
+
// });
|
|
8505
|
+
// // Now apply writing-mode: sideways-lr for grouped charts with date labels in zoomed-out view and many bars
|
|
8506
|
+
// xAxisLabels.each(function(this: SVGTextElement, d: any) {
|
|
8507
|
+
// // Only apply writing-mode for exact date labels, not those containing 'week' or similar
|
|
8508
|
+
// const isDateLabel = /^(\d{2,4}[-\/])?\d{2,4}[-\/]\d{2,4}$/.test(d.trim());
|
|
8509
|
+
// const isWeekLabel = /week|wk|w\d+/i.test(d);
|
|
8510
|
+
// if (subgroups.length > 1 && self.isZoomedOut && data.length > 8 && isDateLabel && !isWeekLabel) {
|
|
8511
|
+
// d3.select(this).style('writing-mode', 'sideways-lr');
|
|
8512
|
+
// }
|
|
8513
|
+
// });
|
|
8514
|
+
// if (!isMobile) {
|
|
8515
|
+
// svg
|
|
8516
|
+
// .selectAll('g.x1.axis1 g.tick')
|
|
8517
|
+
// .filter(function (d) {
|
|
8518
|
+
// return !/\d{2,4}[-\/]/.test(d); // Only process non-date labels
|
|
8519
|
+
// })
|
|
8520
|
+
// .append('text')
|
|
8521
|
+
// .attr('class', 'lib-xaxis-labels-texts-drilldown')
|
|
8522
|
+
// .attr('y', long_tick_length_bg)
|
|
8523
|
+
// .attr('fill', 'var(--chart-text-color)')
|
|
8524
|
+
// .attr('x', function (d) {
|
|
8525
|
+
// if (self.chartData.data.length > 8 && !self.isZoomedOut) {
|
|
8526
|
+
// return 1; // Move text slightly to the left
|
|
8527
|
+
// }
|
|
8528
|
+
// return 0; // Default position
|
|
8529
|
+
// })
|
|
8530
|
+
// .text(function (d) {
|
|
8531
|
+
// if (d.trim().indexOf(' ') > -1) {
|
|
8532
|
+
// return d.trim().substring(d.indexOf(' '), d.length).toLowerCase();
|
|
8533
|
+
// }
|
|
8534
|
+
// return '';
|
|
8535
|
+
// });
|
|
8536
|
+
// }
|
|
8537
|
+
// }
|
|
8538
|
+
// if (isria && self.chartData.data.length > 8) {
|
|
8539
|
+
// svg
|
|
8540
|
+
// .selectAll('g.x1.axis1 g.tick text')
|
|
8541
|
+
// .classed('mobile-xaxis-override', true)
|
|
8542
|
+
// .text(function (d: string) {
|
|
8543
|
+
// return d.substring(0, 3);
|
|
8544
|
+
// })
|
|
8545
|
+
// .style('font-size', '12px')
|
|
8546
|
+
// .attr('y', 5)
|
|
8547
|
+
// .attr('x', 5)
|
|
8548
|
+
// .style('text-anchor', 'middle');
|
|
8549
|
+
// }
|
|
8550
|
+
// if (isMobile && !this.isHeaderVisible) {
|
|
8551
|
+
// svg
|
|
8552
|
+
// .selectAll('g.x1.axis1 g.tick text')
|
|
8553
|
+
// .classed('mobile-xaxis-override', true);
|
|
8554
|
+
// }
|
|
8555
|
+
// /**y scale for left y axis */
|
|
8556
|
+
// var y = d3.scaleLinear().rangeRound([height, 0]);
|
|
8557
|
+
// var maxValue = d3.max(data, (d) => d3.max(keyList, (key) => +d[key]));
|
|
8558
|
+
// if (maxValue == 0) {
|
|
8559
|
+
// if (this.chartData.targetLineData) {
|
|
8560
|
+
// maxValue = this.chartData.targetLineData.target + 20;
|
|
8561
|
+
// } else {
|
|
8562
|
+
// maxValue = 100;
|
|
8563
|
+
// }
|
|
8564
|
+
// }
|
|
8565
|
+
// if (this.chartConfiguration.customYscale) {
|
|
8566
|
+
// /**
|
|
8567
|
+
// * increase y-scale so that values wont cross or exceed out of range
|
|
8568
|
+
// * used in weekly charts
|
|
8569
|
+
// */
|
|
8570
|
+
// maxValue = maxValue * this.chartConfiguration.customYscale;
|
|
8571
|
+
// }
|
|
8572
|
+
// if (
|
|
8573
|
+
// this.chartData.targetLineData &&
|
|
8574
|
+
// maxValue < this.chartData.targetLineData.target
|
|
8575
|
+
// ) {
|
|
8576
|
+
// maxValue =
|
|
8577
|
+
// maxValue < 10 && this.chartData.targetLineData.target < 10
|
|
8578
|
+
// ? this.chartData.targetLineData.target + 3
|
|
8579
|
+
// : this.chartData.targetLineData.target + 20;
|
|
8580
|
+
// }
|
|
8581
|
+
// y.domain([0, maxValue]).nice();
|
|
8582
|
+
// let lineYscale;
|
|
8583
|
+
// if (lineData != null) {
|
|
8584
|
+
// let maxLineValue = d3.max(lineData, function (d) {
|
|
8585
|
+
// return +d.value;
|
|
8586
|
+
// });
|
|
8587
|
+
// maxLineValue = maxLineValue * this.chartConfiguration.customYscale;
|
|
8588
|
+
// let minLineValue = d3.min(lineData, function (d) {
|
|
8589
|
+
// return +d.value;
|
|
8590
|
+
// });
|
|
8591
|
+
// if (maxLineValue > 0) minLineValue = minLineValue - 3;
|
|
8592
|
+
// if (minLineValue > 0) {
|
|
8593
|
+
// minLineValue = 0;
|
|
8594
|
+
// }
|
|
8595
|
+
// lineYscale = d3
|
|
8596
|
+
// .scaleLinear()
|
|
8597
|
+
// .domain([minLineValue, maxLineValue])
|
|
8598
|
+
// .range([height, minLineValue]);
|
|
8599
|
+
// }
|
|
8600
|
+
// let yLineAxis;
|
|
8601
|
+
// if (lineYscale != null) {
|
|
8602
|
+
// yLineAxis = d3
|
|
8603
|
+
// .axisRight(lineYscale)
|
|
8604
|
+
// .ticks(self.chartConfiguration.numberOfYTicks)
|
|
8605
|
+
// .tickSize(0)
|
|
8606
|
+
// .tickFormat(self.chartConfiguration.yLineAxisLabelFomatter);
|
|
8607
|
+
// }
|
|
8608
|
+
// /**
|
|
8609
|
+
// * show x-axis grid between labels
|
|
8610
|
+
// * used by weekly charts
|
|
8611
|
+
// */
|
|
8612
|
+
// if (self.chartConfiguration.isXgridBetweenLabels) {
|
|
8613
|
+
// svg
|
|
8614
|
+
// .append('g')
|
|
8615
|
+
// .attr('class', 'grid')
|
|
8616
|
+
// .attr(
|
|
8617
|
+
// 'transform',
|
|
8618
|
+
// 'translate(' + x.bandwidth() / 2 + ',' + height + ')'
|
|
8619
|
+
// )
|
|
8620
|
+
// .call(d3.axisBottom(x).tickSize(-height).tickFormat(''))
|
|
8621
|
+
// .style('stroke-dasharray', '5 5')
|
|
8622
|
+
// .style('color', 'var(--chart-grid-color, #999999)') // Use CSS variable
|
|
8623
|
+
// .call((g) => g.select('.domain').remove());
|
|
8624
|
+
// }
|
|
8625
|
+
// if (this.chartConfiguration.yAxisGrid) {
|
|
8626
|
+
// svg
|
|
8627
|
+
// .append('g')
|
|
8628
|
+
// .call(
|
|
8629
|
+
// d3
|
|
8630
|
+
// .axisLeft(y)
|
|
8631
|
+
// .ticks(self.chartConfiguration.numberOfYTicks)
|
|
8632
|
+
// .tickSize(-width)
|
|
8633
|
+
// )
|
|
8634
|
+
// .style('color', 'var(--chart-axis-color, #B9B9B9)')
|
|
8635
|
+
// .style('opacity', '0.5')
|
|
8636
|
+
// .call((g) => {
|
|
8637
|
+
// g.select('.domain')
|
|
8638
|
+
// .remove()
|
|
8639
|
+
// .style('stroke', 'var(--chart-domain-color, #000000)'); // Add CSS variable for domain
|
|
8640
|
+
// });
|
|
8641
|
+
// } else {
|
|
8642
|
+
// svg
|
|
8643
|
+
// .append('g')
|
|
8644
|
+
// .call(d3.axisLeft(y).ticks(self.chartConfiguration.numberOfYTicks))
|
|
8645
|
+
// .style('color', 'var(--chart-axis-color, #B9B9B9)')
|
|
8646
|
+
// .style('opacity', '0.5')
|
|
8647
|
+
// .call((g) => {
|
|
8648
|
+
// g.select('.domain')
|
|
8649
|
+
// .style('stroke', 'var(--chart-domain-color, #000000)') // Add CSS variable for domain
|
|
8650
|
+
// .style('stroke-width', '1px'); // Ensure visibility
|
|
8651
|
+
// });
|
|
8652
|
+
// }
|
|
8653
|
+
// var xSubgroup = d3.scaleBand().domain(subgroups);
|
|
8654
|
+
// if (subgroups.length > 1 && !this.isZoomedOut) {
|
|
8655
|
+
// // For grouped bar charts in zoom-in view, use full x.bandwidth() for subgroups
|
|
8656
|
+
// xSubgroup.range([0, x.bandwidth()]);
|
|
8657
|
+
// } else if (subgroups.length === 1 && !this.isZoomedOut) {
|
|
8658
|
+
// // For single-bar (non-grouped) charts in zoom-in view, set bar width to 100 (increased from 80)
|
|
8659
|
+
// xSubgroup.range([0, 100]);
|
|
8660
|
+
// } else if (this.chartConfiguration.isMultiChartGridLine == undefined) {
|
|
8661
|
+
// xSubgroup.range([0, x.bandwidth()]);
|
|
8662
|
+
// } else {
|
|
8663
|
+
// // used to make grouped bars with lesser width as we are not using padding for width
|
|
8664
|
+
// xSubgroup.range([0, x.bandwidth()]);
|
|
8665
|
+
// }
|
|
8666
|
+
// // if (this.chartConfiguration.isDrilldownChart) {
|
|
8667
|
+
// // }
|
|
8668
|
+
// var color = d3
|
|
8669
|
+
// .scaleOrdinal()
|
|
8670
|
+
// .domain(subgroups)
|
|
8671
|
+
// .range(Object.values(metaData.colors));
|
|
8672
|
+
// // var colorAboveTarget = d3
|
|
8673
|
+
// // .scaleOrdinal()
|
|
8674
|
+
// // .domain(subgroups)
|
|
8675
|
+
// // .range(Object.values(metaData.colorAboveTarget));
|
|
8676
|
+
// var state = svg
|
|
8677
|
+
// .append('g')
|
|
8678
|
+
// .selectAll('.state')
|
|
8679
|
+
// .data(data)
|
|
8680
|
+
// .enter()
|
|
8681
|
+
// .append('g')
|
|
8682
|
+
// .attr('transform', function (d) {
|
|
8683
|
+
// return 'translate(' + x(d.name) + ',0)';
|
|
8684
|
+
// });
|
|
8685
|
+
// state
|
|
8686
|
+
// .selectAll('rect')
|
|
8687
|
+
// .data(function (d) {
|
|
8688
|
+
// let newList: any = [];
|
|
8689
|
+
// subgroups.map(function (key) {
|
|
8690
|
+
// // if (key !== "group") {
|
|
8691
|
+
// let obj: any = { key: key, value: d[key], name: d.name };
|
|
8692
|
+
// newList.push(obj);
|
|
8693
|
+
// // }
|
|
8694
|
+
// });
|
|
8695
|
+
// return newList;
|
|
8696
|
+
// })
|
|
8697
|
+
// .enter()
|
|
8698
|
+
// .append('rect')
|
|
8699
|
+
// .attr('class', 'bars')
|
|
8700
|
+
// .on('click', function (d) {
|
|
8701
|
+
// if (d.key != 'Target') {
|
|
8702
|
+
// if (
|
|
8703
|
+
// !metaData.barWithoutClick ||
|
|
8704
|
+
// !metaData.barWithoutClick.length ||
|
|
8705
|
+
// (!metaData.barWithoutClick.includes(d?.name) &&
|
|
8706
|
+
// !metaData.barWithoutClick.includes(d?.key))
|
|
8707
|
+
// )
|
|
8708
|
+
// // self.handleClick(d.data.name);
|
|
8709
|
+
// self.handleClick(d);
|
|
8710
|
+
// }
|
|
8711
|
+
// })
|
|
8712
|
+
// .attr('x', function (d) {
|
|
8713
|
+
// if (self.chartConfiguration.isDrilldownChart) {
|
|
8714
|
+
// data.map((indiv: any) => {
|
|
8715
|
+
// if (indiv.name == d.name) {
|
|
8716
|
+
// let keys = Object.keys(indiv).filter((temp, i) => i != 0);
|
|
8717
|
+
// tempScale = d3.scaleBand().domain(keys).range([0, x.bandwidth()]);
|
|
8718
|
+
// if (x.bandwidth() > 100) {
|
|
8719
|
+
// // Increase bar width a bit in zoom-in view
|
|
8720
|
+
// let reducedBarWidth = 60;
|
|
8721
|
+
// if (!self.isZoomedOut) {
|
|
8722
|
+
// reducedBarWidth = 30;
|
|
8723
|
+
// }
|
|
8724
|
+
// if (self.chartData.data.length == 1) {
|
|
8725
|
+
// if (Object.keys(self.chartData.data[0]).length == 2) {
|
|
8726
|
+
// tempScale.range([
|
|
8727
|
+
// 0 + (x.bandwidth() - reducedBarWidth) / 2,
|
|
8728
|
+
// x.bandwidth() - (x.bandwidth() - reducedBarWidth) / 2,
|
|
8729
|
+
// ]);
|
|
8730
|
+
// } else
|
|
8731
|
+
// tempScale.range([
|
|
8732
|
+
// 0 + (x.bandwidth() - reducedBarWidth) / 2,
|
|
8733
|
+
// x.bandwidth() - (x.bandwidth() - reducedBarWidth) / 2,
|
|
8734
|
+
// ]);
|
|
8735
|
+
// } else
|
|
8736
|
+
// tempScale.range([
|
|
8737
|
+
// 0 + (x.bandwidth() - reducedBarWidth) / 2,
|
|
8738
|
+
// x.bandwidth() - (x.bandwidth() - reducedBarWidth) / 2,
|
|
8739
|
+
// ]);
|
|
8740
|
+
// }
|
|
8741
|
+
// }
|
|
8742
|
+
// });
|
|
8743
|
+
// return tempScale(d.key);
|
|
8744
|
+
// }
|
|
8745
|
+
// return xSubgroup(d.key);
|
|
8746
|
+
// })
|
|
8747
|
+
// .attr('y', function (d) {
|
|
8748
|
+
// if (d.value == -1) {
|
|
8749
|
+
// return y(0);
|
|
8750
|
+
// }
|
|
8751
|
+
// if (d.value >= 0) {
|
|
8752
|
+
// const barHeight = height - y(d.value);
|
|
8753
|
+
// const minHeight = self.chartConfiguration.defaultBarHeight || 2;
|
|
8754
|
+
// return barHeight < minHeight ? y(0) - minHeight : y(d.value);
|
|
8755
|
+
// }
|
|
8756
|
+
// return y(0);
|
|
8757
|
+
// })
|
|
8758
|
+
// .attr('width', function (d) {
|
|
8759
|
+
// // For grouped bar charts in zoom-in view, set bar width to 50 for maximum thickness
|
|
8760
|
+
// if (subgroups.length > 1 && !self.isZoomedOut) {
|
|
8761
|
+
// return 50;
|
|
8762
|
+
// }
|
|
8763
|
+
// // For single-bar (non-grouped) charts in zoom-in view, set bar width to 80
|
|
8764
|
+
// if (subgroups.length === 1 && !self.isZoomedOut) {
|
|
8765
|
+
// return 80;
|
|
8766
|
+
// }
|
|
8767
|
+
// let tempScale = d3.scaleBand().domain([]).range([0, 0]);
|
|
8768
|
+
// // Default logic for other chart types
|
|
8769
|
+
// if (self.chartConfiguration.isDrilldownChart) {
|
|
8770
|
+
// data.map((indiv: any) => {
|
|
8771
|
+
// if (indiv.name == d.name) {
|
|
8772
|
+
// let keys = Object.keys(indiv).filter((temp, i) => i != 0);
|
|
8773
|
+
// tempScale = d3.scaleBand().domain(keys).range([0, x.bandwidth()]);
|
|
8774
|
+
// if (x.bandwidth() > 100) {
|
|
8775
|
+
// // Increase bar width a bit in zoom-in view
|
|
8776
|
+
// let reducedBarWidth = 60;
|
|
8777
|
+
// if (!self.isZoomedOut) {
|
|
8778
|
+
// reducedBarWidth = 100;
|
|
8779
|
+
// }
|
|
8780
|
+
// if (self.chartData.data.length == 1) {
|
|
8781
|
+
// if (Object.keys(self.chartData.data[0]).length == 2) {
|
|
8782
|
+
// tempScale.range([
|
|
8783
|
+
// 0 + (x.bandwidth() - reducedBarWidth) / 2,
|
|
8784
|
+
// x.bandwidth() - (x.bandwidth() - reducedBarWidth) / 2,
|
|
8785
|
+
// ]);
|
|
8786
|
+
// } else
|
|
8787
|
+
// tempScale.range([
|
|
8788
|
+
// 0 + (x.bandwidth() - reducedBarWidth) / 2,
|
|
8789
|
+
// x.bandwidth() - (x.bandwidth() - reducedBarWidth) / 2,
|
|
8790
|
+
// ]);
|
|
8791
|
+
// } else
|
|
8792
|
+
// tempScale.range([
|
|
8793
|
+
// 0 + (x.bandwidth() - reducedBarWidth) / 2,
|
|
8794
|
+
// x.bandwidth() - (x.bandwidth() - reducedBarWidth) / 2,
|
|
8795
|
+
// ]);
|
|
8796
|
+
// }
|
|
8797
|
+
// }
|
|
8798
|
+
// });
|
|
8799
|
+
// return self.isZoomedOut
|
|
8800
|
+
// ? tempScale.bandwidth()
|
|
8801
|
+
// : self.chartData.data.length && self.chartData.data.length > 8
|
|
8802
|
+
// ? tempScale.bandwidth()
|
|
8803
|
+
// : tempScale.bandwidth();
|
|
8804
|
+
// }
|
|
8805
|
+
// return self.isZoomedOut
|
|
8806
|
+
// ? tempScale.bandwidth()
|
|
8807
|
+
// : self.chartData.data.length && self.chartData.data.length > 8
|
|
8808
|
+
// ? tempScale.bandwidth()
|
|
8809
|
+
// : tempScale.bandwidth();
|
|
8810
|
+
// })
|
|
8811
|
+
// .attr('height', function (d) {
|
|
8812
|
+
// if (d.value == -1) {
|
|
8813
|
+
// return height - y(0);
|
|
8814
|
+
// }
|
|
8815
|
+
// if (d.value >= 0) {
|
|
8816
|
+
// const barHeight = height - y(d.value);
|
|
8817
|
+
// const minHeight = self.chartConfiguration.defaultBarHeight || 2;
|
|
8818
|
+
// return Math.max(barHeight, minHeight);
|
|
8819
|
+
// }
|
|
8820
|
+
// return height - y(0);
|
|
8821
|
+
// })
|
|
8822
|
+
// .style('cursor', function (d) {
|
|
8823
|
+
// if (metaData.hasDrillDown && !isria) return 'pointer';
|
|
8824
|
+
// else return 'default';
|
|
8825
|
+
// })
|
|
8826
|
+
// .attr('fill', function (d) {
|
|
8827
|
+
// if (
|
|
8828
|
+
// d.value &&
|
|
8829
|
+
// self.chartData.targetLineData &&
|
|
8830
|
+
// d.value >= parseFloat(self.chartData.targetLineData.target) &&
|
|
8831
|
+
// self.chartData.metaData.colorAboveTarget
|
|
8832
|
+
// ) {
|
|
8833
|
+
// const key = d.key.toLowerCase();
|
|
8834
|
+
// const colorAboveTarget = Object.keys(self.chartData.metaData.colorAboveTarget).find(
|
|
8835
|
+
// k => k.toLowerCase() === key
|
|
8836
|
+
// );
|
|
8837
|
+
// if (colorAboveTarget) {
|
|
8838
|
+
// return self.chartData.metaData.colorAboveTarget[colorAboveTarget];
|
|
8839
|
+
// }
|
|
8840
|
+
// }
|
|
8841
|
+
// return self.chartData.metaData.colors[d.key];
|
|
8842
|
+
// });
|
|
8843
|
+
// /**
|
|
8844
|
+
// * display angled texts on the bars
|
|
8845
|
+
// */
|
|
8846
|
+
// if (this.chartConfiguration.textsOnBar != undefined && !this.isZoomedOut) {
|
|
8847
|
+
// state
|
|
8848
|
+
// .selectAll('text')
|
|
8849
|
+
// .data(function (d) {
|
|
8850
|
+
// let newList: any = [];
|
|
8851
|
+
// subgroups.map(function (key) {
|
|
8852
|
+
// let obj: any = { key: key, value: d[key], name: d.name };
|
|
8853
|
+
// newList.push(obj);
|
|
8854
|
+
// });
|
|
8855
|
+
// return newList;
|
|
8856
|
+
// })
|
|
8857
|
+
// .enter()
|
|
8858
|
+
// .append('text')
|
|
8859
|
+
// .attr('fill', 'var(--chart-text-color)')
|
|
8860
|
+
// .attr('x', function (d) {
|
|
8861
|
+
// return 0;
|
|
8862
|
+
// })
|
|
8863
|
+
// .attr('y', function (d) {
|
|
8864
|
+
// return 0;
|
|
8865
|
+
// })
|
|
8866
|
+
// .attr('class', 'lib-data-labels-weeklycharts')
|
|
8867
|
+
// .text(function (d) {
|
|
8868
|
+
// return d.key && d.value
|
|
8869
|
+
// ? d.key.length > 20
|
|
8870
|
+
// ? d.key.substring(0, 17) + '...'
|
|
8871
|
+
// : d.key
|
|
8872
|
+
// : '';
|
|
8873
|
+
// })
|
|
8874
|
+
// .style('fill', function (d) {
|
|
8875
|
+
// return '#000';
|
|
8876
|
+
// })
|
|
8877
|
+
// .style('font-weight', 'bold')
|
|
8878
|
+
// .style('font-size', function (d) {
|
|
8879
|
+
// if (self.isZoomedOut) {
|
|
8880
|
+
// return '9px'; // 👈 Zoomed out mode
|
|
8881
|
+
// }
|
|
8882
|
+
// if (self.chartConfiguration.isDrilldownChart) {
|
|
8883
|
+
// if (window.innerWidth > 1900) {
|
|
8884
|
+
// return '18px';
|
|
8885
|
+
// } else if (window.innerWidth < 1400) {
|
|
8886
|
+
// return '10px';
|
|
8887
|
+
// } else {
|
|
8888
|
+
// return '14px';
|
|
8889
|
+
// }
|
|
8890
|
+
// } else {
|
|
8891
|
+
// return '14px';
|
|
8892
|
+
// }
|
|
8893
|
+
// })
|
|
8894
|
+
// .attr('transform', function (d) {
|
|
8895
|
+
// data.map((indiv: any) => {
|
|
8896
|
+
// if (indiv.name == d.name) {
|
|
8897
|
+
// let keys = Object.keys(indiv).filter((temp, i) => i != 0);
|
|
8898
|
+
// var temp;
|
|
8899
|
+
// tempScale = d3.scaleBand().domain(keys).range([0, x.bandwidth()]);
|
|
8900
|
+
// if (x.bandwidth() > 100) {
|
|
8901
|
+
// if (self.chartData.data.length == 1) {
|
|
8902
|
+
// if (Object.keys(self.chartData.data[0]).length == 2) {
|
|
8903
|
+
// tempScale.range([
|
|
8904
|
+
// 0 + (x.bandwidth() - 200) / 2,
|
|
8905
|
+
// x.bandwidth() - (x.bandwidth() - 200) / 2,
|
|
8906
|
+
// ]);
|
|
8907
|
+
// // .padding(0.05);
|
|
8908
|
+
// } else
|
|
8909
|
+
// tempScale.range([
|
|
8910
|
+
// 0 + (x.bandwidth() - 300) / 2,
|
|
8911
|
+
// x.bandwidth() - (x.bandwidth() - 300) / 2,
|
|
8912
|
+
// ]);
|
|
8913
|
+
// // .padding(0.05);
|
|
8914
|
+
// } else
|
|
8915
|
+
// tempScale.range([
|
|
8916
|
+
// 0 + (x.bandwidth() - 125) / 2,
|
|
8917
|
+
// x.bandwidth() - (x.bandwidth() - 125) / 2,
|
|
8918
|
+
// ]);
|
|
8919
|
+
// }
|
|
8920
|
+
// }
|
|
8921
|
+
// });
|
|
8922
|
+
// /**
|
|
8923
|
+
// * if set, then all texts ll be horizontal
|
|
8924
|
+
// */
|
|
8925
|
+
// if (self.chartConfiguration.textAlwaysHorizontal) {
|
|
8926
|
+
// return (
|
|
8927
|
+
// 'translate(' + xSubgroup(d.key) + ',' + (y(d.value) - 3) + ')'
|
|
8928
|
+
// );
|
|
8929
|
+
// }
|
|
8930
|
+
// /**
|
|
8931
|
+
// * rotate texts having more than one digits
|
|
8932
|
+
// */
|
|
8933
|
+
// // if (d.value > 9)
|
|
8934
|
+
// if (!isNaN(tempScale(d.key)))
|
|
8935
|
+
// return (
|
|
8936
|
+
// 'translate(' +
|
|
8937
|
+
// (tempScale(d.key) + tempScale.bandwidth() * 0.55) +
|
|
8938
|
+
// ',' +
|
|
8939
|
+
// (y(0) - 10) +
|
|
8940
|
+
// ') rotate(270)'
|
|
8941
|
+
// );
|
|
8942
|
+
// return 'translate(0,0)';
|
|
8943
|
+
// // else
|
|
8944
|
+
// // return (
|
|
8945
|
+
// // 'translate(' +
|
|
8946
|
+
// // (tempScale(d.key) + tempScale.bandwidth() / 2) +
|
|
8947
|
+
// // ',' +
|
|
8948
|
+
// // y(0) +
|
|
8949
|
+
// // ')'
|
|
8950
|
+
// // );
|
|
8951
|
+
// })
|
|
8952
|
+
// .on('click', function (d) {
|
|
8953
|
+
// if (
|
|
8954
|
+
// !metaData.barWithoutClick ||
|
|
8955
|
+
// !metaData.barWithoutClick.length ||
|
|
8956
|
+
// (!metaData.barWithoutClick.includes(d?.name) &&
|
|
8957
|
+
// !metaData.barWithoutClick.includes(d?.key))
|
|
8958
|
+
// )
|
|
8959
|
+
// self.handleClick(d);
|
|
8960
|
+
// });
|
|
8961
|
+
// if (!isria) {
|
|
8962
|
+
// state
|
|
8963
|
+
// .selectAll('.lib-data-labels-weeklycharts')
|
|
8964
|
+
// .on('mouseout', handleMouseOut)
|
|
8965
|
+
// .on('mouseover', handleMouseOver);
|
|
8966
|
+
// }
|
|
8967
|
+
// }
|
|
8968
|
+
// if (this.chartConfiguration.displayTitleOnTop || (
|
|
8969
|
+
// this.chartConfiguration.textsOnBar == undefined &&
|
|
8970
|
+
// this.chartConfiguration.displayTitleOnTop == undefined
|
|
8971
|
+
// )) {
|
|
8972
|
+
// if (!isria) {
|
|
8973
|
+
// state
|
|
8974
|
+
// .selectAll('rect')
|
|
8975
|
+
// .on('mouseout', handleMouseOut)
|
|
8976
|
+
// .on('mouseover', handleMouseOver);
|
|
8977
|
+
// }
|
|
8978
|
+
// }
|
|
8979
|
+
// function handleMouseOver(d, i) {
|
|
8980
|
+
// svg.selectAll('.lib-verticalstack-title-ontop').remove();
|
|
8981
|
+
// svg
|
|
8982
|
+
// .append('foreignObject')
|
|
8983
|
+
// .attr('x', function () {
|
|
8984
|
+
// // ...existing code for tempScale calculation...
|
|
8985
|
+
// var elementsCounter;
|
|
8986
|
+
// data.map((indiv: any) => {
|
|
8987
|
+
// if (indiv.name == d.name) {
|
|
8988
|
+
// let keys = Object.keys(indiv).filter((temp, i) => i != 0);
|
|
8989
|
+
// elementsCounter = keys.length;
|
|
8990
|
+
// tempScale = d3.scaleBand().domain(keys).range([0, x.bandwidth()]);
|
|
8991
|
+
// if (x.bandwidth() > 100) {
|
|
8992
|
+
// if (self.chartData.data.length == 1) {
|
|
8993
|
+
// if (Object.keys(self.chartData.data[0]).length == 2) {
|
|
8994
|
+
// tempScale.range([
|
|
8995
|
+
// 0 + (x.bandwidth() - 200) / 2,
|
|
8996
|
+
// x.bandwidth() - (x.bandwidth() - 200) / 2,
|
|
8997
|
+
// ]);
|
|
8998
|
+
// } else
|
|
8999
|
+
// tempScale.range([
|
|
9000
|
+
// 0 + (x.bandwidth() - 300) / 2,
|
|
9001
|
+
// x.bandwidth() - (x.bandwidth() - 300) / 2,
|
|
9002
|
+
// ]);
|
|
9003
|
+
// } else
|
|
9004
|
+
// tempScale.range([
|
|
9005
|
+
// 0 + (x.bandwidth() - 125) / 2,
|
|
9006
|
+
// x.bandwidth() - (x.bandwidth() - 125) / 2,
|
|
9007
|
+
// ]);
|
|
9008
|
+
// }
|
|
9009
|
+
// }
|
|
9010
|
+
// });
|
|
9011
|
+
// if (metaData.hasDrillDown) {
|
|
9012
|
+
// if (tempScale.bandwidth() + leftAndRightSpaces * 2 > 180) {
|
|
9013
|
+
// return (
|
|
9014
|
+
// x(d.name) + tempScale(d.key) + tempScale.bandwidth() / 2 - 90
|
|
9015
|
+
// );
|
|
9016
|
+
// }
|
|
9017
|
+
// return (
|
|
9018
|
+
// x(d.name) +
|
|
9019
|
+
// tempScale(d.key) -
|
|
9020
|
+
// (tempScale.bandwidth() + leftAndRightSpaces * 2) / 2 +
|
|
9021
|
+
// tempScale.bandwidth() / 2
|
|
9022
|
+
// );
|
|
9023
|
+
// } else return x(d.name) + tempScale(d.key) - (tempScale.bandwidth() + leftAndRightSpaces * 2) / 2 + tempScale.bandwidth() / 2;
|
|
9024
|
+
// })
|
|
9025
|
+
// .attr('class', 'lib-verticalstack-title-ontop')
|
|
9026
|
+
// .attr('y', function () {
|
|
9027
|
+
// return y(d.value) - 3 - 40 - 10;
|
|
9028
|
+
// })
|
|
9029
|
+
// .attr('dy', function () {
|
|
9030
|
+
// return d.class;
|
|
9031
|
+
// })
|
|
9032
|
+
// .attr('width', function () {
|
|
9033
|
+
// data.map((indiv: any) => {
|
|
9034
|
+
// if (indiv.name == d.name) {
|
|
9035
|
+
// let keys = Object.keys(indiv).filter((temp, i) => i != 0);
|
|
9036
|
+
// tempScale = d3.scaleBand().domain(keys).range([0, x.bandwidth()]);
|
|
9037
|
+
// if (x.bandwidth() > 100) {
|
|
9038
|
+
// if (self.chartData.data.length == 1) {
|
|
9039
|
+
// if (Object.keys(self.chartData.data[0]).length == 2) {
|
|
9040
|
+
// tempScale.range([
|
|
9041
|
+
// 0 + (x.bandwidth() - 200) / 2,
|
|
9042
|
+
// x.bandwidth() - (x.bandwidth() - 200) / 2,
|
|
9043
|
+
// ]);
|
|
9044
|
+
// } else
|
|
9045
|
+
// tempScale.range([
|
|
9046
|
+
// 0 + (x.bandwidth() - 300) / 2,
|
|
9047
|
+
// x.bandwidth() - (x.bandwidth() - 300) / 2,
|
|
9048
|
+
// ]);
|
|
9049
|
+
// } else
|
|
9050
|
+
// tempScale.range([
|
|
9051
|
+
// 0 + (x.bandwidth() - 125) / 2,
|
|
9052
|
+
// x.bandwidth() - (x.bandwidth() - 125) / 2,
|
|
9053
|
+
// ]);
|
|
9054
|
+
// }
|
|
9055
|
+
// }
|
|
9056
|
+
// });
|
|
9057
|
+
// if (metaData.hasDrillDown) {
|
|
9058
|
+
// if (tempScale.bandwidth() + leftAndRightSpaces * 2 > 180) {
|
|
9059
|
+
// return '180px';
|
|
9060
|
+
// }
|
|
9061
|
+
// return tempScale.bandwidth() + leftAndRightSpaces * 2;
|
|
9062
|
+
// } else return tempScale.bandwidth() + leftAndRightSpaces * 2;
|
|
9063
|
+
// })
|
|
9064
|
+
// .attr('height', 50)
|
|
9065
|
+
// .append('xhtml:div')
|
|
9066
|
+
// .attr('class', 'title')
|
|
9067
|
+
// .style('z-index', 99)
|
|
9068
|
+
// .html(function () {
|
|
9069
|
+
// let barLabel = d.key;
|
|
9070
|
+
// let dataType = metaData.dataType ? metaData.dataType : '';
|
|
9071
|
+
// let value = d.value;
|
|
9072
|
+
// let desiredText =
|
|
9073
|
+
// '<span class="title-bar-name">' + barLabel + '</span>';
|
|
9074
|
+
// desiredText +=
|
|
9075
|
+
// '<span class="title-bar-value"><span>' +
|
|
9076
|
+
// value +
|
|
9077
|
+
// '</span>' +
|
|
9078
|
+
// dataType +
|
|
9079
|
+
// '</span>';
|
|
9080
|
+
// return desiredText;
|
|
9081
|
+
// });
|
|
9082
|
+
// }
|
|
9083
|
+
// function handleMouseOut(d, i) {
|
|
9084
|
+
// svg.selectAll('.lib-verticalstack-title-ontop').remove();
|
|
9085
|
+
// }
|
|
9086
|
+
// svg
|
|
9087
|
+
// .append('g')
|
|
9088
|
+
// .attr('class', 'x2 axis2')
|
|
9089
|
+
// .attr('transform', 'translate(0,' + height + ')')
|
|
9090
|
+
// .style('color', 'var(--chart-axis-color, #000)') // Use CSS variable instead of hardcoded #000
|
|
9091
|
+
// .call(d3.axisBottom(xScaleFromOrigin).tickSize(0))
|
|
9092
|
+
// .call((g) => g.select('.domain').attr('fill', 'none'));
|
|
9093
|
+
// svg.selectAll('g.x2.axis2 g.tick text').style('display', 'none');
|
|
9094
|
+
// svg
|
|
9095
|
+
// .append('g')
|
|
9096
|
+
// .attr('class', 'lib-stacked-y-axis-text yaxis-dashed')
|
|
9097
|
+
// .attr('style', self.chartConfiguration.yAxisCustomTextStyles)
|
|
9098
|
+
// .attr('transform', 'translate(0,0)')
|
|
9099
|
+
// .call(y)
|
|
9100
|
+
// .style('display', 'none');
|
|
9101
|
+
// svgYAxisLeft
|
|
9102
|
+
// .append('g')
|
|
9103
|
+
// .append('g')
|
|
9104
|
+
// .attr('class', 'lib-yaxis-labels-texts-drilldown yaxis-dashed')
|
|
9105
|
+
// .attr('style', self.chartConfiguration.yAxisCustomTextStyles)
|
|
9106
|
+
// .attr('transform', 'translate(0,0)')
|
|
9107
|
+
// .call(
|
|
9108
|
+
// d3
|
|
9109
|
+
// .axisLeft(y)
|
|
9110
|
+
// .tickSize(0)
|
|
9111
|
+
// .ticks(self.chartConfiguration.numberOfYTicks)
|
|
9112
|
+
// .tickFormat(function (d) {
|
|
9113
|
+
// const formatted = self.chartConfiguration.yAxisLabelFomatter
|
|
9114
|
+
// ? self.chartConfiguration.yAxisLabelFomatter(d)
|
|
9115
|
+
// : d;
|
|
9116
|
+
// return formatted >= 1000 ? formatted / 1000 + 'k' : formatted;
|
|
9117
|
+
// })
|
|
9118
|
+
// )
|
|
9119
|
+
// .call((g) => {
|
|
9120
|
+
// // Style the domain line for theme support
|
|
9121
|
+
// g.select('.domain')
|
|
9122
|
+
// .style('stroke', 'var(--chart-domain-color, #000000)')
|
|
9123
|
+
// .style('stroke-width', '1px');
|
|
9124
|
+
// })
|
|
9125
|
+
// .selectAll('text')
|
|
9126
|
+
// .style('fill', 'var(--chart-text-color)');
|
|
9127
|
+
// svgYAxisRight
|
|
9128
|
+
// .append('g')
|
|
9129
|
+
// .attr('class', 'lib-yaxis-labels-texts-drilldown yaxis-dashed')
|
|
9130
|
+
// .attr('style', self.chartConfiguration.yAxisCustomTextStyles)
|
|
9131
|
+
// .attr('transform', 'translate(0,0)')
|
|
9132
|
+
// .call(y)
|
|
9133
|
+
// .style('display', 'none');
|
|
9134
|
+
// /**
|
|
9135
|
+
// * hide x axis labels
|
|
9136
|
+
// * config is there for future use
|
|
9137
|
+
// * used by weekly charts
|
|
9138
|
+
// */
|
|
9139
|
+
// if (
|
|
9140
|
+
// this.chartConfiguration.isXaxisLabelHidden != undefined &&
|
|
9141
|
+
// this.chartConfiguration.isXaxisLabelHidden
|
|
9142
|
+
// ) {
|
|
9143
|
+
// d3.selectAll('g.lib-line-x-axis-text > g > text').attr(
|
|
9144
|
+
// 'class',
|
|
9145
|
+
// 'lib-display-hidden'
|
|
9146
|
+
// );
|
|
9147
|
+
// }
|
|
9148
|
+
// /**
|
|
9149
|
+
// * hide y axis labels
|
|
9150
|
+
// * used by weekly charts
|
|
9151
|
+
// */
|
|
9152
|
+
// if (
|
|
9153
|
+
// this.chartConfiguration.isYaxisLabelHidden != undefined &&
|
|
9154
|
+
// this.chartConfiguration.isYaxisLabelHidden
|
|
9155
|
+
// ) {
|
|
9156
|
+
// d3.selectAll('.yaxis-dashed > g > text').attr(
|
|
9157
|
+
// 'class',
|
|
9158
|
+
// 'lib-display-hidden'
|
|
9159
|
+
// );
|
|
9160
|
+
// }
|
|
9161
|
+
// /**
|
|
9162
|
+
// * hide y axis labels
|
|
9163
|
+
// * config is there for future use
|
|
9164
|
+
// */
|
|
9165
|
+
// if (
|
|
9166
|
+
// this.chartConfiguration.isYaxisHidden != undefined &&
|
|
9167
|
+
// this.chartConfiguration.isYaxisHidden
|
|
9168
|
+
// ) {
|
|
9169
|
+
// d3.selectAll('.yaxis-dashed').attr('class', 'lib-display-hidden');
|
|
9170
|
+
// }
|
|
9171
|
+
// /**
|
|
9172
|
+
// * dashed y axis
|
|
9173
|
+
// * used by weekly charts
|
|
9174
|
+
// */
|
|
9175
|
+
// if (
|
|
9176
|
+
// this.chartConfiguration.isYaxisDashed != undefined &&
|
|
9177
|
+
// this.chartConfiguration.isYaxisDashed
|
|
9178
|
+
// ) {
|
|
9179
|
+
// d3.selectAll('.yaxis-dashed')
|
|
9180
|
+
// .style('stroke-dasharray', '5 5')
|
|
9181
|
+
// .style('color', 'var(--chart-axis-color, #999999)'); // Use CSS variable
|
|
9182
|
+
// }
|
|
9183
|
+
// if (lineData != null) {
|
|
9184
|
+
// if (lineData && self.chartConfiguration.showLineChartAxis) {
|
|
9185
|
+
// svgYAxisRight
|
|
9186
|
+
// .append('g')
|
|
9187
|
+
// .attr('class', 'lib-stacked-y-axis-text1')
|
|
9188
|
+
// .attr('style', self.chartConfiguration.yAxisCustomTextStyles)
|
|
9189
|
+
// .attr('transform', 'translate(' + 0 + ',0)')
|
|
9190
|
+
// .call(yLineAxis);
|
|
9191
|
+
// }
|
|
9192
|
+
// }
|
|
9193
|
+
// /**
|
|
9194
|
+
// * used to display y label
|
|
9195
|
+
// */
|
|
9196
|
+
// // if (this.isZoomedOut) {
|
|
9197
|
+
// // svg
|
|
9198
|
+
// // .selectAll('.lib-xaxis-labels-texts-drilldown')
|
|
9199
|
+
// // .attr('class', 'lib-display-hidden');
|
|
9200
|
+
// // }
|
|
9201
|
+
// if (this.isZoomedOut) {
|
|
9202
|
+
// svg
|
|
9203
|
+
// .selectAll('.lib-xaxis-labels-texts-drilldown')
|
|
9204
|
+
// .each((d, i, nodes) => {
|
|
9205
|
+
// const text = d3.select(nodes[i]);
|
|
9206
|
+
// const label = text.text();
|
|
9207
|
+
// if (label.indexOf('\n') > -1) {
|
|
9208
|
+
// const lines = label.split('\n');
|
|
9209
|
+
// text.text(null);
|
|
9210
|
+
// lines.forEach((line, idx) => {
|
|
9211
|
+
// text.append('tspan')
|
|
9212
|
+
// .text(line)
|
|
9213
|
+
// .attr('x', 0)
|
|
9214
|
+
// .attr('dy', idx === 0 ? '1em' : '1.1em');
|
|
9215
|
+
// });
|
|
9216
|
+
// } else {
|
|
9217
|
+
// const words = label.split(' ');
|
|
9218
|
+
// text.text(null);
|
|
9219
|
+
// words.forEach((word, index) => {
|
|
9220
|
+
// text.append('tspan').text(word);
|
|
9221
|
+
// });
|
|
9222
|
+
// }
|
|
9223
|
+
// })
|
|
9224
|
+
// .style('fill', 'var(--chart-text-color)')
|
|
9225
|
+
// .attr('transform', null);
|
|
9226
|
+
// svg
|
|
9227
|
+
// .select('.x-axis')
|
|
9228
|
+
// .attr('transform', `translate(0, ${height - margin.bottom + 10})`);
|
|
9229
|
+
// }
|
|
9230
|
+
// /**
|
|
9231
|
+
// * used to write y labels based on configuration
|
|
9232
|
+
// */
|
|
9233
|
+
// if (metaData.yLabel) {
|
|
9234
|
+
// const yPosition = isria ? 0 - margin.left / 2 - 30 : 0 - margin.left / 2 - 40;
|
|
9235
|
+
// svgYAxisLeft
|
|
9236
|
+
// .append('text')
|
|
9237
|
+
// .attr('class', 'lib-axis-group-label font-size-1')
|
|
9238
|
+
// .attr('style', self.chartConfiguration.yAxisCustomlabelStyles)
|
|
9239
|
+
// .attr('transform', 'rotate(-90)')
|
|
9240
|
+
// .attr('y', yPosition)
|
|
9241
|
+
// .attr('x', 0 - height / 2)
|
|
9242
|
+
// .attr('dy', '1em')
|
|
9243
|
+
// .style('text-anchor', 'middle')
|
|
9244
|
+
// .attr('fill', 'var(--chart-text-color)');
|
|
9245
|
+
// if (this.chartConfiguration.isMultiChartGridLine === undefined) {
|
|
9246
|
+
// svgYAxisLeft
|
|
9247
|
+
// .selectAll('.lib-axis-group-label')
|
|
9248
|
+
// .style('font-size', 'smaller')
|
|
9249
|
+
// .text(metaData.yLabel);
|
|
9250
|
+
// } else {
|
|
9251
|
+
// svg
|
|
9252
|
+
// .selectAll('.lib-axis-group-label')
|
|
9253
|
+
// .attr('class', 'lib-ylabel-weeklyCharts')
|
|
9254
|
+
// .text(metaData.yLabel.toLowerCase());
|
|
9255
|
+
// }
|
|
9256
|
+
// }
|
|
9257
|
+
// if (this.chartData.targetLineData) {
|
|
9258
|
+
// const yZero = y(this.chartData.targetLineData.target);
|
|
9259
|
+
// svg
|
|
9260
|
+
// .append('line')
|
|
9261
|
+
// .attr('x1', 0)
|
|
9262
|
+
// .attr('x2', width)
|
|
9263
|
+
// .attr('y1', yZero)
|
|
9264
|
+
// .attr('y2', yZero)
|
|
9265
|
+
// .style('stroke-dasharray', '5 5')
|
|
9266
|
+
// .style('stroke', this.chartData.targetLineData.color);
|
|
9267
|
+
// // svgYAxisRight
|
|
9268
|
+
// // .append('line')
|
|
9269
|
+
// // .attr('x1', 0)
|
|
9270
|
+
// // .attr('x2', rightSvgWidth)
|
|
9271
|
+
// // .attr('y1', yZero)
|
|
9272
|
+
// // .attr('y2', yZero)
|
|
9273
|
+
// // .style('stroke', this.chartData.targetLineData.color);
|
|
9274
|
+
// svgYAxisRight
|
|
9275
|
+
// .append('foreignObject')
|
|
9276
|
+
// .attr('transform', 'translate(' + 0 + ',' + (yZero - 30) + ')')
|
|
9277
|
+
// .attr('width', rightSvgWidth)
|
|
9278
|
+
// .attr('height', 50)
|
|
9279
|
+
// .append('xhtml:div')
|
|
9280
|
+
// .attr('class', 'target-display')
|
|
9281
|
+
// .style('color', 'var(--chart-text-color)')
|
|
9282
|
+
// .html(function () {
|
|
9283
|
+
// let dataTypeTemp = '';
|
|
9284
|
+
// let targetLineName = 'target';
|
|
9285
|
+
// if (metaData.dataType) {
|
|
9286
|
+
// dataTypeTemp = metaData.dataType;
|
|
9287
|
+
// }
|
|
9288
|
+
// if (
|
|
9289
|
+
// self.chartData.targetLineData &&
|
|
9290
|
+
// self.chartData.targetLineData.targetName
|
|
9291
|
+
// ) {
|
|
9292
|
+
// targetLineName = self.chartData.targetLineData.targetName;
|
|
9293
|
+
// }
|
|
9294
|
+
// return (
|
|
9295
|
+
// `<div>${targetLineName}</div>` +
|
|
9296
|
+
// '<div>' +
|
|
9297
|
+
// self.chartData.targetLineData.target +
|
|
9298
|
+
// '' +
|
|
9299
|
+
// dataTypeTemp +
|
|
9300
|
+
// '</div>'
|
|
9301
|
+
// );
|
|
9302
|
+
// });
|
|
9303
|
+
// }
|
|
9304
|
+
// if (this.chartConfiguration.isDrilldownChart) {
|
|
9305
|
+
// /**
|
|
9306
|
+
// * used by drilldown charts
|
|
9307
|
+
// */
|
|
9308
|
+
// // svg
|
|
9309
|
+
// // .selectAll('.lib-axis-group-label')
|
|
9310
|
+
// // .attr('class', 'lib-ylabel-drilldowncharts')
|
|
9311
|
+
// // .text(metaData.yLabel.toLowerCase());
|
|
9312
|
+
// svg.selectAll('g.x1.axis1 g.tick line').style('display', 'none');
|
|
9313
|
+
// }
|
|
9314
|
+
// if (metaData.xLabel) {
|
|
9315
|
+
// function isAcronym(label) {
|
|
9316
|
+
// return (
|
|
9317
|
+
// (label.length <= 4 && /^[A-Z]+$/.test(label)) ||
|
|
9318
|
+
// (label === label.toUpperCase() && /[A-Z]/.test(label))
|
|
9319
|
+
// );
|
|
9320
|
+
// }
|
|
9321
|
+
// const xLabelText = metaData.xLabel;
|
|
9322
|
+
// const isAcr = isAcronym(xLabelText.replace(/[^A-Za-z]/g, ''));
|
|
9323
|
+
// const xPosition = isria ? (height + margin.top + margin.bottom) : (height + margin.top + margin.bottom + 40);
|
|
9324
|
+
// svg
|
|
9325
|
+
// .append('text')
|
|
9326
|
+
// .attr('class', function () {
|
|
9327
|
+
// let baseClass = 'lib-axis-group-label font-size-1';
|
|
9328
|
+
// if (self.chartConfiguration.isDrilldownChart)
|
|
9329
|
+
// return baseClass + ' lib-xlabel-drilldowncharts';
|
|
9330
|
+
// if (self.chartConfiguration.isMultiChartGridLine != undefined)
|
|
9331
|
+
// return baseClass + ' lib-xlabel-weeklyCharts';
|
|
9332
|
+
// return baseClass + ' lib-axis-waterfall-label';
|
|
9333
|
+
// })
|
|
9334
|
+
// .attr('style', self.chartConfiguration.xAxisCustomlabelStyles)
|
|
9335
|
+
// .attr(
|
|
9336
|
+
// 'transform',
|
|
9337
|
+
// 'translate(' + width / 2 + ' ,' + xPosition + ')'
|
|
9338
|
+
// )
|
|
9339
|
+
// .style('text-anchor', 'middle')
|
|
9340
|
+
// .style('fill', 'var(--chart-text-color)')
|
|
9341
|
+
// .text(isAcr ? xLabelText.toUpperCase() : xLabelText.toLowerCase())
|
|
9342
|
+
// .style('text-transform', isAcr ? 'none' : 'capitalize');
|
|
9343
|
+
// }
|
|
9344
|
+
// if (metaData.lineyLabel) {
|
|
9345
|
+
// svgYAxisRight
|
|
9346
|
+
// .append('text')
|
|
9347
|
+
// .attr('class', 'lib-axis-group-label lib-line-axis')
|
|
9348
|
+
// .attr('fill', 'var(--chart-text-color)')
|
|
9349
|
+
// .attr('style', self.chartConfiguration.yAxisCustomlabelStyles)
|
|
9350
|
+
// .attr('transform', 'translate(0,0) rotate(90)')
|
|
9351
|
+
// .attr('y', 0 - 100)
|
|
9352
|
+
// .attr('x', 0 + 100)
|
|
9353
|
+
// .attr('dy', '5em')
|
|
9354
|
+
// .style('text-anchor', 'middle')
|
|
9355
|
+
// .style('font-size', 'smaller')
|
|
9356
|
+
// .text(metaData.lineyLabel);
|
|
9357
|
+
// }
|
|
9358
|
+
// if (lineData) {
|
|
9359
|
+
// svg
|
|
9360
|
+
// .append('path')
|
|
9361
|
+
// .datum(lineData)
|
|
9362
|
+
// .attr('fill', 'none')
|
|
9363
|
+
// .attr('stroke', self.chartConfiguration.lineGraphColor)
|
|
9364
|
+
// .attr('stroke-width', 1.5)
|
|
9365
|
+
// .attr(
|
|
9366
|
+
// 'd',
|
|
9367
|
+
// d3
|
|
9368
|
+
// .line()
|
|
9369
|
+
// .x(function (d) {
|
|
9370
|
+
// return x(d.name) + x.bandwidth() / 2;
|
|
9371
|
+
// })
|
|
9372
|
+
// .y(function (d) {
|
|
9373
|
+
// return lineYscale(d.value);
|
|
9374
|
+
// })
|
|
9375
|
+
// );
|
|
9376
|
+
// var dot = svg
|
|
9377
|
+
// .selectAll('myCircles')
|
|
9378
|
+
// .data(lineData)
|
|
9379
|
+
// .enter()
|
|
9380
|
+
// .append('g')
|
|
9381
|
+
// .on('click', function (d) {
|
|
9382
|
+
// if (
|
|
9383
|
+
// !metaData.barWithoutClick ||
|
|
9384
|
+
// !metaData.barWithoutClick.length ||
|
|
9385
|
+
// (!metaData.barWithoutClick.includes(d?.name) &&
|
|
9386
|
+
// !metaData.barWithoutClick.includes(d?.key))
|
|
9387
|
+
// )
|
|
9388
|
+
// self.handleClick(d);
|
|
9389
|
+
// });
|
|
9390
|
+
// dot
|
|
9391
|
+
// .append('circle')
|
|
9392
|
+
// .attr('fill', function (d) {
|
|
9393
|
+
// return self.chartConfiguration.lineGraphColor;
|
|
9394
|
+
// })
|
|
9395
|
+
// .attr('stroke', 'none')
|
|
9396
|
+
// .attr('cx', function (d) {
|
|
9397
|
+
// return x(d.name) + x.bandwidth() / 2;
|
|
9398
|
+
// })
|
|
9399
|
+
// .attr('cy', function (d) {
|
|
9400
|
+
// return lineYscale(d.value);
|
|
9401
|
+
// })
|
|
9402
|
+
// .style('cursor', () =>
|
|
9403
|
+
// self.chartData.metaData.hasDrillDown ? 'pointer' : 'default'
|
|
9404
|
+
// )
|
|
9405
|
+
// .attr('r', 3);
|
|
9406
|
+
// if (self.chartConfiguration.lineGraphColor) {
|
|
9407
|
+
// dot
|
|
9408
|
+
// .append('text')
|
|
9409
|
+
// .attr('class', 'dot')
|
|
9410
|
+
// .attr('fill', 'var(--chart-text-color)')
|
|
9411
|
+
// .attr('color', self.chartConfiguration.lineGraphColor)
|
|
9412
|
+
// .attr('style', 'font-size: ' + '.85em')
|
|
9413
|
+
// .attr('x', function (d, i) {
|
|
9414
|
+
// return x(d.name) + x.bandwidth() / 2;
|
|
9415
|
+
// })
|
|
9416
|
+
// .attr('y', function (d) {
|
|
9417
|
+
// return lineYscale(d.value);
|
|
9418
|
+
// })
|
|
9419
|
+
// .attr('dy', '-1em')
|
|
9420
|
+
// .text(function (d) {
|
|
9421
|
+
// return self.chartConfiguration.labelFormatter(d.value);
|
|
9422
|
+
// });
|
|
9423
|
+
// }
|
|
9424
|
+
// }
|
|
9425
|
+
// }
|
|
8190
9426
|
initializegroupChart() {
|
|
8191
|
-
|
|
9427
|
+
// ==================== VARIABLE DECLARATIONS ====================
|
|
9428
|
+
const self = this;
|
|
8192
9429
|
let data = [];
|
|
8193
9430
|
let metaData = null;
|
|
8194
9431
|
let keyList = null;
|
|
8195
9432
|
let lineData = null;
|
|
8196
9433
|
let colorMap = {};
|
|
8197
|
-
|
|
8198
|
-
|
|
9434
|
+
let formatFromBackend;
|
|
9435
|
+
let formatForHugeNumbers;
|
|
9436
|
+
// Device detection
|
|
8199
9437
|
const isMobile = window.innerWidth < 576;
|
|
8200
9438
|
const isTablet = window.innerWidth >= 576 && window.innerWidth < 992;
|
|
8201
9439
|
const isDesktop = window.innerWidth >= 992;
|
|
8202
|
-
|
|
8203
|
-
|
|
8204
|
-
|
|
8205
|
-
|
|
8206
|
-
|
|
8207
|
-
|
|
8208
|
-
|
|
8209
|
-
|
|
8210
|
-
|
|
8211
|
-
|
|
8212
|
-
|
|
8213
|
-
|
|
8214
|
-
|
|
8215
|
-
|
|
8216
|
-
|
|
9440
|
+
const isria = this.customChartConfiguration.isRia;
|
|
9441
|
+
// Chart scale variables
|
|
9442
|
+
let x;
|
|
9443
|
+
let tempScale;
|
|
9444
|
+
// Tick length constants
|
|
9445
|
+
const SHORT_TICK_LENGTH = 4;
|
|
9446
|
+
const LONG_TICK_LENGTH = 16;
|
|
9447
|
+
const SHORT_TICK_LENGTH_BG = 5;
|
|
9448
|
+
const LONG_TICK_LENGTH_BG = 30;
|
|
9449
|
+
const LEFT_AND_RIGHT_SPACES = 50;
|
|
9450
|
+
const RIGHT_SVG_WIDTH = 60;
|
|
9451
|
+
// Flags
|
|
9452
|
+
let alternate_text = false;
|
|
9453
|
+
// ==================== CONFIGURATION SETUP ====================
|
|
9454
|
+
for (const key in this.defaultConfiguration) {
|
|
9455
|
+
this.chartConfiguration[key] = ChartHelper.getValueByConfigurationType(key, this.defaultConfiguration, this.customChartConfiguration);
|
|
8217
9456
|
}
|
|
9457
|
+
// Extract chart data
|
|
8218
9458
|
data = this.chartData.data;
|
|
8219
9459
|
metaData = this.chartData.metaData;
|
|
8220
9460
|
lineData = this.chartData.lineData;
|
|
8221
|
-
//
|
|
8222
|
-
// rightSvgWidth = 60;
|
|
8223
|
-
// }
|
|
9461
|
+
// Setup color mappings
|
|
8224
9462
|
if (!metaData.colorAboveTarget) {
|
|
8225
9463
|
metaData['colorAboveTarget'] = metaData.colors;
|
|
8226
9464
|
}
|
|
8227
9465
|
colorMap = metaData.colors;
|
|
8228
9466
|
keyList = metaData.keyList;
|
|
8229
|
-
|
|
8230
|
-
|
|
8231
|
-
|
|
9467
|
+
// ==================== CONTAINER SETUP ====================
|
|
9468
|
+
const chartContainer = d3.select(this.containerElt.nativeElement);
|
|
9469
|
+
const verticalstackedcontainer = d3.select(this.groupcontainerElt.nativeElement);
|
|
9470
|
+
const margin = this.chartConfiguration.margin;
|
|
8232
9471
|
const { width, height } = this.calculateChartDimensions(chartContainer, verticalstackedcontainer, margin, self);
|
|
8233
|
-
|
|
8234
|
-
|
|
8235
|
-
* used by weekly charts
|
|
8236
|
-
*/
|
|
8237
|
-
if (this.chartConfiguration.isHeaderVisible != undefined)
|
|
9472
|
+
// ==================== VISIBILITY CONFIGURATION ====================
|
|
9473
|
+
if (this.chartConfiguration.isHeaderVisible !== undefined) {
|
|
8238
9474
|
this.isHeaderVisible = this.chartConfiguration.isHeaderVisible;
|
|
8239
|
-
|
|
8240
|
-
|
|
8241
|
-
* used by weekly charts
|
|
8242
|
-
*/
|
|
8243
|
-
if (this.chartConfiguration.legendVisible != undefined) {
|
|
9475
|
+
}
|
|
9476
|
+
if (this.chartConfiguration.legendVisible !== undefined) {
|
|
8244
9477
|
this.legendVisible = this.chartConfiguration.legendVisible;
|
|
8245
9478
|
}
|
|
8246
|
-
|
|
8247
|
-
|
|
8248
|
-
*
|
|
8249
|
-
*/
|
|
8250
|
-
if (this.chartConfiguration.isTransparentBackground != undefined) {
|
|
8251
|
-
this.isTransparentBackground =
|
|
8252
|
-
this.chartConfiguration.isTransparentBackground;
|
|
9479
|
+
if (this.chartConfiguration.isTransparentBackground !== undefined) {
|
|
9480
|
+
this.isTransparentBackground = this.chartConfiguration.isTransparentBackground;
|
|
8253
9481
|
}
|
|
8254
|
-
|
|
8255
|
-
|
|
8256
|
-
*/
|
|
8257
|
-
if (this.chartConfiguration.textFormatter != undefined) {
|
|
9482
|
+
// ==================== DATA FORMATTING ====================
|
|
9483
|
+
if (this.chartConfiguration.textFormatter !== undefined) {
|
|
8258
9484
|
formatFromBackend = ChartHelper.dataValueFormatter(this.chartConfiguration.textFormatter);
|
|
8259
9485
|
formatForHugeNumbers = ChartHelper.dataValueFormatter('.2s');
|
|
8260
9486
|
}
|
|
8261
|
-
|
|
8262
|
-
|
|
8263
|
-
|
|
8264
|
-
|
|
8265
|
-
|
|
8266
|
-
|
|
8267
|
-
|
|
8268
|
-
|
|
8269
|
-
* x axis range made similar to line chart or vertical stack so that all the charts will get aligned with each other.
|
|
8270
|
-
*/
|
|
8271
|
-
if (this.chartConfiguration.isMultiChartGridLine != undefined) {
|
|
8272
|
-
x = d3
|
|
8273
|
-
.scaleBand()
|
|
9487
|
+
// ==================== SVG CONTAINERS CREATION ====================
|
|
9488
|
+
const { outerContainer, svgYAxisLeft, svgYAxisRight, innerContainer, svg } = this.createChartContainers(chartContainer, margin, height, RIGHT_SVG_WIDTH, self, width);
|
|
9489
|
+
// ==================== SCALES SETUP ====================
|
|
9490
|
+
const subgroups = keyList;
|
|
9491
|
+
const groups = d3.map(data, (d) => d.name).keys();
|
|
9492
|
+
// X-axis scale configuration
|
|
9493
|
+
if (this.chartConfiguration.isMultiChartGridLine !== undefined) {
|
|
9494
|
+
x = d3.scaleBand()
|
|
8274
9495
|
.rangeRound([width, 0])
|
|
8275
9496
|
.align(0.5)
|
|
8276
9497
|
.padding([0.5])
|
|
8277
|
-
.domain(data.map(
|
|
8278
|
-
return d.name.toLowerCase();
|
|
8279
|
-
}));
|
|
9498
|
+
.domain(data.map((d) => d.name.toLowerCase()));
|
|
8280
9499
|
}
|
|
8281
9500
|
else {
|
|
8282
|
-
x = d3
|
|
8283
|
-
.scaleBand()
|
|
9501
|
+
x = d3.scaleBand()
|
|
8284
9502
|
.domain(groups)
|
|
8285
|
-
.range([
|
|
9503
|
+
.range([LEFT_AND_RIGHT_SPACES, width - RIGHT_SVG_WIDTH - LEFT_AND_RIGHT_SPACES])
|
|
8286
9504
|
.padding([0.3]);
|
|
8287
9505
|
}
|
|
8288
|
-
|
|
8289
|
-
var xScaleFromOrigin = d3
|
|
8290
|
-
.scaleBand()
|
|
9506
|
+
const xScaleFromOrigin = d3.scaleBand()
|
|
8291
9507
|
.domain(groups)
|
|
8292
|
-
.range([0, width -
|
|
8293
|
-
//
|
|
8294
|
-
|
|
8295
|
-
|
|
8296
|
-
|
|
8297
|
-
|
|
8298
|
-
|
|
8299
|
-
|
|
9508
|
+
.range([0, width - RIGHT_SVG_WIDTH]);
|
|
9509
|
+
// ==================== X-AXIS RENDERING ====================
|
|
9510
|
+
this.renderXAxis(svg, x, height, metaData, subgroups, data, SHORT_TICK_LENGTH_BG, LONG_TICK_LENGTH_BG, self, isria, isMobile);
|
|
9511
|
+
// ==================== Y-AXIS SETUP ====================
|
|
9512
|
+
const y = d3.scaleLinear().rangeRound([height, 0]);
|
|
9513
|
+
let maxValue = this.calculateMaxValue(data, keyList);
|
|
9514
|
+
if (this.chartConfiguration.customYscale) {
|
|
9515
|
+
maxValue = maxValue * this.chartConfiguration.customYscale;
|
|
9516
|
+
}
|
|
9517
|
+
if (this.chartData.targetLineData && maxValue < this.chartData.targetLineData.target) {
|
|
9518
|
+
maxValue = maxValue < 10 && this.chartData.targetLineData.target < 10
|
|
9519
|
+
? this.chartData.targetLineData.target + 3
|
|
9520
|
+
: this.chartData.targetLineData.target + 20;
|
|
9521
|
+
}
|
|
9522
|
+
y.domain([0, maxValue]).nice();
|
|
9523
|
+
// ==================== LINE CHART Y-SCALE ====================
|
|
9524
|
+
let lineYscale;
|
|
9525
|
+
let yLineAxis;
|
|
9526
|
+
if (lineData != null) {
|
|
9527
|
+
const result = this.setupLineYScale(lineData, height, self);
|
|
9528
|
+
lineYscale = result.lineYscale;
|
|
9529
|
+
yLineAxis = result.yLineAxis;
|
|
9530
|
+
}
|
|
9531
|
+
// ==================== GRID LINES ====================
|
|
9532
|
+
this.renderGridLines(svg, x, y, height, width, self);
|
|
9533
|
+
// ==================== BARS RENDERING ====================
|
|
9534
|
+
const xSubgroup = this.setupXSubgroupScale(subgroups, x, self);
|
|
9535
|
+
const color = d3.scaleOrdinal()
|
|
9536
|
+
.domain(subgroups)
|
|
9537
|
+
.range(Object.values(metaData.colors));
|
|
9538
|
+
this.renderBars(svg, data, subgroups, x, xSubgroup, y, height, color, metaData, self, LEFT_AND_RIGHT_SPACES, tempScale, isria);
|
|
9539
|
+
// ==================== BAR LABELS ====================
|
|
9540
|
+
if (this.chartConfiguration.textsOnBar !== undefined && !this.isZoomedOut) {
|
|
9541
|
+
this.renderBarLabels(svg, data, subgroups, x, xSubgroup, y, height, metaData, self, tempScale, isria);
|
|
9542
|
+
}
|
|
9543
|
+
// ==================== Y-AXIS RENDERING ====================
|
|
9544
|
+
this.renderYAxis(svg, svgYAxisLeft, svgYAxisRight, y, yLineAxis, lineData, self, isria, margin);
|
|
9545
|
+
// ==================== AXIS LABELS ====================
|
|
9546
|
+
this.renderAxisLabels(svg, svgYAxisLeft, svgYAxisRight, metaData, width, height, margin, self, isria, RIGHT_SVG_WIDTH);
|
|
9547
|
+
// ==================== TARGET LINE ====================
|
|
9548
|
+
if (this.chartData.targetLineData) {
|
|
9549
|
+
this.renderTargetLine(svg, svgYAxisRight, y, width, RIGHT_SVG_WIDTH, metaData, self);
|
|
9550
|
+
}
|
|
9551
|
+
// ==================== LINE CHART ====================
|
|
9552
|
+
if (lineData) {
|
|
9553
|
+
this.renderLineChart(svg, lineData, x, lineYscale, metaData, self);
|
|
9554
|
+
}
|
|
9555
|
+
// ==================== ZOOM HANDLING ====================
|
|
9556
|
+
if (this.isZoomedOut) {
|
|
9557
|
+
this.handleZoomOut(svg, height, margin);
|
|
9558
|
+
}
|
|
9559
|
+
}
|
|
9560
|
+
// ==================== HELPER METHODS ====================
|
|
9561
|
+
renderXAxis(svg, x, height, metaData, subgroups, data, shortTickLengthBg, longTickLengthBg, self, isria, isMobile) {
|
|
9562
|
+
let alternate_text = false;
|
|
9563
|
+
if (this.chartConfiguration.isMultiChartGridLine === undefined) {
|
|
9564
|
+
// Normal ticks for dashboard charts
|
|
9565
|
+
svg.append('g')
|
|
8300
9566
|
.attr('class', 'x1 axis1')
|
|
8301
|
-
.attr('transform',
|
|
9567
|
+
.attr('transform', `translate(0,${height})`)
|
|
8302
9568
|
.call(d3.axisBottom(x))
|
|
8303
9569
|
.call((g) => g.select('.domain').remove());
|
|
8304
9570
|
svg.selectAll('g.x1.axis1 g.tick line').remove();
|
|
8305
|
-
|
|
8306
|
-
|
|
8307
|
-
|
|
8308
|
-
|
|
8309
|
-
|
|
8310
|
-
.style('fill', 'var(--chart-text-color)')
|
|
8311
|
-
.attr('y', 32); // Increase distance from bars (default is ~9)
|
|
8312
|
-
}
|
|
8313
|
-
else {
|
|
8314
|
-
svg
|
|
8315
|
-
.selectAll('g.x1.axis1 g.tick text')
|
|
8316
|
-
.attr('class', 'lib-xaxis-labels-texts-drilldown')
|
|
8317
|
-
.style('fill', 'var(--chart-text-color)');
|
|
8318
|
-
}
|
|
9571
|
+
const yOffset = subgroups.length > 1 && !metaData.xLabel ? 32 : 0;
|
|
9572
|
+
svg.selectAll('g.x1.axis1 g.tick text')
|
|
9573
|
+
.attr('class', 'lib-xaxis-labels-texts-drilldown')
|
|
9574
|
+
.style('fill', 'var(--chart-text-color)')
|
|
9575
|
+
.attr('y', yOffset || null);
|
|
8319
9576
|
}
|
|
8320
9577
|
else {
|
|
8321
|
-
|
|
8322
|
-
|
|
8323
|
-
*/
|
|
8324
|
-
/**
|
|
8325
|
-
* draw x axis
|
|
8326
|
-
*/
|
|
8327
|
-
svg
|
|
8328
|
-
.append('g')
|
|
9578
|
+
// Bigger ticks for weekly charts
|
|
9579
|
+
svg.append('g')
|
|
8329
9580
|
.attr('class', 'x1 axis1')
|
|
8330
|
-
.attr('transform',
|
|
9581
|
+
.attr('transform', `translate(0,${height})`)
|
|
8331
9582
|
.call(d3.axisBottom(x).tickSize(0))
|
|
8332
9583
|
.call((g) => g.select('.domain').attr('fill', 'none'));
|
|
8333
|
-
|
|
8334
|
-
* tick line size in alternate fashion
|
|
8335
|
-
*/
|
|
9584
|
+
// Alternate tick line sizes
|
|
8336
9585
|
svg.selectAll('g.x1.axis1 g.tick line').attr('y2', function () {
|
|
8337
|
-
if (alternate_text &&
|
|
8338
|
-
self.chartConfiguration.isNoAlternateXaxisText == undefined) {
|
|
9586
|
+
if (alternate_text && self.chartConfiguration.isNoAlternateXaxisText === undefined) {
|
|
8339
9587
|
alternate_text = false;
|
|
8340
|
-
return
|
|
9588
|
+
return longTickLengthBg - 7;
|
|
8341
9589
|
}
|
|
8342
9590
|
else {
|
|
8343
9591
|
alternate_text = true;
|
|
8344
|
-
return
|
|
9592
|
+
return shortTickLengthBg - 4;
|
|
8345
9593
|
}
|
|
8346
9594
|
});
|
|
8347
|
-
/**
|
|
8348
|
-
* reset the flag so that values can be shown in same alternate fashion
|
|
8349
|
-
*/
|
|
8350
9595
|
alternate_text = false;
|
|
8351
|
-
|
|
8352
|
-
|
|
8353
|
-
* used by weekly charts
|
|
8354
|
-
*/
|
|
8355
|
-
svg
|
|
8356
|
-
.selectAll('g.x1.axis1 g.tick text')
|
|
9596
|
+
// X-axis label texts
|
|
9597
|
+
svg.selectAll('g.x1.axis1 g.tick text')
|
|
8357
9598
|
.attr('class', 'lib-xaxis-labels-texts-weeklycharts')
|
|
8358
9599
|
.attr('y', function () {
|
|
8359
|
-
// Minimize gap in maximized (fullscreen) view for weekly charts
|
|
8360
9600
|
if (self.chartConfiguration.isFullScreen) {
|
|
8361
|
-
return
|
|
9601
|
+
return shortTickLengthBg;
|
|
8362
9602
|
}
|
|
8363
9603
|
if (alternate_text) {
|
|
8364
9604
|
alternate_text = false;
|
|
8365
|
-
return
|
|
9605
|
+
return longTickLengthBg;
|
|
8366
9606
|
}
|
|
8367
9607
|
else {
|
|
8368
9608
|
alternate_text = true;
|
|
8369
|
-
return
|
|
9609
|
+
return shortTickLengthBg;
|
|
8370
9610
|
}
|
|
8371
9611
|
});
|
|
8372
9612
|
}
|
|
9613
|
+
// Apply labels on same line configuration
|
|
8373
9614
|
if (self.chartConfiguration.xLabelsOnSameLine) {
|
|
8374
|
-
|
|
8375
|
-
.selectAll('g.x1.axis1 g.tick text')
|
|
8376
|
-
.attr('class', 'lib-xaxis-labels-texts-drilldown')
|
|
8377
|
-
.style('font-size', this.isHeaderVisible ? '18px' : '14px')
|
|
8378
|
-
.attr('text-anchor', 'middle')
|
|
8379
|
-
.attr('y', function (d) {
|
|
8380
|
-
// For grouped bar charts with many bars and xLabel present, only add 5 if the label is a date
|
|
8381
|
-
if (subgroups.length > 1 && data.length > 8 && metaData.xLabel) {
|
|
8382
|
-
const isDateLabel = /\d{2,4}[-\/]/.test(d);
|
|
8383
|
-
if (self.chartConfiguration.isFullScreen) {
|
|
8384
|
-
return isDateLabel ? short_tick_length_bg + 14 : short_tick_length_bg;
|
|
8385
|
-
}
|
|
8386
|
-
return isDateLabel ? short_tick_length_bg + 14 : short_tick_length_bg;
|
|
8387
|
-
}
|
|
8388
|
-
// For grouped bar charts with many bars and NO xLabel, add space as before, but reduce in fullscreen
|
|
8389
|
-
if (subgroups.length > 1 && data.length > 8 && !metaData.xLabel) {
|
|
8390
|
-
const chartHasExtraBottom = (self.chartConfiguration.margin && self.chartConfiguration.margin.bottom >= 40);
|
|
8391
|
-
if (self.chartConfiguration.isFullScreen) {
|
|
8392
|
-
// Reduce extra gap in maximized view
|
|
8393
|
-
return short_tick_length_bg + 2;
|
|
8394
|
-
}
|
|
8395
|
-
return chartHasExtraBottom ? short_tick_length_bg : short_tick_length_bg + 10;
|
|
8396
|
-
}
|
|
8397
|
-
// Default/fallback logic for other cases
|
|
8398
|
-
let baseY = self.isHeaderVisible ? short_tick_length_bg + 25 : short_tick_length_bg;
|
|
8399
|
-
if (subgroups.length > 1 &&
|
|
8400
|
-
!metaData.xLabel &&
|
|
8401
|
-
(/\d{2,4}[-\/]\d{2}[-\/]\d{2,4}/.test(d) || /\d{2,4}[-\/]\d{2,4}/.test(d))) {
|
|
8402
|
-
baseY = self.isHeaderVisible ? short_tick_length_bg + 15 : short_tick_length_bg + 25;
|
|
8403
|
-
}
|
|
8404
|
-
if (/\d{2,4}[-\/]\d{2,4}/.test(d) && d.indexOf(' ') > -1) {
|
|
8405
|
-
baseY += 4;
|
|
8406
|
-
}
|
|
8407
|
-
// In maximized view, reduce baseY slightly for grouped bars
|
|
8408
|
-
if (self.chartConfiguration.isFullScreen && subgroups.length > 1) {
|
|
8409
|
-
baseY = Math.max(short_tick_length_bg, baseY - 10);
|
|
8410
|
-
}
|
|
8411
|
-
return baseY;
|
|
8412
|
-
})
|
|
8413
|
-
.attr('x', function (d) {
|
|
8414
|
-
if (self.chartData.data.length > 8 && !self.isZoomedOut) {
|
|
8415
|
-
return 1; // Move first line text slightly to the left in zoom-in view for better alignment
|
|
8416
|
-
}
|
|
8417
|
-
return 0; // Default position
|
|
8418
|
-
})
|
|
8419
|
-
.text(function (d) {
|
|
8420
|
-
var isValueToBeIgnored = false;
|
|
8421
|
-
if (isMobile && !self.isHeaderVisible) {
|
|
8422
|
-
let firstPart = d.split(/[\s\-]+/)[0];
|
|
8423
|
-
return firstPart.substring(0, 3).toLowerCase();
|
|
8424
|
-
}
|
|
8425
|
-
data.map((indiv) => {
|
|
8426
|
-
if (indiv.name &&
|
|
8427
|
-
indiv.name.toLowerCase() == d.trim().toLowerCase() &&
|
|
8428
|
-
indiv[metaData.keyList[0]] == -1) {
|
|
8429
|
-
isValueToBeIgnored = true;
|
|
8430
|
-
}
|
|
8431
|
-
});
|
|
8432
|
-
if (isValueToBeIgnored) {
|
|
8433
|
-
return '';
|
|
8434
|
-
}
|
|
8435
|
-
// Always add space before and after hyphen for date range labels, even when header is visible and label is single line
|
|
8436
|
-
// Apply for grouped bar charts and single bar charts, header visible, single line
|
|
8437
|
-
const dateRangeRegex = /(\d{2,4}[-\/]\d{2}[-\/]\d{2,4})\s*-\s*(\d{2,4}[-\/]\d{2}[-\/]\d{2,4})/;
|
|
8438
|
-
if (dateRangeRegex.test(d.trim())) {
|
|
8439
|
-
return d.trim().replace(dateRangeRegex, (m, d1, d2) => `${d1} - ${d2}`);
|
|
8440
|
-
}
|
|
8441
|
-
// Split date and week labels into two lines in grouped bar zoom-in view (and minimized view)
|
|
8442
|
-
const isDateLabel = /\d{2,4}[-\/]/.test(d);
|
|
8443
|
-
const isWeekLabel = /week|wk|w\d+/i.test(d);
|
|
8444
|
-
if (subgroups.length > 1 && !self.isZoomedOut && data.length > 8 && d.indexOf(' ') > -1 && (isDateLabel || isWeekLabel)) {
|
|
8445
|
-
var first = d.substring(0, d.indexOf(' '));
|
|
8446
|
-
var second = d.substring(d.indexOf(' ') + 1).trim();
|
|
8447
|
-
return first + '\n' + second;
|
|
8448
|
-
}
|
|
8449
|
-
// Also keep previous logic for minimized view
|
|
8450
|
-
if (isDateLabel) {
|
|
8451
|
-
if (!self.isHeaderVisible && data.length > 8 && d.indexOf(' ') > -1) {
|
|
8452
|
-
var first = d.substring(0, d.indexOf(' '));
|
|
8453
|
-
var second = d.substring(d.indexOf(' ') + 1).trim();
|
|
8454
|
-
return first + '\n' + second;
|
|
8455
|
-
}
|
|
8456
|
-
else {
|
|
8457
|
-
return d;
|
|
8458
|
-
}
|
|
8459
|
-
}
|
|
8460
|
-
if (d.trim().indexOf(' ') > -1) {
|
|
8461
|
-
return d.trim().substring(0, d.indexOf(' ')).toLowerCase();
|
|
8462
|
-
}
|
|
8463
|
-
return d.toLowerCase();
|
|
8464
|
-
// If label looks like a date (contains digits and - or /)
|
|
8465
|
-
const isDateLabel2 = /\d{2,4}[-\/]/.test(d);
|
|
8466
|
-
// Only split date/week labels if there are many grouped bars and header is not visible
|
|
8467
|
-
if (isDateLabel) {
|
|
8468
|
-
if (!self.isHeaderVisible && data.length > 8 && d.indexOf(' ') > -1) {
|
|
8469
|
-
var first = d.substring(0, d.indexOf(' '));
|
|
8470
|
-
var second = d.substring(d.indexOf(' ') + 1).trim();
|
|
8471
|
-
return first + '\n' + second;
|
|
8472
|
-
}
|
|
8473
|
-
else {
|
|
8474
|
-
return d;
|
|
8475
|
-
}
|
|
8476
|
-
}
|
|
8477
|
-
if (d.trim().indexOf(' ') > -1) {
|
|
8478
|
-
return d.trim().substring(0, d.indexOf(' ')).toLowerCase();
|
|
8479
|
-
}
|
|
8480
|
-
return d.toLowerCase();
|
|
8481
|
-
});
|
|
8482
|
-
// Now apply writing-mode: sideways-lr for grouped charts with date labels in zoomed-out view and many bars
|
|
8483
|
-
xAxisLabels.each(function (d) {
|
|
8484
|
-
// Only apply writing-mode for exact date labels, not those containing 'week' or similar
|
|
8485
|
-
const isDateLabel = /^(\d{2,4}[-\/])?\d{2,4}[-\/]\d{2,4}$/.test(d.trim());
|
|
8486
|
-
const isWeekLabel = /week|wk|w\d+/i.test(d);
|
|
8487
|
-
if (subgroups.length > 1 && self.isZoomedOut && data.length > 8 && isDateLabel && !isWeekLabel) {
|
|
8488
|
-
d3.select(this).style('writing-mode', 'sideways-lr');
|
|
8489
|
-
}
|
|
8490
|
-
});
|
|
8491
|
-
if (!isMobile) {
|
|
8492
|
-
svg
|
|
8493
|
-
.selectAll('g.x1.axis1 g.tick')
|
|
8494
|
-
.filter(function (d) {
|
|
8495
|
-
return !/\d{2,4}[-\/]/.test(d); // Only process non-date labels
|
|
8496
|
-
})
|
|
8497
|
-
.append('text')
|
|
8498
|
-
.attr('class', 'lib-xaxis-labels-texts-drilldown')
|
|
8499
|
-
.attr('y', long_tick_length_bg)
|
|
8500
|
-
.attr('fill', 'var(--chart-text-color)')
|
|
8501
|
-
.attr('x', function (d) {
|
|
8502
|
-
if (self.chartData.data.length > 8 && !self.isZoomedOut) {
|
|
8503
|
-
return 1; // Move text slightly to the left
|
|
8504
|
-
}
|
|
8505
|
-
return 0; // Default position
|
|
8506
|
-
})
|
|
8507
|
-
.text(function (d) {
|
|
8508
|
-
if (d.trim().indexOf(' ') > -1) {
|
|
8509
|
-
return d.trim().substring(d.indexOf(' '), d.length).toLowerCase();
|
|
8510
|
-
}
|
|
8511
|
-
return '';
|
|
8512
|
-
});
|
|
8513
|
-
}
|
|
9615
|
+
this.applyXLabelsOnSameLine(svg, subgroups, data, metaData, self, shortTickLengthBg, isMobile, isria);
|
|
8514
9616
|
}
|
|
9617
|
+
// Mobile override for RIA
|
|
8515
9618
|
if (isria && self.chartData.data.length > 8) {
|
|
8516
|
-
svg
|
|
8517
|
-
.selectAll('g.x1.axis1 g.tick text')
|
|
9619
|
+
svg.selectAll('g.x1.axis1 g.tick text')
|
|
8518
9620
|
.classed('mobile-xaxis-override', true)
|
|
8519
|
-
.text(
|
|
8520
|
-
return d.substring(0, 3);
|
|
8521
|
-
})
|
|
9621
|
+
.text((d) => d.substring(0, 3))
|
|
8522
9622
|
.style('font-size', '12px')
|
|
8523
9623
|
.attr('y', 5)
|
|
8524
9624
|
.attr('x', 5)
|
|
8525
9625
|
.style('text-anchor', 'middle');
|
|
8526
9626
|
}
|
|
9627
|
+
// Mobile override
|
|
8527
9628
|
if (isMobile && !this.isHeaderVisible) {
|
|
8528
|
-
svg
|
|
8529
|
-
.selectAll('g.x1.axis1 g.tick text')
|
|
9629
|
+
svg.selectAll('g.x1.axis1 g.tick text')
|
|
8530
9630
|
.classed('mobile-xaxis-override', true);
|
|
8531
9631
|
}
|
|
8532
|
-
|
|
8533
|
-
|
|
8534
|
-
|
|
8535
|
-
|
|
9632
|
+
}
|
|
9633
|
+
applyXLabelsOnSameLine(svg, subgroups, data, metaData, self, shortTickLengthBg, isMobile, isria) {
|
|
9634
|
+
const xAxisLabels = svg.selectAll('g.x1.axis1 g.tick text')
|
|
9635
|
+
.attr('class', 'lib-xaxis-labels-texts-drilldown')
|
|
9636
|
+
.style('font-size', this.isHeaderVisible ? '18px' : '14px')
|
|
9637
|
+
.attr('text-anchor', 'middle')
|
|
9638
|
+
.attr('y', (d) => this.calculateXLabelYPosition(d, subgroups, data, metaData, self, shortTickLengthBg))
|
|
9639
|
+
.attr('x', (d) => (self.chartData.data.length > 8 && !self.isZoomedOut) ? 1 : 0)
|
|
9640
|
+
.text((d) => this.formatXLabelText(d, data, metaData, subgroups, self, isMobile));
|
|
9641
|
+
// Apply writing-mode for grouped charts with date labels in zoomed-out view
|
|
9642
|
+
xAxisLabels.each(function (d) {
|
|
9643
|
+
const isDateLabel = /^(\d{2,4}[-\/])?\d{2,4}[-\/]\d{2,4}$/.test(d.trim());
|
|
9644
|
+
const isWeekLabel = /week|wk|w\d+/i.test(d);
|
|
9645
|
+
if (subgroups.length > 1 && self.isZoomedOut && data.length > 8 && isDateLabel && !isWeekLabel) {
|
|
9646
|
+
d3.select(this).style('writing-mode', 'sideways-lr');
|
|
9647
|
+
}
|
|
9648
|
+
});
|
|
9649
|
+
// Add second line for non-date labels on desktop
|
|
9650
|
+
if (!isMobile) {
|
|
9651
|
+
svg.selectAll('g.x1.axis1 g.tick')
|
|
9652
|
+
.filter((d) => !/\d{2,4}[-\/]/.test(d))
|
|
9653
|
+
.append('text')
|
|
9654
|
+
.attr('class', 'lib-xaxis-labels-texts-drilldown')
|
|
9655
|
+
.attr('y', 30)
|
|
9656
|
+
.attr('fill', 'var(--chart-text-color)')
|
|
9657
|
+
.attr('x', (d) => (self.chartData.data.length > 8 && !self.isZoomedOut) ? 1 : 0)
|
|
9658
|
+
.text((d) => {
|
|
9659
|
+
if (d.trim().indexOf(' ') > -1) {
|
|
9660
|
+
return d.trim().substring(d.indexOf(' '), d.length).toLowerCase();
|
|
9661
|
+
}
|
|
9662
|
+
return '';
|
|
9663
|
+
});
|
|
9664
|
+
}
|
|
9665
|
+
}
|
|
9666
|
+
calculateXLabelYPosition(d, subgroups, data, metaData, self, shortTickLengthBg) {
|
|
9667
|
+
// For grouped bar charts with many bars and xLabel present
|
|
9668
|
+
if (subgroups.length > 1 && data.length > 8 && metaData.xLabel) {
|
|
9669
|
+
const isDateLabel = /\d{2,4}[-\/]/.test(d);
|
|
9670
|
+
return isDateLabel ? shortTickLengthBg + 14 : shortTickLengthBg;
|
|
9671
|
+
}
|
|
9672
|
+
// For grouped bar charts with many bars and NO xLabel
|
|
9673
|
+
if (subgroups.length > 1 && data.length > 8 && !metaData.xLabel) {
|
|
9674
|
+
const chartHasExtraBottom = self.chartConfiguration.margin && self.chartConfiguration.margin.bottom >= 40;
|
|
9675
|
+
if (self.chartConfiguration.isFullScreen) {
|
|
9676
|
+
return shortTickLengthBg + 2;
|
|
9677
|
+
}
|
|
9678
|
+
return chartHasExtraBottom ? shortTickLengthBg : shortTickLengthBg + 10;
|
|
9679
|
+
}
|
|
9680
|
+
// Default/fallback logic
|
|
9681
|
+
let baseY = self.isHeaderVisible ? shortTickLengthBg + 25 : shortTickLengthBg;
|
|
9682
|
+
if (subgroups.length > 1 && !metaData.xLabel &&
|
|
9683
|
+
(/\d{2,4}[-\/]\d{2}[-\/]\d{2,4}/.test(d) || /\d{2,4}[-\/]\d{2,4}/.test(d))) {
|
|
9684
|
+
baseY = self.isHeaderVisible ? shortTickLengthBg + 15 : shortTickLengthBg + 25;
|
|
9685
|
+
}
|
|
9686
|
+
if (/\d{2,4}[-\/]\d{2,4}/.test(d) && d.indexOf(' ') > -1) {
|
|
9687
|
+
baseY += 4;
|
|
9688
|
+
}
|
|
9689
|
+
if (self.chartConfiguration.isFullScreen && subgroups.length > 1) {
|
|
9690
|
+
baseY = Math.max(shortTickLengthBg, baseY - 10);
|
|
9691
|
+
}
|
|
9692
|
+
return baseY;
|
|
9693
|
+
}
|
|
9694
|
+
formatXLabelText(d, data, metaData, subgroups, self, isMobile) {
|
|
9695
|
+
if (isMobile && !self.isHeaderVisible) {
|
|
9696
|
+
const firstPart = d.split(/[\s\-]+/)[0];
|
|
9697
|
+
return firstPart.substring(0, 3).toLowerCase();
|
|
9698
|
+
}
|
|
9699
|
+
// Check if value should be ignored
|
|
9700
|
+
const isValueToBeIgnored = data.some((indiv) => indiv.name && indiv.name.toLowerCase() === d.trim().toLowerCase() &&
|
|
9701
|
+
indiv[metaData.keyList[0]] === -1);
|
|
9702
|
+
if (isValueToBeIgnored) {
|
|
9703
|
+
return '';
|
|
9704
|
+
}
|
|
9705
|
+
// Handle date range labels
|
|
9706
|
+
const dateRangeRegex = /(\d{2,4}[-\/]\d{2}[-\/]\d{2,4})\s*-\s*(\d{2,4}[-\/]\d{2}[-\/]\d{2,4})/;
|
|
9707
|
+
if (dateRangeRegex.test(d.trim())) {
|
|
9708
|
+
return d.trim().replace(dateRangeRegex, (m, d1, d2) => `${d1} - ${d2}`);
|
|
9709
|
+
}
|
|
9710
|
+
// Split date and week labels into two lines
|
|
9711
|
+
const isDateLabel = /\d{2,4}[-\/]/.test(d);
|
|
9712
|
+
const isWeekLabel = /week|wk|w\d+/i.test(d);
|
|
9713
|
+
if (subgroups.length > 1 && !self.isZoomedOut && data.length > 8 &&
|
|
9714
|
+
d.indexOf(' ') > -1 && (isDateLabel || isWeekLabel)) {
|
|
9715
|
+
const first = d.substring(0, d.indexOf(' '));
|
|
9716
|
+
const second = d.substring(d.indexOf(' ') + 1).trim();
|
|
9717
|
+
return `${first}\n${second}`;
|
|
9718
|
+
}
|
|
9719
|
+
// Handle date labels in minimized view
|
|
9720
|
+
if (isDateLabel) {
|
|
9721
|
+
if (!self.isHeaderVisible && data.length > 8 && d.indexOf(' ') > -1) {
|
|
9722
|
+
const first = d.substring(0, d.indexOf(' '));
|
|
9723
|
+
const second = d.substring(d.indexOf(' ') + 1).trim();
|
|
9724
|
+
return `${first}\n${second}`;
|
|
9725
|
+
}
|
|
9726
|
+
return d;
|
|
9727
|
+
}
|
|
9728
|
+
// Handle labels with spaces
|
|
9729
|
+
if (d.trim().indexOf(' ') > -1) {
|
|
9730
|
+
return d.trim().substring(0, d.indexOf(' ')).toLowerCase();
|
|
9731
|
+
}
|
|
9732
|
+
return d.toLowerCase();
|
|
9733
|
+
}
|
|
9734
|
+
calculateMaxValue(data, keyList) {
|
|
9735
|
+
let maxValue = d3.max(data, (d) => d3.max(keyList, (key) => +d[key]));
|
|
9736
|
+
if (maxValue === 0) {
|
|
8536
9737
|
if (this.chartData.targetLineData) {
|
|
8537
9738
|
maxValue = this.chartData.targetLineData.target + 20;
|
|
8538
9739
|
}
|
|
@@ -8540,661 +9741,401 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
8540
9741
|
maxValue = 100;
|
|
8541
9742
|
}
|
|
8542
9743
|
}
|
|
8543
|
-
|
|
8544
|
-
|
|
8545
|
-
|
|
8546
|
-
|
|
8547
|
-
|
|
8548
|
-
|
|
9744
|
+
return maxValue;
|
|
9745
|
+
}
|
|
9746
|
+
setupLineYScale(lineData, height, self) {
|
|
9747
|
+
let maxLineValue = d3.max(lineData, (d) => +d.value);
|
|
9748
|
+
maxLineValue = maxLineValue * self.chartConfiguration.customYscale;
|
|
9749
|
+
let minLineValue = d3.min(lineData, (d) => +d.value);
|
|
9750
|
+
if (maxLineValue > 0)
|
|
9751
|
+
minLineValue = minLineValue - 3;
|
|
9752
|
+
if (minLineValue > 0)
|
|
9753
|
+
minLineValue = 0;
|
|
9754
|
+
const lineYscale = d3.scaleLinear()
|
|
9755
|
+
.domain([minLineValue, maxLineValue])
|
|
9756
|
+
.range([height, minLineValue]);
|
|
9757
|
+
const yLineAxis = d3.axisRight(lineYscale)
|
|
9758
|
+
.ticks(self.chartConfiguration.numberOfYTicks)
|
|
9759
|
+
.tickSize(0)
|
|
9760
|
+
.tickFormat(self.chartConfiguration.yLineAxisLabelFomatter);
|
|
9761
|
+
return { lineYscale, yLineAxis };
|
|
9762
|
+
}
|
|
9763
|
+
renderGridLines(svg, x, y, height, width, self) {
|
|
9764
|
+
// X-axis grid between labels
|
|
9765
|
+
if (self.chartConfiguration.isXgridBetweenLabels) {
|
|
9766
|
+
svg.append('g')
|
|
9767
|
+
.attr('class', 'grid')
|
|
9768
|
+
.attr('transform', `translate(${x.bandwidth() / 2},${height})`)
|
|
9769
|
+
.call(d3.axisBottom(x).tickSize(-height).tickFormat(''))
|
|
9770
|
+
.style('stroke-dasharray', '5 5')
|
|
9771
|
+
.style('color', 'var(--chart-grid-color, #999999)')
|
|
9772
|
+
.call((g) => g.select('.domain').remove());
|
|
8549
9773
|
}
|
|
8550
|
-
|
|
8551
|
-
|
|
8552
|
-
|
|
8553
|
-
|
|
8554
|
-
|
|
8555
|
-
|
|
8556
|
-
|
|
8557
|
-
y.domain([0, maxValue]).nice();
|
|
8558
|
-
let lineYscale;
|
|
8559
|
-
if (lineData != null) {
|
|
8560
|
-
let maxLineValue = d3.max(lineData, function (d) {
|
|
8561
|
-
return +d.value;
|
|
8562
|
-
});
|
|
8563
|
-
maxLineValue = maxLineValue * this.chartConfiguration.customYscale;
|
|
8564
|
-
let minLineValue = d3.min(lineData, function (d) {
|
|
8565
|
-
return +d.value;
|
|
8566
|
-
});
|
|
8567
|
-
if (maxLineValue > 0)
|
|
8568
|
-
minLineValue = minLineValue - 3;
|
|
8569
|
-
if (minLineValue > 0) {
|
|
8570
|
-
minLineValue = 0;
|
|
8571
|
-
}
|
|
8572
|
-
lineYscale = d3
|
|
8573
|
-
.scaleLinear()
|
|
8574
|
-
.domain([minLineValue, maxLineValue])
|
|
8575
|
-
.range([height, minLineValue]);
|
|
8576
|
-
}
|
|
8577
|
-
let yLineAxis;
|
|
8578
|
-
if (lineYscale != null) {
|
|
8579
|
-
yLineAxis = d3
|
|
8580
|
-
.axisRight(lineYscale)
|
|
8581
|
-
.ticks(self.chartConfiguration.numberOfYTicks)
|
|
8582
|
-
.tickSize(0)
|
|
8583
|
-
.tickFormat(self.chartConfiguration.yLineAxisLabelFomatter);
|
|
8584
|
-
}
|
|
8585
|
-
/**
|
|
8586
|
-
* show x-axis grid between labels
|
|
8587
|
-
* used by weekly charts
|
|
8588
|
-
*/
|
|
8589
|
-
if (self.chartConfiguration.isXgridBetweenLabels) {
|
|
8590
|
-
svg
|
|
8591
|
-
.append('g')
|
|
8592
|
-
.attr('class', 'grid')
|
|
8593
|
-
.attr('transform', 'translate(' + x.bandwidth() / 2 + ',' + height + ')')
|
|
8594
|
-
.call(d3.axisBottom(x).tickSize(-height).tickFormat(''))
|
|
8595
|
-
.style('stroke-dasharray', '5 5')
|
|
8596
|
-
.style('color', 'var(--chart-grid-color, #999999)') // Use CSS variable
|
|
8597
|
-
.call((g) => g.select('.domain').remove());
|
|
8598
|
-
}
|
|
8599
|
-
if (this.chartConfiguration.yAxisGrid) {
|
|
8600
|
-
svg
|
|
8601
|
-
.append('g')
|
|
8602
|
-
.call(d3
|
|
8603
|
-
.axisLeft(y)
|
|
8604
|
-
.ticks(self.chartConfiguration.numberOfYTicks)
|
|
8605
|
-
.tickSize(-width))
|
|
8606
|
-
.style('color', 'var(--chart-axis-color, #B9B9B9)')
|
|
8607
|
-
.style('opacity', '0.5')
|
|
8608
|
-
.call((g) => {
|
|
8609
|
-
g.select('.domain')
|
|
8610
|
-
.remove()
|
|
8611
|
-
.style('stroke', 'var(--chart-domain-color, #000000)'); // Add CSS variable for domain
|
|
8612
|
-
});
|
|
9774
|
+
// Y-axis grid
|
|
9775
|
+
if (this.chartConfiguration.yAxisGrid) {
|
|
9776
|
+
svg.append('g')
|
|
9777
|
+
.call(d3.axisLeft(y).ticks(self.chartConfiguration.numberOfYTicks).tickSize(-width))
|
|
9778
|
+
.style('color', 'var(--chart-axis-color, #B9B9B9)')
|
|
9779
|
+
.style('opacity', '0.5')
|
|
9780
|
+
.call((g) => g.select('.domain').remove().style('stroke', 'var(--chart-domain-color, #000000)'));
|
|
8613
9781
|
}
|
|
8614
9782
|
else {
|
|
8615
|
-
svg
|
|
8616
|
-
.append('g')
|
|
9783
|
+
svg.append('g')
|
|
8617
9784
|
.call(d3.axisLeft(y).ticks(self.chartConfiguration.numberOfYTicks))
|
|
8618
9785
|
.style('color', 'var(--chart-axis-color, #B9B9B9)')
|
|
8619
9786
|
.style('opacity', '0.5')
|
|
8620
|
-
.call((g) =>
|
|
8621
|
-
|
|
8622
|
-
|
|
8623
|
-
.style('stroke-width', '1px'); // Ensure visibility
|
|
8624
|
-
});
|
|
9787
|
+
.call((g) => g.select('.domain')
|
|
9788
|
+
.style('stroke', 'var(--chart-domain-color, #000000)')
|
|
9789
|
+
.style('stroke-width', '1px'));
|
|
8625
9790
|
}
|
|
8626
|
-
|
|
9791
|
+
}
|
|
9792
|
+
setupXSubgroupScale(subgroups, x, self) {
|
|
9793
|
+
const xSubgroup = d3.scaleBand().domain(subgroups);
|
|
8627
9794
|
if (subgroups.length > 1 && !this.isZoomedOut) {
|
|
8628
|
-
// For grouped bar charts in zoom-in view, use full x.bandwidth() for subgroups
|
|
8629
9795
|
xSubgroup.range([0, x.bandwidth()]);
|
|
8630
9796
|
}
|
|
8631
9797
|
else if (subgroups.length === 1 && !this.isZoomedOut) {
|
|
8632
|
-
// For single-bar (non-grouped) charts in zoom-in view, set bar width to 100 (increased from 80)
|
|
8633
9798
|
xSubgroup.range([0, 100]);
|
|
8634
9799
|
}
|
|
8635
|
-
else if (this.chartConfiguration.isMultiChartGridLine
|
|
9800
|
+
else if (this.chartConfiguration.isMultiChartGridLine === undefined) {
|
|
8636
9801
|
xSubgroup.range([0, x.bandwidth()]);
|
|
8637
9802
|
}
|
|
8638
9803
|
else {
|
|
8639
|
-
// used to make grouped bars with lesser width as we are not using padding for width
|
|
8640
9804
|
xSubgroup.range([0, x.bandwidth()]);
|
|
8641
9805
|
}
|
|
8642
|
-
|
|
8643
|
-
|
|
8644
|
-
|
|
8645
|
-
|
|
8646
|
-
.domain(subgroups)
|
|
8647
|
-
.range(Object.values(metaData.colors));
|
|
8648
|
-
// var colorAboveTarget = d3
|
|
8649
|
-
// .scaleOrdinal()
|
|
8650
|
-
// .domain(subgroups)
|
|
8651
|
-
// .range(Object.values(metaData.colorAboveTarget));
|
|
8652
|
-
var state = svg
|
|
8653
|
-
.append('g')
|
|
9806
|
+
return xSubgroup;
|
|
9807
|
+
}
|
|
9808
|
+
renderBars(svg, data, subgroups, x, xSubgroup, y, height, color, metaData, self, leftAndRightSpaces, tempScale, isria) {
|
|
9809
|
+
const state = svg.append('g')
|
|
8654
9810
|
.selectAll('.state')
|
|
8655
9811
|
.data(data)
|
|
8656
9812
|
.enter()
|
|
8657
9813
|
.append('g')
|
|
8658
|
-
.attr('transform',
|
|
8659
|
-
|
|
8660
|
-
|
|
8661
|
-
state
|
|
8662
|
-
.selectAll('rect')
|
|
8663
|
-
.data(function (d) {
|
|
8664
|
-
let newList = [];
|
|
8665
|
-
subgroups.map(function (key) {
|
|
8666
|
-
// if (key !== "group") {
|
|
8667
|
-
let obj = { key: key, value: d[key], name: d.name };
|
|
8668
|
-
newList.push(obj);
|
|
8669
|
-
// }
|
|
8670
|
-
});
|
|
8671
|
-
return newList;
|
|
8672
|
-
})
|
|
9814
|
+
.attr('transform', (d) => `translate(${x(d.name)},0)`);
|
|
9815
|
+
const bars = state.selectAll('rect')
|
|
9816
|
+
.data((d) => this.prepareBarData(d, subgroups))
|
|
8673
9817
|
.enter()
|
|
8674
9818
|
.append('rect')
|
|
8675
9819
|
.attr('class', 'bars')
|
|
8676
|
-
.on('click',
|
|
8677
|
-
|
|
8678
|
-
|
|
8679
|
-
|
|
8680
|
-
|
|
8681
|
-
|
|
8682
|
-
|
|
8683
|
-
|
|
8684
|
-
|
|
8685
|
-
|
|
8686
|
-
|
|
8687
|
-
|
|
8688
|
-
|
|
8689
|
-
|
|
8690
|
-
|
|
8691
|
-
|
|
8692
|
-
|
|
8693
|
-
|
|
8694
|
-
|
|
8695
|
-
|
|
8696
|
-
|
|
8697
|
-
|
|
8698
|
-
|
|
8699
|
-
|
|
8700
|
-
|
|
8701
|
-
|
|
8702
|
-
|
|
8703
|
-
|
|
8704
|
-
}
|
|
8705
|
-
else
|
|
8706
|
-
tempScale.range([
|
|
8707
|
-
0 + (x.bandwidth() - reducedBarWidth) / 2,
|
|
8708
|
-
x.bandwidth() - (x.bandwidth() - reducedBarWidth) / 2,
|
|
8709
|
-
]);
|
|
8710
|
-
}
|
|
8711
|
-
else
|
|
8712
|
-
tempScale.range([
|
|
8713
|
-
0 + (x.bandwidth() - reducedBarWidth) / 2,
|
|
8714
|
-
x.bandwidth() - (x.bandwidth() - reducedBarWidth) / 2,
|
|
8715
|
-
]);
|
|
8716
|
-
}
|
|
8717
|
-
}
|
|
8718
|
-
});
|
|
8719
|
-
return tempScale(d.key);
|
|
8720
|
-
}
|
|
8721
|
-
return xSubgroup(d.key);
|
|
8722
|
-
})
|
|
8723
|
-
.attr('y', function (d) {
|
|
8724
|
-
if (d.value == -1) {
|
|
8725
|
-
return y(0);
|
|
8726
|
-
}
|
|
8727
|
-
if (d.value >= 0) {
|
|
8728
|
-
const barHeight = height - y(d.value);
|
|
8729
|
-
const minHeight = self.chartConfiguration.defaultBarHeight || 2;
|
|
8730
|
-
return barHeight < minHeight ? y(0) - minHeight : y(d.value);
|
|
8731
|
-
}
|
|
8732
|
-
return y(0);
|
|
8733
|
-
})
|
|
8734
|
-
.attr('width', function (d) {
|
|
8735
|
-
// For grouped bar charts in zoom-in view, set bar width to 50 for maximum thickness
|
|
8736
|
-
if (subgroups.length > 1 && !self.isZoomedOut) {
|
|
8737
|
-
return 50;
|
|
8738
|
-
}
|
|
8739
|
-
// For single-bar (non-grouped) charts in zoom-in view, set bar width to 80
|
|
8740
|
-
if (subgroups.length === 1 && !self.isZoomedOut) {
|
|
8741
|
-
return 80;
|
|
8742
|
-
}
|
|
8743
|
-
let tempScale = d3.scaleBand().domain([]).range([0, 0]);
|
|
8744
|
-
// Default logic for other chart types
|
|
8745
|
-
if (self.chartConfiguration.isDrilldownChart) {
|
|
8746
|
-
data.map((indiv) => {
|
|
8747
|
-
if (indiv.name == d.name) {
|
|
8748
|
-
let keys = Object.keys(indiv).filter((temp, i) => i != 0);
|
|
8749
|
-
tempScale = d3.scaleBand().domain(keys).range([0, x.bandwidth()]);
|
|
8750
|
-
if (x.bandwidth() > 100) {
|
|
8751
|
-
// Increase bar width a bit in zoom-in view
|
|
8752
|
-
let reducedBarWidth = 60;
|
|
8753
|
-
if (!self.isZoomedOut) {
|
|
8754
|
-
reducedBarWidth = 100;
|
|
8755
|
-
}
|
|
8756
|
-
if (self.chartData.data.length == 1) {
|
|
8757
|
-
if (Object.keys(self.chartData.data[0]).length == 2) {
|
|
8758
|
-
tempScale.range([
|
|
8759
|
-
0 + (x.bandwidth() - reducedBarWidth) / 2,
|
|
8760
|
-
x.bandwidth() - (x.bandwidth() - reducedBarWidth) / 2,
|
|
8761
|
-
]);
|
|
8762
|
-
}
|
|
8763
|
-
else
|
|
8764
|
-
tempScale.range([
|
|
8765
|
-
0 + (x.bandwidth() - reducedBarWidth) / 2,
|
|
8766
|
-
x.bandwidth() - (x.bandwidth() - reducedBarWidth) / 2,
|
|
8767
|
-
]);
|
|
8768
|
-
}
|
|
8769
|
-
else
|
|
8770
|
-
tempScale.range([
|
|
8771
|
-
0 + (x.bandwidth() - reducedBarWidth) / 2,
|
|
8772
|
-
x.bandwidth() - (x.bandwidth() - reducedBarWidth) / 2,
|
|
8773
|
-
]);
|
|
8774
|
-
}
|
|
8775
|
-
}
|
|
8776
|
-
});
|
|
8777
|
-
return self.isZoomedOut
|
|
8778
|
-
? tempScale.bandwidth()
|
|
8779
|
-
: self.chartData.data.length && self.chartData.data.length > 8
|
|
8780
|
-
? tempScale.bandwidth()
|
|
8781
|
-
: tempScale.bandwidth();
|
|
8782
|
-
}
|
|
8783
|
-
return self.isZoomedOut
|
|
8784
|
-
? tempScale.bandwidth()
|
|
8785
|
-
: self.chartData.data.length && self.chartData.data.length > 8
|
|
8786
|
-
? tempScale.bandwidth()
|
|
8787
|
-
: tempScale.bandwidth();
|
|
8788
|
-
})
|
|
8789
|
-
.attr('height', function (d) {
|
|
8790
|
-
if (d.value == -1) {
|
|
8791
|
-
return height - y(0);
|
|
8792
|
-
}
|
|
8793
|
-
if (d.value >= 0) {
|
|
8794
|
-
const barHeight = height - y(d.value);
|
|
8795
|
-
const minHeight = self.chartConfiguration.defaultBarHeight || 2;
|
|
8796
|
-
return Math.max(barHeight, minHeight);
|
|
9820
|
+
.on('click', (d) => this.handleBarClick(d, metaData, self))
|
|
9821
|
+
.attr('x', (d) => this.calculateBarX(d, data, x, xSubgroup, self, tempScale))
|
|
9822
|
+
.attr('y', (d) => this.calculateBarY(d, y, height, self))
|
|
9823
|
+
.attr('width', (d) => this.calculateBarWidth(d, data, subgroups, x, xSubgroup, self, tempScale))
|
|
9824
|
+
.attr('height', (d) => this.calculateBarHeight(d, y, height, self))
|
|
9825
|
+
.style('cursor', () => (metaData.hasDrillDown && !isria) ? 'pointer' : 'default')
|
|
9826
|
+
.attr('fill', (d) => this.getBarColor(d, metaData, self));
|
|
9827
|
+
// Attach mouse events if not RIA
|
|
9828
|
+
if (!isria && (this.chartConfiguration.displayTitleOnTop ||
|
|
9829
|
+
(this.chartConfiguration.textsOnBar === undefined &&
|
|
9830
|
+
this.chartConfiguration.displayTitleOnTop === undefined))) {
|
|
9831
|
+
bars.on('mouseout', (d, i) => this.handleMouseOut(svg))
|
|
9832
|
+
.on('mouseover', (d, i) => this.handleMouseOver(d, svg, data, x, y, height, metaData, self, leftAndRightSpaces, tempScale));
|
|
9833
|
+
}
|
|
9834
|
+
}
|
|
9835
|
+
prepareBarData(d, subgroups) {
|
|
9836
|
+
const newList = [];
|
|
9837
|
+
subgroups.forEach((key) => {
|
|
9838
|
+
newList.push({ key: key, value: d[key], name: d.name });
|
|
9839
|
+
});
|
|
9840
|
+
return newList;
|
|
9841
|
+
}
|
|
9842
|
+
handleBarClick(d, metaData, self) {
|
|
9843
|
+
if (d.key !== 'Target') {
|
|
9844
|
+
if (!metaData.barWithoutClick || !metaData.barWithoutClick.length ||
|
|
9845
|
+
(!metaData.barWithoutClick.includes(d?.name) &&
|
|
9846
|
+
!metaData.barWithoutClick.includes(d?.key))) {
|
|
9847
|
+
self.handleClick(d);
|
|
8797
9848
|
}
|
|
8798
|
-
|
|
8799
|
-
|
|
8800
|
-
|
|
8801
|
-
|
|
8802
|
-
|
|
8803
|
-
|
|
8804
|
-
|
|
8805
|
-
|
|
8806
|
-
|
|
8807
|
-
|
|
8808
|
-
|
|
8809
|
-
|
|
8810
|
-
|
|
8811
|
-
|
|
8812
|
-
|
|
8813
|
-
|
|
8814
|
-
|
|
9849
|
+
}
|
|
9850
|
+
}
|
|
9851
|
+
calculateBarX(d, data, x, xSubgroup, self, tempScale) {
|
|
9852
|
+
if (self.chartConfiguration.isDrilldownChart) {
|
|
9853
|
+
return this.calculateDrilldownBarX(d, data, x, self, tempScale);
|
|
9854
|
+
}
|
|
9855
|
+
return xSubgroup(d.key);
|
|
9856
|
+
}
|
|
9857
|
+
calculateDrilldownBarX(d, data, x, self, tempScale) {
|
|
9858
|
+
data.forEach((indiv) => {
|
|
9859
|
+
if (indiv.name === d.name) {
|
|
9860
|
+
const keys = Object.keys(indiv).filter((temp, i) => i !== 0);
|
|
9861
|
+
tempScale = d3.scaleBand().domain(keys).range([0, x.bandwidth()]);
|
|
9862
|
+
if (x.bandwidth() > 100) {
|
|
9863
|
+
const reducedBarWidth = self.isZoomedOut ? 60 : 30;
|
|
9864
|
+
const offset = (x.bandwidth() - reducedBarWidth) / 2;
|
|
9865
|
+
tempScale.range([offset, x.bandwidth() - offset]);
|
|
8815
9866
|
}
|
|
8816
9867
|
}
|
|
8817
|
-
return self.chartData.metaData.colors[d.key];
|
|
8818
9868
|
});
|
|
8819
|
-
|
|
8820
|
-
|
|
8821
|
-
|
|
8822
|
-
if (
|
|
8823
|
-
|
|
8824
|
-
|
|
8825
|
-
|
|
8826
|
-
|
|
8827
|
-
|
|
8828
|
-
|
|
8829
|
-
|
|
8830
|
-
|
|
8831
|
-
|
|
8832
|
-
|
|
8833
|
-
|
|
8834
|
-
|
|
8835
|
-
|
|
8836
|
-
|
|
8837
|
-
|
|
8838
|
-
|
|
8839
|
-
|
|
8840
|
-
|
|
8841
|
-
|
|
8842
|
-
|
|
8843
|
-
|
|
8844
|
-
|
|
8845
|
-
|
|
8846
|
-
|
|
8847
|
-
|
|
8848
|
-
|
|
8849
|
-
|
|
8850
|
-
|
|
8851
|
-
|
|
8852
|
-
})
|
|
8853
|
-
.style('font-weight', 'bold')
|
|
8854
|
-
.style('font-size', function (d) {
|
|
8855
|
-
if (self.isZoomedOut) {
|
|
8856
|
-
return '9px'; // 👈 Zoomed out mode
|
|
8857
|
-
}
|
|
8858
|
-
if (self.chartConfiguration.isDrilldownChart) {
|
|
8859
|
-
if (window.innerWidth > 1900) {
|
|
8860
|
-
return '18px';
|
|
8861
|
-
}
|
|
8862
|
-
else if (window.innerWidth < 1400) {
|
|
8863
|
-
return '10px';
|
|
8864
|
-
}
|
|
8865
|
-
else {
|
|
8866
|
-
return '14px';
|
|
8867
|
-
}
|
|
8868
|
-
}
|
|
8869
|
-
else {
|
|
8870
|
-
return '14px';
|
|
8871
|
-
}
|
|
8872
|
-
})
|
|
8873
|
-
.attr('transform', function (d) {
|
|
8874
|
-
data.map((indiv) => {
|
|
8875
|
-
if (indiv.name == d.name) {
|
|
8876
|
-
let keys = Object.keys(indiv).filter((temp, i) => i != 0);
|
|
8877
|
-
var temp;
|
|
8878
|
-
tempScale = d3.scaleBand().domain(keys).range([0, x.bandwidth()]);
|
|
8879
|
-
if (x.bandwidth() > 100) {
|
|
8880
|
-
if (self.chartData.data.length == 1) {
|
|
8881
|
-
if (Object.keys(self.chartData.data[0]).length == 2) {
|
|
8882
|
-
tempScale.range([
|
|
8883
|
-
0 + (x.bandwidth() - 200) / 2,
|
|
8884
|
-
x.bandwidth() - (x.bandwidth() - 200) / 2,
|
|
8885
|
-
]);
|
|
8886
|
-
// .padding(0.05);
|
|
8887
|
-
}
|
|
8888
|
-
else
|
|
8889
|
-
tempScale.range([
|
|
8890
|
-
0 + (x.bandwidth() - 300) / 2,
|
|
8891
|
-
x.bandwidth() - (x.bandwidth() - 300) / 2,
|
|
8892
|
-
]);
|
|
8893
|
-
// .padding(0.05);
|
|
8894
|
-
}
|
|
8895
|
-
else
|
|
8896
|
-
tempScale.range([
|
|
8897
|
-
0 + (x.bandwidth() - 125) / 2,
|
|
8898
|
-
x.bandwidth() - (x.bandwidth() - 125) / 2,
|
|
8899
|
-
]);
|
|
8900
|
-
}
|
|
9869
|
+
return tempScale(d.key);
|
|
9870
|
+
}
|
|
9871
|
+
calculateBarY(d, y, height, self) {
|
|
9872
|
+
if (d.value === -1) {
|
|
9873
|
+
return y(0);
|
|
9874
|
+
}
|
|
9875
|
+
if (d.value >= 0) {
|
|
9876
|
+
const barHeight = height - y(d.value);
|
|
9877
|
+
const minHeight = self.chartConfiguration.defaultBarHeight || 2;
|
|
9878
|
+
return barHeight < minHeight ? y(0) - minHeight : y(d.value);
|
|
9879
|
+
}
|
|
9880
|
+
return y(0);
|
|
9881
|
+
}
|
|
9882
|
+
calculateBarWidth(d, data, subgroups, x, xSubgroup, self, tempScale) {
|
|
9883
|
+
// For grouped bar charts in zoom-in view
|
|
9884
|
+
if (subgroups.length > 1 && !self.isZoomedOut) {
|
|
9885
|
+
return 50;
|
|
9886
|
+
}
|
|
9887
|
+
// For single-bar charts in zoom-in view
|
|
9888
|
+
if (subgroups.length === 1 && !self.isZoomedOut) {
|
|
9889
|
+
return 80;
|
|
9890
|
+
}
|
|
9891
|
+
// Default logic for drilldown charts
|
|
9892
|
+
if (self.chartConfiguration.isDrilldownChart) {
|
|
9893
|
+
let calculatedScale = d3.scaleBand().domain([]).range([0, 0]);
|
|
9894
|
+
data.forEach((indiv) => {
|
|
9895
|
+
if (indiv.name === d.name) {
|
|
9896
|
+
const keys = Object.keys(indiv).filter((temp, i) => i !== 0);
|
|
9897
|
+
calculatedScale = d3.scaleBand().domain(keys).range([0, x.bandwidth()]);
|
|
9898
|
+
if (x.bandwidth() > 100) {
|
|
9899
|
+
const reducedBarWidth = self.isZoomedOut ? 60 : 100;
|
|
9900
|
+
const offset = (x.bandwidth() - reducedBarWidth) / 2;
|
|
9901
|
+
calculatedScale.range([offset, x.bandwidth() - offset]);
|
|
8901
9902
|
}
|
|
8902
|
-
});
|
|
8903
|
-
/**
|
|
8904
|
-
* if set, then all texts ll be horizontal
|
|
8905
|
-
*/
|
|
8906
|
-
if (self.chartConfiguration.textAlwaysHorizontal) {
|
|
8907
|
-
return ('translate(' + xSubgroup(d.key) + ',' + (y(d.value) - 3) + ')');
|
|
8908
9903
|
}
|
|
8909
|
-
/**
|
|
8910
|
-
* rotate texts having more than one digits
|
|
8911
|
-
*/
|
|
8912
|
-
// if (d.value > 9)
|
|
8913
|
-
if (!isNaN(tempScale(d.key)))
|
|
8914
|
-
return ('translate(' +
|
|
8915
|
-
(tempScale(d.key) + tempScale.bandwidth() * 0.55) +
|
|
8916
|
-
',' +
|
|
8917
|
-
(y(0) - 10) +
|
|
8918
|
-
') rotate(270)');
|
|
8919
|
-
return 'translate(0,0)';
|
|
8920
|
-
// else
|
|
8921
|
-
// return (
|
|
8922
|
-
// 'translate(' +
|
|
8923
|
-
// (tempScale(d.key) + tempScale.bandwidth() / 2) +
|
|
8924
|
-
// ',' +
|
|
8925
|
-
// y(0) +
|
|
8926
|
-
// ')'
|
|
8927
|
-
// );
|
|
8928
|
-
})
|
|
8929
|
-
.on('click', function (d) {
|
|
8930
|
-
if (!metaData.barWithoutClick ||
|
|
8931
|
-
!metaData.barWithoutClick.length ||
|
|
8932
|
-
(!metaData.barWithoutClick.includes(d?.name) &&
|
|
8933
|
-
!metaData.barWithoutClick.includes(d?.key)))
|
|
8934
|
-
self.handleClick(d);
|
|
8935
9904
|
});
|
|
8936
|
-
|
|
8937
|
-
state
|
|
8938
|
-
.selectAll('.lib-data-labels-weeklycharts')
|
|
8939
|
-
.on('mouseout', handleMouseOut)
|
|
8940
|
-
.on('mouseover', handleMouseOver);
|
|
8941
|
-
}
|
|
9905
|
+
return calculatedScale.bandwidth();
|
|
8942
9906
|
}
|
|
8943
|
-
|
|
8944
|
-
|
|
8945
|
-
|
|
8946
|
-
|
|
8947
|
-
|
|
8948
|
-
|
|
8949
|
-
|
|
9907
|
+
return xSubgroup.bandwidth();
|
|
9908
|
+
}
|
|
9909
|
+
calculateBarHeight(d, y, height, self) {
|
|
9910
|
+
if (d.value === -1) {
|
|
9911
|
+
return height - y(0);
|
|
9912
|
+
}
|
|
9913
|
+
if (d.value >= 0) {
|
|
9914
|
+
const barHeight = height - y(d.value);
|
|
9915
|
+
const minHeight = self.chartConfiguration.defaultBarHeight || 2;
|
|
9916
|
+
return Math.max(barHeight, minHeight);
|
|
9917
|
+
}
|
|
9918
|
+
return height - y(0);
|
|
9919
|
+
}
|
|
9920
|
+
getBarColor(d, metaData, self) {
|
|
9921
|
+
if (d.value && self.chartData.targetLineData &&
|
|
9922
|
+
d.value >= parseFloat(self.chartData.targetLineData.target) &&
|
|
9923
|
+
self.chartData.metaData.colorAboveTarget) {
|
|
9924
|
+
const key = d.key.toLowerCase();
|
|
9925
|
+
const colorAboveTarget = Object.keys(self.chartData.metaData.colorAboveTarget)
|
|
9926
|
+
.find(k => k.toLowerCase() === key);
|
|
9927
|
+
if (colorAboveTarget) {
|
|
9928
|
+
return self.chartData.metaData.colorAboveTarget[colorAboveTarget];
|
|
8950
9929
|
}
|
|
8951
9930
|
}
|
|
8952
|
-
|
|
8953
|
-
|
|
8954
|
-
|
|
8955
|
-
|
|
8956
|
-
|
|
8957
|
-
|
|
8958
|
-
|
|
8959
|
-
|
|
8960
|
-
|
|
8961
|
-
|
|
8962
|
-
|
|
8963
|
-
|
|
8964
|
-
|
|
8965
|
-
|
|
8966
|
-
|
|
8967
|
-
|
|
8968
|
-
|
|
8969
|
-
|
|
8970
|
-
|
|
8971
|
-
|
|
8972
|
-
|
|
8973
|
-
|
|
8974
|
-
|
|
8975
|
-
|
|
8976
|
-
|
|
8977
|
-
|
|
8978
|
-
|
|
8979
|
-
|
|
8980
|
-
|
|
8981
|
-
|
|
8982
|
-
|
|
8983
|
-
|
|
8984
|
-
|
|
8985
|
-
|
|
8986
|
-
|
|
8987
|
-
|
|
8988
|
-
|
|
8989
|
-
|
|
8990
|
-
|
|
8991
|
-
|
|
8992
|
-
|
|
8993
|
-
|
|
8994
|
-
|
|
8995
|
-
|
|
8996
|
-
|
|
8997
|
-
|
|
8998
|
-
.
|
|
8999
|
-
|
|
9000
|
-
|
|
9001
|
-
|
|
9002
|
-
|
|
9003
|
-
return d.class;
|
|
9004
|
-
})
|
|
9005
|
-
.attr('width', function () {
|
|
9006
|
-
data.map((indiv) => {
|
|
9007
|
-
if (indiv.name == d.name) {
|
|
9008
|
-
let keys = Object.keys(indiv).filter((temp, i) => i != 0);
|
|
9009
|
-
tempScale = d3.scaleBand().domain(keys).range([0, x.bandwidth()]);
|
|
9010
|
-
if (x.bandwidth() > 100) {
|
|
9011
|
-
if (self.chartData.data.length == 1) {
|
|
9012
|
-
if (Object.keys(self.chartData.data[0]).length == 2) {
|
|
9013
|
-
tempScale.range([
|
|
9014
|
-
0 + (x.bandwidth() - 200) / 2,
|
|
9015
|
-
x.bandwidth() - (x.bandwidth() - 200) / 2,
|
|
9016
|
-
]);
|
|
9017
|
-
}
|
|
9018
|
-
else
|
|
9019
|
-
tempScale.range([
|
|
9020
|
-
0 + (x.bandwidth() - 300) / 2,
|
|
9021
|
-
x.bandwidth() - (x.bandwidth() - 300) / 2,
|
|
9022
|
-
]);
|
|
9023
|
-
}
|
|
9024
|
-
else
|
|
9025
|
-
tempScale.range([
|
|
9026
|
-
0 + (x.bandwidth() - 125) / 2,
|
|
9027
|
-
x.bandwidth() - (x.bandwidth() - 125) / 2,
|
|
9028
|
-
]);
|
|
9029
|
-
}
|
|
9030
|
-
}
|
|
9031
|
-
});
|
|
9032
|
-
if (metaData.hasDrillDown) {
|
|
9033
|
-
if (tempScale.bandwidth() + leftAndRightSpaces * 2 > 180) {
|
|
9034
|
-
return '180px';
|
|
9931
|
+
return self.chartData.metaData.colors[d.key];
|
|
9932
|
+
}
|
|
9933
|
+
renderBarLabels(svg, data, subgroups, x, xSubgroup, y, height, metaData, self, tempScale, isria) {
|
|
9934
|
+
const state = svg.selectAll('.state');
|
|
9935
|
+
const labels = state.selectAll('text')
|
|
9936
|
+
.data((d) => this.prepareBarData(d, subgroups))
|
|
9937
|
+
.enter()
|
|
9938
|
+
.append('text')
|
|
9939
|
+
.attr('fill', 'var(--chart-text-color)')
|
|
9940
|
+
.attr('x', 0)
|
|
9941
|
+
.attr('y', 0)
|
|
9942
|
+
.attr('class', 'lib-data-labels-weeklycharts')
|
|
9943
|
+
.text((d) => this.formatBarLabel(d))
|
|
9944
|
+
.style('fill', '#000')
|
|
9945
|
+
.style('font-weight', 'bold')
|
|
9946
|
+
.style('font-size', (d) => this.calculateLabelFontSize(self))
|
|
9947
|
+
.attr('transform', (d) => this.calculateLabelTransform(d, data, x, xSubgroup, y, self, tempScale))
|
|
9948
|
+
.on('click', (d) => this.handleBarClick(d, metaData, self));
|
|
9949
|
+
if (!isria) {
|
|
9950
|
+
labels.on('mouseout', () => this.handleMouseOut(svg))
|
|
9951
|
+
.on('mouseover', (d) => this.handleMouseOver(d, svg, data, x, y, height, metaData, self, 50, tempScale));
|
|
9952
|
+
}
|
|
9953
|
+
}
|
|
9954
|
+
formatBarLabel(d) {
|
|
9955
|
+
if (!d.key || !d.value)
|
|
9956
|
+
return '';
|
|
9957
|
+
return d.key.length > 20 ? d.key.substring(0, 17) + '...' : d.key;
|
|
9958
|
+
}
|
|
9959
|
+
calculateLabelFontSize(self) {
|
|
9960
|
+
if (self.isZoomedOut)
|
|
9961
|
+
return '9px';
|
|
9962
|
+
if (self.chartConfiguration.isDrilldownChart) {
|
|
9963
|
+
if (window.innerWidth > 1900)
|
|
9964
|
+
return '18px';
|
|
9965
|
+
if (window.innerWidth < 1400)
|
|
9966
|
+
return '10px';
|
|
9967
|
+
return '14px';
|
|
9968
|
+
}
|
|
9969
|
+
return '14px';
|
|
9970
|
+
}
|
|
9971
|
+
calculateLabelTransform(d, data, x, xSubgroup, y, self, tempScale) {
|
|
9972
|
+
let calculatedScale;
|
|
9973
|
+
data.forEach((indiv) => {
|
|
9974
|
+
if (indiv.name === d.name) {
|
|
9975
|
+
const keys = Object.keys(indiv).filter((temp, i) => i !== 0);
|
|
9976
|
+
calculatedScale = d3.scaleBand().domain(keys).range([0, x.bandwidth()]);
|
|
9977
|
+
if (x.bandwidth() > 100) {
|
|
9978
|
+
if (self.chartData.data.length === 1) {
|
|
9979
|
+
const reducedWidth = Object.keys(self.chartData.data[0]).length === 2 ? 200 : 300;
|
|
9980
|
+
const offset = (x.bandwidth() - reducedWidth) / 2;
|
|
9981
|
+
calculatedScale.range([offset, x.bandwidth() - offset]);
|
|
9035
9982
|
}
|
|
9036
|
-
|
|
9037
|
-
|
|
9038
|
-
|
|
9039
|
-
|
|
9040
|
-
|
|
9041
|
-
|
|
9042
|
-
|
|
9043
|
-
|
|
9044
|
-
|
|
9045
|
-
|
|
9046
|
-
|
|
9047
|
-
|
|
9048
|
-
|
|
9049
|
-
|
|
9050
|
-
|
|
9051
|
-
|
|
9052
|
-
|
|
9053
|
-
|
|
9054
|
-
|
|
9055
|
-
|
|
9056
|
-
|
|
9057
|
-
|
|
9058
|
-
|
|
9059
|
-
|
|
9060
|
-
|
|
9983
|
+
else {
|
|
9984
|
+
const offset = (x.bandwidth() - 125) / 2;
|
|
9985
|
+
calculatedScale.range([offset, x.bandwidth() - offset]);
|
|
9986
|
+
}
|
|
9987
|
+
}
|
|
9988
|
+
}
|
|
9989
|
+
});
|
|
9990
|
+
if (self.chartConfiguration.textAlwaysHorizontal) {
|
|
9991
|
+
return `translate(${xSubgroup(d.key)},${y(d.value) - 3})`;
|
|
9992
|
+
}
|
|
9993
|
+
if (!isNaN(calculatedScale(d.key))) {
|
|
9994
|
+
return `translate(${calculatedScale(d.key) + calculatedScale.bandwidth() * 0.55},${y(0) - 10}) rotate(270)`;
|
|
9995
|
+
}
|
|
9996
|
+
return 'translate(0,0)';
|
|
9997
|
+
}
|
|
9998
|
+
handleMouseOver(d, svg, data, x, y, height, metaData, self, leftAndRightSpaces, tempScale) {
|
|
9999
|
+
svg.selectAll('.lib-verticalstack-title-ontop').remove();
|
|
10000
|
+
let calculatedScale;
|
|
10001
|
+
let elementsCounter;
|
|
10002
|
+
data.forEach((indiv) => {
|
|
10003
|
+
if (indiv.name === d.name) {
|
|
10004
|
+
const keys = Object.keys(indiv).filter((temp, i) => i !== 0);
|
|
10005
|
+
elementsCounter = keys.length;
|
|
10006
|
+
calculatedScale = d3.scaleBand().domain(keys).range([0, x.bandwidth()]);
|
|
10007
|
+
if (x.bandwidth() > 100) {
|
|
10008
|
+
if (self.chartData.data.length === 1) {
|
|
10009
|
+
const reducedWidth = Object.keys(self.chartData.data[0]).length === 2 ? 200 : 300;
|
|
10010
|
+
const offset = (x.bandwidth() - reducedWidth) / 2;
|
|
10011
|
+
calculatedScale.range([offset, x.bandwidth() - offset]);
|
|
10012
|
+
}
|
|
10013
|
+
else {
|
|
10014
|
+
const offset = (x.bandwidth() - 125) / 2;
|
|
10015
|
+
calculatedScale.range([offset, x.bandwidth() - offset]);
|
|
10016
|
+
}
|
|
10017
|
+
}
|
|
10018
|
+
}
|
|
10019
|
+
});
|
|
10020
|
+
const xPosition = this.calculateTooltipX(d, x, calculatedScale, metaData, leftAndRightSpaces);
|
|
10021
|
+
const width = this.calculateTooltipWidth(calculatedScale, metaData, leftAndRightSpaces);
|
|
10022
|
+
svg.append('foreignObject')
|
|
10023
|
+
.attr('x', xPosition)
|
|
10024
|
+
.attr('class', 'lib-verticalstack-title-ontop')
|
|
10025
|
+
.attr('y', y(d.value) - 3 - 40 - 10)
|
|
10026
|
+
.attr('dy', d.class)
|
|
10027
|
+
.attr('width', width)
|
|
10028
|
+
.attr('height', 50)
|
|
10029
|
+
.append('xhtml:div')
|
|
10030
|
+
.attr('class', 'title')
|
|
10031
|
+
.style('z-index', 99)
|
|
10032
|
+
.html(() => this.generateTooltipHTML(d, metaData));
|
|
10033
|
+
}
|
|
10034
|
+
calculateTooltipX(d, x, calculatedScale, metaData, leftAndRightSpaces) {
|
|
10035
|
+
if (metaData.hasDrillDown) {
|
|
10036
|
+
if (calculatedScale.bandwidth() + leftAndRightSpaces * 2 > 180) {
|
|
10037
|
+
return x(d.name) + calculatedScale(d.key) + calculatedScale.bandwidth() / 2 - 90;
|
|
10038
|
+
}
|
|
10039
|
+
return x(d.name) + calculatedScale(d.key) -
|
|
10040
|
+
(calculatedScale.bandwidth() + leftAndRightSpaces * 2) / 2 +
|
|
10041
|
+
calculatedScale.bandwidth() / 2;
|
|
10042
|
+
}
|
|
10043
|
+
return x(d.name) + calculatedScale(d.key) -
|
|
10044
|
+
(calculatedScale.bandwidth() + leftAndRightSpaces * 2) / 2 +
|
|
10045
|
+
calculatedScale.bandwidth() / 2;
|
|
10046
|
+
}
|
|
10047
|
+
calculateTooltipWidth(calculatedScale, metaData, leftAndRightSpaces) {
|
|
10048
|
+
if (metaData.hasDrillDown) {
|
|
10049
|
+
if (calculatedScale.bandwidth() + leftAndRightSpaces * 2 > 180) {
|
|
10050
|
+
return '180px';
|
|
10051
|
+
}
|
|
10052
|
+
return calculatedScale.bandwidth() + leftAndRightSpaces * 2;
|
|
9061
10053
|
}
|
|
9062
|
-
|
|
9063
|
-
|
|
9064
|
-
|
|
9065
|
-
|
|
9066
|
-
|
|
9067
|
-
|
|
9068
|
-
|
|
9069
|
-
|
|
9070
|
-
|
|
9071
|
-
|
|
10054
|
+
return calculatedScale.bandwidth() + leftAndRightSpaces * 2;
|
|
10055
|
+
}
|
|
10056
|
+
generateTooltipHTML(d, metaData) {
|
|
10057
|
+
const barLabel = d.key;
|
|
10058
|
+
const dataType = metaData.dataType || '';
|
|
10059
|
+
const value = d.value;
|
|
10060
|
+
let html = `<span class="title-bar-name">${barLabel}</span>`;
|
|
10061
|
+
html += `<span class="title-bar-value"><span>${value}</span>${dataType}</span>`;
|
|
10062
|
+
return html;
|
|
10063
|
+
}
|
|
10064
|
+
handleMouseOut(svg) {
|
|
10065
|
+
svg.selectAll('.lib-verticalstack-title-ontop').remove();
|
|
10066
|
+
}
|
|
10067
|
+
renderYAxis(svg, svgYAxisLeft, svgYAxisRight, y, yLineAxis, lineData, self, isria, margin) {
|
|
10068
|
+
// Hidden y-axis for reference
|
|
10069
|
+
svg.append('g')
|
|
9072
10070
|
.attr('class', 'lib-stacked-y-axis-text yaxis-dashed')
|
|
9073
10071
|
.attr('style', self.chartConfiguration.yAxisCustomTextStyles)
|
|
9074
10072
|
.attr('transform', 'translate(0,0)')
|
|
9075
10073
|
.call(y)
|
|
9076
10074
|
.style('display', 'none');
|
|
9077
|
-
|
|
9078
|
-
|
|
10075
|
+
// Left y-axis
|
|
10076
|
+
svgYAxisLeft.append('g')
|
|
9079
10077
|
.append('g')
|
|
9080
10078
|
.attr('class', 'lib-yaxis-labels-texts-drilldown yaxis-dashed')
|
|
9081
10079
|
.attr('style', self.chartConfiguration.yAxisCustomTextStyles)
|
|
9082
10080
|
.attr('transform', 'translate(0,0)')
|
|
9083
|
-
.call(d3
|
|
9084
|
-
.axisLeft(y)
|
|
10081
|
+
.call(d3.axisLeft(y)
|
|
9085
10082
|
.tickSize(0)
|
|
9086
10083
|
.ticks(self.chartConfiguration.numberOfYTicks)
|
|
9087
|
-
.tickFormat(
|
|
10084
|
+
.tickFormat((d) => {
|
|
9088
10085
|
const formatted = self.chartConfiguration.yAxisLabelFomatter
|
|
9089
10086
|
? self.chartConfiguration.yAxisLabelFomatter(d)
|
|
9090
10087
|
: d;
|
|
9091
10088
|
return formatted >= 1000 ? formatted / 1000 + 'k' : formatted;
|
|
9092
10089
|
}))
|
|
9093
10090
|
.call((g) => {
|
|
9094
|
-
// Style the domain line for theme support
|
|
9095
10091
|
g.select('.domain')
|
|
9096
10092
|
.style('stroke', 'var(--chart-domain-color, #000000)')
|
|
9097
10093
|
.style('stroke-width', '1px');
|
|
9098
10094
|
})
|
|
9099
10095
|
.selectAll('text')
|
|
9100
10096
|
.style('fill', 'var(--chart-text-color)');
|
|
9101
|
-
|
|
9102
|
-
|
|
10097
|
+
// Right y-axis (hidden by default)
|
|
10098
|
+
svgYAxisRight.append('g')
|
|
9103
10099
|
.attr('class', 'lib-yaxis-labels-texts-drilldown yaxis-dashed')
|
|
9104
10100
|
.attr('style', self.chartConfiguration.yAxisCustomTextStyles)
|
|
9105
10101
|
.attr('transform', 'translate(0,0)')
|
|
9106
10102
|
.call(y)
|
|
9107
10103
|
.style('display', 'none');
|
|
9108
|
-
|
|
9109
|
-
|
|
9110
|
-
|
|
9111
|
-
|
|
9112
|
-
|
|
9113
|
-
|
|
9114
|
-
|
|
9115
|
-
d3.selectAll('g.lib-line-x-axis-text > g > text').attr('class', 'lib-display-hidden');
|
|
10104
|
+
// Line chart axis if applicable
|
|
10105
|
+
if (lineData != null && lineData && self.chartConfiguration.showLineChartAxis) {
|
|
10106
|
+
svgYAxisRight.append('g')
|
|
10107
|
+
.attr('class', 'lib-stacked-y-axis-text1')
|
|
10108
|
+
.attr('style', self.chartConfiguration.yAxisCustomTextStyles)
|
|
10109
|
+
.attr('transform', 'translate(0,0)')
|
|
10110
|
+
.call(yLineAxis);
|
|
9116
10111
|
}
|
|
9117
|
-
|
|
9118
|
-
|
|
9119
|
-
|
|
9120
|
-
|
|
9121
|
-
if (
|
|
9122
|
-
|
|
9123
|
-
|
|
10112
|
+
// Apply axis visibility configurations
|
|
10113
|
+
this.applyAxisVisibilityConfig(self);
|
|
10114
|
+
}
|
|
10115
|
+
applyAxisVisibilityConfig(self) {
|
|
10116
|
+
if (self.chartConfiguration.isXaxisLabelHidden) {
|
|
10117
|
+
d3.selectAll('g.lib-line-x-axis-text > g > text')
|
|
10118
|
+
.attr('class', 'lib-display-hidden');
|
|
9124
10119
|
}
|
|
9125
|
-
|
|
9126
|
-
|
|
9127
|
-
|
|
9128
|
-
*/
|
|
9129
|
-
if (this.chartConfiguration.isYaxisHidden != undefined &&
|
|
9130
|
-
this.chartConfiguration.isYaxisHidden) {
|
|
9131
|
-
d3.selectAll('.yaxis-dashed').attr('class', 'lib-display-hidden');
|
|
10120
|
+
if (self.chartConfiguration.isYaxisLabelHidden) {
|
|
10121
|
+
d3.selectAll('.yaxis-dashed > g > text')
|
|
10122
|
+
.attr('class', 'lib-display-hidden');
|
|
9132
10123
|
}
|
|
9133
|
-
|
|
9134
|
-
* dashed y axis
|
|
9135
|
-
* used by weekly charts
|
|
9136
|
-
*/
|
|
9137
|
-
if (this.chartConfiguration.isYaxisDashed != undefined &&
|
|
9138
|
-
this.chartConfiguration.isYaxisDashed) {
|
|
10124
|
+
if (self.chartConfiguration.isYaxisHidden) {
|
|
9139
10125
|
d3.selectAll('.yaxis-dashed')
|
|
9140
|
-
.
|
|
9141
|
-
.style('color', 'var(--chart-axis-color, #999999)'); // Use CSS variable
|
|
9142
|
-
}
|
|
9143
|
-
if (lineData != null) {
|
|
9144
|
-
if (lineData && self.chartConfiguration.showLineChartAxis) {
|
|
9145
|
-
svgYAxisRight
|
|
9146
|
-
.append('g')
|
|
9147
|
-
.attr('class', 'lib-stacked-y-axis-text1')
|
|
9148
|
-
.attr('style', self.chartConfiguration.yAxisCustomTextStyles)
|
|
9149
|
-
.attr('transform', 'translate(' + 0 + ',0)')
|
|
9150
|
-
.call(yLineAxis);
|
|
9151
|
-
}
|
|
10126
|
+
.attr('class', 'lib-display-hidden');
|
|
9152
10127
|
}
|
|
9153
|
-
|
|
9154
|
-
|
|
9155
|
-
|
|
9156
|
-
|
|
9157
|
-
// svg
|
|
9158
|
-
// .selectAll('.lib-xaxis-labels-texts-drilldown')
|
|
9159
|
-
// .attr('class', 'lib-display-hidden');
|
|
9160
|
-
// }
|
|
9161
|
-
if (this.isZoomedOut) {
|
|
9162
|
-
svg
|
|
9163
|
-
.selectAll('.lib-xaxis-labels-texts-drilldown')
|
|
9164
|
-
.each((d, i, nodes) => {
|
|
9165
|
-
const text = d3.select(nodes[i]);
|
|
9166
|
-
const label = text.text();
|
|
9167
|
-
if (label.indexOf('\n') > -1) {
|
|
9168
|
-
const lines = label.split('\n');
|
|
9169
|
-
text.text(null);
|
|
9170
|
-
lines.forEach((line, idx) => {
|
|
9171
|
-
text.append('tspan')
|
|
9172
|
-
.text(line)
|
|
9173
|
-
.attr('x', 0)
|
|
9174
|
-
.attr('dy', idx === 0 ? '1em' : '1.1em');
|
|
9175
|
-
});
|
|
9176
|
-
}
|
|
9177
|
-
else {
|
|
9178
|
-
const words = label.split(' ');
|
|
9179
|
-
text.text(null);
|
|
9180
|
-
words.forEach((word, index) => {
|
|
9181
|
-
text.append('tspan').text(word);
|
|
9182
|
-
});
|
|
9183
|
-
}
|
|
9184
|
-
})
|
|
9185
|
-
.style('fill', 'var(--chart-text-color)')
|
|
9186
|
-
.attr('transform', null);
|
|
9187
|
-
svg
|
|
9188
|
-
.select('.x-axis')
|
|
9189
|
-
.attr('transform', `translate(0, ${height - margin.bottom + 10})`);
|
|
10128
|
+
if (self.chartConfiguration.isYaxisDashed) {
|
|
10129
|
+
d3.selectAll('.yaxis-dashed')
|
|
10130
|
+
.style('stroke-dasharray', '5 5')
|
|
10131
|
+
.style('color', 'var(--chart-axis-color, #999999)');
|
|
9190
10132
|
}
|
|
9191
|
-
|
|
9192
|
-
|
|
9193
|
-
|
|
10133
|
+
}
|
|
10134
|
+
renderAxisLabels(svg, svgYAxisLeft, svgYAxisRight, metaData, width, height, margin, self, isria, rightSvgWidth) {
|
|
10135
|
+
// Y-axis label
|
|
9194
10136
|
if (metaData.yLabel) {
|
|
9195
10137
|
const yPosition = isria ? 0 - margin.left / 2 - 30 : 0 - margin.left / 2 - 40;
|
|
9196
|
-
svgYAxisLeft
|
|
9197
|
-
.append('text')
|
|
10138
|
+
svgYAxisLeft.append('text')
|
|
9198
10139
|
.attr('class', 'lib-axis-group-label font-size-1')
|
|
9199
10140
|
.attr('style', self.chartConfiguration.yAxisCustomlabelStyles)
|
|
9200
10141
|
.attr('transform', 'rotate(-90)')
|
|
@@ -9204,170 +10145,155 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
9204
10145
|
.style('text-anchor', 'middle')
|
|
9205
10146
|
.attr('fill', 'var(--chart-text-color)');
|
|
9206
10147
|
if (this.chartConfiguration.isMultiChartGridLine === undefined) {
|
|
9207
|
-
svgYAxisLeft
|
|
9208
|
-
.selectAll('.lib-axis-group-label')
|
|
10148
|
+
svgYAxisLeft.selectAll('.lib-axis-group-label')
|
|
9209
10149
|
.style('font-size', 'smaller')
|
|
9210
10150
|
.text(metaData.yLabel);
|
|
9211
10151
|
}
|
|
9212
10152
|
else {
|
|
9213
|
-
svg
|
|
9214
|
-
.selectAll('.lib-axis-group-label')
|
|
10153
|
+
svg.selectAll('.lib-axis-group-label')
|
|
9215
10154
|
.attr('class', 'lib-ylabel-weeklyCharts')
|
|
9216
10155
|
.text(metaData.yLabel.toLowerCase());
|
|
9217
10156
|
}
|
|
9218
10157
|
}
|
|
9219
|
-
|
|
9220
|
-
const yZero = y(this.chartData.targetLineData.target);
|
|
9221
|
-
svg
|
|
9222
|
-
.append('line')
|
|
9223
|
-
.attr('x1', 0)
|
|
9224
|
-
.attr('x2', width)
|
|
9225
|
-
.attr('y1', yZero)
|
|
9226
|
-
.attr('y2', yZero)
|
|
9227
|
-
.style('stroke-dasharray', '5 5')
|
|
9228
|
-
.style('stroke', this.chartData.targetLineData.color);
|
|
9229
|
-
// svgYAxisRight
|
|
9230
|
-
// .append('line')
|
|
9231
|
-
// .attr('x1', 0)
|
|
9232
|
-
// .attr('x2', rightSvgWidth)
|
|
9233
|
-
// .attr('y1', yZero)
|
|
9234
|
-
// .attr('y2', yZero)
|
|
9235
|
-
// .style('stroke', this.chartData.targetLineData.color);
|
|
9236
|
-
svgYAxisRight
|
|
9237
|
-
.append('foreignObject')
|
|
9238
|
-
.attr('transform', 'translate(' + 0 + ',' + (yZero - 30) + ')')
|
|
9239
|
-
.attr('width', rightSvgWidth)
|
|
9240
|
-
.attr('height', 50)
|
|
9241
|
-
.append('xhtml:div')
|
|
9242
|
-
.attr('class', 'target-display')
|
|
9243
|
-
.style('color', 'var(--chart-text-color)')
|
|
9244
|
-
.html(function () {
|
|
9245
|
-
let dataTypeTemp = '';
|
|
9246
|
-
let targetLineName = 'target';
|
|
9247
|
-
if (metaData.dataType) {
|
|
9248
|
-
dataTypeTemp = metaData.dataType;
|
|
9249
|
-
}
|
|
9250
|
-
if (self.chartData.targetLineData &&
|
|
9251
|
-
self.chartData.targetLineData.targetName) {
|
|
9252
|
-
targetLineName = self.chartData.targetLineData.targetName;
|
|
9253
|
-
}
|
|
9254
|
-
return (`<div>${targetLineName}</div>` +
|
|
9255
|
-
'<div>' +
|
|
9256
|
-
self.chartData.targetLineData.target +
|
|
9257
|
-
'' +
|
|
9258
|
-
dataTypeTemp +
|
|
9259
|
-
'</div>');
|
|
9260
|
-
});
|
|
9261
|
-
}
|
|
9262
|
-
if (this.chartConfiguration.isDrilldownChart) {
|
|
9263
|
-
/**
|
|
9264
|
-
* used by drilldown charts
|
|
9265
|
-
*/
|
|
9266
|
-
// svg
|
|
9267
|
-
// .selectAll('.lib-axis-group-label')
|
|
9268
|
-
// .attr('class', 'lib-ylabel-drilldowncharts')
|
|
9269
|
-
// .text(metaData.yLabel.toLowerCase());
|
|
9270
|
-
svg.selectAll('g.x1.axis1 g.tick line').style('display', 'none');
|
|
9271
|
-
}
|
|
10158
|
+
// X-axis label
|
|
9272
10159
|
if (metaData.xLabel) {
|
|
9273
|
-
|
|
9274
|
-
|
|
9275
|
-
|
|
9276
|
-
|
|
9277
|
-
|
|
9278
|
-
|
|
9279
|
-
const xPosition = isria ? (height + margin.top + margin.bottom) : (height + margin.top + margin.bottom + 40);
|
|
9280
|
-
svg
|
|
9281
|
-
.append('text')
|
|
9282
|
-
.attr('class', function () {
|
|
9283
|
-
let baseClass = 'lib-axis-group-label font-size-1';
|
|
9284
|
-
if (self.chartConfiguration.isDrilldownChart)
|
|
9285
|
-
return baseClass + ' lib-xlabel-drilldowncharts';
|
|
9286
|
-
if (self.chartConfiguration.isMultiChartGridLine != undefined)
|
|
9287
|
-
return baseClass + ' lib-xlabel-weeklyCharts';
|
|
9288
|
-
return baseClass + ' lib-axis-waterfall-label';
|
|
9289
|
-
})
|
|
10160
|
+
const isAcronym = this.isLabelAcronym(metaData.xLabel);
|
|
10161
|
+
const xPosition = isria
|
|
10162
|
+
? (height + margin.top + margin.bottom)
|
|
10163
|
+
: (height + margin.top + margin.bottom + 40);
|
|
10164
|
+
svg.append('text')
|
|
10165
|
+
.attr('class', this.getXLabelClass(self))
|
|
9290
10166
|
.attr('style', self.chartConfiguration.xAxisCustomlabelStyles)
|
|
9291
|
-
.attr('transform',
|
|
10167
|
+
.attr('transform', `translate(${width / 2},${xPosition})`)
|
|
9292
10168
|
.style('text-anchor', 'middle')
|
|
9293
10169
|
.style('fill', 'var(--chart-text-color)')
|
|
9294
|
-
.text(
|
|
9295
|
-
.style('text-transform',
|
|
10170
|
+
.text(isAcronym ? metaData.xLabel.toUpperCase() : metaData.xLabel.toLowerCase())
|
|
10171
|
+
.style('text-transform', isAcronym ? 'none' : 'capitalize');
|
|
9296
10172
|
}
|
|
10173
|
+
// Line y-axis label
|
|
9297
10174
|
if (metaData.lineyLabel) {
|
|
9298
|
-
svgYAxisRight
|
|
9299
|
-
.append('text')
|
|
10175
|
+
svgYAxisRight.append('text')
|
|
9300
10176
|
.attr('class', 'lib-axis-group-label lib-line-axis')
|
|
9301
10177
|
.attr('fill', 'var(--chart-text-color)')
|
|
9302
10178
|
.attr('style', self.chartConfiguration.yAxisCustomlabelStyles)
|
|
9303
10179
|
.attr('transform', 'translate(0,0) rotate(90)')
|
|
9304
|
-
.attr('y',
|
|
9305
|
-
.attr('x',
|
|
10180
|
+
.attr('y', -100)
|
|
10181
|
+
.attr('x', 100)
|
|
9306
10182
|
.attr('dy', '5em')
|
|
9307
10183
|
.style('text-anchor', 'middle')
|
|
9308
10184
|
.style('font-size', 'smaller')
|
|
9309
10185
|
.text(metaData.lineyLabel);
|
|
9310
10186
|
}
|
|
9311
|
-
|
|
9312
|
-
|
|
9313
|
-
|
|
9314
|
-
|
|
9315
|
-
|
|
9316
|
-
|
|
9317
|
-
|
|
9318
|
-
|
|
9319
|
-
|
|
9320
|
-
|
|
9321
|
-
|
|
9322
|
-
|
|
9323
|
-
|
|
9324
|
-
|
|
9325
|
-
|
|
9326
|
-
|
|
9327
|
-
|
|
9328
|
-
|
|
9329
|
-
|
|
9330
|
-
|
|
9331
|
-
|
|
9332
|
-
|
|
9333
|
-
|
|
9334
|
-
|
|
9335
|
-
|
|
9336
|
-
|
|
9337
|
-
|
|
9338
|
-
|
|
9339
|
-
|
|
9340
|
-
|
|
9341
|
-
|
|
9342
|
-
|
|
9343
|
-
|
|
9344
|
-
|
|
9345
|
-
|
|
9346
|
-
|
|
9347
|
-
|
|
9348
|
-
|
|
9349
|
-
|
|
9350
|
-
|
|
9351
|
-
|
|
9352
|
-
|
|
9353
|
-
|
|
9354
|
-
|
|
9355
|
-
|
|
9356
|
-
|
|
9357
|
-
|
|
9358
|
-
|
|
9359
|
-
|
|
9360
|
-
|
|
9361
|
-
|
|
9362
|
-
|
|
9363
|
-
|
|
9364
|
-
|
|
9365
|
-
|
|
9366
|
-
|
|
9367
|
-
|
|
10187
|
+
// Apply drilldown chart specific styles
|
|
10188
|
+
if (this.chartConfiguration.isDrilldownChart) {
|
|
10189
|
+
svg.selectAll('g.x1.axis1 g.tick line').style('display', 'none');
|
|
10190
|
+
}
|
|
10191
|
+
}
|
|
10192
|
+
isLabelAcronym(label) {
|
|
10193
|
+
return (label.length <= 4 && /^[A-Z]+$/.test(label)) ||
|
|
10194
|
+
(label === label.toUpperCase() && /[A-Z]/.test(label));
|
|
10195
|
+
}
|
|
10196
|
+
getXLabelClass(self) {
|
|
10197
|
+
let baseClass = 'lib-axis-group-label font-size-1';
|
|
10198
|
+
if (self.chartConfiguration.isDrilldownChart) {
|
|
10199
|
+
return baseClass + ' lib-xlabel-drilldowncharts';
|
|
10200
|
+
}
|
|
10201
|
+
if (self.chartConfiguration.isMultiChartGridLine !== undefined) {
|
|
10202
|
+
return baseClass + ' lib-xlabel-weeklyCharts';
|
|
10203
|
+
}
|
|
10204
|
+
return baseClass + ' lib-axis-waterfall-label';
|
|
10205
|
+
}
|
|
10206
|
+
renderTargetLine(svg, svgYAxisRight, y, width, rightSvgWidth, metaData, self) {
|
|
10207
|
+
const yZero = y(this.chartData.targetLineData.target);
|
|
10208
|
+
// Draw target line
|
|
10209
|
+
svg.append('line')
|
|
10210
|
+
.attr('x1', 0)
|
|
10211
|
+
.attr('x2', width)
|
|
10212
|
+
.attr('y1', yZero)
|
|
10213
|
+
.attr('y2', yZero)
|
|
10214
|
+
.style('stroke-dasharray', '5 5')
|
|
10215
|
+
.style('stroke', this.chartData.targetLineData.color);
|
|
10216
|
+
// Add target label
|
|
10217
|
+
const dataTypeTemp = metaData.dataType || '';
|
|
10218
|
+
const targetLineName = this.chartData.targetLineData.targetName || 'target';
|
|
10219
|
+
svgYAxisRight.append('foreignObject')
|
|
10220
|
+
.attr('transform', `translate(0,${yZero - 30})`)
|
|
10221
|
+
.attr('width', rightSvgWidth)
|
|
10222
|
+
.attr('height', 50)
|
|
10223
|
+
.append('xhtml:div')
|
|
10224
|
+
.attr('class', 'target-display')
|
|
10225
|
+
.style('color', 'var(--chart-text-color)')
|
|
10226
|
+
.html(`<div>${targetLineName}</div><div>${self.chartData.targetLineData.target}${dataTypeTemp}</div>`);
|
|
10227
|
+
}
|
|
10228
|
+
renderLineChart(svg, lineData, x, lineYscale, metaData, self) {
|
|
10229
|
+
// Draw line path
|
|
10230
|
+
svg.append('path')
|
|
10231
|
+
.datum(lineData)
|
|
10232
|
+
.attr('fill', 'none')
|
|
10233
|
+
.attr('stroke', self.chartConfiguration.lineGraphColor)
|
|
10234
|
+
.attr('stroke-width', 1.5)
|
|
10235
|
+
.attr('d', d3.line()
|
|
10236
|
+
.x((d) => x(d.name) + x.bandwidth() / 2)
|
|
10237
|
+
.y((d) => lineYscale(d.value)));
|
|
10238
|
+
// Add dots
|
|
10239
|
+
const dot = svg.selectAll('myCircles')
|
|
10240
|
+
.data(lineData)
|
|
10241
|
+
.enter()
|
|
10242
|
+
.append('g')
|
|
10243
|
+
.on('click', (d) => {
|
|
10244
|
+
if (!metaData.barWithoutClick || !metaData.barWithoutClick.length ||
|
|
10245
|
+
(!metaData.barWithoutClick.includes(d?.name) &&
|
|
10246
|
+
!metaData.barWithoutClick.includes(d?.key))) {
|
|
10247
|
+
self.handleClick(d);
|
|
10248
|
+
}
|
|
10249
|
+
});
|
|
10250
|
+
dot.append('circle')
|
|
10251
|
+
.attr('fill', self.chartConfiguration.lineGraphColor)
|
|
10252
|
+
.attr('stroke', 'none')
|
|
10253
|
+
.attr('cx', (d) => x(d.name) + x.bandwidth() / 2)
|
|
10254
|
+
.attr('cy', (d) => lineYscale(d.value))
|
|
10255
|
+
.style('cursor', () => self.chartData.metaData.hasDrillDown ? 'pointer' : 'default')
|
|
10256
|
+
.attr('r', 3);
|
|
10257
|
+
// Add value labels
|
|
10258
|
+
if (self.chartConfiguration.lineGraphColor) {
|
|
10259
|
+
dot.append('text')
|
|
10260
|
+
.attr('class', 'dot')
|
|
10261
|
+
.attr('fill', 'var(--chart-text-color)')
|
|
10262
|
+
.attr('color', self.chartConfiguration.lineGraphColor)
|
|
10263
|
+
.attr('style', 'font-size: .85em')
|
|
10264
|
+
.attr('x', (d) => x(d.name) + x.bandwidth() / 2)
|
|
10265
|
+
.attr('y', (d) => lineYscale(d.value))
|
|
10266
|
+
.attr('dy', '-1em')
|
|
10267
|
+
.text((d) => self.chartConfiguration.labelFormatter(d.value));
|
|
10268
|
+
}
|
|
10269
|
+
}
|
|
10270
|
+
handleZoomOut(svg, height, margin) {
|
|
10271
|
+
svg.selectAll('.lib-xaxis-labels-texts-drilldown')
|
|
10272
|
+
.each((d, i, nodes) => {
|
|
10273
|
+
const text = d3.select(nodes[i]);
|
|
10274
|
+
const label = text.text();
|
|
10275
|
+
if (label.indexOf('\n') > -1) {
|
|
10276
|
+
const lines = label.split('\n');
|
|
10277
|
+
text.text(null);
|
|
10278
|
+
lines.forEach((line, idx) => {
|
|
10279
|
+
text.append('tspan')
|
|
10280
|
+
.text(line)
|
|
10281
|
+
.attr('x', 0)
|
|
10282
|
+
.attr('dy', idx === 0 ? '1em' : '1.1em');
|
|
9368
10283
|
});
|
|
9369
10284
|
}
|
|
9370
|
-
|
|
10285
|
+
else {
|
|
10286
|
+
const words = label.split(' ');
|
|
10287
|
+
text.text(null);
|
|
10288
|
+
words.forEach((word) => {
|
|
10289
|
+
text.append('tspan').text(word);
|
|
10290
|
+
});
|
|
10291
|
+
}
|
|
10292
|
+
})
|
|
10293
|
+
.style('fill', 'var(--chart-text-color)')
|
|
10294
|
+
.attr('transform', null);
|
|
10295
|
+
svg.select('.x-axis')
|
|
10296
|
+
.attr('transform', `translate(0, ${height - margin.bottom + 10})`);
|
|
9371
10297
|
}
|
|
9372
10298
|
calculateChartDimensions(chartContainer, verticalstackedcontainer, margin, self) {
|
|
9373
10299
|
let width = parseInt(chartContainer.style('width')) - margin.left - margin.right;
|