axidio-styleguide-library1-v2 0.2.24 → 0.2.25
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-bars-with-scroll-zoom/horizontal-bars-with-scroll-zoom.component.mjs +696 -392
- package/esm2022/lib/horizontal-grouped-bar-with-scroll-zoom/horizontal-grouped-bar-with-scroll-zoom.component.mjs +220 -15
- package/fesm2022/axidio-styleguide-library1-v2.mjs +913 -404
- package/fesm2022/axidio-styleguide-library1-v2.mjs.map +1 -1
- package/lib/horizontal-bars-with-scroll-zoom/horizontal-bars-with-scroll-zoom.component.d.ts +98 -35
- package/package.json +1 -1
|
@@ -6640,15 +6640,18 @@ class HorizontalBarsWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
6640
6640
|
this.isTransparentBackground = false;
|
|
6641
6641
|
this.isCC = false;
|
|
6642
6642
|
this.isZoomedOut = true;
|
|
6643
|
-
this.
|
|
6644
|
-
|
|
6645
|
-
|
|
6646
|
-
|
|
6647
|
-
|
|
6648
|
-
|
|
6649
|
-
|
|
6650
|
-
|
|
6651
|
-
|
|
6643
|
+
this.CONSTANTS = {
|
|
6644
|
+
RIGHT_SVG_WIDTH: 60,
|
|
6645
|
+
LEFT_RIGHT_SPACES: 50,
|
|
6646
|
+
SHORT_TICK_LENGTH: 4,
|
|
6647
|
+
LONG_TICK_LENGTH: 16,
|
|
6648
|
+
SHORT_TICK_LENGTH_BG: 5,
|
|
6649
|
+
LONG_TICK_LENGTH_BG: 30,
|
|
6650
|
+
MIN_MOBILE_BAR_WIDTH: 32,
|
|
6651
|
+
DESKTOP_MIN_BAR_WIDTH: 40,
|
|
6652
|
+
MOBILE_BAR_PADDING: 12,
|
|
6653
|
+
ZOOM_THRESHOLD: 30,
|
|
6654
|
+
ZOOM_IN_THRESHOLD: 8,
|
|
6652
6655
|
};
|
|
6653
6656
|
this.defaultConfiguration = {
|
|
6654
6657
|
margin: { top: 20, right: 20, bottom: 20, left: 40 },
|
|
@@ -6665,24 +6668,54 @@ class HorizontalBarsWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
6665
6668
|
forComparison: true,
|
|
6666
6669
|
headerMenuOptions: HeaderConfigHelper.headerConfig.headerMenuOptions,
|
|
6667
6670
|
yAxisGrid: false,
|
|
6671
|
+
// Optional configs with undefined defaults
|
|
6672
|
+
isHeaderVisible: undefined,
|
|
6673
|
+
isTransparentBackground: undefined,
|
|
6674
|
+
isTopCaptionVisible: undefined,
|
|
6675
|
+
isMultiChartGridLine: undefined,
|
|
6676
|
+
isFullScreen: undefined,
|
|
6677
|
+
customYscale: undefined,
|
|
6678
|
+
isXaxisLabelHidden: undefined,
|
|
6679
|
+
isYaxisLabelHidden: undefined,
|
|
6680
|
+
isYaxisHidden: undefined,
|
|
6681
|
+
isYaxisDashed: undefined,
|
|
6682
|
+
isXaxisColor: undefined,
|
|
6683
|
+
textFormatter: undefined,
|
|
6684
|
+
showTotalOnTop: undefined,
|
|
6685
|
+
backendFormatterHasPriority: undefined,
|
|
6686
|
+
showAngledLabels: undefined,
|
|
6687
|
+
isNoAlternateXaxisText: undefined,
|
|
6688
|
+
isXgridBetweenLabels: undefined,
|
|
6689
|
+
showXaxisTop: undefined,
|
|
6690
|
+
xAxisGrid: undefined,
|
|
6691
|
+
xLabelsOnSameLine: undefined,
|
|
6692
|
+
hideXaxisTick: undefined,
|
|
6693
|
+
isDrilldownChart: undefined,
|
|
6694
|
+
isTargetLine: undefined,
|
|
6695
|
+
displayTitleOnTop: undefined,
|
|
6696
|
+
isToggleVisible: undefined,
|
|
6697
|
+
isTitleHidden: undefined,
|
|
6668
6698
|
};
|
|
6669
6699
|
}
|
|
6670
6700
|
ngOnInit() { }
|
|
6671
|
-
ngOnChanges(
|
|
6672
|
-
this.
|
|
6701
|
+
ngOnChanges() {
|
|
6702
|
+
this.removeExistingChart();
|
|
6703
|
+
this.initializeStackedChart();
|
|
6673
6704
|
}
|
|
6674
6705
|
onResized(event) {
|
|
6675
|
-
setTimeout(() =>
|
|
6706
|
+
setTimeout(() => {
|
|
6707
|
+
this.removeExistingChart();
|
|
6708
|
+
this.initializeStackedChart();
|
|
6709
|
+
}, 10);
|
|
6676
6710
|
}
|
|
6677
6711
|
isZoomOutSelected(isZoomOut) {
|
|
6678
6712
|
this.isZoomedOut = isZoomOut;
|
|
6679
|
-
this.
|
|
6713
|
+
this.ngOnChanges();
|
|
6680
6714
|
}
|
|
6681
|
-
|
|
6715
|
+
removeExistingChart() {
|
|
6682
6716
|
d3.select('#' + this.uniqueId).remove();
|
|
6683
|
-
this.initializeStackedChart();
|
|
6684
6717
|
}
|
|
6685
|
-
|
|
6718
|
+
getDeviceConfig() {
|
|
6686
6719
|
const width = window.innerWidth;
|
|
6687
6720
|
return {
|
|
6688
6721
|
isMobile: width < 576,
|
|
@@ -6690,7 +6723,7 @@ class HorizontalBarsWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
6690
6723
|
isDesktop: width >= 992,
|
|
6691
6724
|
};
|
|
6692
6725
|
}
|
|
6693
|
-
|
|
6726
|
+
configureResponsiveSettings(device) {
|
|
6694
6727
|
if (device.isMobile) {
|
|
6695
6728
|
this.chartConfiguration.margin = { top: 20, right: 10, bottom: 40, left: 30 };
|
|
6696
6729
|
this.chartConfiguration.numberOfYTicks = 4;
|
|
@@ -6708,9 +6741,9 @@ class HorizontalBarsWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
6708
6741
|
}
|
|
6709
6742
|
}
|
|
6710
6743
|
mergeConfigurations() {
|
|
6711
|
-
|
|
6744
|
+
for (const key in this.defaultConfiguration) {
|
|
6712
6745
|
this.chartConfiguration[key] = ChartHelper.getValueByConfigurationType(key, this.defaultConfiguration, this.customChartConfiguration);
|
|
6713
|
-
}
|
|
6746
|
+
}
|
|
6714
6747
|
}
|
|
6715
6748
|
prepareMetaData(metaData) {
|
|
6716
6749
|
if (!metaData.unit)
|
|
@@ -6725,183 +6758,70 @@ class HorizontalBarsWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
6725
6758
|
}
|
|
6726
6759
|
return metaData;
|
|
6727
6760
|
}
|
|
6728
|
-
|
|
6729
|
-
|
|
6730
|
-
|
|
6731
|
-
const parsedNum = parseFloat(String(targetLineData.target));
|
|
6732
|
-
if (isNaN(parsedNum))
|
|
6733
|
-
return null;
|
|
6734
|
-
return Number.isInteger(parsedNum)
|
|
6735
|
-
? parseInt(String(targetLineData.target))
|
|
6736
|
-
: parsedNum;
|
|
6737
|
-
}
|
|
6738
|
-
calculateDimensions(containerWidth, containerHeight, margin, device) {
|
|
6761
|
+
calculateDimensions(chartContainer, verticalContainer, margin, device, dataLength) {
|
|
6762
|
+
const containerWidth = chartContainer.node().getBoundingClientRect().width;
|
|
6763
|
+
const containerHeight = verticalContainer.node().getBoundingClientRect().height;
|
|
6739
6764
|
let width = containerWidth - margin.left - margin.right;
|
|
6740
6765
|
let height = containerHeight * (this.chartConfiguration.svgHeight / 100) - margin.top - margin.bottom;
|
|
6741
|
-
//
|
|
6742
|
-
|
|
6743
|
-
if (dataLength > 30 && this.isZoomedOut) {
|
|
6766
|
+
// Handle zoom out scenario
|
|
6767
|
+
if (dataLength > this.CONSTANTS.ZOOM_THRESHOLD && this.isZoomedOut) {
|
|
6744
6768
|
const minWidth = dataLength * (device.isMobile ? 15 : 25);
|
|
6745
6769
|
width = Math.max(width, minWidth);
|
|
6746
6770
|
}
|
|
6747
|
-
|
|
6771
|
+
// Handle zoom in scenario
|
|
6772
|
+
if (dataLength > this.CONSTANTS.ZOOM_IN_THRESHOLD && !this.isZoomedOut) {
|
|
6748
6773
|
width = dataLength * (device.isMobile ? 60 : 130);
|
|
6749
6774
|
}
|
|
6750
|
-
//
|
|
6751
|
-
if (this.chartConfiguration.isFullScreen
|
|
6752
|
-
height = this.chartConfiguration.svgHeight
|
|
6753
|
-
|
|
6754
|
-
|
|
6755
|
-
height = containerHeight;
|
|
6775
|
+
// Handle full screen
|
|
6776
|
+
if (this.chartConfiguration.isFullScreen) {
|
|
6777
|
+
height = this.chartConfiguration.svgHeight !== 80
|
|
6778
|
+
? this.chartConfiguration.svgHeight
|
|
6779
|
+
: containerHeight;
|
|
6756
6780
|
}
|
|
6781
|
+
// Handle drilldown
|
|
6757
6782
|
if (this.chartConfiguration.isDrilldownChart) {
|
|
6758
6783
|
height = containerHeight - margin.top - margin.bottom - (device.isMobile ? 60 : 130);
|
|
6759
6784
|
}
|
|
6760
|
-
|
|
6761
|
-
}
|
|
6762
|
-
calculateBarDimensions(width, dataLength, device) {
|
|
6785
|
+
// Calculate bar dimensions
|
|
6763
6786
|
let barWidth;
|
|
6764
6787
|
let barPadding;
|
|
6765
6788
|
let requiredSvgWidth;
|
|
6766
6789
|
if (device.isMobile) {
|
|
6767
|
-
|
|
6768
|
-
|
|
6769
|
-
|
|
6770
|
-
|
|
6771
|
-
this.SPACING.rightSvgWidth - barPadding);
|
|
6790
|
+
barWidth = this.CONSTANTS.MIN_MOBILE_BAR_WIDTH;
|
|
6791
|
+
barPadding = this.CONSTANTS.MOBILE_BAR_PADDING;
|
|
6792
|
+
requiredSvgWidth = Math.max(width - this.CONSTANTS.RIGHT_SVG_WIDTH, (barWidth + barPadding) * dataLength + this.CONSTANTS.LEFT_RIGHT_SPACES * 2 +
|
|
6793
|
+
this.CONSTANTS.RIGHT_SVG_WIDTH - barPadding);
|
|
6772
6794
|
}
|
|
6773
6795
|
else {
|
|
6774
|
-
barWidth = Math.max(
|
|
6796
|
+
barWidth = Math.max(this.CONSTANTS.DESKTOP_MIN_BAR_WIDTH, (width - this.CONSTANTS.RIGHT_SVG_WIDTH - this.CONSTANTS.LEFT_RIGHT_SPACES * 2) / dataLength);
|
|
6775
6797
|
barPadding = 0;
|
|
6776
|
-
requiredSvgWidth = width - this.
|
|
6777
|
-
}
|
|
6778
|
-
return { barWidth, barPadding, requiredSvgWidth };
|
|
6779
|
-
}
|
|
6780
|
-
createScales(data, height, width, device) {
|
|
6781
|
-
const xScale = d3
|
|
6782
|
-
.scaleBand()
|
|
6783
|
-
.rangeRound([
|
|
6784
|
-
this.SPACING.leftAndRight,
|
|
6785
|
-
width - this.SPACING.rightSvgWidth - this.SPACING.leftAndRight
|
|
6786
|
-
])
|
|
6787
|
-
.domain(data.map(d => d.name).reverse())
|
|
6788
|
-
.padding(device.isMobile ? 0.2 : 0.5);
|
|
6789
|
-
const yScale = d3.scaleLinear().rangeRound([height, 0]);
|
|
6790
|
-
return { xScale, yScale };
|
|
6791
|
-
}
|
|
6792
|
-
calculateYScaleDomain(layers, targetValue) {
|
|
6793
|
-
let maxValue = d3.max(layers, (d) => d3.max(d, (d) => d[1])) || 0;
|
|
6794
|
-
if (maxValue === 0) {
|
|
6795
|
-
maxValue = targetValue ? targetValue + 20 : 100;
|
|
6796
|
-
}
|
|
6797
|
-
if (this.chartConfiguration.customYscale) {
|
|
6798
|
-
maxValue *= this.chartConfiguration.customYscale;
|
|
6799
|
-
}
|
|
6800
|
-
if (targetValue && maxValue < targetValue) {
|
|
6801
|
-
maxValue = maxValue < 10 && targetValue < 10
|
|
6802
|
-
? targetValue + 3
|
|
6803
|
-
: targetValue + 20;
|
|
6804
|
-
}
|
|
6805
|
-
return maxValue;
|
|
6806
|
-
}
|
|
6807
|
-
shouldShowTargetLineColor(d, targetValue) {
|
|
6808
|
-
return !!(!isNaN(d[0]) &&
|
|
6809
|
-
!isNaN(d[1]) &&
|
|
6810
|
-
this.chartData.targetLineData &&
|
|
6811
|
-
targetValue &&
|
|
6812
|
-
parseFloat(d[1]) - parseFloat(d[0]) >= targetValue);
|
|
6813
|
-
}
|
|
6814
|
-
getBarFillColor(d, key, metaData, targetValue) {
|
|
6815
|
-
if (this.shouldShowTargetLineColor(d, targetValue)) {
|
|
6816
|
-
return this.chartData.targetLineData?.barAboveTargetColor || metaData.colors[key];
|
|
6798
|
+
requiredSvgWidth = width - this.CONSTANTS.RIGHT_SVG_WIDTH;
|
|
6817
6799
|
}
|
|
6818
|
-
return metaData.colors[key];
|
|
6819
|
-
}
|
|
6820
|
-
isAcronym(label) {
|
|
6821
|
-
const alphaOnly = label.replace(/[^A-Za-z]/g, '');
|
|
6822
|
-
return (label.length <= 4 && /^[A-Z]+$/.test(label)) ||
|
|
6823
|
-
(label === label.toUpperCase() && /[A-Z]/.test(label));
|
|
6824
|
-
}
|
|
6825
|
-
formatAxisLabel(text) {
|
|
6826
|
-
const isAcr = this.isAcronym(text);
|
|
6827
6800
|
return {
|
|
6828
|
-
|
|
6829
|
-
|
|
6801
|
+
width,
|
|
6802
|
+
height,
|
|
6803
|
+
containerWidth,
|
|
6804
|
+
containerHeight,
|
|
6805
|
+
barWidth,
|
|
6806
|
+
barPadding,
|
|
6807
|
+
requiredSvgWidth,
|
|
6830
6808
|
};
|
|
6831
6809
|
}
|
|
6832
|
-
|
|
6833
|
-
const
|
|
6834
|
-
this.applyResponsiveConfig(device);
|
|
6835
|
-
this.mergeConfigurations();
|
|
6836
|
-
const { data, metaData, lineData } = this.chartData;
|
|
6837
|
-
const preparedMetaData = this.prepareMetaData(metaData);
|
|
6838
|
-
const targetValue = this.parseTargetValue(this.chartData.targetLineData);
|
|
6839
|
-
const chartContainer = d3.select(this.containerElt.nativeElement);
|
|
6840
|
-
const verticalstackedcontainer = d3.select(this.verticalstackedcontainerElt.nativeElement);
|
|
6841
|
-
const margin = this.chartConfiguration.margin;
|
|
6842
|
-
const containerWidth = chartContainer.node().getBoundingClientRect().width;
|
|
6843
|
-
const containerHeight = verticalstackedcontainer.node().getBoundingClientRect().height;
|
|
6844
|
-
const { width, height } = this.calculateDimensions(containerWidth, containerHeight, margin, device);
|
|
6845
|
-
// Apply visibility configurations
|
|
6846
|
-
if (this.chartConfiguration.isHeaderVisible !== undefined) {
|
|
6847
|
-
this.isHeaderVisible = this.chartConfiguration.isHeaderVisible;
|
|
6848
|
-
}
|
|
6849
|
-
if (this.chartConfiguration.isTopCaptionVisible !== undefined) {
|
|
6850
|
-
this.isTopCaptionVisible = this.chartConfiguration.isTopCaptionVisible;
|
|
6851
|
-
}
|
|
6852
|
-
if (this.chartConfiguration.isTransparentBackground !== undefined) {
|
|
6853
|
-
this.isTransparentBackground = this.chartConfiguration.isTransparentBackground;
|
|
6854
|
-
}
|
|
6855
|
-
// Create formatters
|
|
6856
|
-
const formatFromBackend = this.chartConfiguration.textFormatter
|
|
6857
|
-
? ChartHelper.dataValueFormatter(this.chartConfiguration.textFormatter)
|
|
6858
|
-
: null;
|
|
6859
|
-
const formatForHugeNumbers = ChartHelper.dataValueFormatter('.2s');
|
|
6860
|
-
// Create SVG containers
|
|
6861
|
-
const { barWidth, barPadding, requiredSvgWidth } = this.calculateBarDimensions(width, data.length, device);
|
|
6862
|
-
const outerContainer = this.createOuterContainer(chartContainer, height, margin);
|
|
6863
|
-
const { svgYAxisLeft, svgYAxisRight } = this.createAxisContainers(outerContainer, height, margin);
|
|
6864
|
-
const { innerContainer, svg } = this.createInnerContainer(outerContainer, requiredSvgWidth, height, margin, device);
|
|
6865
|
-
// Create scales
|
|
6866
|
-
const { xScale, yScale } = this.createScales(data, height, width, device);
|
|
6867
|
-
// Stack data
|
|
6868
|
-
const stack = d3
|
|
6869
|
-
.stack()
|
|
6870
|
-
.keys(preparedMetaData.keyList)
|
|
6871
|
-
.offset(d3.stackOffsetNone);
|
|
6872
|
-
const layers = stack(data);
|
|
6873
|
-
// Set Y scale domain
|
|
6874
|
-
const maxValue = this.calculateYScaleDomain(layers, targetValue || undefined);
|
|
6875
|
-
yScale.domain([0, maxValue]).nice();
|
|
6876
|
-
// Render chart elements
|
|
6877
|
-
this.renderGrids(svg, xScale, yScale, height, width);
|
|
6878
|
-
this.renderBars(svg, layers, xScale, yScale, preparedMetaData, device, barWidth, barPadding, targetValue, formatFromBackend, formatForHugeNumbers);
|
|
6879
|
-
this.renderAxes(svg, svgYAxisLeft, svgYAxisRight, xScale, yScale, data, height, width, device);
|
|
6880
|
-
this.renderLabels(svg, svgYAxisLeft, preparedMetaData, height, width, margin);
|
|
6881
|
-
if (this.chartData.targetLineData && targetValue) {
|
|
6882
|
-
this.renderTargetLine(svg, svgYAxisRight, yScale, width, targetValue, preparedMetaData);
|
|
6883
|
-
}
|
|
6884
|
-
if (lineData) {
|
|
6885
|
-
this.renderLineChart(svg, lineData, xScale, height, preparedMetaData.colors);
|
|
6886
|
-
}
|
|
6887
|
-
}
|
|
6888
|
-
createOuterContainer(chartContainer, height, margin) {
|
|
6889
|
-
return chartContainer
|
|
6810
|
+
createSvgContainers(chartContainer, dimensions, margin) {
|
|
6811
|
+
const outerContainer = chartContainer
|
|
6890
6812
|
.append('div')
|
|
6891
6813
|
.attr('id', this.uniqueId)
|
|
6892
6814
|
.attr('class', 'outer-container')
|
|
6893
6815
|
.style('width', '100%')
|
|
6894
|
-
.style('height', height)
|
|
6816
|
+
.style('height', dimensions.height)
|
|
6895
6817
|
.style('overflow-x', 'hidden')
|
|
6896
6818
|
.style('padding-left', `${margin.left}px`)
|
|
6897
6819
|
.style('margin-left', '10px')
|
|
6898
|
-
.style('padding-right', `${this.
|
|
6899
|
-
}
|
|
6900
|
-
createAxisContainers(outerContainer, height, margin) {
|
|
6820
|
+
.style('padding-right', `${this.CONSTANTS.RIGHT_SVG_WIDTH}px`);
|
|
6901
6821
|
const svgYAxisLeft = outerContainer
|
|
6902
6822
|
.append('svg')
|
|
6903
6823
|
.attr('width', '80')
|
|
6904
|
-
.attr('height', height + margin.top + margin.bottom)
|
|
6824
|
+
.attr('height', dimensions.height + margin.top + margin.bottom)
|
|
6905
6825
|
.style('position', 'absolute')
|
|
6906
6826
|
.style('left', '0')
|
|
6907
6827
|
.style('z-index', 1)
|
|
@@ -6909,65 +6829,85 @@ class HorizontalBarsWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
6909
6829
|
.attr('transform', `translate(${margin.left + 10},${margin.top})`);
|
|
6910
6830
|
const svgYAxisRight = outerContainer
|
|
6911
6831
|
.append('svg')
|
|
6912
|
-
.attr('width', this.
|
|
6913
|
-
.attr('height', height + margin.top + margin.bottom)
|
|
6832
|
+
.attr('width', this.CONSTANTS.RIGHT_SVG_WIDTH)
|
|
6833
|
+
.attr('height', dimensions.height + margin.top + margin.bottom)
|
|
6914
6834
|
.style('position', 'absolute')
|
|
6915
6835
|
.style('right', '2px')
|
|
6916
6836
|
.style('z-index', 1)
|
|
6917
6837
|
.append('g')
|
|
6918
6838
|
.attr('transform', `translate(0,${margin.top})`);
|
|
6919
|
-
return { svgYAxisLeft, svgYAxisRight };
|
|
6920
|
-
}
|
|
6921
|
-
createInnerContainer(outerContainer, requiredSvgWidth, height, margin, device) {
|
|
6922
6839
|
const innerContainer = outerContainer
|
|
6923
6840
|
.append('div')
|
|
6924
6841
|
.attr('class', 'inner-container')
|
|
6925
6842
|
.style('width', '100%')
|
|
6926
|
-
.style('overflow-x',
|
|
6843
|
+
.style('overflow-x', 'auto');
|
|
6927
6844
|
const svg = innerContainer
|
|
6928
6845
|
.append('svg')
|
|
6929
|
-
.attr('width', requiredSvgWidth)
|
|
6930
|
-
.attr('height', height + margin.top + margin.bottom + 30)
|
|
6846
|
+
.attr('width', dimensions.requiredSvgWidth)
|
|
6847
|
+
.attr('height', dimensions.height + margin.top + margin.bottom + 30)
|
|
6931
6848
|
.append('g')
|
|
6932
6849
|
.attr('transform', `translate(0,${margin.top})`);
|
|
6933
|
-
return {
|
|
6850
|
+
return { svg, svgYAxisLeft, svgYAxisRight, innerContainer };
|
|
6934
6851
|
}
|
|
6935
|
-
|
|
6936
|
-
|
|
6937
|
-
|
|
6938
|
-
|
|
6939
|
-
|
|
6940
|
-
|
|
6941
|
-
|
|
6942
|
-
|
|
6943
|
-
|
|
6944
|
-
|
|
6852
|
+
createScales(data, layers, lineData, dimensions, device) {
|
|
6853
|
+
const { width, height, barWidth, barPadding } = dimensions;
|
|
6854
|
+
const xScale = d3
|
|
6855
|
+
.scaleBand()
|
|
6856
|
+
.rangeRound([
|
|
6857
|
+
this.CONSTANTS.LEFT_RIGHT_SPACES,
|
|
6858
|
+
width - this.CONSTANTS.RIGHT_SVG_WIDTH - this.CONSTANTS.LEFT_RIGHT_SPACES
|
|
6859
|
+
])
|
|
6860
|
+
.domain(data.map(d => d.name).reverse())
|
|
6861
|
+
.padding(device.isMobile ? 0.2 : 0.5);
|
|
6862
|
+
const xScaleFromOrigin = d3
|
|
6863
|
+
.scaleBand()
|
|
6864
|
+
.rangeRound([width - this.CONSTANTS.RIGHT_SVG_WIDTH, 0])
|
|
6865
|
+
.domain(data.map(d => d.name).reverse());
|
|
6866
|
+
const yScale = d3.scaleLinear().rangeRound([height, 0]);
|
|
6867
|
+
let maxValue = d3.max(layers, (d) => d3.max(d, (d) => d[1]));
|
|
6868
|
+
if (maxValue === 0) {
|
|
6869
|
+
maxValue = this.chartData.targetLineData
|
|
6870
|
+
? Number(this.chartData.targetLineData.target) + 20
|
|
6871
|
+
: 100;
|
|
6945
6872
|
}
|
|
6946
|
-
if (this.chartConfiguration.
|
|
6947
|
-
|
|
6948
|
-
.append('g')
|
|
6949
|
-
.attr('class', 'grid')
|
|
6950
|
-
.call(d3
|
|
6951
|
-
.axisLeft(yScale)
|
|
6952
|
-
.ticks(this.chartConfiguration.numberOfYTicks)
|
|
6953
|
-
.tickSize(-width)
|
|
6954
|
-
.tickFormat(''))
|
|
6955
|
-
.style('color', 'var(--chart-grid-color)')
|
|
6956
|
-
.style('opacity', '1');
|
|
6873
|
+
if (this.chartConfiguration.customYscale) {
|
|
6874
|
+
maxValue *= this.chartConfiguration.customYscale;
|
|
6957
6875
|
}
|
|
6958
|
-
if (this.
|
|
6959
|
-
this.
|
|
6960
|
-
|
|
6961
|
-
|
|
6962
|
-
|
|
6963
|
-
|
|
6964
|
-
|
|
6965
|
-
|
|
6966
|
-
|
|
6967
|
-
|
|
6876
|
+
if (this.chartData.targetLineData && maxValue < Number(this.chartData.targetLineData.target)) {
|
|
6877
|
+
const target = Number(this.chartData.targetLineData.target);
|
|
6878
|
+
maxValue = maxValue < 10 && target < 10 ? target + 3 : target + 20;
|
|
6879
|
+
}
|
|
6880
|
+
yScale.domain([0, maxValue]).nice();
|
|
6881
|
+
let lineYscale = null;
|
|
6882
|
+
if (lineData) {
|
|
6883
|
+
lineYscale = d3
|
|
6884
|
+
.scaleLinear()
|
|
6885
|
+
.domain([0, d3.max(lineData, d => +d.value)])
|
|
6886
|
+
.range([height, 0]);
|
|
6887
|
+
}
|
|
6888
|
+
return { xScale, xScaleFromOrigin, yScale, lineYscale };
|
|
6889
|
+
}
|
|
6890
|
+
createAxes(scales) {
|
|
6891
|
+
const xAxis = d3
|
|
6892
|
+
.axisBottom(scales.xScale)
|
|
6893
|
+
.tickSize(0)
|
|
6894
|
+
.tickFormat(this.chartConfiguration.xAxisLabelFomatter);
|
|
6895
|
+
const yAxis = d3
|
|
6896
|
+
.axisLeft(scales.yScale)
|
|
6897
|
+
.ticks(this.chartConfiguration.numberOfYTicks)
|
|
6898
|
+
.tickSize(0)
|
|
6899
|
+
.tickFormat(this.chartConfiguration.yAxisLabelFomatter);
|
|
6900
|
+
let yLineAxis = null;
|
|
6901
|
+
if (scales.lineYscale) {
|
|
6902
|
+
yLineAxis = d3
|
|
6903
|
+
.axisRight(scales.lineYscale)
|
|
6904
|
+
.ticks(this.chartConfiguration.numberOfYTicks)
|
|
6905
|
+
.tickSize(0)
|
|
6906
|
+
.tickFormat(this.chartConfiguration.yLineAxisLabelFomatter);
|
|
6968
6907
|
}
|
|
6908
|
+
return { xAxis, yAxis, yLineAxis };
|
|
6969
6909
|
}
|
|
6970
|
-
renderBars(svg, layers,
|
|
6910
|
+
renderBars(svg, layers, scales, metaData, dimensions, device) {
|
|
6971
6911
|
const layer = svg
|
|
6972
6912
|
.selectAll('.layer')
|
|
6973
6913
|
.data(layers)
|
|
@@ -6975,7 +6915,17 @@ class HorizontalBarsWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
6975
6915
|
.append('g')
|
|
6976
6916
|
.attr('class', 'layer')
|
|
6977
6917
|
.style('fill', (d) => metaData.colors[d.key]);
|
|
6978
|
-
const rect = layer
|
|
6918
|
+
const rect = layer
|
|
6919
|
+
.selectAll('rect')
|
|
6920
|
+
.data((d) => d)
|
|
6921
|
+
.enter();
|
|
6922
|
+
this.appendRectangles(rect, scales, metaData, dimensions, device);
|
|
6923
|
+
this.addInteractions(rect, svg, metaData, scales);
|
|
6924
|
+
return rect;
|
|
6925
|
+
}
|
|
6926
|
+
appendRectangles(rect, scales, metaData, dimensions, device) {
|
|
6927
|
+
const { barWidth, barPadding } = dimensions;
|
|
6928
|
+
const { xScale, yScale } = scales;
|
|
6979
6929
|
rect
|
|
6980
6930
|
.append('rect')
|
|
6981
6931
|
.on('click', (d) => {
|
|
@@ -6994,9 +6944,9 @@ class HorizontalBarsWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
6994
6944
|
})
|
|
6995
6945
|
.attr('x', (d, i) => {
|
|
6996
6946
|
if (device.isMobile) {
|
|
6997
|
-
return this.
|
|
6947
|
+
return this.CONSTANTS.LEFT_RIGHT_SPACES + i * (barWidth + barPadding);
|
|
6998
6948
|
}
|
|
6999
|
-
if (this.chartConfiguration.isMultiChartGridLine
|
|
6949
|
+
if (!this.chartConfiguration.isMultiChartGridLine) {
|
|
7000
6950
|
return xScale(d.data.name);
|
|
7001
6951
|
}
|
|
7002
6952
|
if (this.chartConfiguration.isDrilldownChart && this.chartData.data.length <= 3) {
|
|
@@ -7014,99 +6964,307 @@ class HorizontalBarsWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
7014
6964
|
.attr('width', (d) => {
|
|
7015
6965
|
if (device.isMobile)
|
|
7016
6966
|
return barWidth;
|
|
7017
|
-
if (this.chartConfiguration.isMultiChartGridLine
|
|
6967
|
+
if (!this.chartConfiguration.isMultiChartGridLine)
|
|
7018
6968
|
return xScale.bandwidth();
|
|
6969
|
+
if (this.chartConfiguration.isDrilldownChart && this.chartData.data.length <= 3) {
|
|
6970
|
+
return 70;
|
|
7019
6971
|
}
|
|
7020
|
-
return
|
|
7021
|
-
? 70
|
|
7022
|
-
: xScale.bandwidth() * 0.8;
|
|
6972
|
+
return xScale.bandwidth() * 0.8;
|
|
7023
6973
|
})
|
|
7024
6974
|
.style('cursor', (d) => {
|
|
7025
|
-
if (
|
|
7026
|
-
|
|
7027
|
-
|
|
7028
|
-
|
|
6975
|
+
if (metaData.hasDrillDown) {
|
|
6976
|
+
if (metaData.barWithoutClick?.includes(d.data.name.toLowerCase())) {
|
|
6977
|
+
return 'default';
|
|
6978
|
+
}
|
|
6979
|
+
return 'pointer';
|
|
7029
6980
|
}
|
|
7030
|
-
return '
|
|
6981
|
+
return 'default';
|
|
7031
6982
|
})
|
|
7032
|
-
.style('fill', (d) => this.
|
|
7033
|
-
|
|
7034
|
-
|
|
7035
|
-
|
|
6983
|
+
.style('fill', (d) => this.getBarColor(d, metaData));
|
|
6984
|
+
}
|
|
6985
|
+
getBarColor(d, metaData) {
|
|
6986
|
+
if (!isNaN(d[0]) &&
|
|
6987
|
+
!isNaN(d[1]) &&
|
|
6988
|
+
this.chartData.targetLineData &&
|
|
6989
|
+
parseFloat(d[1]) - parseFloat(d[0]) >= parseFloat(String(this.chartData.targetLineData.target))) {
|
|
6990
|
+
return this.chartData.targetLineData.barAboveTargetColor || metaData.colors[d.key];
|
|
7036
6991
|
}
|
|
7037
|
-
|
|
6992
|
+
return metaData.colors[d.key];
|
|
7038
6993
|
}
|
|
7039
|
-
|
|
7040
|
-
|
|
7041
|
-
rect
|
|
7042
|
-
|
|
7043
|
-
|
|
7044
|
-
|
|
7045
|
-
|
|
7046
|
-
|
|
7047
|
-
|
|
7048
|
-
|
|
7049
|
-
|
|
7050
|
-
|
|
7051
|
-
|
|
7052
|
-
|
|
6994
|
+
addInteractions(rect, svg, metaData, scales) {
|
|
6995
|
+
rect
|
|
6996
|
+
.selectAll('rect')
|
|
6997
|
+
.on('mouseenter', (d) => this.handleMouseOver(d, svg, metaData, scales))
|
|
6998
|
+
.on('mouseout', (d) => this.handleMouseOut(svg, metaData));
|
|
6999
|
+
}
|
|
7000
|
+
handleMouseOver(d, svg, metaData, scales) {
|
|
7001
|
+
if (!this.chartConfiguration.displayTitleOnTop)
|
|
7002
|
+
return;
|
|
7003
|
+
svg.selectAll('rect')
|
|
7004
|
+
.filter((data) => data === d)
|
|
7005
|
+
.style('fill', (d) => this.getHoverColor(d, metaData));
|
|
7006
|
+
this.displayTooltip(d, svg, metaData, scales);
|
|
7007
|
+
}
|
|
7008
|
+
getHoverColor(d, metaData) {
|
|
7009
|
+
if (!isNaN(d[0]) &&
|
|
7010
|
+
!isNaN(d[1]) &&
|
|
7011
|
+
this.chartData.targetLineData &&
|
|
7012
|
+
parseFloat(d[1]) - parseFloat(d[0]) >= parseFloat(String(this.chartData.targetLineData.target))) {
|
|
7013
|
+
return this.chartData.targetLineData.barAboveTargetHoverColor ||
|
|
7014
|
+
this.chartData.targetLineData.barAboveTargetColor ||
|
|
7015
|
+
metaData.colors[d.key];
|
|
7053
7016
|
}
|
|
7017
|
+
return metaData.hoverColor || metaData.colors[d.key];
|
|
7054
7018
|
}
|
|
7055
|
-
|
|
7056
|
-
const
|
|
7057
|
-
|
|
7058
|
-
|
|
7059
|
-
|
|
7060
|
-
const
|
|
7061
|
-
|
|
7062
|
-
.
|
|
7063
|
-
|
|
7064
|
-
|
|
7065
|
-
|
|
7066
|
-
|
|
7067
|
-
|
|
7019
|
+
displayTooltip(d, svg, metaData, scales) {
|
|
7020
|
+
const { xScale, yScale } = scales;
|
|
7021
|
+
const value = d[1] - d[0];
|
|
7022
|
+
if (isNaN(value))
|
|
7023
|
+
return;
|
|
7024
|
+
const width = /week/i.test(d.data.name) && /\d{4}-\d{2}-\d{2}/.test(d.data.name)
|
|
7025
|
+
? '250px'
|
|
7026
|
+
: xScale.bandwidth() + this.CONSTANTS.LEFT_RIGHT_SPACES * 2 > 180
|
|
7027
|
+
? '180px'
|
|
7028
|
+
: xScale.bandwidth() + this.CONSTANTS.LEFT_RIGHT_SPACES * 2;
|
|
7029
|
+
svg
|
|
7030
|
+
.append('foreignObject')
|
|
7031
|
+
.attr('x', this.calculateTooltipX(d, xScale, width))
|
|
7032
|
+
.attr('class', 'lib-verticalstack-title-ontop')
|
|
7033
|
+
.attr('y', yScale(d[1]) - 51)
|
|
7034
|
+
.attr('width', width)
|
|
7035
|
+
.attr('height', 40)
|
|
7036
|
+
.append('xhtml:div')
|
|
7037
|
+
.attr('class', 'title')
|
|
7038
|
+
.style('z-index', 99)
|
|
7039
|
+
.html(this.generateTooltipHtml(d, metaData, value));
|
|
7040
|
+
}
|
|
7041
|
+
calculateTooltipX(d, xScale, width) {
|
|
7042
|
+
const bandwidth = xScale.bandwidth();
|
|
7043
|
+
const numericWidth = typeof width === 'string' ? parseInt(width) : width;
|
|
7044
|
+
if (bandwidth + this.CONSTANTS.LEFT_RIGHT_SPACES * 2 > 180) {
|
|
7045
|
+
return xScale(d.data.name) - this.CONSTANTS.LEFT_RIGHT_SPACES +
|
|
7046
|
+
(bandwidth + this.CONSTANTS.LEFT_RIGHT_SPACES * 2 - 180) / 2;
|
|
7047
|
+
}
|
|
7048
|
+
return xScale(d.data.name) - this.CONSTANTS.LEFT_RIGHT_SPACES;
|
|
7049
|
+
}
|
|
7050
|
+
generateTooltipHtml(d, metaData, value) {
|
|
7051
|
+
if (value === 0)
|
|
7052
|
+
return '<span class="title-top-text">0</span>';
|
|
7053
|
+
const dataType = metaData.dataType || '';
|
|
7054
|
+
const name = d.data.name ? `<span class="title-bar-name">${d.data.name}</span>` : '';
|
|
7055
|
+
const valueText = metaData.unit
|
|
7056
|
+
? `${metaData.unit}${value} ${dataType}`
|
|
7057
|
+
: `${value} ${dataType}`;
|
|
7058
|
+
return `${name}<span class="title-top-text">${valueText}</span>`;
|
|
7059
|
+
}
|
|
7060
|
+
handleMouseOut(svg, metaData) {
|
|
7061
|
+
if (!this.chartConfiguration.displayTitleOnTop)
|
|
7062
|
+
return;
|
|
7063
|
+
svg.selectAll('rect')
|
|
7064
|
+
.style('fill', (d) => this.getBarColor(d, metaData));
|
|
7065
|
+
svg.selectAll('.lib-verticalstack-title-ontop').remove();
|
|
7066
|
+
}
|
|
7067
|
+
renderAxisLabels(svg, svgYAxisLeft, metaData, dimensions, margin) {
|
|
7068
|
+
if (metaData.yLabel) {
|
|
7069
|
+
this.addYAxisLabel(svgYAxisLeft, metaData.yLabel, dimensions.height, margin);
|
|
7070
|
+
}
|
|
7071
|
+
if (metaData.xLabel) {
|
|
7072
|
+
this.addXAxisLabel(svg, metaData.xLabel, dimensions.width, dimensions.height, margin);
|
|
7073
|
+
}
|
|
7074
|
+
}
|
|
7075
|
+
addYAxisLabel(svgYAxisLeft, label, height, margin) {
|
|
7076
|
+
const isria = this.customChartConfiguration?.isRia;
|
|
7077
|
+
const isAcronym = this.isAcronymLabel(label);
|
|
7078
|
+
const yPosition = isria ? -margin.left / 2 - 30 : -margin.left / 2 - 40;
|
|
7079
|
+
svgYAxisLeft.selectAll('.lib-axis-group-label, .lib-ylabel-drilldowncharts, .lib-ylabel-weeklyCharts').remove();
|
|
7080
|
+
svgYAxisLeft
|
|
7081
|
+
.append('text')
|
|
7082
|
+
.attr('class', this.getYAxisLabelClass())
|
|
7083
|
+
.attr('style', this.chartConfiguration.yAxisCustomlabelStyles)
|
|
7084
|
+
.attr('transform', 'rotate(-90)')
|
|
7085
|
+
.attr('y', yPosition)
|
|
7086
|
+
.attr('x', -height / 2)
|
|
7087
|
+
.attr('dy', '1em')
|
|
7088
|
+
.style('text-anchor', 'middle')
|
|
7089
|
+
.style('fill', 'var(--chart-text-color)')
|
|
7090
|
+
.text(isAcronym ? label.toUpperCase() : label.toLowerCase())
|
|
7091
|
+
.style('text-transform', isAcronym ? 'none' : 'capitalize');
|
|
7092
|
+
}
|
|
7093
|
+
addXAxisLabel(svg, label, width, height, margin) {
|
|
7094
|
+
const isria = this.customChartConfiguration?.isRia;
|
|
7095
|
+
const isAcronym = this.isAcronymLabel(label);
|
|
7096
|
+
const xPosition = isria
|
|
7097
|
+
? height + margin.top + margin.bottom
|
|
7098
|
+
: height + margin.top + margin.bottom + 10;
|
|
7099
|
+
svg
|
|
7100
|
+
.append('text')
|
|
7101
|
+
.attr('class', this.getXAxisLabelClass())
|
|
7102
|
+
.attr('style', this.chartConfiguration.xAxisCustomlabelStyles)
|
|
7103
|
+
.attr('transform', `translate(${width / 2},${xPosition})`)
|
|
7104
|
+
.style('text-anchor', 'middle')
|
|
7105
|
+
.style('fill', 'var(--chart-text-color)')
|
|
7106
|
+
.text(isAcronym ? label.toUpperCase() : label.toLowerCase())
|
|
7107
|
+
.style('text-transform', isAcronym ? 'none' : 'capitalize');
|
|
7108
|
+
}
|
|
7109
|
+
isAcronymLabel(label) {
|
|
7110
|
+
const cleanLabel = label.replace(/[^A-Za-z]/g, '');
|
|
7111
|
+
return (label.length <= 4 && /^[A-Z]+$/.test(label)) ||
|
|
7112
|
+
(label === label.toUpperCase() && /[A-Z]/.test(label));
|
|
7113
|
+
}
|
|
7114
|
+
getYAxisLabelClass() {
|
|
7115
|
+
let baseClass = 'lib-axis-group-label font-size-1';
|
|
7116
|
+
if (this.chartConfiguration.isDrilldownChart) {
|
|
7117
|
+
return `${baseClass} lib-ylabel-drilldowncharts`;
|
|
7118
|
+
}
|
|
7119
|
+
if (this.chartConfiguration.isMultiChartGridLine !== undefined) {
|
|
7120
|
+
return `${baseClass} lib-ylabel-weeklyCharts`;
|
|
7121
|
+
}
|
|
7122
|
+
return `${baseClass} lib-axis-waterfall-label`;
|
|
7123
|
+
}
|
|
7124
|
+
getXAxisLabelClass() {
|
|
7125
|
+
let baseClass = 'lib-axis-group-label font-size-1';
|
|
7126
|
+
if (this.chartConfiguration.isDrilldownChart) {
|
|
7127
|
+
return `${baseClass} lib-xlabel-drilldowncharts`;
|
|
7128
|
+
}
|
|
7129
|
+
if (this.chartConfiguration.isMultiChartGridLine !== undefined) {
|
|
7130
|
+
return `${baseClass} lib-xlabel-weeklyCharts`;
|
|
7131
|
+
}
|
|
7132
|
+
return `${baseClass} lib-axis-waterfall-label`;
|
|
7133
|
+
}
|
|
7134
|
+
applyConfigurationFlags() {
|
|
7135
|
+
if (this.chartConfiguration.isHeaderVisible !== undefined) {
|
|
7136
|
+
this.isHeaderVisible = this.chartConfiguration.isHeaderVisible;
|
|
7137
|
+
}
|
|
7138
|
+
if (this.chartConfiguration.isTopCaptionVisible !== undefined) {
|
|
7139
|
+
this.isTopCaptionVisible = this.chartConfiguration.isTopCaptionVisible;
|
|
7140
|
+
}
|
|
7141
|
+
if (this.chartConfiguration.isTransparentBackground !== undefined) {
|
|
7142
|
+
this.isTransparentBackground = this.chartConfiguration.isTransparentBackground;
|
|
7143
|
+
}
|
|
7144
|
+
}
|
|
7145
|
+
initializeStackedChart() {
|
|
7146
|
+
const device = this.getDeviceConfig();
|
|
7147
|
+
this.configureResponsiveSettings(device);
|
|
7148
|
+
this.mergeConfigurations();
|
|
7149
|
+
this.applyConfigurationFlags();
|
|
7150
|
+
const data = this.chartData.data;
|
|
7151
|
+
const metaData = this.prepareMetaData(this.chartData.metaData);
|
|
7152
|
+
const lineData = this.chartData.lineData;
|
|
7153
|
+
const colors = metaData.colors;
|
|
7154
|
+
const keyList = metaData.keyList;
|
|
7155
|
+
const chartContainer = d3.select(this.containerElt.nativeElement);
|
|
7156
|
+
const verticalstackedcontainer = d3.select(this.verticalstackedcontainerElt.nativeElement);
|
|
7157
|
+
const margin = this.chartConfiguration.margin;
|
|
7158
|
+
const dimensions = this.calculateDimensions(chartContainer, verticalstackedcontainer, margin, device, data.length);
|
|
7159
|
+
const { svg, svgYAxisLeft, svgYAxisRight } = this.createSvgContainers(chartContainer, dimensions, margin);
|
|
7160
|
+
// Create stack and layers
|
|
7161
|
+
const stack = d3.stack().keys(keyList).offset(d3.stackOffsetNone);
|
|
7162
|
+
const layers = stack(data);
|
|
7163
|
+
data.sort((a, b) => b.total - a.total);
|
|
7164
|
+
const scales = this.createScales(data, layers, lineData, dimensions, device);
|
|
7165
|
+
const axes = this.createAxes(scales);
|
|
7166
|
+
// Render chart elements
|
|
7167
|
+
this.renderGrids(svg, scales, dimensions);
|
|
7168
|
+
const rect = this.renderBars(svg, layers, scales, metaData, dimensions, device);
|
|
7169
|
+
this.renderAxes(svg, svgYAxisLeft, svgYAxisRight, axes, scales, dimensions, device, data);
|
|
7170
|
+
this.renderAxisLabels(svg, svgYAxisLeft, metaData, dimensions, margin);
|
|
7171
|
+
this.renderTargetLine(svg, svgYAxisRight, scales, dimensions, metaData);
|
|
7172
|
+
this.renderDataLabels(rect, scales, metaData, dimensions);
|
|
7173
|
+
this.renderLineChart(svg, lineData, scales, colors, metaData);
|
|
7174
|
+
}
|
|
7175
|
+
renderGrids(svg, scales, dimensions) {
|
|
7176
|
+
if (this.chartConfiguration.isXgridBetweenLabels) {
|
|
7177
|
+
svg
|
|
7178
|
+
.append('g')
|
|
7179
|
+
.attr('class', 'grid')
|
|
7180
|
+
.attr('transform', `translate(${scales.xScale.bandwidth() / 2},${dimensions.height})`)
|
|
7181
|
+
.call(d3.axisBottom(scales.xScale).tickSize(-dimensions.height).tickFormat(''))
|
|
7182
|
+
.style('stroke-dasharray', '5 5')
|
|
7183
|
+
.style('color', '#999999')
|
|
7184
|
+
.call((g) => g.select('.domain').remove());
|
|
7185
|
+
}
|
|
7186
|
+
if (this.chartConfiguration.yAxisGrid) {
|
|
7187
|
+
svg
|
|
7188
|
+
.append('g')
|
|
7189
|
+
.attr('class', 'grid')
|
|
7190
|
+
.call(d3
|
|
7191
|
+
.axisLeft(scales.yScale)
|
|
7192
|
+
.ticks(this.chartConfiguration.numberOfYTicks)
|
|
7193
|
+
.tickSize(-dimensions.width)
|
|
7194
|
+
.tickFormat(''))
|
|
7195
|
+
.style('color', 'var(--chart-grid-color)')
|
|
7196
|
+
.style('opacity', '1');
|
|
7197
|
+
}
|
|
7198
|
+
if (this.chartConfiguration.xAxisGrid) {
|
|
7199
|
+
for (let j = 0; j < this.chartConfiguration.xAxisGrid.length; j++) {
|
|
7200
|
+
svg
|
|
7201
|
+
.append('g')
|
|
7202
|
+
.attr('class', `x${j + 2} axis${j + 2}`)
|
|
7203
|
+
.style('color', 'var(--chart-grid-color)')
|
|
7204
|
+
.attr('transform', `translate(0,${dimensions.height * this.chartConfiguration.xAxisGrid[j]})`)
|
|
7205
|
+
.call(d3.axisBottom(scales.xScale).tickSize(0).ticks(5).tickFormat(''))
|
|
7206
|
+
.style('fill', 'var(--chart-text-color)');
|
|
7207
|
+
}
|
|
7208
|
+
}
|
|
7209
|
+
}
|
|
7210
|
+
renderAxes(svg, svgYAxisLeft, svgYAxisRight, axes, scales, dimensions, device, data) {
|
|
7211
|
+
if (this.chartConfiguration.showXaxisTop) {
|
|
7212
|
+
svg
|
|
7213
|
+
.append('g')
|
|
7214
|
+
.attr('class', 'lib-line-axis-text lib-line-x-axis-text x-axis')
|
|
7215
|
+
.attr('style', this.chartConfiguration.xAxisCustomTextStyles)
|
|
7216
|
+
.call(d3.axisBottom(scales.xScale).tickSize(0));
|
|
7217
|
+
svg.selectAll('.x-axis > g > text').attr('class', 'lib-display-hidden');
|
|
7218
|
+
}
|
|
7219
|
+
if (!this.chartConfiguration.isMultiChartGridLine) {
|
|
7220
|
+
this.renderStandardAxes(svg, axes, scales, dimensions, device, data);
|
|
7068
7221
|
}
|
|
7069
7222
|
else if (this.chartConfiguration.isDrilldownChart) {
|
|
7070
|
-
this.renderDrilldownAxes(svg, svgYAxisLeft, svgYAxisRight,
|
|
7223
|
+
this.renderDrilldownAxes(svg, svgYAxisLeft, svgYAxisRight, axes, scales, dimensions);
|
|
7071
7224
|
}
|
|
7072
7225
|
else {
|
|
7073
|
-
this.renderMultiChartAxes(svg,
|
|
7226
|
+
this.renderMultiChartAxes(svg, axes, scales, dimensions);
|
|
7074
7227
|
}
|
|
7075
|
-
this.
|
|
7228
|
+
this.applyAxisStyling(svg, svgYAxisLeft, svgYAxisRight);
|
|
7229
|
+
this.applyAxisConfigurations(svg, scales, dimensions, data);
|
|
7076
7230
|
}
|
|
7077
|
-
renderStandardAxes(svg,
|
|
7231
|
+
renderStandardAxes(svg, axes, scales, dimensions, device, data) {
|
|
7078
7232
|
if (device.isMobile) {
|
|
7079
|
-
this.renderMobileXAxis(svg, data,
|
|
7233
|
+
this.renderMobileXAxis(svg, data, dimensions);
|
|
7080
7234
|
}
|
|
7081
7235
|
else {
|
|
7082
7236
|
svg
|
|
7083
7237
|
.append('g')
|
|
7084
|
-
.attr('transform', `translate(0,${height})`)
|
|
7238
|
+
.attr('transform', `translate(0,${dimensions.height})`)
|
|
7085
7239
|
.attr('class', 'lib-stacked-x-axis-text')
|
|
7086
|
-
.call(xAxis)
|
|
7240
|
+
.call(axes.xAxis)
|
|
7087
7241
|
.selectAll('text')
|
|
7088
7242
|
.style('fill', 'var(--chart-text-color)')
|
|
7089
7243
|
.style('font-size', '12px')
|
|
7090
|
-
.attr('text-anchor', 'middle')
|
|
7244
|
+
.attr('text-anchor', 'middle')
|
|
7245
|
+
.attr('dx', '0')
|
|
7246
|
+
.attr('dy', '0.71em')
|
|
7247
|
+
.attr('transform', null);
|
|
7091
7248
|
}
|
|
7092
7249
|
svg
|
|
7093
7250
|
.append('g')
|
|
7094
7251
|
.attr('class', 'lib-stacked-y-axis-text')
|
|
7095
|
-
.
|
|
7252
|
+
.attr('style', this.chartConfiguration.yAxisCustomTextStyles)
|
|
7253
|
+
.call(axes.yAxis)
|
|
7096
7254
|
.selectAll('text')
|
|
7097
7255
|
.style('fill', 'var(--chart-text-color)');
|
|
7098
7256
|
}
|
|
7099
|
-
renderMobileXAxis(svg, data,
|
|
7100
|
-
const barWidth = 32;
|
|
7101
|
-
const barPadding = 12;
|
|
7257
|
+
renderMobileXAxis(svg, data, dimensions) {
|
|
7102
7258
|
svg.selectAll('.custom-x-label').remove();
|
|
7103
7259
|
data.forEach((d, i) => {
|
|
7104
|
-
const xVal = this.
|
|
7260
|
+
const xVal = this.CONSTANTS.LEFT_RIGHT_SPACES +
|
|
7261
|
+
i * (dimensions.barWidth + dimensions.barPadding) +
|
|
7262
|
+
dimensions.barWidth / 2;
|
|
7105
7263
|
svg
|
|
7106
7264
|
.append('text')
|
|
7107
7265
|
.attr('class', 'custom-x-label')
|
|
7108
7266
|
.attr('x', 0)
|
|
7109
|
-
.attr('y', height + 18)
|
|
7267
|
+
.attr('y', dimensions.height + 18)
|
|
7110
7268
|
.attr('text-anchor', 'middle')
|
|
7111
7269
|
.attr('transform', `translate(${xVal + 20},0)`)
|
|
7112
7270
|
.style('font-size', '10px')
|
|
@@ -7115,204 +7273,350 @@ class HorizontalBarsWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
7115
7273
|
.text(d.name.substring(0, 3));
|
|
7116
7274
|
});
|
|
7117
7275
|
}
|
|
7118
|
-
renderDrilldownAxes(svg, svgYAxisLeft, svgYAxisRight,
|
|
7276
|
+
renderDrilldownAxes(svg, svgYAxisLeft, svgYAxisRight, axes, scales, dimensions) {
|
|
7119
7277
|
svg
|
|
7120
7278
|
.append('g')
|
|
7121
|
-
.attr('transform', `translate(0,${height})`)
|
|
7279
|
+
.attr('transform', `translate(0,${dimensions.height})`)
|
|
7122
7280
|
.attr('class', 'lib-stacked-x-axis-text multichart1')
|
|
7123
|
-
.call(xAxis)
|
|
7281
|
+
.call(axes.xAxis)
|
|
7124
7282
|
.style('display', 'none');
|
|
7125
7283
|
svgYAxisLeft
|
|
7126
7284
|
.append('g')
|
|
7127
7285
|
.attr('class', 'lib-yaxis-labels-texts-drilldown yaxis-dashed')
|
|
7128
|
-
.
|
|
7286
|
+
.attr('style', this.chartConfiguration.yAxisCustomTextStyles)
|
|
7287
|
+
.call(axes.yAxis)
|
|
7129
7288
|
.selectAll('text')
|
|
7130
7289
|
.style('fill', 'var(--chart-text-color)');
|
|
7131
7290
|
svgYAxisRight
|
|
7132
7291
|
.append('g')
|
|
7133
7292
|
.attr('class', 'lib-yaxis-labels-texts-drilldown yaxis-dashed')
|
|
7134
|
-
.
|
|
7293
|
+
.attr('style', this.chartConfiguration.yAxisCustomTextStyles)
|
|
7294
|
+
.call(axes.yAxis)
|
|
7135
7295
|
.style('display', 'none');
|
|
7136
7296
|
}
|
|
7137
|
-
renderMultiChartAxes(svg,
|
|
7297
|
+
renderMultiChartAxes(svg, axes, scales, dimensions) {
|
|
7138
7298
|
svg
|
|
7139
7299
|
.append('g')
|
|
7140
|
-
.attr('transform', `translate(0,${height})`)
|
|
7300
|
+
.attr('transform', `translate(0,${dimensions.height})`)
|
|
7141
7301
|
.attr('class', 'lib-stacked-x-axis-text multichart')
|
|
7142
|
-
.call(xAxis)
|
|
7302
|
+
.call(axes.xAxis)
|
|
7143
7303
|
.selectAll('text')
|
|
7144
7304
|
.style('fill', 'var(--chart-text-color)');
|
|
7145
7305
|
svg
|
|
7146
7306
|
.append('g')
|
|
7147
7307
|
.attr('class', 'lib-stacked-y-axis-text yaxis-dashed')
|
|
7148
|
-
.
|
|
7308
|
+
.attr('style', this.chartConfiguration.yAxisCustomTextStyles)
|
|
7309
|
+
.call(axes.yAxis)
|
|
7149
7310
|
.selectAll('text')
|
|
7150
7311
|
.style('fill', 'var(--chart-text-color)');
|
|
7151
7312
|
}
|
|
7152
|
-
|
|
7153
|
-
const
|
|
7154
|
-
|
|
7155
|
-
|
|
7313
|
+
applyAxisStyling(svg, svgYAxisLeft, svgYAxisRight) {
|
|
7314
|
+
const styleAxisDomain = (container) => {
|
|
7315
|
+
container.selectAll('.domain')
|
|
7316
|
+
.style('stroke', 'var(--chart-axis-color)')
|
|
7317
|
+
.style('stroke-width', '1px');
|
|
7156
7318
|
};
|
|
7157
|
-
|
|
7158
|
-
|
|
7159
|
-
|
|
7160
|
-
|
|
7161
|
-
|
|
7162
|
-
|
|
7163
|
-
|
|
7164
|
-
if (metaData.yLabel) {
|
|
7165
|
-
this.renderYAxisLabel(svgYAxisLeft, metaData.yLabel, height, margin);
|
|
7319
|
+
styleAxisDomain(svg);
|
|
7320
|
+
styleAxisDomain(svgYAxisLeft);
|
|
7321
|
+
styleAxisDomain(svgYAxisRight);
|
|
7322
|
+
if (this.chartConfiguration.isYaxisDashed) {
|
|
7323
|
+
d3.selectAll('.yaxis-dashed')
|
|
7324
|
+
.style('stroke-dasharray', '5 5')
|
|
7325
|
+
.style('color', 'var(--chart-grid-color)');
|
|
7166
7326
|
}
|
|
7167
|
-
if (
|
|
7168
|
-
|
|
7327
|
+
if (this.chartConfiguration.isXaxisColor) {
|
|
7328
|
+
d3.selectAll('.multichart').style('color', this.chartConfiguration.isXaxisColor || 'var(--chart-text-color)');
|
|
7169
7329
|
}
|
|
7170
7330
|
}
|
|
7171
|
-
|
|
7172
|
-
|
|
7173
|
-
|
|
7174
|
-
const isRia = this.customChartConfiguration?.isRia;
|
|
7175
|
-
const yPosition = isRia ? -margin.left / 2 - 30 : -margin.left / 2 - 40;
|
|
7176
|
-
let labelClass = 'lib-axis-group-label font-size-1';
|
|
7177
|
-
if (this.chartConfiguration.isDrilldownChart) {
|
|
7178
|
-
labelClass += ' lib-ylabel-drilldowncharts';
|
|
7331
|
+
applyAxisConfigurations(svg, scales, dimensions, data) {
|
|
7332
|
+
if (this.chartConfiguration.isMultiChartGridLine !== undefined) {
|
|
7333
|
+
d3.selectAll('.multichart > g > text').attr('class', 'lib-display-hidden');
|
|
7179
7334
|
}
|
|
7180
|
-
|
|
7181
|
-
|
|
7335
|
+
if (this.chartConfiguration.isXaxisLabelHidden) {
|
|
7336
|
+
d3.selectAll('.multichart > g > text').attr('class', 'lib-display-hidden');
|
|
7182
7337
|
}
|
|
7183
|
-
else {
|
|
7184
|
-
|
|
7338
|
+
else if (this.chartConfiguration.isXaxisLabelHidden !== undefined) {
|
|
7339
|
+
this.renderCustomXAxis(svg, scales, dimensions, data);
|
|
7185
7340
|
}
|
|
7186
|
-
|
|
7341
|
+
if (this.chartConfiguration.isYaxisLabelHidden) {
|
|
7342
|
+
svg.selectAll('.yaxis-dashed > g > text').attr('class', 'lib-display-hidden');
|
|
7343
|
+
}
|
|
7344
|
+
if (this.chartConfiguration.isYaxisHidden) {
|
|
7345
|
+
d3.selectAll('.yaxis-dashed').attr('class', 'lib-display-hidden');
|
|
7346
|
+
}
|
|
7347
|
+
if (this.isZoomedOut && data.length > 9) {
|
|
7348
|
+
svg
|
|
7349
|
+
.selectAll('.lib-xaxis-labels-texts-drilldown')
|
|
7350
|
+
.attr('transform', 'rotate(-90)')
|
|
7351
|
+
.attr('text-anchor', 'end')
|
|
7352
|
+
.attr('x', '-5')
|
|
7353
|
+
.attr('dy', null);
|
|
7354
|
+
}
|
|
7355
|
+
}
|
|
7356
|
+
renderCustomXAxis(svg, scales, dimensions, data) {
|
|
7357
|
+
const device = this.getDeviceConfig();
|
|
7358
|
+
svg
|
|
7359
|
+
.append('g')
|
|
7360
|
+
.attr('class', 'x1 axis1')
|
|
7361
|
+
.attr('transform', `translate(0,${dimensions.height})`)
|
|
7362
|
+
.style('color', '#000')
|
|
7363
|
+
.call(d3.axisBottom(scales.xScale).tickSize(0))
|
|
7364
|
+
.call((g) => g.select('.domain').attr('fill', 'none'));
|
|
7365
|
+
this.styleCustomXAxisTicks(svg, data, device);
|
|
7366
|
+
if (this.chartConfiguration.xLabelsOnSameLine) {
|
|
7367
|
+
this.applyXLabelsOnSameLine(svg, device);
|
|
7368
|
+
}
|
|
7369
|
+
}
|
|
7370
|
+
styleCustomXAxisTicks(svg, data, device) {
|
|
7371
|
+
let alternateText = false;
|
|
7372
|
+
svg.selectAll('.x1.axis1 .tick line').attr('y2', () => {
|
|
7373
|
+
if (this.chartConfiguration.hideXaxisTick)
|
|
7374
|
+
return 0;
|
|
7375
|
+
if (alternateText && !this.chartConfiguration.isNoAlternateXaxisText) {
|
|
7376
|
+
alternateText = false;
|
|
7377
|
+
return this.CONSTANTS.LONG_TICK_LENGTH_BG - 7;
|
|
7378
|
+
}
|
|
7379
|
+
alternateText = true;
|
|
7380
|
+
return this.CONSTANTS.SHORT_TICK_LENGTH_BG - 4;
|
|
7381
|
+
});
|
|
7382
|
+
alternateText = false;
|
|
7383
|
+
svg
|
|
7384
|
+
.selectAll('g.x1.axis1 g.tick text')
|
|
7385
|
+
.attr('class', () => {
|
|
7386
|
+
if (this.chartConfiguration.isDrilldownChart) {
|
|
7387
|
+
return data.length > 8
|
|
7388
|
+
? 'lib-xaxis-labels-texts-drilldown-alt'
|
|
7389
|
+
: 'lib-xaxis-labels-texts-drilldown';
|
|
7390
|
+
}
|
|
7391
|
+
return 'lib-xaxis-labels-texts-weeklycharts';
|
|
7392
|
+
})
|
|
7393
|
+
.attr('y', () => {
|
|
7394
|
+
if (alternateText) {
|
|
7395
|
+
alternateText = false;
|
|
7396
|
+
return this.CONSTANTS.LONG_TICK_LENGTH_BG;
|
|
7397
|
+
}
|
|
7398
|
+
alternateText = true;
|
|
7399
|
+
return this.CONSTANTS.SHORT_TICK_LENGTH_BG;
|
|
7400
|
+
});
|
|
7401
|
+
}
|
|
7402
|
+
applyXLabelsOnSameLine(svg, device) {
|
|
7403
|
+
svg
|
|
7404
|
+
.selectAll('g.x1.axis1 g.tick text')
|
|
7405
|
+
.attr('class', 'lib-xaxis-labels-texts-drilldown')
|
|
7406
|
+
.attr('y', this.CONSTANTS.SHORT_TICK_LENGTH_BG)
|
|
7407
|
+
.text((d) => {
|
|
7408
|
+
if (device.isMobile) {
|
|
7409
|
+
return d.split(' ')[0].substring(0, 3);
|
|
7410
|
+
}
|
|
7411
|
+
const trimmed = d.trim();
|
|
7412
|
+
const spaceIndex = trimmed.indexOf(' ');
|
|
7413
|
+
return spaceIndex > -1
|
|
7414
|
+
? trimmed.substring(0, spaceIndex).toLowerCase()
|
|
7415
|
+
: trimmed.toLowerCase();
|
|
7416
|
+
})
|
|
7417
|
+
.attr('transform', function (d, i) {
|
|
7418
|
+
if (device.isMobile) {
|
|
7419
|
+
const parent = this.parentNode?.parentNode;
|
|
7420
|
+
const totalBars = parent ? d3.select(parent).selectAll('g.tick').size() : 0;
|
|
7421
|
+
return totalBars === 2 ? 'translate(0,0)' : `translate(${i * 30},0)`;
|
|
7422
|
+
}
|
|
7423
|
+
return null;
|
|
7424
|
+
});
|
|
7425
|
+
svg
|
|
7426
|
+
.selectAll('g.x1.axis1 g.tick')
|
|
7187
7427
|
.append('text')
|
|
7188
|
-
.attr('class',
|
|
7189
|
-
.attr('
|
|
7190
|
-
.attr('
|
|
7191
|
-
.
|
|
7192
|
-
.
|
|
7193
|
-
|
|
7194
|
-
.
|
|
7195
|
-
.
|
|
7196
|
-
|
|
7197
|
-
|
|
7428
|
+
.attr('class', 'lib-xaxis-labels-texts-drilldown')
|
|
7429
|
+
.attr('y', this.CONSTANTS.LONG_TICK_LENGTH_BG)
|
|
7430
|
+
.attr('fill', 'currentColor')
|
|
7431
|
+
.text((d) => {
|
|
7432
|
+
if (device.isMobile)
|
|
7433
|
+
return '';
|
|
7434
|
+
const trimmed = d.trim();
|
|
7435
|
+
const spaceIndex = trimmed.indexOf(' ');
|
|
7436
|
+
return spaceIndex > -1
|
|
7437
|
+
? trimmed.substring(spaceIndex).toLowerCase()
|
|
7438
|
+
: '';
|
|
7439
|
+
})
|
|
7440
|
+
.attr('transform', (d, i) => {
|
|
7441
|
+
return device.isMobile && i === 0 ? 'translate(20,0)' : null;
|
|
7442
|
+
});
|
|
7198
7443
|
}
|
|
7199
|
-
|
|
7200
|
-
|
|
7201
|
-
|
|
7202
|
-
const xPosition = isRia
|
|
7203
|
-
? height + margin.top + margin.bottom
|
|
7204
|
-
: height + margin.top + margin.bottom + 10;
|
|
7205
|
-
let labelClass = 'lib-axis-group-label font-size-1';
|
|
7206
|
-
if (this.chartConfiguration.isDrilldownChart) {
|
|
7207
|
-
labelClass += ' lib-xlabel-drilldowncharts';
|
|
7444
|
+
renderDataLabels(rect, scales, metaData, dimensions) {
|
|
7445
|
+
if (!this.isCC && !this.chartConfiguration.isMultiChartGridLine) {
|
|
7446
|
+
rect.append('svg:title').text((d) => d[1] - d[0]);
|
|
7208
7447
|
}
|
|
7209
|
-
|
|
7210
|
-
|
|
7448
|
+
if (this.chartConfiguration.showTotalOnTop) {
|
|
7449
|
+
this.renderTopLabels(rect, scales, metaData);
|
|
7211
7450
|
}
|
|
7212
|
-
|
|
7213
|
-
|
|
7451
|
+
if (this.chartConfiguration.showAngledLabels) {
|
|
7452
|
+
this.renderAngledLabels(rect, scales, metaData);
|
|
7214
7453
|
}
|
|
7215
|
-
|
|
7454
|
+
}
|
|
7455
|
+
renderTopLabels(rect, scales, metaData) {
|
|
7456
|
+
const formatFromBackend = this.chartConfiguration.textFormatter
|
|
7457
|
+
? ChartHelper.dataValueFormatter(this.chartConfiguration.textFormatter)
|
|
7458
|
+
: (d) => d;
|
|
7459
|
+
const formatForHugeNumbers = ChartHelper.dataValueFormatter('.2s');
|
|
7460
|
+
rect
|
|
7216
7461
|
.append('text')
|
|
7217
|
-
.attr('
|
|
7218
|
-
.attr('
|
|
7219
|
-
.attr('
|
|
7220
|
-
.
|
|
7221
|
-
|
|
7222
|
-
|
|
7223
|
-
|
|
7462
|
+
.attr('x', (d) => scales.xScale(d.data.name) + scales.xScale.bandwidth() / 2)
|
|
7463
|
+
.attr('class', 'lib-verticalstack-labels-ontop-weklycharts')
|
|
7464
|
+
.attr('y', (d) => scales.yScale(d[1]) - 3)
|
|
7465
|
+
.text((d) => {
|
|
7466
|
+
const value = d[1] - d[0];
|
|
7467
|
+
if (isNaN(value) || value === 0)
|
|
7468
|
+
return;
|
|
7469
|
+
const formattedValue = value <= 999
|
|
7470
|
+
? formatFromBackend(value)
|
|
7471
|
+
: formatForHugeNumbers(value);
|
|
7472
|
+
return metaData.unit ? metaData.unit + formattedValue : formattedValue;
|
|
7473
|
+
});
|
|
7224
7474
|
}
|
|
7225
|
-
|
|
7226
|
-
const
|
|
7227
|
-
|
|
7475
|
+
renderAngledLabels(rect, scales, metaData) {
|
|
7476
|
+
const formatFromBackend = this.chartConfiguration.textFormatter
|
|
7477
|
+
? ChartHelper.dataValueFormatter(this.chartConfiguration.textFormatter)
|
|
7478
|
+
: (d) => d;
|
|
7479
|
+
const formatForHugeNumbers = ChartHelper.dataValueFormatter('.2s');
|
|
7480
|
+
const tempObjectHolder = {};
|
|
7481
|
+
rect
|
|
7482
|
+
.append('text')
|
|
7483
|
+
.attr('x', 0)
|
|
7484
|
+
.attr('y', 0)
|
|
7485
|
+
.attr('fill', (d) => metaData.colors[d.key])
|
|
7486
|
+
.attr('class', 'lib-data-labels-angled-weeklycharts')
|
|
7487
|
+
.text((d) => {
|
|
7488
|
+
const value = d[1] - d[0];
|
|
7489
|
+
if (isNaN(value) || value <= 0)
|
|
7490
|
+
return;
|
|
7491
|
+
const formattedValue = value <= 999
|
|
7492
|
+
? formatFromBackend(value)
|
|
7493
|
+
: formatForHugeNumbers(value);
|
|
7494
|
+
return metaData.unit ? metaData.unit + formattedValue : formattedValue;
|
|
7495
|
+
})
|
|
7496
|
+
.attr('transform', (d) => {
|
|
7497
|
+
const value = d[1] - d[0];
|
|
7498
|
+
if (isNaN(value) || value <= 0)
|
|
7499
|
+
return 'rotate(0)';
|
|
7500
|
+
let total = 0;
|
|
7501
|
+
let incrementer = 1;
|
|
7502
|
+
metaData.keyList.forEach(key => {
|
|
7503
|
+
if (d.data[key]) {
|
|
7504
|
+
total += d.data[key];
|
|
7505
|
+
}
|
|
7506
|
+
else {
|
|
7507
|
+
incrementer = 2;
|
|
7508
|
+
}
|
|
7509
|
+
});
|
|
7510
|
+
tempObjectHolder[d.data.name] = (tempObjectHolder[d.data.name] || 0) + incrementer;
|
|
7511
|
+
const position = tempObjectHolder[d.data.name];
|
|
7512
|
+
const xPos = scales.xScale(d.data.name);
|
|
7513
|
+
const bandwidth = scales.xScale.bandwidth();
|
|
7514
|
+
const yPos = scales.yScale(total) - 3;
|
|
7515
|
+
switch (position) {
|
|
7516
|
+
case 1:
|
|
7517
|
+
return `translate(${xPos + bandwidth / 3},${yPos}) rotate(270)`;
|
|
7518
|
+
case 2:
|
|
7519
|
+
return `translate(${xPos + bandwidth / 2 + 2},${yPos}) rotate(270)`;
|
|
7520
|
+
default:
|
|
7521
|
+
return `translate(${xPos + (bandwidth * 3) / 4},${yPos}) rotate(270)`;
|
|
7522
|
+
}
|
|
7523
|
+
});
|
|
7524
|
+
}
|
|
7525
|
+
renderTargetLine(svg, svgYAxisRight, scales, dimensions, metaData) {
|
|
7526
|
+
if (!this.chartData.targetLineData)
|
|
7527
|
+
return;
|
|
7528
|
+
const parsedTarget = this.parseTargetValue(this.chartData.targetLineData.target);
|
|
7529
|
+
const yZero = scales.yScale(parsedTarget);
|
|
7228
7530
|
svg
|
|
7229
7531
|
.append('line')
|
|
7230
7532
|
.attr('x1', 0)
|
|
7231
|
-
.attr('x2', width)
|
|
7533
|
+
.attr('x2', dimensions.width)
|
|
7232
7534
|
.attr('y1', yZero)
|
|
7233
7535
|
.attr('y2', yZero)
|
|
7234
7536
|
.style('stroke-dasharray', '5 5')
|
|
7235
7537
|
.style('stroke', this.chartData.targetLineData.color);
|
|
7236
|
-
|
|
7237
|
-
|
|
7538
|
+
this.renderTargetLabel(svgYAxisRight, yZero, metaData);
|
|
7539
|
+
}
|
|
7540
|
+
parseTargetValue(target) {
|
|
7541
|
+
const parsed = parseFloat(String(target));
|
|
7542
|
+
if (isNaN(parsed))
|
|
7543
|
+
return 0;
|
|
7544
|
+
return Number.isInteger(parsed) ? parseInt(String(target)) : parsed;
|
|
7545
|
+
}
|
|
7546
|
+
renderTargetLabel(svgYAxisRight, yZero, metaData) {
|
|
7238
7547
|
const dataType = metaData.dataType || '';
|
|
7548
|
+
const targetName = this.chartData.targetLineData.targetName || 'target';
|
|
7239
7549
|
svgYAxisRight
|
|
7240
7550
|
.append('foreignObject')
|
|
7241
7551
|
.attr('transform', `translate(0,${yZero - 13})`)
|
|
7242
|
-
.attr('width', this.
|
|
7552
|
+
.attr('width', this.CONSTANTS.RIGHT_SVG_WIDTH)
|
|
7243
7553
|
.attr('height', 50)
|
|
7244
7554
|
.append('xhtml:div')
|
|
7245
7555
|
.attr('class', 'target-display')
|
|
7246
7556
|
.style('color', 'var(--chart-text-color)')
|
|
7247
|
-
.html(
|
|
7248
|
-
<div>${targetLineName}</div>
|
|
7249
|
-
<div>${targetValue}${dataType}</div>
|
|
7250
|
-
`);
|
|
7557
|
+
.html(`<div>${targetName}</div><div>${this.chartData.targetLineData.target}${dataType}</div>`);
|
|
7251
7558
|
}
|
|
7252
|
-
renderLineChart(svg, lineData,
|
|
7253
|
-
|
|
7254
|
-
|
|
7255
|
-
.domain([0, d3.max(lineData, (d) => +d.value) || 0])
|
|
7256
|
-
.range([height, 0]);
|
|
7559
|
+
renderLineChart(svg, lineData, scales, colors, metaData) {
|
|
7560
|
+
if (!lineData || !colors)
|
|
7561
|
+
return;
|
|
7257
7562
|
const dataGroup = d3
|
|
7258
7563
|
.nest()
|
|
7259
7564
|
.key((d) => d.category)
|
|
7260
7565
|
.entries(lineData);
|
|
7261
7566
|
const lineGen = d3
|
|
7262
7567
|
.line()
|
|
7263
|
-
.x((d) => xScale(d.name) + xScale.bandwidth() / 2)
|
|
7264
|
-
.y((d) => lineYscale(d.value));
|
|
7568
|
+
.x((d) => scales.xScale(d.name) + scales.xScale.bandwidth() / 2)
|
|
7569
|
+
.y((d) => scales.lineYscale(d.value));
|
|
7265
7570
|
dataGroup.forEach((group) => {
|
|
7266
|
-
// Draw line
|
|
7267
7571
|
svg
|
|
7268
7572
|
.append('path')
|
|
7269
7573
|
.datum(group.values)
|
|
7270
7574
|
.attr('fill', 'none')
|
|
7271
7575
|
.attr('stroke', (d) => {
|
|
7272
|
-
|
|
7273
|
-
|
|
7274
|
-
|
|
7275
|
-
return this.chartConfiguration.lineGraphColor;
|
|
7576
|
+
return d[0]?.category
|
|
7577
|
+
? colors[d[0].category]
|
|
7578
|
+
: this.chartConfiguration.lineGraphColor;
|
|
7276
7579
|
})
|
|
7277
7580
|
.attr('stroke-width', 2.5)
|
|
7278
|
-
.attr('d', lineGen
|
|
7279
|
-
|
|
7280
|
-
const dot = svg
|
|
7281
|
-
.selectAll('myCircles')
|
|
7282
|
-
.data(group.values)
|
|
7283
|
-
.enter()
|
|
7284
|
-
.append('g')
|
|
7285
|
-
.on('click', (d) => this.handleClick(d));
|
|
7286
|
-
dot
|
|
7287
|
-
.append('circle')
|
|
7288
|
-
.attr('fill', (d) => {
|
|
7289
|
-
if ('category' in d) {
|
|
7290
|
-
return colors[d.category];
|
|
7291
|
-
}
|
|
7292
|
-
return this.chartConfiguration.lineGraphColor;
|
|
7293
|
-
})
|
|
7294
|
-
.attr('stroke', 'none')
|
|
7295
|
-
.attr('cx', (d) => xScale(d.name) + xScale.bandwidth() / 2)
|
|
7296
|
-
.attr('cy', (d) => lineYscale(d.value))
|
|
7297
|
-
.attr('r', 3)
|
|
7298
|
-
.style('cursor', 'pointer');
|
|
7299
|
-
// Add labels if configured
|
|
7300
|
-
if (this.chartConfiguration.lineGraphColor) {
|
|
7301
|
-
dot
|
|
7302
|
-
.append('text')
|
|
7303
|
-
.attr('class', 'dots')
|
|
7304
|
-
.attr('fill', this.chartConfiguration.lineGraphColor)
|
|
7305
|
-
.attr('style', 'font-size: 0.85em; font-weight: bold')
|
|
7306
|
-
.attr('x', (d) => xScale(d.name) + xScale.bandwidth() / 2)
|
|
7307
|
-
.attr('y', (d) => lineYscale(d.value))
|
|
7308
|
-
.attr('dy', '-1em')
|
|
7309
|
-
.text((d) => this.chartConfiguration.labelFormatter(d.value));
|
|
7310
|
-
}
|
|
7581
|
+
.attr('d', lineGen);
|
|
7582
|
+
this.renderLineDots(svg, group.values, scales, colors);
|
|
7311
7583
|
});
|
|
7312
7584
|
}
|
|
7313
|
-
|
|
7314
|
-
|
|
7315
|
-
|
|
7585
|
+
renderLineDots(svg, values, scales, colors) {
|
|
7586
|
+
const dot = svg
|
|
7587
|
+
.selectAll('.line-dots')
|
|
7588
|
+
.data(values)
|
|
7589
|
+
.enter()
|
|
7590
|
+
.append('g')
|
|
7591
|
+
.on('click', (d) => this.handleClick(d));
|
|
7592
|
+
dot
|
|
7593
|
+
.append('circle')
|
|
7594
|
+
.attr('fill', (d) => {
|
|
7595
|
+
return d.category
|
|
7596
|
+
? colors[d.category]
|
|
7597
|
+
: this.chartConfiguration.lineGraphColor;
|
|
7598
|
+
})
|
|
7599
|
+
.attr('stroke', 'none')
|
|
7600
|
+
.attr('cx', (d) => scales.xScale(d.name) + scales.xScale.bandwidth() / 2)
|
|
7601
|
+
.attr('cy', (d) => scales.lineYscale(d.value))
|
|
7602
|
+
.attr('r', 3)
|
|
7603
|
+
.style('cursor', 'pointer');
|
|
7604
|
+
if (this.chartConfiguration.lineGraphColor) {
|
|
7605
|
+
dot
|
|
7606
|
+
.append('text')
|
|
7607
|
+
.attr('class', 'dots')
|
|
7608
|
+
.attr('fill', this.chartConfiguration.lineGraphColor)
|
|
7609
|
+
.style('font-size', '.85em')
|
|
7610
|
+
.style('font-weight', 'bold')
|
|
7611
|
+
.attr('x', (d) => scales.xScale(d.name) + scales.xScale.bandwidth() / 2)
|
|
7612
|
+
.attr('y', (d) => scales.lineYscale(d.value))
|
|
7613
|
+
.attr('dy', '-1em')
|
|
7614
|
+
.text((d) => this.chartConfiguration.labelFormatter(d.value));
|
|
7615
|
+
}
|
|
7616
|
+
}
|
|
7617
|
+
handleClick(d) {
|
|
7618
|
+
if (this.chartData?.metaData?.hasDrillDown || d?.toggleFrom) {
|
|
7619
|
+
this.clickEvent.emit(d);
|
|
7316
7620
|
}
|
|
7317
7621
|
}
|
|
7318
7622
|
handleHeaderMenuClick(id) {
|
|
@@ -7455,6 +7759,9 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
7455
7759
|
var alternate_text = false;
|
|
7456
7760
|
var short_tick_length = 4;
|
|
7457
7761
|
var long_tick_length = 16;
|
|
7762
|
+
/**
|
|
7763
|
+
* longer tick length needed for weekly charts
|
|
7764
|
+
*/
|
|
7458
7765
|
var short_tick_length_bg = 5;
|
|
7459
7766
|
var long_tick_length_bg = 30;
|
|
7460
7767
|
var leftAndRightSpaces = 50;
|
|
@@ -7466,6 +7773,9 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
7466
7773
|
data = this.chartData.data;
|
|
7467
7774
|
metaData = this.chartData.metaData;
|
|
7468
7775
|
lineData = this.chartData.lineData;
|
|
7776
|
+
// if (lineData || this.chartData.targetLineData) {
|
|
7777
|
+
// rightSvgWidth = 60;
|
|
7778
|
+
// }
|
|
7469
7779
|
if (!metaData.colorAboveTarget) {
|
|
7470
7780
|
metaData['colorAboveTarget'] = metaData.colors;
|
|
7471
7781
|
}
|
|
@@ -7502,10 +7812,16 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
7502
7812
|
else
|
|
7503
7813
|
width = this.chartData.data.length * 160;
|
|
7504
7814
|
}
|
|
7815
|
+
// if (this.chartData.data.length > 8) {
|
|
7816
|
+
// width = this.chartData.data.length * 140;
|
|
7817
|
+
// }
|
|
7505
7818
|
var height = parseInt(verticalstackedcontainer.style('height')) *
|
|
7506
7819
|
(self.chartConfiguration.svgHeight / 100) -
|
|
7507
7820
|
margin.top -
|
|
7508
7821
|
margin.bottom;
|
|
7822
|
+
/**
|
|
7823
|
+
* entire height used in weekly charts as x axis needed to be displayed at the bottom of the chart
|
|
7824
|
+
*/
|
|
7509
7825
|
if (this.chartConfiguration.isFullScreen != undefined &&
|
|
7510
7826
|
this.chartConfiguration.isFullScreen) {
|
|
7511
7827
|
height =
|
|
@@ -7527,15 +7843,30 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
7527
7843
|
margin.bottom -
|
|
7528
7844
|
100;
|
|
7529
7845
|
}
|
|
7846
|
+
/**
|
|
7847
|
+
* for hiding header
|
|
7848
|
+
* used by weekly charts
|
|
7849
|
+
*/
|
|
7530
7850
|
if (this.chartConfiguration.isHeaderVisible != undefined)
|
|
7531
7851
|
this.isHeaderVisible = this.chartConfiguration.isHeaderVisible;
|
|
7852
|
+
/**
|
|
7853
|
+
* for hiding legends
|
|
7854
|
+
* used by weekly charts
|
|
7855
|
+
*/
|
|
7532
7856
|
if (this.chartConfiguration.legendVisible != undefined) {
|
|
7533
7857
|
this.legendVisible = this.chartConfiguration.legendVisible;
|
|
7534
7858
|
}
|
|
7859
|
+
/**
|
|
7860
|
+
* for removing background color so that it can take parents color
|
|
7861
|
+
*
|
|
7862
|
+
*/
|
|
7535
7863
|
if (this.chartConfiguration.isTransparentBackground != undefined) {
|
|
7536
7864
|
this.isTransparentBackground =
|
|
7537
7865
|
this.chartConfiguration.isTransparentBackground;
|
|
7538
7866
|
}
|
|
7867
|
+
/**
|
|
7868
|
+
* format data values based on configuration received
|
|
7869
|
+
*/
|
|
7539
7870
|
if (this.chartConfiguration.textFormatter != undefined) {
|
|
7540
7871
|
formatFromBackend = ChartHelper.dataValueFormatter(this.chartConfiguration.textFormatter);
|
|
7541
7872
|
formatForHugeNumbers = ChartHelper.dataValueFormatter('.2s');
|
|
@@ -7548,6 +7879,7 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
7548
7879
|
.style('height', height)
|
|
7549
7880
|
.style('overflow-x', 'hidden')
|
|
7550
7881
|
.style('padding-left', `${margin.left}px`)
|
|
7882
|
+
// .call(ChartHelper.responsivefy)
|
|
7551
7883
|
.style('padding-right', `${rightSvgWidth}px`)
|
|
7552
7884
|
.style('margin-left', '15px');
|
|
7553
7885
|
var svgYAxisLeft = outerContainer
|
|
@@ -7575,8 +7907,10 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
7575
7907
|
.style('overflow-x', 'auto');
|
|
7576
7908
|
var svg = innerContainer
|
|
7577
7909
|
.append('svg')
|
|
7910
|
+
// .attr('id', self.uniqueId)
|
|
7578
7911
|
.attr('width', width - rightSvgWidth)
|
|
7579
7912
|
.attr('height', height + margin.top + margin.bottom + 60)
|
|
7913
|
+
// .call(ChartHelper.responsivefy)
|
|
7580
7914
|
.append('g')
|
|
7581
7915
|
.attr('transform', 'translate(' + 0 + ',' + margin.top + ')');
|
|
7582
7916
|
var subgroups = keyList;
|
|
@@ -7585,6 +7919,9 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
7585
7919
|
return d.name;
|
|
7586
7920
|
})
|
|
7587
7921
|
.keys();
|
|
7922
|
+
/**
|
|
7923
|
+
* x axis range made similar to line chart or vertical stack so that all the charts will get aligned with each other.
|
|
7924
|
+
*/
|
|
7588
7925
|
if (this.chartConfiguration.isMultiChartGridLine != undefined) {
|
|
7589
7926
|
x = d3
|
|
7590
7927
|
.scaleBand()
|
|
@@ -7602,11 +7939,27 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
7602
7939
|
.range([leftAndRightSpaces, width - rightSvgWidth - leftAndRightSpaces])
|
|
7603
7940
|
.padding([0.3]);
|
|
7604
7941
|
}
|
|
7942
|
+
// x.bandwidth(96);
|
|
7605
7943
|
var xScaleFromOrigin = d3
|
|
7606
7944
|
.scaleBand()
|
|
7607
7945
|
.domain(groups)
|
|
7608
7946
|
.range([0, width - rightSvgWidth]);
|
|
7947
|
+
// .padding([0.2]);
|
|
7948
|
+
/**
|
|
7949
|
+
* draw second x axis on top
|
|
7950
|
+
*/
|
|
7951
|
+
// if (self.chartConfiguration.showXaxisTop) {
|
|
7952
|
+
// svg
|
|
7953
|
+
// .append('g')
|
|
7954
|
+
// .attr('class', 'lib-line-axis-text lib-line-x-axis-text x-axis')
|
|
7955
|
+
// .attr('style', self.chartConfiguration.xAxisCustomTextStyles)
|
|
7956
|
+
// .call(d3.axisBottom(x).tickSize(0));
|
|
7957
|
+
// }
|
|
7958
|
+
// d3.svg.axis().scale(x).orient('bottom').ticks(1).innerTickSize(-height);
|
|
7609
7959
|
if (this.chartConfiguration.isMultiChartGridLine == undefined) {
|
|
7960
|
+
/**
|
|
7961
|
+
* normal ticks for all dashboard charts
|
|
7962
|
+
*/
|
|
7610
7963
|
svg
|
|
7611
7964
|
.append('g')
|
|
7612
7965
|
.attr('class', 'x1 axis1')
|
|
@@ -7614,12 +7967,13 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
7614
7967
|
.call(d3.axisBottom(x))
|
|
7615
7968
|
.call((g) => g.select('.domain').remove());
|
|
7616
7969
|
svg.selectAll('g.x1.axis1 g.tick line').remove();
|
|
7970
|
+
// Only move x-axis labels further down for grouped charts if there is no xLabel
|
|
7617
7971
|
if (subgroups.length > 1 && !metaData.xLabel) {
|
|
7618
7972
|
svg
|
|
7619
7973
|
.selectAll('g.x1.axis1 g.tick text')
|
|
7620
7974
|
.attr('class', 'lib-xaxis-labels-texts-drilldown')
|
|
7621
7975
|
.style('fill', 'var(--chart-text-color)')
|
|
7622
|
-
.attr('y', 32);
|
|
7976
|
+
.attr('y', 32); // Increase distance from bars (default is ~9)
|
|
7623
7977
|
}
|
|
7624
7978
|
else {
|
|
7625
7979
|
svg
|
|
@@ -7627,14 +7981,32 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
7627
7981
|
.attr('class', 'lib-xaxis-labels-texts-drilldown')
|
|
7628
7982
|
.style('fill', 'var(--chart-text-color)');
|
|
7629
7983
|
}
|
|
7984
|
+
// .attr('y', function () {
|
|
7985
|
+
// if (alternate_text) {
|
|
7986
|
+
// alternate_text = false;
|
|
7987
|
+
// return long_tick_length + 1;
|
|
7988
|
+
// } else {
|
|
7989
|
+
// alternate_text = true;
|
|
7990
|
+
// return short_tick_length + 1;
|
|
7991
|
+
// }
|
|
7992
|
+
// });
|
|
7630
7993
|
}
|
|
7631
7994
|
else {
|
|
7995
|
+
/**
|
|
7996
|
+
* bigger ticks for weekly charts and more space from x axis to labels
|
|
7997
|
+
*/
|
|
7998
|
+
/**
|
|
7999
|
+
* draw x axis
|
|
8000
|
+
*/
|
|
7632
8001
|
svg
|
|
7633
8002
|
.append('g')
|
|
7634
8003
|
.attr('class', 'x1 axis1')
|
|
7635
8004
|
.attr('transform', 'translate(0,' + height + ')')
|
|
7636
8005
|
.call(d3.axisBottom(x).tickSize(0))
|
|
7637
8006
|
.call((g) => g.select('.domain').attr('fill', 'none'));
|
|
8007
|
+
/**
|
|
8008
|
+
* tick line size in alternate fashion
|
|
8009
|
+
*/
|
|
7638
8010
|
svg.selectAll('g.x1.axis1 g.tick line').attr('y2', function () {
|
|
7639
8011
|
if (alternate_text &&
|
|
7640
8012
|
self.chartConfiguration.isNoAlternateXaxisText == undefined) {
|
|
@@ -7646,11 +8018,19 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
7646
8018
|
return short_tick_length_bg - 4;
|
|
7647
8019
|
}
|
|
7648
8020
|
});
|
|
8021
|
+
/**
|
|
8022
|
+
* reset the flag so that values can be shown in same alternate fashion
|
|
8023
|
+
*/
|
|
7649
8024
|
alternate_text = false;
|
|
8025
|
+
/**
|
|
8026
|
+
* print x-axis label texts
|
|
8027
|
+
* used by weekly charts
|
|
8028
|
+
*/
|
|
7650
8029
|
svg
|
|
7651
8030
|
.selectAll('g.x1.axis1 g.tick text')
|
|
7652
8031
|
.attr('class', 'lib-xaxis-labels-texts-weeklycharts')
|
|
7653
8032
|
.attr('y', function () {
|
|
8033
|
+
// Minimize gap in maximized (fullscreen) view for weekly charts
|
|
7654
8034
|
if (self.chartConfiguration.isFullScreen) {
|
|
7655
8035
|
return short_tick_length_bg;
|
|
7656
8036
|
}
|
|
@@ -7671,6 +8051,7 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
7671
8051
|
.style('font-size', this.isHeaderVisible ? '18px' : '14px')
|
|
7672
8052
|
.attr('text-anchor', 'middle')
|
|
7673
8053
|
.attr('y', function (d) {
|
|
8054
|
+
// For grouped bar charts with many bars and xLabel present, only add 5 if the label is a date
|
|
7674
8055
|
if (subgroups.length > 1 && data.length > 8 && metaData.xLabel) {
|
|
7675
8056
|
const isDateLabel = /\d{2,4}[-\/]/.test(d);
|
|
7676
8057
|
if (self.chartConfiguration.isFullScreen) {
|
|
@@ -7678,13 +8059,16 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
7678
8059
|
}
|
|
7679
8060
|
return isDateLabel ? short_tick_length_bg + 14 : short_tick_length_bg;
|
|
7680
8061
|
}
|
|
8062
|
+
// For grouped bar charts with many bars and NO xLabel, add space as before, but reduce in fullscreen
|
|
7681
8063
|
if (subgroups.length > 1 && data.length > 8 && !metaData.xLabel) {
|
|
7682
8064
|
const chartHasExtraBottom = (self.chartConfiguration.margin && self.chartConfiguration.margin.bottom >= 40);
|
|
7683
8065
|
if (self.chartConfiguration.isFullScreen) {
|
|
8066
|
+
// Reduce extra gap in maximized view
|
|
7684
8067
|
return short_tick_length_bg + 2;
|
|
7685
8068
|
}
|
|
7686
8069
|
return chartHasExtraBottom ? short_tick_length_bg : short_tick_length_bg + 10;
|
|
7687
8070
|
}
|
|
8071
|
+
// Default/fallback logic for other cases
|
|
7688
8072
|
let baseY = self.isHeaderVisible ? short_tick_length_bg + 25 : short_tick_length_bg;
|
|
7689
8073
|
if (subgroups.length > 1 &&
|
|
7690
8074
|
!metaData.xLabel &&
|
|
@@ -7694,6 +8078,7 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
7694
8078
|
if (/\d{2,4}[-\/]\d{2,4}/.test(d) && d.indexOf(' ') > -1) {
|
|
7695
8079
|
baseY += 4;
|
|
7696
8080
|
}
|
|
8081
|
+
// In maximized view, reduce baseY slightly for grouped bars
|
|
7697
8082
|
if (self.chartConfiguration.isFullScreen && subgroups.length > 1) {
|
|
7698
8083
|
baseY = Math.max(short_tick_length_bg, baseY - 10);
|
|
7699
8084
|
}
|
|
@@ -7701,9 +8086,9 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
7701
8086
|
})
|
|
7702
8087
|
.attr('x', function (d) {
|
|
7703
8088
|
if (self.chartData.data.length > 8 && !self.isZoomedOut) {
|
|
7704
|
-
return 1;
|
|
8089
|
+
return 1; // Move first line text slightly to the left in zoom-in view for better alignment
|
|
7705
8090
|
}
|
|
7706
|
-
return 0;
|
|
8091
|
+
return 0; // Default position
|
|
7707
8092
|
})
|
|
7708
8093
|
.text(function (d) {
|
|
7709
8094
|
var isValueToBeIgnored = false;
|
|
@@ -7721,10 +8106,13 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
7721
8106
|
if (isValueToBeIgnored) {
|
|
7722
8107
|
return '';
|
|
7723
8108
|
}
|
|
8109
|
+
// Always add space before and after hyphen for date range labels, even when header is visible and label is single line
|
|
8110
|
+
// Apply for grouped bar charts and single bar charts, header visible, single line
|
|
7724
8111
|
const dateRangeRegex = /(\d{2,4}[-\/]\d{2}[-\/]\d{2,4})\s*-\s*(\d{2,4}[-\/]\d{2}[-\/]\d{2,4})/;
|
|
7725
8112
|
if (dateRangeRegex.test(d.trim())) {
|
|
7726
8113
|
return d.trim().replace(dateRangeRegex, (m, d1, d2) => `${d1} - ${d2}`);
|
|
7727
8114
|
}
|
|
8115
|
+
// Split date and week labels into two lines in grouped bar zoom-in view (and minimized view)
|
|
7728
8116
|
const isDateLabel = /\d{2,4}[-\/]/.test(d);
|
|
7729
8117
|
const isWeekLabel = /week|wk|w\d+/i.test(d);
|
|
7730
8118
|
if (subgroups.length > 1 && !self.isZoomedOut && data.length > 8 && d.indexOf(' ') > -1 && (isDateLabel || isWeekLabel)) {
|
|
@@ -7732,6 +8120,7 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
7732
8120
|
var second = d.substring(d.indexOf(' ') + 1).trim();
|
|
7733
8121
|
return first + '\n' + second;
|
|
7734
8122
|
}
|
|
8123
|
+
// Also keep previous logic for minimized view
|
|
7735
8124
|
if (isDateLabel) {
|
|
7736
8125
|
if (!self.isHeaderVisible && data.length > 8 && d.indexOf(' ') > -1) {
|
|
7737
8126
|
var first = d.substring(0, d.indexOf(' '));
|
|
@@ -7746,7 +8135,9 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
7746
8135
|
return d.trim().substring(0, d.indexOf(' ')).toLowerCase();
|
|
7747
8136
|
}
|
|
7748
8137
|
return d.toLowerCase();
|
|
8138
|
+
// If label looks like a date (contains digits and - or /)
|
|
7749
8139
|
const isDateLabel2 = /\d{2,4}[-\/]/.test(d);
|
|
8140
|
+
// Only split date/week labels if there are many grouped bars and header is not visible
|
|
7750
8141
|
if (isDateLabel) {
|
|
7751
8142
|
if (!self.isHeaderVisible && data.length > 8 && d.indexOf(' ') > -1) {
|
|
7752
8143
|
var first = d.substring(0, d.indexOf(' '));
|
|
@@ -7762,7 +8153,9 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
7762
8153
|
}
|
|
7763
8154
|
return d.toLowerCase();
|
|
7764
8155
|
});
|
|
8156
|
+
// Now apply writing-mode: sideways-lr for grouped charts with date labels in zoomed-out view and many bars
|
|
7765
8157
|
xAxisLabels.each(function (d) {
|
|
8158
|
+
// Only apply writing-mode for exact date labels, not those containing 'week' or similar
|
|
7766
8159
|
const isDateLabel = /^(\d{2,4}[-\/])?\d{2,4}[-\/]\d{2,4}$/.test(d.trim());
|
|
7767
8160
|
const isWeekLabel = /week|wk|w\d+/i.test(d);
|
|
7768
8161
|
if (subgroups.length > 1 && self.isZoomedOut && data.length > 8 && isDateLabel && !isWeekLabel) {
|
|
@@ -7773,7 +8166,7 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
7773
8166
|
svg
|
|
7774
8167
|
.selectAll('g.x1.axis1 g.tick')
|
|
7775
8168
|
.filter(function (d) {
|
|
7776
|
-
return !/\d{2,4}[-\/]/.test(d);
|
|
8169
|
+
return !/\d{2,4}[-\/]/.test(d); // Only process non-date labels
|
|
7777
8170
|
})
|
|
7778
8171
|
.append('text')
|
|
7779
8172
|
.attr('class', 'lib-xaxis-labels-texts-drilldown')
|
|
@@ -7781,9 +8174,9 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
7781
8174
|
.attr('fill', 'var(--chart-text-color)')
|
|
7782
8175
|
.attr('x', function (d) {
|
|
7783
8176
|
if (self.chartData.data.length > 8 && !self.isZoomedOut) {
|
|
7784
|
-
return 1;
|
|
8177
|
+
return 1; // Move text slightly to the left
|
|
7785
8178
|
}
|
|
7786
|
-
return 0;
|
|
8179
|
+
return 0; // Default position
|
|
7787
8180
|
})
|
|
7788
8181
|
.text(function (d) {
|
|
7789
8182
|
if (d.trim().indexOf(' ') > -1) {
|
|
@@ -7810,6 +8203,7 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
7810
8203
|
.selectAll('g.x1.axis1 g.tick text')
|
|
7811
8204
|
.classed('mobile-xaxis-override', true);
|
|
7812
8205
|
}
|
|
8206
|
+
/**y scale for left y axis */
|
|
7813
8207
|
var y = d3.scaleLinear().rangeRound([height, 0]);
|
|
7814
8208
|
var maxValue = d3.max(data, (d) => d3.max(keyList, (key) => +d[key]));
|
|
7815
8209
|
if (maxValue == 0) {
|
|
@@ -7820,7 +8214,27 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
7820
8214
|
maxValue = 100;
|
|
7821
8215
|
}
|
|
7822
8216
|
}
|
|
8217
|
+
if (self.chartConfiguration.yAxisGrid) {
|
|
8218
|
+
// svg
|
|
8219
|
+
// .append('g')
|
|
8220
|
+
// .attr('class', 'grid')
|
|
8221
|
+
// .call(
|
|
8222
|
+
// d3
|
|
8223
|
+
// .axisLeft(y)
|
|
8224
|
+
// .ticks(self.chartConfiguration.numberOfYTicks)
|
|
8225
|
+
// .tickSize(-width)
|
|
8226
|
+
// .tickFormat('')
|
|
8227
|
+
// )
|
|
8228
|
+
// // .style('stroke-dasharray', '5 5')
|
|
8229
|
+
// .style('color', '#B9B9B9')
|
|
8230
|
+
// .style('opacity', '0.5')
|
|
8231
|
+
// .call((g) => g.select('.domain').remove());
|
|
8232
|
+
}
|
|
7823
8233
|
if (this.chartConfiguration.customYscale) {
|
|
8234
|
+
/**
|
|
8235
|
+
* increase y-scale so that values wont cross or exceed out of range
|
|
8236
|
+
* used in weekly charts
|
|
8237
|
+
*/
|
|
7824
8238
|
maxValue = maxValue * this.chartConfiguration.customYscale;
|
|
7825
8239
|
}
|
|
7826
8240
|
if (this.chartData.targetLineData &&
|
|
@@ -7858,6 +8272,10 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
7858
8272
|
.tickSize(0)
|
|
7859
8273
|
.tickFormat(self.chartConfiguration.yLineAxisLabelFomatter);
|
|
7860
8274
|
}
|
|
8275
|
+
/**
|
|
8276
|
+
* show x-axis grid between labels
|
|
8277
|
+
* used by weekly charts
|
|
8278
|
+
*/
|
|
7861
8279
|
if (self.chartConfiguration.isXgridBetweenLabels) {
|
|
7862
8280
|
svg
|
|
7863
8281
|
.append('g')
|
|
@@ -7865,7 +8283,7 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
7865
8283
|
.attr('transform', 'translate(' + x.bandwidth() / 2 + ',' + height + ')')
|
|
7866
8284
|
.call(d3.axisBottom(x).tickSize(-height).tickFormat(''))
|
|
7867
8285
|
.style('stroke-dasharray', '5 5')
|
|
7868
|
-
.style('color', 'var(--chart-grid-color, #999999)')
|
|
8286
|
+
.style('color', 'var(--chart-grid-color, #999999)') // Use CSS variable
|
|
7869
8287
|
.call((g) => g.select('.domain').remove());
|
|
7870
8288
|
}
|
|
7871
8289
|
if (this.chartConfiguration.yAxisGrid) {
|
|
@@ -7880,7 +8298,7 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
7880
8298
|
.call((g) => {
|
|
7881
8299
|
g.select('.domain')
|
|
7882
8300
|
.remove()
|
|
7883
|
-
.style('stroke', 'var(--chart-domain-color, #000000)');
|
|
8301
|
+
.style('stroke', 'var(--chart-domain-color, #000000)'); // Add CSS variable for domain
|
|
7884
8302
|
});
|
|
7885
8303
|
}
|
|
7886
8304
|
else {
|
|
@@ -7891,27 +8309,36 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
7891
8309
|
.style('opacity', '0.5')
|
|
7892
8310
|
.call((g) => {
|
|
7893
8311
|
g.select('.domain')
|
|
7894
|
-
.style('stroke', 'var(--chart-domain-color, #000000)')
|
|
7895
|
-
.style('stroke-width', '1px');
|
|
8312
|
+
.style('stroke', 'var(--chart-domain-color, #000000)') // Add CSS variable for domain
|
|
8313
|
+
.style('stroke-width', '1px'); // Ensure visibility
|
|
7896
8314
|
});
|
|
7897
8315
|
}
|
|
7898
8316
|
var xSubgroup = d3.scaleBand().domain(subgroups);
|
|
7899
8317
|
if (subgroups.length > 1 && !this.isZoomedOut) {
|
|
8318
|
+
// For grouped bar charts in zoom-in view, use full x.bandwidth() for subgroups
|
|
7900
8319
|
xSubgroup.range([0, x.bandwidth()]);
|
|
7901
8320
|
}
|
|
7902
8321
|
else if (subgroups.length === 1 && !this.isZoomedOut) {
|
|
8322
|
+
// For single-bar (non-grouped) charts in zoom-in view, set bar width to 100 (increased from 80)
|
|
7903
8323
|
xSubgroup.range([0, 100]);
|
|
7904
8324
|
}
|
|
7905
8325
|
else if (this.chartConfiguration.isMultiChartGridLine == undefined) {
|
|
7906
8326
|
xSubgroup.range([0, x.bandwidth()]);
|
|
7907
8327
|
}
|
|
7908
8328
|
else {
|
|
8329
|
+
// used to make grouped bars with lesser width as we are not using padding for width
|
|
7909
8330
|
xSubgroup.range([0, x.bandwidth()]);
|
|
7910
8331
|
}
|
|
8332
|
+
// if (this.chartConfiguration.isDrilldownChart) {
|
|
8333
|
+
// }
|
|
7911
8334
|
var color = d3
|
|
7912
8335
|
.scaleOrdinal()
|
|
7913
8336
|
.domain(subgroups)
|
|
7914
8337
|
.range(Object.values(metaData.colors));
|
|
8338
|
+
// var colorAboveTarget = d3
|
|
8339
|
+
// .scaleOrdinal()
|
|
8340
|
+
// .domain(subgroups)
|
|
8341
|
+
// .range(Object.values(metaData.colorAboveTarget));
|
|
7915
8342
|
var state = svg
|
|
7916
8343
|
.append('g')
|
|
7917
8344
|
.selectAll('.state')
|
|
@@ -7926,8 +8353,10 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
7926
8353
|
.data(function (d) {
|
|
7927
8354
|
let newList = [];
|
|
7928
8355
|
subgroups.map(function (key) {
|
|
8356
|
+
// if (key !== "group") {
|
|
7929
8357
|
let obj = { key: key, value: d[key], name: d.name };
|
|
7930
8358
|
newList.push(obj);
|
|
8359
|
+
// }
|
|
7931
8360
|
});
|
|
7932
8361
|
return newList;
|
|
7933
8362
|
})
|
|
@@ -7940,6 +8369,7 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
7940
8369
|
!metaData.barWithoutClick.length ||
|
|
7941
8370
|
(!metaData.barWithoutClick.includes(d?.name) &&
|
|
7942
8371
|
!metaData.barWithoutClick.includes(d?.key)))
|
|
8372
|
+
// self.handleClick(d.data.name);
|
|
7943
8373
|
self.handleClick(d);
|
|
7944
8374
|
}
|
|
7945
8375
|
})
|
|
@@ -7950,6 +8380,7 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
7950
8380
|
let keys = Object.keys(indiv).filter((temp, i) => i != 0);
|
|
7951
8381
|
tempScale = d3.scaleBand().domain(keys).range([0, x.bandwidth()]);
|
|
7952
8382
|
if (x.bandwidth() > 100) {
|
|
8383
|
+
// Increase bar width a bit in zoom-in view
|
|
7953
8384
|
let reducedBarWidth = 60;
|
|
7954
8385
|
if (!self.isZoomedOut) {
|
|
7955
8386
|
reducedBarWidth = 30;
|
|
@@ -7991,19 +8422,23 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
7991
8422
|
return y(0);
|
|
7992
8423
|
})
|
|
7993
8424
|
.attr('width', function (d) {
|
|
8425
|
+
// For grouped bar charts in zoom-in view, set bar width to 50 for maximum thickness
|
|
7994
8426
|
if (subgroups.length > 1 && !self.isZoomedOut) {
|
|
7995
8427
|
return 50;
|
|
7996
8428
|
}
|
|
8429
|
+
// For single-bar (non-grouped) charts in zoom-in view, set bar width to 80
|
|
7997
8430
|
if (subgroups.length === 1 && !self.isZoomedOut) {
|
|
7998
8431
|
return 80;
|
|
7999
8432
|
}
|
|
8000
8433
|
let tempScale = d3.scaleBand().domain([]).range([0, 0]);
|
|
8434
|
+
// Default logic for other chart types
|
|
8001
8435
|
if (self.chartConfiguration.isDrilldownChart) {
|
|
8002
8436
|
data.map((indiv) => {
|
|
8003
8437
|
if (indiv.name == d.name) {
|
|
8004
8438
|
let keys = Object.keys(indiv).filter((temp, i) => i != 0);
|
|
8005
8439
|
tempScale = d3.scaleBand().domain(keys).range([0, x.bandwidth()]);
|
|
8006
8440
|
if (x.bandwidth() > 100) {
|
|
8441
|
+
// Increase bar width a bit in zoom-in view
|
|
8007
8442
|
let reducedBarWidth = 60;
|
|
8008
8443
|
if (!self.isZoomedOut) {
|
|
8009
8444
|
reducedBarWidth = 100;
|
|
@@ -8071,6 +8506,9 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
8071
8506
|
}
|
|
8072
8507
|
return self.chartData.metaData.colors[d.key];
|
|
8073
8508
|
});
|
|
8509
|
+
/**
|
|
8510
|
+
* display angled texts on the bars
|
|
8511
|
+
*/
|
|
8074
8512
|
if (this.chartConfiguration.textsOnBar != undefined && !this.isZoomedOut) {
|
|
8075
8513
|
state
|
|
8076
8514
|
.selectAll('text')
|
|
@@ -8105,7 +8543,7 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
8105
8543
|
.style('font-weight', 'bold')
|
|
8106
8544
|
.style('font-size', function (d) {
|
|
8107
8545
|
if (self.isZoomedOut) {
|
|
8108
|
-
return '9px';
|
|
8546
|
+
return '9px'; // 👈 Zoomed out mode
|
|
8109
8547
|
}
|
|
8110
8548
|
if (self.chartConfiguration.isDrilldownChart) {
|
|
8111
8549
|
if (window.innerWidth > 1900) {
|
|
@@ -8135,12 +8573,14 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
8135
8573
|
0 + (x.bandwidth() - 200) / 2,
|
|
8136
8574
|
x.bandwidth() - (x.bandwidth() - 200) / 2,
|
|
8137
8575
|
]);
|
|
8576
|
+
// .padding(0.05);
|
|
8138
8577
|
}
|
|
8139
8578
|
else
|
|
8140
8579
|
tempScale.range([
|
|
8141
8580
|
0 + (x.bandwidth() - 300) / 2,
|
|
8142
8581
|
x.bandwidth() - (x.bandwidth() - 300) / 2,
|
|
8143
8582
|
]);
|
|
8583
|
+
// .padding(0.05);
|
|
8144
8584
|
}
|
|
8145
8585
|
else
|
|
8146
8586
|
tempScale.range([
|
|
@@ -8150,9 +8590,16 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
8150
8590
|
}
|
|
8151
8591
|
}
|
|
8152
8592
|
});
|
|
8593
|
+
/**
|
|
8594
|
+
* if set, then all texts ll be horizontal
|
|
8595
|
+
*/
|
|
8153
8596
|
if (self.chartConfiguration.textAlwaysHorizontal) {
|
|
8154
8597
|
return ('translate(' + xSubgroup(d.key) + ',' + (y(d.value) - 3) + ')');
|
|
8155
8598
|
}
|
|
8599
|
+
/**
|
|
8600
|
+
* rotate texts having more than one digits
|
|
8601
|
+
*/
|
|
8602
|
+
// if (d.value > 9)
|
|
8156
8603
|
if (!isNaN(tempScale(d.key)))
|
|
8157
8604
|
return ('translate(' +
|
|
8158
8605
|
(tempScale(d.key) + tempScale.bandwidth() * 0.55) +
|
|
@@ -8160,6 +8607,14 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
8160
8607
|
(y(0) - 10) +
|
|
8161
8608
|
') rotate(270)');
|
|
8162
8609
|
return 'translate(0,0)';
|
|
8610
|
+
// else
|
|
8611
|
+
// return (
|
|
8612
|
+
// 'translate(' +
|
|
8613
|
+
// (tempScale(d.key) + tempScale.bandwidth() / 2) +
|
|
8614
|
+
// ',' +
|
|
8615
|
+
// y(0) +
|
|
8616
|
+
// ')'
|
|
8617
|
+
// );
|
|
8163
8618
|
})
|
|
8164
8619
|
.on('click', function (d) {
|
|
8165
8620
|
if (!metaData.barWithoutClick ||
|
|
@@ -8189,6 +8644,7 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
8189
8644
|
svg
|
|
8190
8645
|
.append('foreignObject')
|
|
8191
8646
|
.attr('x', function () {
|
|
8647
|
+
// ...existing code for tempScale calculation...
|
|
8192
8648
|
var elementsCounter;
|
|
8193
8649
|
data.map((indiv) => {
|
|
8194
8650
|
if (indiv.name == d.name) {
|
|
@@ -8297,7 +8753,7 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
8297
8753
|
.append('g')
|
|
8298
8754
|
.attr('class', 'x2 axis2')
|
|
8299
8755
|
.attr('transform', 'translate(0,' + height + ')')
|
|
8300
|
-
.style('color', 'var(--chart-axis-color, #000)')
|
|
8756
|
+
.style('color', 'var(--chart-axis-color, #000)') // Use CSS variable instead of hardcoded #000
|
|
8301
8757
|
.call(d3.axisBottom(xScaleFromOrigin).tickSize(0))
|
|
8302
8758
|
.call((g) => g.select('.domain').attr('fill', 'none'));
|
|
8303
8759
|
svg.selectAll('g.x2.axis2 g.tick text').style('display', 'none');
|
|
@@ -8325,6 +8781,7 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
8325
8781
|
return formatted >= 1000 ? formatted / 1000 + 'k' : formatted;
|
|
8326
8782
|
}))
|
|
8327
8783
|
.call((g) => {
|
|
8784
|
+
// Style the domain line for theme support
|
|
8328
8785
|
g.select('.domain')
|
|
8329
8786
|
.style('stroke', 'var(--chart-domain-color, #000000)')
|
|
8330
8787
|
.style('stroke-width', '1px');
|
|
@@ -8338,23 +8795,40 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
8338
8795
|
.attr('transform', 'translate(0,0)')
|
|
8339
8796
|
.call(y)
|
|
8340
8797
|
.style('display', 'none');
|
|
8798
|
+
/**
|
|
8799
|
+
* hide x axis labels
|
|
8800
|
+
* config is there for future use
|
|
8801
|
+
* used by weekly charts
|
|
8802
|
+
*/
|
|
8341
8803
|
if (this.chartConfiguration.isXaxisLabelHidden != undefined &&
|
|
8342
8804
|
this.chartConfiguration.isXaxisLabelHidden) {
|
|
8343
8805
|
d3.selectAll('g.lib-line-x-axis-text > g > text').attr('class', 'lib-display-hidden');
|
|
8344
8806
|
}
|
|
8807
|
+
/**
|
|
8808
|
+
* hide y axis labels
|
|
8809
|
+
* used by weekly charts
|
|
8810
|
+
*/
|
|
8345
8811
|
if (this.chartConfiguration.isYaxisLabelHidden != undefined &&
|
|
8346
8812
|
this.chartConfiguration.isYaxisLabelHidden) {
|
|
8347
8813
|
d3.selectAll('.yaxis-dashed > g > text').attr('class', 'lib-display-hidden');
|
|
8348
8814
|
}
|
|
8815
|
+
/**
|
|
8816
|
+
* hide y axis labels
|
|
8817
|
+
* config is there for future use
|
|
8818
|
+
*/
|
|
8349
8819
|
if (this.chartConfiguration.isYaxisHidden != undefined &&
|
|
8350
8820
|
this.chartConfiguration.isYaxisHidden) {
|
|
8351
8821
|
d3.selectAll('.yaxis-dashed').attr('class', 'lib-display-hidden');
|
|
8352
8822
|
}
|
|
8823
|
+
/**
|
|
8824
|
+
* dashed y axis
|
|
8825
|
+
* used by weekly charts
|
|
8826
|
+
*/
|
|
8353
8827
|
if (this.chartConfiguration.isYaxisDashed != undefined &&
|
|
8354
8828
|
this.chartConfiguration.isYaxisDashed) {
|
|
8355
8829
|
d3.selectAll('.yaxis-dashed')
|
|
8356
8830
|
.style('stroke-dasharray', '5 5')
|
|
8357
|
-
.style('color', 'var(--chart-axis-color, #999999)');
|
|
8831
|
+
.style('color', 'var(--chart-axis-color, #999999)'); // Use CSS variable
|
|
8358
8832
|
}
|
|
8359
8833
|
if (lineData != null) {
|
|
8360
8834
|
if (lineData && self.chartConfiguration.showLineChartAxis) {
|
|
@@ -8366,12 +8840,28 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
8366
8840
|
.call(yLineAxis);
|
|
8367
8841
|
}
|
|
8368
8842
|
}
|
|
8843
|
+
/**
|
|
8844
|
+
* used to display y label
|
|
8845
|
+
*/
|
|
8846
|
+
// if (this.isZoomedOut) {
|
|
8847
|
+
// svg
|
|
8848
|
+
// .selectAll('.lib-xaxis-labels-texts-drilldown')
|
|
8849
|
+
// .attr('class', 'lib-display-hidden');
|
|
8850
|
+
// }
|
|
8369
8851
|
if (this.isZoomedOut) {
|
|
8852
|
+
// svg
|
|
8853
|
+
// .selectAll('.lib-xaxis-labels-texts-drilldown')
|
|
8854
|
+
// .attr('transform', 'rotate(-30)')
|
|
8855
|
+
// .attr('text-anchor', 'end')
|
|
8856
|
+
// .attr('x', '-5')
|
|
8857
|
+
// .attr('dy', null)
|
|
8858
|
+
// .style('fill', 'var(--chart-text-color)');
|
|
8370
8859
|
svg
|
|
8371
8860
|
.selectAll('.lib-xaxis-labels-texts-drilldown')
|
|
8372
8861
|
.each((d, i, nodes) => {
|
|
8373
8862
|
const text = d3.select(nodes[i]);
|
|
8374
8863
|
const label = text.text();
|
|
8864
|
+
// If label contains \n, split and use tspan for each line
|
|
8375
8865
|
if (label.indexOf('\n') > -1) {
|
|
8376
8866
|
const lines = label.split('\n');
|
|
8377
8867
|
text.text(null);
|
|
@@ -8383,6 +8873,7 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
8383
8873
|
});
|
|
8384
8874
|
}
|
|
8385
8875
|
else {
|
|
8876
|
+
// Fallback: split by space for other labels
|
|
8386
8877
|
const words = label.split(' ');
|
|
8387
8878
|
text.text(null);
|
|
8388
8879
|
words.forEach((word, index) => {
|
|
@@ -8391,11 +8882,15 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
8391
8882
|
}
|
|
8392
8883
|
})
|
|
8393
8884
|
.style('fill', 'var(--chart-text-color)')
|
|
8394
|
-
.attr('transform', null);
|
|
8885
|
+
.attr('transform', null); // Remove rotate if using line breaks
|
|
8886
|
+
// Optional: Adjust bottom margin or chart layout
|
|
8395
8887
|
svg
|
|
8396
8888
|
.select('.x-axis')
|
|
8397
8889
|
.attr('transform', `translate(0, ${height - margin.bottom + 10})`);
|
|
8398
8890
|
}
|
|
8891
|
+
/**
|
|
8892
|
+
* used to write y labels based on configuration
|
|
8893
|
+
*/
|
|
8399
8894
|
if (metaData.yLabel) {
|
|
8400
8895
|
const yPosition = isria ? 0 - margin.left / 2 - 30 : 0 - margin.left / 2 - 40;
|
|
8401
8896
|
svgYAxisLeft
|
|
@@ -8431,6 +8926,13 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
8431
8926
|
.attr('y2', yZero)
|
|
8432
8927
|
.style('stroke-dasharray', '5 5')
|
|
8433
8928
|
.style('stroke', this.chartData.targetLineData.color);
|
|
8929
|
+
// svgYAxisRight
|
|
8930
|
+
// .append('line')
|
|
8931
|
+
// .attr('x1', 0)
|
|
8932
|
+
// .attr('x2', rightSvgWidth)
|
|
8933
|
+
// .attr('y1', yZero)
|
|
8934
|
+
// .attr('y2', yZero)
|
|
8935
|
+
// .style('stroke', this.chartData.targetLineData.color);
|
|
8434
8936
|
svgYAxisRight
|
|
8435
8937
|
.append('foreignObject')
|
|
8436
8938
|
.attr('transform', 'translate(' + 0 + ',' + (yZero - 30) + ')')
|
|
@@ -8458,6 +8960,13 @@ class HorizontalGroupedBarWithScrollZoomComponent extends ComponentUniqueId {
|
|
|
8458
8960
|
});
|
|
8459
8961
|
}
|
|
8460
8962
|
if (this.chartConfiguration.isDrilldownChart) {
|
|
8963
|
+
/**
|
|
8964
|
+
* used by drilldown charts
|
|
8965
|
+
*/
|
|
8966
|
+
// svg
|
|
8967
|
+
// .selectAll('.lib-axis-group-label')
|
|
8968
|
+
// .attr('class', 'lib-ylabel-drilldowncharts')
|
|
8969
|
+
// .text(metaData.yLabel.toLowerCase());
|
|
8461
8970
|
svg.selectAll('g.x1.axis1 g.tick line').style('display', 'none');
|
|
8462
8971
|
}
|
|
8463
8972
|
if (metaData.xLabel) {
|