Skip to content

Commit

Permalink
Refactor MetricCharts and LineChart components for improved readabili…
Browse files Browse the repository at this point in the history
…ty; update DashboardChartComponent to handle dynamic height and adjust DashboardValueComponent for new metric query configuration
  • Loading branch information
simlarsen committed Dec 2, 2024
1 parent 285fe7f commit 359c36e
Show file tree
Hide file tree
Showing 9 changed files with 205 additions and 32 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import MetricsViewConfig from "../../Metrics/MetricsViewConfig";
import MetricQueryConfigData from "../../Metrics/MetricQueryConfigData";
import ObjectID from "../../ObjectID";
import DashboardComponentType from "../DashboardComponentType";
import BaseComponent from "./DashboardBaseComponent";
Expand All @@ -7,6 +7,7 @@ export default interface DashboardValueComponent extends BaseComponent {
componentType: DashboardComponentType.Value;
componentId: ObjectID;
arguments: {
metricsViewConfig?: MetricsViewConfig | undefined;
metricQueryConfig?: MetricQueryConfigData | undefined;
title: string;
};
}
13 changes: 10 additions & 3 deletions Common/UI/Components/Charts/ChartGroup/ChartGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ export interface Chart {
description?: string | undefined;
type: ChartType;
props: LineChartProps;

}

