/*! Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 */ import { makeStyles } from '@material-ui/core/styles'; import Box from 'aws-northstar/layouts/Box'; import Button from 'aws-northstar/components/Button'; import CircularProgress, { CircularProgressProps } from '@material-ui/core/CircularProgress'; import Grid from 'aws-northstar/layouts/Grid'; import Heading from 'aws-northstar/components/Heading'; import LinearProgress, { LinearProgressProps } from '@material-ui/core/LinearProgress'; import React, { FunctionComponent, useMemo } from 'react'; import StatusIndicator from 'aws-northstar/components/StatusIndicator'; import Text from 'aws-northstar/components/Text'; import Typography from '@material-ui/core/Typography'; const useStyles = makeStyles((theme) => ({ colorPrimary: { marginTop: '8px', }, circularColorPrimary: { color: theme.palette.info.dark, position: 'absolute', left: 0, }, circularColorBottom: { color: theme.palette.grey[theme.palette.type === 'light' ? 200 : 700], }, barColorPrimary: { backgroundColor: theme.palette.info.dark, }, label: { color: theme.palette.text.primary, }, description: { padding: theme.spacing(0.3, 0), color: theme.palette.text.secondary, }, body: { display: 'inline-flex', }, icon: { paddingTop: '4px', }, resultButton: { marginLeft: '10px', }, })); export interface ProgressBarProps { /** Percentage value of the progress */ value?: number; /** * Use "in-progress" to display a progress bar. * "success" and "error" are result states and replace the progress element with a status indicator, * resultText and, if set, with a button containing resultButtonText. * */ status?: 'in-progress' | 'success' | 'error'; /** * Text for the button that gets displayed when status is set to "error" or "success". * If resultButtonText is empty, no button will be displayed. */ resultButtonText?: string; /** Short information summarizing the operation */ label?: string; /** More detailed information about the operation, rendered between the progress bar and label. */ description?: string; /** Information that is displayed below the progress bar. */ additionalInfo?: string; /** Content that is displayed whenever status is set to "error" or "success". */ resultText?: string; /** Indicate whether to display value on the right end */ displayValue?: boolean; /** Fired when the user triggers the result state button. */ resultButtonClick?: () => void; /** Indicate what type of progress bar to render */ variant?: 'linear' | 'circular'; } interface ProgressBarComponentProps { value: number; displayValue: boolean; } const statusMapping: { [key in 'error' | 'success']: 'negative' | 'positive' } = { error: 'negative', success: 'positive', }; const LinearProgressComponent: React.FunctionComponent< ProgressBarComponentProps & Omit > = ({ value, displayValue, ...props }) => { const classes = useStyles(); let variant: LinearProgressProps['variant'] = 'determinate'; // CHANGE - enable indeterminate variant if (value === Infinity) { variant = 'indeterminate'; // @ts-ignore value = undefined; } return ( {/* CHANGE: fix 0 value display conditional */} {displayValue && value && ( {value}% )} ); }; const CircularProgressWithLabel: React.FunctionComponent< ProgressBarComponentProps & Omit > = ({ value, displayValue, ...props }) => { const classes = useStyles(); let variant: CircularProgressProps['variant'] = 'determinate'; if (value === Infinity) { variant = 'indeterminate'; // @ts-ignore value = undefined; } return ( {displayValue && ( {`${Math.round(value)}%`} )} ); }; /** * A progress bar is a horizontal progress-bar for indicating progress and activity. */ export const ProgressBar: FunctionComponent< ProgressBarProps & Omit > = ({ value, displayValue = true, status = 'in-progress', variant = 'linear', label, description, additionalInfo, resultText, resultButtonText, resultButtonClick, ...props }) => { const classes = useStyles(); const progressBody = (_ProgressBarComponent: React.FunctionComponent): React.ReactNode => { if (status === 'error' || status === 'success') { return (
{resultText}
{resultButtonText && (
)}
); } return <_ProgressBarComponent value={value || (value === 0 ? 0 : 100)} displayValue={displayValue} {...props} />; }; const ProgressBarComponent = useMemo( () => (variant === 'linear' ? LinearProgressComponent : CircularProgressWithLabel), [variant], ); return ( <> {label && {label}} {description && ( {description} )} {progressBody(ProgressBarComponent)} {additionalInfo && ( {additionalInfo} )} ); }; export default ProgressBar;