Skip to content

Commit 8bdaf97

Browse files
authored
fix(charts): resolve minor Gantt chart bugs and optimize logic (#34841)
1 parent 5cf70b3 commit 8bdaf97

File tree

13 files changed

+891
-1395
lines changed

13 files changed

+891
-1395
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "patch",
3+
"comment": "fix: correct check for string x-values in horizontal bar trace",
4+
"packageName": "@fluentui/chart-utilities",
5+
"email": "[email protected]",
6+
"dependentChangeType": "patch"
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "patch",
3+
"comment": "fix: resolve minor Gantt chart bugs and optimize logic",
4+
"packageName": "@fluentui/react-charting",
5+
"email": "[email protected]",
6+
"dependentChangeType": "patch"
7+
}

packages/charts/chart-utilities/src/PlotlySchemaConverter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ const validateSeriesData = (series: Partial<PlotData>, validateNumericY: boolean
225225

226226
const validateBarData = (data: Partial<PlotData>) => {
227227
if (data.orientation === 'h') {
228-
if (isStringArray(data.x) && !isDateArray(data.x)) {
228+
if (!isNumberArray(data.x) && !isDateArray(data.x)) {
229229
throw new Error(
230230
`${UNSUPPORTED_MSG_PREFIX} ${data.type}, orientation: ${data.orientation}, string x values not supported.`,
231231
);

packages/charts/react-charting/etc/react-charting.api.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,7 @@ export interface IGanttChartProps extends ICartesianChartProps {
689689
culture?: string;
690690
data?: IGanttChartDataPoint[];
691691
enableGradient?: boolean;
692+
maxBarHeight?: number;
692693
onRenderCalloutPerDataPoint?: IRenderFunction<IGanttChartDataPoint>;
693694
roundCorners?: boolean;
694695
showYAxisLables?: boolean;

packages/charts/react-charting/src/components/CommonComponents/CartesianChart.base.tsx

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -444,19 +444,6 @@ export class CartesianChartBase
444444
}
445445

446446
if (chartTypesWithStringYAxis.includes(this.props.chartType) && this.props.yAxisType === YAxisType.StringAxis) {
447-
// To create y axis tick values by if specified truncating the rest of the text
448-
// and showing elipsis or showing the whole string,
449-
yScalePrimary &&
450-
// Note: This function should be invoked within the showYAxisLablesTooltip check,
451-
// as its sole purpose is to truncate labels that exceed the noOfCharsToTruncate limit.
452-
createYAxisLabels(
453-
this.yAxisElement,
454-
yScalePrimary,
455-
this.props.noOfCharsToTruncate || 4,
456-
this.props.showYAxisLablesTooltip || false,
457-
this._isRtl,
458-
);
459-
460447
// Removing un wanted tooltip div from DOM, when prop not provided, for proper cleanup
461448
// of unwanted DOM elements, to prevent flacky behaviour in tooltips , that might occur
462449
// in creating tooltips when tooltips are enabled( as we try to recreate a tspan with this._tooltipId)
@@ -468,6 +455,19 @@ export class CartesianChartBase
468455
}
469456
// Used to display tooltip at y axis labels.
470457
if (this.props.showYAxisLablesTooltip) {
458+
// To create y axis tick values by if specified truncating the rest of the text
459+
// and showing elipsis or showing the whole string,
460+
yScalePrimary &&
461+
// Note: This function should be invoked within the showYAxisLablesTooltip check,
462+
// as its sole purpose is to truncate labels that exceed the noOfCharsToTruncate limit.
463+
createYAxisLabels(
464+
this.yAxisElement,
465+
yScalePrimary,
466+
this.props.noOfCharsToTruncate || 4,
467+
this.props.showYAxisLablesTooltip || false,
468+
this._isRtl,
469+
);
470+
471471
const yAxisElement = d3Select(this.yAxisElement).call(yScalePrimary);
472472
try {
473473
document.getElementById(this._tooltipId) && document.getElementById(this._tooltipId)!.remove();

packages/charts/react-charting/src/components/DeclarativeChart/PlotlySchemaAdapter.ts

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,7 +1021,7 @@ export const transformPlotlyJsonToGanttChartProps = (
10211021
const isXDate = input.layout?.xaxis?.type === 'date' || isDateArray(series.x);
10221022
// eslint-disable-next-line @typescript-eslint/no-explicit-any
10231023
const convertXValueToNumber = (value: any) => {
1024-
return isInvalidValue(value) ? 0 : isXDate ? new Date(value as string | number).getTime() : (value as number);
1024+
return isInvalidValue(value) ? 0 : isXDate ? +parseLocalDate(value) : +value;
10251025
};
10261026

10271027
return (series.y as Datum[])
@@ -2434,7 +2434,7 @@ const getAxisCategoryOrderProps = (data: Data[], layout: Partial<Layout> | undef
24342434

24352435
if (!ax?.categoryorder || ax.categoryorder === 'trace' || ax.categoryorder === 'array') {
24362436
const categoriesInTraceOrder = Array.from(new Set(values as string[]));
2437-
result[propName] = categoriesInTraceOrder;
2437+
result[propName] = ax?.autorange === 'reversed' ? categoriesInTraceOrder.reverse() : categoriesInTraceOrder;
24382438
return;
24392439
}
24402440

@@ -2443,3 +2443,31 @@ const getAxisCategoryOrderProps = (data: Data[], layout: Partial<Layout> | undef
24432443

24442444
return result;
24452445
};
2446+
2447+
/**
2448+
* This is experimental. Use it only with valid datetime strings to verify if they conform to the ISO 8601 format.
2449+
*/
2450+
const isoDateRegex = /^\d{4}(-\d{2}(-\d{2})?)?(T\d{2}:\d{2}(:\d{2}(\.\d{1,9})?)?(Z)?)?$/;
2451+
2452+
/**
2453+
* We want to display localized date and time in the charts, so the useUTC prop is set to false.
2454+
* But this can sometimes cause the formatters to display the datetime incorrectly.
2455+
* To work around this issue, we use this function to adjust datetime strings so that they are always interpreted
2456+
* as local time, allowing the formatters to produce the correct output.
2457+
*
2458+
* FIXME: The formatters should always produce a clear and accurate localized output, regardless of the
2459+
* format used to create the date object.
2460+
*/
2461+
const parseLocalDate = (value: string | number) => {
2462+
if (typeof value === 'string') {
2463+
const match = value.match(isoDateRegex);
2464+
if (match) {
2465+
if (!match[3]) {
2466+
value += 'T00:00';
2467+
} else if (match[6]) {
2468+
value = value.replace('Z', '');
2469+
}
2470+
}
2471+
}
2472+
return new Date(value);
2473+
};

0 commit comments

Comments
 (0)