export interface ComponentProps {
Expand All @@ -34,7 +33,10 @@ const ChartGroup: FunctionComponent<ComponentProps> = (
switch (chart.type) {
case ChartType.LINE:
return (
<div key={index} className={`p-6 ${props.hideCard ? "" : "rounded-md bg-white shadow" }`}>
<div
key={index}
className={`p-6 ${props.hideCard ? "" : "rounded-md bg-white shadow"}`}
>
<h2
data-testid="card-details-heading"
id="card-details-heading"
Expand All @@ -50,7 +52,12 @@ const ChartGroup: FunctionComponent<ComponentProps> = (
{chart.description}
</p>
)}
<LineChart key={index} {...chart.props} syncid={syncId} heightInPx={props.heightInPx} />
<LineChart
key={index}
{...chart.props}
syncid={syncId}
heightInPx={props.heightInPx}
/>
</div>
);
default:
Expand Down
5 changes: 3 additions & 2 deletions Common/UI/Components/Charts/Line/LineChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,10 @@ const LineChartElement: FunctionComponent<LineInternalProps> = (
setRecords(records);
}, [props.data]);


const className: string = props.heightInPx ? `` : "h-80";
const style: React.CSSProperties = props.heightInPx ? { height: `${props.heightInPx}px` } : {};
const style: React.CSSProperties = props.heightInPx
? { height: `${props.heightInPx}px` }
: {};

return (
<LineChart
Expand Down
4 changes: 2 additions & 2 deletions Common/Utils/Dashboard/Components/DashboardChartComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ export default class DashboardChartComponentUtil extends DashboardBaseComponentU
return {
_type: ObjectType.DashboardComponent,
componentType: DashboardComponentType.Chart,
widthInDashboardUnits: 12,
heightInDashboardUnits: 6,
widthInDashboardUnits: 6,
heightInDashboardUnits: 3,
topInDashboardUnits: 0,
leftInDashboardUnits: 0,
componentId: ObjectID.generate(),
Expand Down
18 changes: 14 additions & 4 deletions Common/Utils/Dashboard/Components/DashboardValueComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ export default class DashboardValueComponentUtil extends DashboardBaseComponentU
componentId: ObjectID.generate(),
minHeightInDashboardUnits: 1,
minWidthInDashboardUnits: 1,
arguments: {},
arguments: {
title: ''
},
};
}

Expand All @@ -32,11 +34,19 @@ export default class DashboardValueComponentUtil extends DashboardBaseComponentU
> = [];

componentArguments.push({
name: "Metrics",
description: "Please select the metrics to display on the chart",
name: "Title",
description: "The title to display",
required: false,
type: ComponentInputType.Text,
id: "title",
});

componentArguments.push({
name: "Value Configuration",
description: "Please select the metric to display",
required: true,
type: ComponentInputType.MetricsQueryConfig,
id: "metricsViewConfig",
id: "metricQueryConfig",
});

return componentArguments;
Expand Down
20 changes: 10 additions & 10 deletions Dashboard/src/Components/Dashboard/Canvas/Index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -186,19 +186,19 @@ const DashboardCanvas: FunctionComponent<ComponentProps> = (
const isSelected: boolean =
props.selectedComponentId?.toString() === componentId.toString();

const component: DashboardBaseComponent | undefined =
props.dashboardViewConfig.components.find(
(c: DashboardBaseComponent) =>
c.componentId.toString() === componentId.toString(),
);

const currentUnitSizeInPx: number = props.currentTotalDashboardWidthInPx / 12;

const heightOfComponentInPx: number = currentUnitSizeInPx * (component?.heightInDashboardUnits || 0);
const component: DashboardBaseComponent | undefined =
props.dashboardViewConfig.components.find((c: DashboardBaseComponent) => {
return c.componentId.toString() === componentId.toString();
});

const widthOfComponentInPx: number = currentUnitSizeInPx * (component?.widthInDashboardUnits || 0);
const currentUnitSizeInPx: number =
props.currentTotalDashboardWidthInPx / 12;

const heightOfComponentInPx: number =
currentUnitSizeInPx * (component?.heightInDashboardUnits || 0);

const widthOfComponentInPx: number =
currentUnitSizeInPx * (component?.widthInDashboardUnits || 0);

return (
<DashboardBaseComponentElement
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,8 @@ const DashboardChartComponentElement: FunctionComponent<ComponentProps> = (

if (
!metricViewData.queryConfigs[0] ||
!metricViewData.queryConfigs[0].metricQueryData.groupBy ||
Object.keys(metricViewData.queryConfigs[0].metricQueryData.groupBy)
.length === 0
!metricViewData.queryConfigs[0].metricQueryData.filterData ||
metricViewData.queryConfigs[0].metricQueryData.filterData?.aggegationType
) {
setIsLoading(false);
setError(
Expand Down Expand Up @@ -105,13 +104,21 @@ const DashboardChartComponentElement: FunctionComponent<ComponentProps> = (
return <ErrorMessage error={error} />;
}

let heightOfChart: number | undefined =
(props.dashboardComponentHeightInPx || 0) - 100;

if (heightOfChart < 0) {
heightOfChart = undefined;
}

return (
<div>
<MetricCharts
metricResults={metricResults}
metricNamesAndUnits={props.metricNameAndUnits}
metricViewData={metricViewData}
hideCard={true}
heightInPx={heightOfChart}
/>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,156 @@
import React, { FunctionComponent, ReactElement } from "react";
import DashboardValueComponent from "Common/Types/Dashboard/DashboardComponents/DashboardValueComponent";
import React, { FunctionComponent, ReactElement, useEffect } from "react";
import { DashboardBaseComponentProps } from "./DashboardBaseComponent";
import AggregatedResult from "Common/Types/BaseDatabase/AggregatedResult";
import { DashboardStartAndEndDateUtil } from "../Types/DashboardStartAndEndDate";
import PageLoader from "Common/UI/Components/Loader/PageLoader";
import ErrorMessage from "Common/UI/Components/ErrorMessage/ErrorMessage";
import { PromiseVoidFunction } from "Common/Types/FunctionTypes";
import MetricViewData from "../../Metrics/Types/MetricViewData";
import MetricUtil from "../../Metrics/Utils/Metrics";
import API from "Common/UI/Utils/API/API";
import DashboardValueComponent from "Common/Types/Dashboard/DashboardComponents/DashboardValueComponent";
import AggregationType from "Common/Types/BaseDatabase/AggregationType";

export interface ComponentProps extends DashboardBaseComponentProps {
component: DashboardValueComponent;
}

const DashboardValueComponentElement: FunctionComponent<ComponentProps> = (
const DashboardValueComponent: FunctionComponent<ComponentProps> = (
props: ComponentProps,
): ReactElement => {
return <div>Value Component {props.component.componentId.toString()}</div>;
const [metricResults, setMetricResults] = React.useState<
Array<AggregatedResult>
>([]);
const [aggregationType, setAggregationType] = React.useState<AggregationType>(AggregationType.Avg);
const [error, setError] = React.useState<string | null>(null);
const [isLoading, setIsLoading] = React.useState<boolean>(true);

const metricViewData: MetricViewData = {
queryConfigs: props.component.arguments.metricQueryConfig
? [props.component.arguments.metricQueryConfig]
: [],
startAndEndDate: DashboardStartAndEndDateUtil.getStartAndEndDate(
props.dashboardStartAndEndDate,
),
formulaConfigs: [],
};

const fetchAggregatedResults: PromiseVoidFunction =
async (): Promise<void> => {
setIsLoading(true);

if (
!metricViewData.startAndEndDate?.startValue ||
!metricViewData.startAndEndDate?.endValue
) {
setIsLoading(false);
setError("Please select a valid start and end date.");
}

if (
!metricViewData.queryConfigs ||
metricViewData.queryConfigs.length === 0 ||
!metricViewData.queryConfigs[0] ||
!metricViewData.queryConfigs[0].metricQueryData ||
!metricViewData.queryConfigs[0].metricQueryData.filterData ||
Object.keys(metricViewData.queryConfigs[0].metricQueryData.filterData)
.length === 0
) {
setIsLoading(false);
setError("Please select a metric. Click here to add a metric.");
}

if (
!metricViewData.queryConfigs[0] ||
!metricViewData.queryConfigs[0].metricQueryData.filterData ||
metricViewData.queryConfigs[0].metricQueryData.filterData?.aggegationType
) {
setIsLoading(false);
setError(
"Please select a aggregation. Click here to add a aggregation.",
);
} else {
setAggregationType(metricViewData.queryConfigs[0].metricQueryData.filterData?.aggegationType as AggregationType || AggregationType.Avg);
}

try {
const results: Array<AggregatedResult> = await MetricUtil.fetchResults({
metricViewData: metricViewData,
});

setMetricResults(results);
setError("");
} catch (err: unknown) {
setError(API.getFriendlyErrorMessage(err as Error));
}

setIsLoading(false);
};

useEffect(() => {
fetchAggregatedResults();
}, [
props.dashboardStartAndEndDate,
props.component.arguments.metricQueryConfig,
props.metricNameAndUnits,
]);

useEffect(() => {
fetchAggregatedResults();
}, []);

if (isLoading) {
return <PageLoader isVisible={true} />;
}

if (error) {
return <ErrorMessage error={error} />;
}

let heightOfText: number | undefined =
(props.dashboardComponentHeightInPx || 0) - 100;

if (heightOfText < 0) {
heightOfText = undefined;
}

let aggregatedValue: number = 0;
let avgCount: number = 0;

for (const result of metricResults) {
for (const item of result.data) {
const value: number = item.value;

if (aggregationType === AggregationType.Avg) {
aggregatedValue += value;
avgCount += 1;
} else if (aggregationType === AggregationType.Sum) {
aggregatedValue += value;
} else if (aggregationType === AggregationType.Min) {
aggregatedValue = Math.min(aggregatedValue, value);
} else if (aggregationType === AggregationType.Max) {
aggregatedValue = Math.max(aggregatedValue, value);
} else if (aggregationType === AggregationType.Count) {
aggregatedValue += 1;
}

}
}

if(aggregationType === AggregationType.Avg && avgCount > 0) {
aggregatedValue = aggregatedValue / avgCount;
}

return (
<div>
<div className="text-center text-sm text-semibold">
{props.component.arguments.title || ''}
</div>
<div>
{aggregatedValue || '-'}
</div>
</div>
);
};

export default DashboardValueComponentElement;
export default DashboardValueComponent;
8 changes: 7 additions & 1 deletion Dashboard/src/Components/Metrics/MetricCharts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,13 @@ const MetricCharts: FunctionComponent<ComponentProps> = (
return charts;
};

return <ChartGroup charts={getCharts()} hideCard={props.hideCard} heightInPx={props.heightInPx}/>;
return (
<ChartGroup
charts={getCharts()}
hideCard={props.hideCard}
heightInPx={props.heightInPx}
/>
);
};

export default MetricCharts;

0 comments on commit 359c36e

Please sign in to comment.