diff --git a/classes/DataWarehouse/Access/Usage.php b/classes/DataWarehouse/Access/Usage.php index 1c95a6c317..2751093d20 100644 --- a/classes/DataWarehouse/Access/Usage.php +++ b/classes/DataWarehouse/Access/Usage.php @@ -848,6 +848,7 @@ function ($drillTarget) { ) { $rank = $meDataSeries['legendrank'] / 3; $meDataSeries['name'] = "${rank}. " . $meDataSeries['name']; + $meDataSeries['oname'] = "${rank}. " . $meDataSeries['oname']; } } diff --git a/classes/DataWarehouse/Visualization/AggregateChart.php b/classes/DataWarehouse/Visualization/AggregateChart.php index 15215ea334..fcb216e319 100644 --- a/classes/DataWarehouse/Visualization/AggregateChart.php +++ b/classes/DataWarehouse/Visualization/AggregateChart.php @@ -1135,6 +1135,7 @@ public function configure( $trace = array_merge($trace, array( 'automargin'=> $data_description->display_type == 'pie' ? true : null, 'name' => $lookupDataSeriesName, + 'oname' => $lookupDataSeriesName, 'meta' => array( 'primarySeries' => true ), @@ -1501,6 +1502,7 @@ protected function buildErrorDataSeries( // create the data series description: $error_trace = array_merge($trace, array( 'name' => $lookupDataSeriesName, + 'oname' => $lookupDataSeriesName, 'meta' => array( 'primarySeries' => false ), diff --git a/classes/DataWarehouse/Visualization/TimeseriesChart.php b/classes/DataWarehouse/Visualization/TimeseriesChart.php index 67a7b982c0..1a710dce93 100644 --- a/classes/DataWarehouse/Visualization/TimeseriesChart.php +++ b/classes/DataWarehouse/Visualization/TimeseriesChart.php @@ -580,6 +580,7 @@ public function configure( $trace = array( 'name' => $lookupDataSeriesName, + 'oname' => $lookupDataSeriesName, 'meta' => array( 'primarySeries' => true ), @@ -878,6 +879,7 @@ public function configure( } $trendline_trace = array( 'name' => $lookupDataSeriesName, + 'oname' => $lookupDataSeriesName, 'meta' => array( 'primarySeries' => false, 'trendlineSeries' => true diff --git a/html/gui/js/PlotlyChartWrapper.js b/html/gui/js/PlotlyChartWrapper.js index 18df5fc413..f728d5c58e 100644 --- a/html/gui/js/PlotlyChartWrapper.js +++ b/html/gui/js/PlotlyChartWrapper.js @@ -135,8 +135,8 @@ XDMoD.utils.createChart = function (chartOptions, extraHandlers) { return; } - const update = relayoutChart(chartDiv, baseChartOptions.layout.height, true, baseChartOptions.isExport); - Plotly.relayout(baseChartOptions.renderTo, update); + const update = relayoutChart(chartDiv, baseChartOptions.layout.width, baseChartOptions.layout.height, true, baseChartOptions.isExport); + Plotly.update(baseChartOptions.renderTo, update.data, update.layout, update.traces); }); return chart; diff --git a/html/gui/js/libraries/PlotlyUtilities.js b/html/gui/js/libraries/PlotlyUtilities.js index c05e6cf9e3..80d74721e0 100644 --- a/html/gui/js/libraries/PlotlyUtilities.js +++ b/html/gui/js/libraries/PlotlyUtilities.js @@ -353,9 +353,44 @@ function adjustSubtitle(layout, subtitleIndex, legendTopCenter, firstRender) { * @return {Object} update - Layout object passed to Plotly.relayout */ /* exported relayoutChart */ -function relayoutChart(chartDiv, adjHeight, firstRender = false, isExport = false) { - let update = {}; +function relayoutChart(chartDiv, adjWidth, adjHeight, firstRender = false, isExport = false) { + const update = {}; if (chartDiv._fullLayout.annotations.length > 0) { + // Wrap long titles based on width + const traceNameUpdates = { name: [] }; + const traceIndices = []; + const chartRatioChange = adjWidth / chartDiv.clientWidth; + let characterLimit = 150; + if (adjWidth < 400) { + characterLimit = 20; + } else if (adjWidth < 650) { + characterLimit = 40; + } else if (adjWidth < 850) { + characterLimit = 70; + } else if (adjWidth < 1250) { + characterLimit = 100; + } + const wordWrapLimit = Number.parseInt(chartRatioChange * characterLimit, 10); + const regex = new RegExp(`(?![^\\n]{1,${wordWrapLimit}}$)(?:([^\\n]{1,${wordWrapLimit}})\\s|([^\\n]{${wordWrapLimit}}))`, 'g'); + + chartDiv.data.forEach((trace, index) => { + if (trace.oname) { + traceNameUpdates.name.push( + // Hardwrap is when we have to break middle of a word (add hyphen) + // Otherwise we are soft word wrapping and will break on whitespace. + trace.oname.replaceAll(regex, (match, softWrap, hardWrap) => { + if (hardWrap) { + return `${hardWrap}-
`; + } + return `${softWrap}
`; + }) + ); + traceIndices.push(index); + } + }); + update.data = traceNameUpdates; + update.traces = traceIndices; + const topCenter = isTopLegend(chartDiv._fullLayout); const marginRight = chartDiv._fullLayout._size.r; const marginLeft = chartDiv._fullLayout._size.l; @@ -393,7 +428,7 @@ function relayoutChart(chartDiv, adjHeight, firstRender = false, isExport = fals const isPie = chartDiv._fullData.length > 0 && chartDiv._fullData[0].type === 'pie'; const subtitleUpdates = adjustSubtitle(chartDiv._fullLayout, subtitleIndex, topCenter, firstRender); - update = subtitleUpdates.chartUpdates; + update.layout = subtitleUpdates.chartUpdates; if (isPie && topCenter && subtitleUpdates.subtitleLineCount > 0) { extraShift -= 10; @@ -418,7 +453,7 @@ function relayoutChart(chartDiv, adjHeight, firstRender = false, isExport = fals // Observed inconsistency with margin when subtitle is one line long. Unsure of the cause. if (lineBreakCount > 0) { if (firstRender) { - update['margin.t'] = marginTop + (titleHeight * lineBreakCount); + update.layout['margin.t'] = marginTop + (titleHeight * lineBreakCount); } else if (subtitleUpdates.subtitleLineCount === 1) { marginTop = subtitleUpdates.chartUpdates['margin.t'] - (titleHeight * lineBreakCount); } else { @@ -427,8 +462,8 @@ function relayoutChart(chartDiv, adjHeight, firstRender = false, isExport = fals if (topCenter) { if (subtitleUpdates.subtitleLineCount > 0) { marginTop += subtitleHeight + 5; - update['legend.y'] -= 0.025; - update['margin.t'] += chartDiv._fullLayout.legend._height + subtitleHeight; + update.layout['legend.y'] -= 0.025; + update.layout['margin.t'] += chartDiv._fullLayout.legend._height + subtitleHeight; } else { marginTop -= chartDiv._fullLayout.legend._height / 2; } @@ -443,20 +478,20 @@ function relayoutChart(chartDiv, adjHeight, firstRender = false, isExport = fals if ((titleIndex === -1 || chartDiv._fullLayout.annotations[titleIndex].text.length === 0) && subtitleUpdates.subtitleLineCount === 0) { if (topCenter) { - update['legend.y'] = 1.0; + update.layout['legend.y'] = 1; } else { - update['margin.t'] = 10; + update.layout['margin.t'] = 10; } } const titleYShift = (marginTop + legendHeight) - titleHeight; if (titleIndex !== -1) { - update[`annotations[${titleIndex}].yshift`] = subtitleUpdates.subtitleLineCount >= 3 ? titleYShift + 5 : titleYShift; + update.layout[`annotations[${titleIndex}].yshift`] = subtitleUpdates.subtitleLineCount >= 3 ? titleYShift + 5 : titleYShift; } if (subtitleIndex !== -1) { - update[`annotations[${subtitleIndex}].yshift`] = titleYShift - (subtitleHeight * subtitleUpdates.subtitleLineCount); + update.layout[`annotations[${subtitleIndex}].yshift`] = titleYShift - (subtitleHeight * subtitleUpdates.subtitleLineCount); } const marginBottom = chartDiv._fullLayout._size.b; @@ -468,12 +503,12 @@ function relayoutChart(chartDiv, adjHeight, firstRender = false, isExport = fals const shiftYDown = marginBottom * -1; const exportShift = isExport ? 30 : 0; if (creditsIndex !== -1) { - update[`annotations[${creditsIndex}].yshift`] = shiftYDown; - update[`annotations[${creditsIndex}].xshift`] = marginRight - pieChartXShift - exportShift; + update.layout[`annotations[${creditsIndex}].yshift`] = shiftYDown; + update.layout[`annotations[${creditsIndex}].xshift`] = marginRight - pieChartXShift - exportShift; } if (restrictedIndex !== -1) { - update[`annotations[${restrictedIndex}].yshift`] = shiftYDown; - update[`annotations[${restrictedIndex}].xshift`] = (marginLeft - pieChartXShift - exportShift) * -1; + update.layout[`annotations[${restrictedIndex}].yshift`] = shiftYDown; + update.layout[`annotations[${restrictedIndex}].xshift`] = (marginLeft - pieChartXShift - exportShift) * -1; } } return update; diff --git a/html/gui/js/modules/Usage.js b/html/gui/js/modules/Usage.js index 18426e80d8..d3b81fed15 100644 --- a/html/gui/js/modules/Usage.js +++ b/html/gui/js/modules/Usage.js @@ -2612,8 +2612,8 @@ Ext.extend(XDMoD.Module.Usage, XDMoD.PortalModule, { const chartDiv = document.getElementById(this.chartId); if (chartDiv) { Plotly.relayout(this.chartId, { width: adjWidth, height: adjHeight }); - const update = relayoutChart(chartDiv, adjHeight, false); - Plotly.relayout(this.chartId, update); + const update = relayoutChart(chartDiv, adjWidth, adjHeight, false); + Plotly.update(this.chartId, update.data, update.layout, update.traces); } } } //onResize diff --git a/html/gui/js/modules/metric_explorer/MetricExplorer.js b/html/gui/js/modules/metric_explorer/MetricExplorer.js index 4985c9e1c9..0756964217 100644 --- a/html/gui/js/modules/metric_explorer/MetricExplorer.js +++ b/html/gui/js/modules/metric_explorer/MetricExplorer.js @@ -6335,8 +6335,8 @@ Ext.extend(XDMoD.Module.MetricExplorer, XDMoD.PortalModule, { const chartDiv = document.getElementById(`plotly-panel${this.id}`); if (chartDiv) { Plotly.relayout(`plotly-panel${this.id}`, { width: adjWidth, height: adjHeight }); - const update = relayoutChart(chartDiv, adjHeight, false); - Plotly.relayout(`plotly-panel${this.id}`, update); + const update = relayoutChart(chartDiv, adjWidth, adjHeight, false); + Plotly.update(`plotly-panel${this.id}`, update.data, update.layout, update.traces); } } //onResize