anantaoutlook commented on code in PR #33146: URL: https://github.com/apache/superset/pull/33146#discussion_r2077019490
########## superset-frontend/plugins/plugin-chart-echarts/src/Waterfall/EchartsWaterfall.tsx: ########## @@ -37,13 +158,326 @@ export default function EchartsWaterfall( }, }; + const getSubtotalOptions = (options: EChartsCoreOption) => { + if (!useFirstValueAsSubtotal) return options; + + const xAxisData = [ + ...((options.xAxis as { data: (string | number)[] }).data || []), + ]; + + const processedSeries = ((options.series as any[]) || []).map(series => { + const newData = series.data.map((dataPoint: any, index: number) => { + if (index !== 0) return dataPoint; + + const isTransparent = + dataPoint?.itemStyle?.color && + dataPoint.itemStyle.color === 'transparent'; + + if (isTransparent) return dataPoint; + + if (dataPoint.value === '-') return dataPoint; + + const updatedColor = `rgba(${totalColor.r}, ${totalColor.g}, ${totalColor.b}, ${totalColor.a})`; + return { + ...dataPoint, + itemStyle: { + ...dataPoint.itemStyle, + color: updatedColor, + borderColor: updatedColor, + }, + }; + }); + + return { + ...series, + data: newData, + }; + }); + + return { + ...options, + xAxis: { + ...(options.xAxis as any), + data: xAxisData, + }, + series: processedSeries, + }; + }; + + const getShowTotalOptions = (options: EChartsCoreOption) => { + if (showTotal) return options; + + const totalsIndex = + ((options.series as any[]) || []) + .find(series => series.name === 'Total') + ?.data.map((dataPoint: any, index: number) => + dataPoint.value !== '-' ? index : -1, + ) + .filter((index: number) => index !== -1) || []; + + const xAxisData = [ + ...((options.xAxis as { data: (string | number)[] }).data || []), + ].filter((_, index) => !totalsIndex.includes(index)); + + const filteredSeries = ((options.series as any[]) || []).map(series => ({ + ...series, + data: series.data.filter( + (_: any, index: number) => !totalsIndex.includes(index), + ), + })); + + return { + ...options, + xAxis: { + ...(options.xAxis as any), + data: xAxisData, + }, + series: filteredSeries, + }; + }; + + const getSortedOptions = (options: EChartsCoreOption) => { + if (sortXAxis === 'none') return options; + const xAxisData = [ + ...((options.xAxis as { data: (string | number)[] }).data || []), + ]; + + const sortedData = [...xAxisData]; + + sortedData.sort((a, b) => { + if (typeof a === 'number' && typeof b === 'number') { + return sortXAxis === 'asc' ? a - b : b - a; + } + const aStr = String(a); + const bStr = String(b); + return sortXAxis === 'asc' + ? aStr.localeCompare(bStr) + : bStr.localeCompare(aStr); + }); + + const indexMap = new Map(xAxisData.map((val, index) => [val, index])); + + const sortedSeries = ((options.series as any[]) || []).map(series => ({ + ...series, + data: sortedData.map(value => { + const index = indexMap.get(value); + return index !== undefined ? (series as any).data[index] : null; + }), + })); + + return { + ...options, + xAxis: { + ...(options.xAxis as any), + data: sortedData, + }, + series: sortedSeries, + }; + }; + + const getFlippedOptions = (options: EChartsCoreOption) => { + if (orientation === 'vertical') return options; + + return { + ...options, + xAxis: { + ...((options.yAxis as any) || {}), + type: 'value', + axisLine: { + show: true, + lineStyle: { + color: theme.colors.grayscale.light3, + width: 1, + }, + }, + splitLine: { + show: true, + lineStyle: { + color: theme.colors.grayscale.light2, + width: 1, + type: 'solid', + }, + }, + name: (options.yAxis as any)?.name || '', + nameLocation: 'middle', + }, + yAxis: { + ...((options.xAxis as any) || {}), + type: 'category', + axisLine: { show: true }, + data: [...(options.xAxis as any).data].reverse(), + name: (options.xAxis as any)?.name || '', + nameLocation: 'middle', + }, + series: Array.isArray(options.series) + ? options.series.map((series: any) => ({ + ...series, + encode: { + x: series.encode?.y, + y: series.encode?.x, + }, + data: [...series.data].reverse(), + label: { + ...(series.label || {}), + position: series.name === 'Decrease' ? 'left' : 'right', + }, + })) + : [], + }; + }; + + const getFormattedAxisOptions = (options: EChartsCoreOption) => { + const { xTicksLayout, xTicksWrapLength } = props.formData; + + // If no formatting needed, return original options + if (boldLabels === 'none' && xTicksLayout !== 'flat') { + return options; + } + + // Get total indices for bold formatting + const totalsIndex = ['total', 'both'].includes(boldLabels) + ? ((options.series as any[]) || []) + .find(series => series.name === 'Total') + ?.data.map((dataPoint: any, index: number) => + dataPoint.value !== '-' ? index : -1, + ) + .filter((index: number) => index !== -1) || [] + : []; + + const formatText = (value: string, index: number) => { + // Handle bold formatting first + let formattedValue = value; + + if (orientation === 'vertical') { + if (index === 0 && ['subtotal', 'both'].includes(boldLabels)) { + formattedValue = `{subtotal|${value}}`; + } else if (totalsIndex.includes(index) && ['total', 'both'].includes(boldLabels)) { + formattedValue = `{total|${value}}`; + } + } else { + const axisData = (options.yAxis as { data?: any[] })?.data || []; + const isLast = index === axisData.length - 1; + if (isLast && ['subtotal', 'both'].includes(boldLabels)) { + formattedValue = `{subtotal|${value}}`; + } else if (totalsIndex.includes(index) && ['total', 'both'].includes(boldLabels)) { + formattedValue = `{total|${value}}`; + } + } + + // get the width of xAxis to calculate the maxCharsPerLine + const getAxisRange = (options: EChartsCoreOption) => { Review Comment: > I'm still trying to understand why all these calculations are needed given that ECharts makes most of them already. There is even an option to force all labels to be rendered. What use case is not covered by ECharts? Can you create an example using their [code editor](https://echarts.apache.org/examples/en/editor.html?c=bar-waterfall2)? Here the label break arbitrarily on any point [https://echarts.apache.org/examples/en/editor.html?c=bar-waterfall2&code=PYBwLglsB2AEC[…]JlyPLW3bNv630Olm2jzlmrnpc52jfR47A2oI5jsCvDp2rygkHmwM3qiNEAA](https://echarts.apache.org/examples/en/editor.html?c=bar-waterfall2&code=PYBwLglsB2AEC8sDeBYAULWkwBsCmAXMuppmHgB5hEDkAggMYMCuAtszgIbkAmsA6tzwAnAGaccOWAGEAFp2FgaJWAF8ANCrDBgOSCCKoMpMMIgBzcyNqcKEAM41NxzLYcAFYBGjlhhlaRYAJ4ghLA09vI8wADuyi5qzoGiwMKs3L5EoszQDJAwsAAUIAqcrPYAlMQJmPhgWAoA3AGkEKJFJcJl9gDaAIwAurAAZMOwnd39AwB0AG4SzHiwAITwiDQAtDRVRoGBYAoI46XlU801arB4OPZLu3tkh4gTpwBMA-cPqi2YwnhgzGEcAOwhGYxB02gZSWAGpwgAeABGwgA9AA-GiwOEQ25mPD2ABy0Kx4VgtBJEPmOEWn1I32MGhU-Cs0B4_gSPG4nCIPRoAFEKKFoLdHOpwgBJXLAVh4GgDFSM4zmMxs6qBfCiajhADMAFInC0zOZZFqaAAWfVJUiI4BgbSsWh6g0JBgwA7eAAynER1yIpkWCqtFDodns7P2ITCNAYQnMqSCzsCnIOREK2Vy-TghR2P1gruF9RwDnqiB6KhoAHloEXoEsACIQPAx-z1aR_bhQYUyYDTRPhABCXEWoIAynglnRmNoxdIe32aAA1CAHBiyYTSpaShi9q00fucTi12AAWW8EFg4tYIFSYFF5b5gOAsBHslAIG85hk8mgtZw87rh4OLIAivvg9gSJuV43nexg0AASsAszXEWsAAOJtLe85eqysDAO0AAqwBBPYF65Du5ZtswABeIzPjA JGzuRsHHraqQnt49QNi2ZiIlOqQkVuvboB8uZ_ACQKwEWLa0pgqgVNmVquKGXo-jg4Z7BxIhUkQAAMimkIhIiiDgsS0MieCcAA1n2gQxBAPBgLIRAAKx6S09KyVaQQhg46lkJGtBUos8SeSouKNmGsBlgk9yBFCMq0O4XAMHgoE8CINkmAF4SIgomWYC2nAMJZtCEQcf76QVED4D4frCIslWwMueCsCOYBBPgfl7DawjpcIs4mX44SmIe9idHgPj5aQrqDbQI3CuNk25oqDwtSA8j2L5aoPE15Cte1nXbTtsA9X1A2pHNXQLQoE1KI1gQzRdw1XWNN1LRcsnLY1ybclFemwAAnDp_19K8ZrOWKfTOdqIPagA7AAbJD8NI7AUN9H0kMIwAHADkPY85qN9GaAMQ2jrwA-87n6bFpDxVGW4blN7WhGZeWNYVxWlbaEhTVwqldYEkSmVg9V4Pd4zAJtmZzaAIV7Ctew_TyQP_dq4NitqAPamKmxOOEWzI2TfRw9jYqvNjqN67rhsG3K1MtLTmD07QApCiKzPZTQuXCFNnMleEZW841_O-kdezCzEdUNbmmDXtLnZmba9ry4EitJlyPLW3bNv630Olm2jzlmrnpc52jfR47A2oI5jsCvDp2rygkHmwM3qiNEAA) but the current change supports breaking at the end of word  -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: notifications-unsubscr...@superset.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: notifications-unsubscr...@superset.apache.org For additional commands, e-mail: notifications-h...@superset.apache.org