From 64e3aa5b25b34b209b1977e8145a00c73d775561 Mon Sep 17 00:00:00 2001 From: Zachery Date: Sun, 3 Mar 2024 13:41:25 +0800 Subject: [PATCH] [T-4913] Create Project - Deploy page (#152) --- .../src/components/FormatMilliSecond.tsx | 15 +- .../frontend/src/components/StopWatch.tsx | 10 +- .../src/components/projects/create/Deploy.tsx | 84 ++++++----- .../components/projects/create/DeployStep.tsx | 142 +++++++++++++----- .../components/shared/CustomIcon/CopyIcon.tsx | 21 +++ .../shared/CustomIcon/LoaderIcon.tsx | 22 +++ .../shared/CustomIcon/MinusCircleIcon.tsx | 21 +++ .../src/components/shared/CustomIcon/index.ts | 3 + 8 files changed, 232 insertions(+), 86 deletions(-) create mode 100644 packages/frontend/src/components/shared/CustomIcon/CopyIcon.tsx create mode 100644 packages/frontend/src/components/shared/CustomIcon/LoaderIcon.tsx create mode 100644 packages/frontend/src/components/shared/CustomIcon/MinusCircleIcon.tsx diff --git a/packages/frontend/src/components/FormatMilliSecond.tsx b/packages/frontend/src/components/FormatMilliSecond.tsx index 047a5479..bc8dcda6 100644 --- a/packages/frontend/src/components/FormatMilliSecond.tsx +++ b/packages/frontend/src/components/FormatMilliSecond.tsx @@ -1,13 +1,22 @@ import { Duration } from 'luxon'; -import React from 'react'; +import React, { ComponentPropsWithoutRef } from 'react'; +import { cn } from 'utils/classnames'; -const FormatMillisecond = ({ time }: { time: number }) => { +export interface FormatMilliSecondProps + extends ComponentPropsWithoutRef<'div'> { + time: number; +} + +const FormatMillisecond = ({ time, ...props }: FormatMilliSecondProps) => { const formatTime = Duration.fromMillis(time) .shiftTo('days', 'hours', 'minutes', 'seconds') .toObject(); return ( -
+
{formatTime.days !== 0 && {formatTime.days}d } {formatTime.hours !== 0 && {formatTime.hours}h } {formatTime.minutes !== 0 && {formatTime.minutes}m } diff --git a/packages/frontend/src/components/StopWatch.tsx b/packages/frontend/src/components/StopWatch.tsx index 4e70f9b0..239b1197 100644 --- a/packages/frontend/src/components/StopWatch.tsx +++ b/packages/frontend/src/components/StopWatch.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { useStopwatch } from 'react-timer-hook'; -import FormatMillisecond from './FormatMilliSecond'; +import FormatMillisecond, { FormatMilliSecondProps } from './FormatMilliSecond'; const setStopWatchOffset = (time: string) => { const providedTime = new Date(time); @@ -11,13 +11,17 @@ const setStopWatchOffset = (time: string) => { return currentTime; }; -const Stopwatch = ({ offsetTimestamp }: { offsetTimestamp: Date }) => { +interface StopwatchProps extends Omit { + offsetTimestamp: Date; +} + +const Stopwatch = ({ offsetTimestamp, ...props }: StopwatchProps) => { const { totalSeconds } = useStopwatch({ autoStart: true, offsetTimestamp: offsetTimestamp, }); - return ; + return ; }; export { Stopwatch, setStopWatchOffset }; diff --git a/packages/frontend/src/components/projects/create/Deploy.tsx b/packages/frontend/src/components/projects/create/Deploy.tsx index 67698959..a251773d 100644 --- a/packages/frontend/src/components/projects/create/Deploy.tsx +++ b/packages/frontend/src/components/projects/create/Deploy.tsx @@ -1,11 +1,14 @@ import React, { useCallback, useEffect } from 'react'; import { useNavigate, useParams, useSearchParams } from 'react-router-dom'; -import { Button, Typography } from '@material-tailwind/react'; +import { Typography } from '@material-tailwind/react'; import { DeployStep, DeployStatus } from './DeployStep'; import { Stopwatch, setStopWatchOffset } from '../../StopWatch'; import ConfirmDialog from 'components/shared/ConfirmDialog'; +import { Heading } from 'components/shared/Heading'; +import { Button } from 'components/shared/Button'; +import { ClockOutlineIcon, WarningIcon } from 'components/shared/CustomIcon'; const TIMEOUT_DURATION = 5000; const Deploy = () => { @@ -31,27 +34,27 @@ const Deploy = () => { }, []); return ( -
-
-
-

Deployment started ...

-
- ^  +
+
+
+ + Deployment started ... + +
+
-
- -
+ {
- - - - + +
+ + + + +
); }; diff --git a/packages/frontend/src/components/projects/create/DeployStep.tsx b/packages/frontend/src/components/projects/create/DeployStep.tsx index 1aae9c0c..71283ddb 100644 --- a/packages/frontend/src/components/projects/create/DeployStep.tsx +++ b/packages/frontend/src/components/projects/create/DeployStep.tsx @@ -1,11 +1,22 @@ import React, { useState } from 'react'; -import toast from 'react-hot-toast'; -import { Collapse, Button, Typography } from '@material-tailwind/react'; +import { Collapse } from '@material-tailwind/react'; import { Stopwatch, setStopWatchOffset } from '../../StopWatch'; import FormatMillisecond from '../../FormatMilliSecond'; import processLogs from '../../../assets/process-logs.json'; +import { cn } from 'utils/classnames'; +import { + CheckRoundFilledIcon, + ClockOutlineIcon, + CopyIcon, + LoaderIcon, + MinusCircleIcon, + PlusIcon, +} from 'components/shared/CustomIcon'; +import { Button } from 'components/shared/Button'; +import { useToast } from 'components/shared/Toast'; +import { useIntersectionObserver } from 'usehooks-ts'; enum DeployStatus { PROCESSING = 'progress', @@ -28,61 +39,110 @@ const DeployStep = ({ startTime, processTime, }: DeployStepsProps) => { - const [collapse, setCollapse] = useState(false); + const [isOpen, setIsOpen] = useState(false); + const { toast, dismiss } = useToast(); + const { isIntersecting: hideGradientOverlay, ref } = useIntersectionObserver({ + threshold: 1, + }); + + const disableCollapse = status !== DeployStatus.COMPLETE; return ( -
-
- {status === DeployStatus.NOT_STARTED &&
{step}
} - {status === DeployStatus.PROCESSING &&
O
} - {status === DeployStatus.COMPLETE && ( -
- +
+ {/* Collapisble trigger */} +
- -
+ + + {/* Collapsible */} + +
+ {/* Logs */} {processLogs.map((log, key) => { return ( - +

{log} - +

); })} -
+ + {/* End of logs ref used for hiding gradient overlay */} +
+ + {/* Overflow gradient overlay */} + {!hideGradientOverlay && ( +
+ )} + + {/* Copy log button */} +
diff --git a/packages/frontend/src/components/shared/CustomIcon/CopyIcon.tsx b/packages/frontend/src/components/shared/CustomIcon/CopyIcon.tsx new file mode 100644 index 00000000..34975bec --- /dev/null +++ b/packages/frontend/src/components/shared/CustomIcon/CopyIcon.tsx @@ -0,0 +1,21 @@ +import React from 'react'; +import { CustomIcon, CustomIconProps } from './CustomIcon'; + +export const CopyIcon = (props: CustomIconProps) => { + return ( + + + + ); +}; diff --git a/packages/frontend/src/components/shared/CustomIcon/LoaderIcon.tsx b/packages/frontend/src/components/shared/CustomIcon/LoaderIcon.tsx new file mode 100644 index 00000000..720bfc22 --- /dev/null +++ b/packages/frontend/src/components/shared/CustomIcon/LoaderIcon.tsx @@ -0,0 +1,22 @@ +import React from 'react'; +import { CustomIcon, CustomIconProps } from './CustomIcon'; + +export const LoaderIcon = (props: CustomIconProps) => { + return ( + + + + ); +}; diff --git a/packages/frontend/src/components/shared/CustomIcon/MinusCircleIcon.tsx b/packages/frontend/src/components/shared/CustomIcon/MinusCircleIcon.tsx new file mode 100644 index 00000000..7f685677 --- /dev/null +++ b/packages/frontend/src/components/shared/CustomIcon/MinusCircleIcon.tsx @@ -0,0 +1,21 @@ +import React from 'react'; +import { CustomIcon, CustomIconProps } from './CustomIcon'; + +export const MinusCircleIcon = (props: CustomIconProps) => { + return ( + + + + ); +}; diff --git a/packages/frontend/src/components/shared/CustomIcon/index.ts b/packages/frontend/src/components/shared/CustomIcon/index.ts index 61239304..096761a5 100644 --- a/packages/frontend/src/components/shared/CustomIcon/index.ts +++ b/packages/frontend/src/components/shared/CustomIcon/index.ts @@ -45,6 +45,9 @@ export * from './CommitIcon'; export * from './RocketIcon'; export * from './RefreshIcon'; export * from './UndoIcon'; +export * from './LoaderIcon'; +export * from './MinusCircleIcon'; +export * from './CopyIcon'; // Templates export * from './templates';