123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- /*
- * Copyright 2021-2024 Avaiga Private Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
- * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations under the License.
- */
- import React, {CSSProperties, lazy, Suspense, useMemo} from 'react';
- import {Data} from "plotly.js";
- import {useClassNames, useDynamicJsonProperty, useDynamicProperty} from "../../utils/hooks";
- import {extractPrefix, extractSuffix, extractFormatSpecifier} from "../../utils/formatConversion";
- import {TaipyBaseProps, TaipyHoverProps} from "./utils";
- import Box from "@mui/material/Box";
- import Skeleton from "@mui/material/Skeleton";
- const Plot = lazy(() => import("react-plotly.js"));
- interface MetricProps extends TaipyBaseProps, TaipyHoverProps {
- type?: string
- min?: number
- max?: number
- value?: number
- defaultValue?: number
- delta?: number
- defaultDelta?: number
- threshold?: number
- defaultThreshold?: number
- testId?: string
- defaultLayout?: string;
- layout?: string;
- defaultStyle?: string;
- style?: string;
- width?: string | number;
- height?: string | number;
- showValue?: boolean;
- format?: string;
- deltaFormat?: string;
- }
- const emptyLayout = {} as Record<string, Record<string, unknown>>;
- const defaultStyle = {position: "relative", display: "inline-block"};
- const Metric = (props: MetricProps) => {
- const {
- width = "100%",
- height,
- showValue = true
- } = props;
- const value = useDynamicProperty(props.value, props.defaultValue, 0)
- const threshold = useDynamicProperty(props.threshold, props.defaultThreshold, undefined)
- const delta = useDynamicProperty(props.delta, props.defaultDelta, undefined)
- const className = useClassNames(props.libClassName, props.dynamicClassName, props.className);
- const baseLayout = useDynamicJsonProperty(props.layout, props.defaultLayout || "", emptyLayout);
- const baseStyle = useDynamicJsonProperty(props.style, props.defaultStyle || "", defaultStyle);
- const data = useMemo(() => {
- return [
- {
- domain: {x: [0, 1], y: [0, 1]},
- value: value,
- type: "indicator",
- mode: "gauge" + (showValue ? "+number" : "") + (delta !== undefined ? "+delta" : ""),
- number: {
- prefix: extractPrefix(props.format),
- suffix: extractSuffix(props.format),
- valueformat: extractFormatSpecifier(props.format),
- },
- delta: {
- reference: typeof value === 'number' && typeof delta === 'number' ? value - delta : undefined,
- prefix: extractPrefix(props.deltaFormat),
- suffix: extractSuffix(props.deltaFormat),
- valueformat: extractFormatSpecifier(props.deltaFormat)
- },
- gauge: {
- axis: {
- range: [
- props.min ?? 0,
- props.max ?? 100
- ]
- },
- shape: props.type === "linear" ? "bullet" : "angular",
- threshold: {
- line: {color: "red", width: 4},
- thickness: 0.75,
- value: threshold
- }
- },
- }
- ];
- }, [
- props.format,
- props.deltaFormat,
- props.min,
- props.max,
- props.type,
- value,
- showValue,
- delta,
- threshold
- ]);
- const style = useMemo(
- () =>
- height === undefined
- ? ({...baseStyle, width: width} as CSSProperties)
- : ({...baseStyle, width: width, height: height} as CSSProperties),
- [baseStyle, height, width]
- );
- const skelStyle = useMemo(() => ({...style, minHeight: "7em"}), [style]);
- return (
- <Box data-testid={props.testId} className={className}>
- <Suspense fallback={<Skeleton key="skeleton" sx={skelStyle}/>}>
- <Plot
- data={data as Data[]}
- layout={baseLayout}
- style={style}
- useResizeHandler
- />
- </Suspense>
- </Box>
- );
- }
- export default Metric;
|