From f5dfd52f6efece2f4cad227044ecf4dd66301bbc Mon Sep 17 00:00:00 2001 From: crupest Date: Sat, 26 Aug 2023 21:36:58 +0800 Subject: ... --- FrontEnd/src/views/common/dialog/ConfirmDialog.css | 0 FrontEnd/src/views/common/dialog/ConfirmDialog.tsx | 59 ------ FrontEnd/src/views/common/dialog/Dialog.css | 60 ------ FrontEnd/src/views/common/dialog/Dialog.tsx | 63 ------ .../src/views/common/dialog/DialogContainer.css | 20 -- .../src/views/common/dialog/DialogContainer.tsx | 95 --------- .../src/views/common/dialog/FullPageDialog.css | 44 ---- .../src/views/common/dialog/FullPageDialog.tsx | 53 ----- .../src/views/common/dialog/OperationDialog.css | 8 - .../src/views/common/dialog/OperationDialog.tsx | 228 --------------------- FrontEnd/src/views/common/dialog/index.ts | 64 ------ 11 files changed, 694 deletions(-) delete mode 100644 FrontEnd/src/views/common/dialog/ConfirmDialog.css delete mode 100644 FrontEnd/src/views/common/dialog/ConfirmDialog.tsx delete mode 100644 FrontEnd/src/views/common/dialog/Dialog.css delete mode 100644 FrontEnd/src/views/common/dialog/Dialog.tsx delete mode 100644 FrontEnd/src/views/common/dialog/DialogContainer.css delete mode 100644 FrontEnd/src/views/common/dialog/DialogContainer.tsx delete mode 100644 FrontEnd/src/views/common/dialog/FullPageDialog.css delete mode 100644 FrontEnd/src/views/common/dialog/FullPageDialog.tsx delete mode 100644 FrontEnd/src/views/common/dialog/OperationDialog.css delete mode 100644 FrontEnd/src/views/common/dialog/OperationDialog.tsx delete mode 100644 FrontEnd/src/views/common/dialog/index.ts (limited to 'FrontEnd/src/views/common/dialog') diff --git a/FrontEnd/src/views/common/dialog/ConfirmDialog.css b/FrontEnd/src/views/common/dialog/ConfirmDialog.css deleted file mode 100644 index e69de29b..00000000 diff --git a/FrontEnd/src/views/common/dialog/ConfirmDialog.tsx b/FrontEnd/src/views/common/dialog/ConfirmDialog.tsx deleted file mode 100644 index dbbd15c6..00000000 --- a/FrontEnd/src/views/common/dialog/ConfirmDialog.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { useC, Text, ThemeColor } from "@/views/common/common"; - -import Dialog from "./Dialog"; -import DialogContainer from "./DialogContainer"; - -export default function ConfirmDialog({ - open, - onClose, - onConfirm, - title, - body, - color, - bodyColor, -}: { - open: boolean; - onClose: () => void; - onConfirm: () => void; - title: Text; - body: Text; - color?: ThemeColor; - bodyColor?: ThemeColor; -}) { - const c = useC(); - - return ( - - { - onConfirm(); - onClose(); - }, - }, - }, - ]} - > -
{c(body)}
-
-
- ); -} diff --git a/FrontEnd/src/views/common/dialog/Dialog.css b/FrontEnd/src/views/common/dialog/Dialog.css deleted file mode 100644 index e4c61440..00000000 --- a/FrontEnd/src/views/common/dialog/Dialog.css +++ /dev/null @@ -1,60 +0,0 @@ -.cru-dialog-overlay { - position: fixed; - z-index: 1040; - left: 0; - top: 0; - right: 0; - bottom: 0; - display: flex; - align-items: center; - overflow: auto; -} - -.cru-dialog-background { - position: absolute; - z-index: -1; - left: 0; - right: 0; - top: 0; - bottom: 0; - background-color: var(--cru-surface-dim-color); - opacity: 0.8; -} - -.cru-dialog-container { - max-width: 100%; - min-width: 30vw; - - margin: 2em auto; - - border: var(--cru-key-container-color) 1px solid; - border-radius: 5px; - padding: 1.5em; - background-color: var(--cru-surface-color); -} - -@media (min-width: 576px) { - .cru-dialog-container { - max-width: 800px; - } -} - -.cru-dialog-enter .cru-dialog-container { - transform: scale(0, 0); - opacity: 0; - transform-origin: center; -} - -.cru-dialog-enter-active .cru-dialog-container { - transform: scale(1, 1); - opacity: 1; - transition: transform 0.3s, opacity 0.3s; - transform-origin: center; -} - -.cru-dialog-exit-active .cru-dialog-container { - transition: transform 0.3s, opacity 0.3s; - transform: scale(0, 0); - opacity: 0; - transform-origin: center; -} \ No newline at end of file diff --git a/FrontEnd/src/views/common/dialog/Dialog.tsx b/FrontEnd/src/views/common/dialog/Dialog.tsx deleted file mode 100644 index 2ff7bea8..00000000 --- a/FrontEnd/src/views/common/dialog/Dialog.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import { ReactNode, useRef } from "react"; -import ReactDOM from "react-dom"; -import { CSSTransition } from "react-transition-group"; -import classNames from "classnames"; - -import { ThemeColor } from "../common"; - -import "./Dialog.css"; - -const optionalPortalElement = document.getElementById("portal"); -if (optionalPortalElement == null) { - throw new Error("Portal element not found"); -} -const portalElement = optionalPortalElement; - -interface DialogProps { - open: boolean; - onClose: () => void; - color?: ThemeColor; - children?: ReactNode; - disableCloseOnClickOnOverlay?: boolean; -} - -export default function Dialog({ - open, - onClose, - color, - children, - disableCloseOnClickOnOverlay, -}: DialogProps) { - color = color ?? "primary"; - - const nodeRef = useRef(null); - - return ReactDOM.createPortal( - -
-
{ - onClose(); - } - } - /> -
{children}
-
- , - portalElement, - ); -} diff --git a/FrontEnd/src/views/common/dialog/DialogContainer.css b/FrontEnd/src/views/common/dialog/DialogContainer.css deleted file mode 100644 index fbb18e0d..00000000 --- a/FrontEnd/src/views/common/dialog/DialogContainer.css +++ /dev/null @@ -1,20 +0,0 @@ -.cru-dialog-container-title { - font-size: 1.2em; - font-weight: bold; - color: var(--cru-key-color); - margin-bottom: 0.5em; -} - - -.cru-dialog-container-hr { - margin: 1em 0; -} - -.cru-dialog-container-button-row { - display: flex; - justify-content: flex-end; -} - -.cru-dialog-container-button { - margin-left: 1em; -} \ No newline at end of file diff --git a/FrontEnd/src/views/common/dialog/DialogContainer.tsx b/FrontEnd/src/views/common/dialog/DialogContainer.tsx deleted file mode 100644 index afee2669..00000000 --- a/FrontEnd/src/views/common/dialog/DialogContainer.tsx +++ /dev/null @@ -1,95 +0,0 @@ -import { ComponentProps, Ref, ReactNode } from "react"; -import classNames from "classnames"; - -import { ThemeColor, Text, useC } from "../common"; -import { ButtonRow, ButtonRowV2 } from "../button"; - -import "./DialogContainer.css"; - -interface DialogContainerBaseProps { - className?: string; - title: Text; - titleColor?: ThemeColor; - titleClassName?: string; - titleRef?: Ref; - bodyContainerClassName?: string; - bodyContainerRef?: Ref; - buttonsClassName?: string; - buttonsContainerRef?: ComponentProps["containerRef"]; - children: ReactNode; -} - -interface DialogContainerWithButtonsProps extends DialogContainerBaseProps { - buttons: ComponentProps["buttons"]; -} - -interface DialogContainerWithButtonsV2Props extends DialogContainerBaseProps { - buttonsV2: ComponentProps["buttons"]; -} - -type DialogContainerProps = - | DialogContainerWithButtonsProps - | DialogContainerWithButtonsV2Props; - -export default function DialogContainer(props: DialogContainerProps) { - const { - className, - title, - titleColor, - titleClassName, - titleRef, - bodyContainerClassName, - bodyContainerRef, - buttonsClassName, - buttonsContainerRef, - children, - } = props; - - const c = useC(); - - return ( -
-
- {c(title)} -
-
-
- {children} -
-
- {"buttons" in props ? ( - - ) : ( - - )} -
- ); -} diff --git a/FrontEnd/src/views/common/dialog/FullPageDialog.css b/FrontEnd/src/views/common/dialog/FullPageDialog.css deleted file mode 100644 index 2f1fc636..00000000 --- a/FrontEnd/src/views/common/dialog/FullPageDialog.css +++ /dev/null @@ -1,44 +0,0 @@ -.cru-full-page { - position: fixed; - z-index: 1030; - left: 0; - top: 0; - right: 0; - bottom: 0; - background-color: white; - padding-top: 56px; -} - -.cru-full-page-top-bar { - height: 56px; - position: absolute; - top: 0; - left: 0; - right: 0; - z-index: 1; - background-color: var(--cru-primary-color); - display: flex; - align-items: center; -} - -.cru-full-page-content-container { - overflow: scroll; -} - -.cru-full-page-back-button { - color: var(--cru-primary-t-color); -} - -.cru-full-page-enter { - transform: translate(100%, 0); -} - -.cru-full-page-enter-active { - transform: none; - transition: transform 0.3s; -} - -.cru-full-page-exit-active { - transition: transform 0.3s; - transform: translate(100%, 0); -} diff --git a/FrontEnd/src/views/common/dialog/FullPageDialog.tsx b/FrontEnd/src/views/common/dialog/FullPageDialog.tsx deleted file mode 100644 index 6368fc0a..00000000 --- a/FrontEnd/src/views/common/dialog/FullPageDialog.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import * as React from "react"; -import { createPortal } from "react-dom"; -import classnames from "classnames"; -import { CSSTransition } from "react-transition-group"; - -import "./FullPageDialog.css"; -import IconButton from "../button/IconButton"; - -export interface FullPageDialogProps { - show: boolean; - onBack: () => void; - contentContainerClassName?: string; - children: React.ReactNode; -} - -const FullPageDialog: React.FC = ({ - show, - onBack, - children, - contentContainerClassName, -}) => { - return createPortal( - -
-
- -
-
- {children} -
-
-
, - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - document.getElementById("portal")! - ); -}; - -export default FullPageDialog; diff --git a/FrontEnd/src/views/common/dialog/OperationDialog.css b/FrontEnd/src/views/common/dialog/OperationDialog.css deleted file mode 100644 index f4b7237e..00000000 --- a/FrontEnd/src/views/common/dialog/OperationDialog.css +++ /dev/null @@ -1,8 +0,0 @@ -.cru-operation-dialog-prompt { - color: var(--cru-surface-on-color); -} - -.cru-operation-dialog-input-group { - display: block; - margin: 0.5em 0; -} diff --git a/FrontEnd/src/views/common/dialog/OperationDialog.tsx b/FrontEnd/src/views/common/dialog/OperationDialog.tsx deleted file mode 100644 index 4335b2b0..00000000 --- a/FrontEnd/src/views/common/dialog/OperationDialog.tsx +++ /dev/null @@ -1,228 +0,0 @@ -import { useState, ReactNode, ComponentProps } from "react"; -import classNames from "classnames"; - -import { useC, Text, ThemeColor } from "../common"; - -import { - useInputs, - InputGroup, - Initializer as InputInitializer, - InputValueDict, - InputErrorDict, -} from "../input/InputGroup"; -import Dialog from "./Dialog"; -import DialogContainer from "./DialogContainer"; - -import "./OperationDialog.css"; - -export type { InputInitializer, InputValueDict, InputErrorDict }; - -interface OperationDialogPromptProps { - message?: Text; - customMessage?: Text; - customMessageNode?: ReactNode; - className?: string; -} - -function OperationDialogPrompt(props: OperationDialogPromptProps) { - const { message, customMessage, customMessageNode, className } = props; - - const c = useC(); - - return ( -
- {message &&

{c(message)}

} - {customMessageNode ?? (customMessage != null ? c(customMessage) : null)} -
- ); -} - -export interface OperationDialogProps { - open: boolean; - onClose: () => void; - - color?: ThemeColor; - inputColor?: ThemeColor; - title: Text; - inputPrompt?: Text; - inputPromptNode?: ReactNode; - successPrompt?: (data: TData) => Text; - successPromptNode?: (data: TData) => ReactNode; - failurePrompt?: (error: unknown) => Text; - failurePromptNode?: (error: unknown) => ReactNode; - - inputs: InputInitializer; - - onProcess: (inputs: InputValueDict) => Promise; - onSuccessAndClose?: (data: TData) => void; -} - -function OperationDialog(props: OperationDialogProps) { - const { - open, - onClose, - color, - inputColor, - title, - inputPrompt, - inputPromptNode, - successPrompt, - successPromptNode, - failurePrompt, - failurePromptNode, - inputs, - onProcess, - onSuccessAndClose, - } = props; - - if (process.env.NODE_ENV === "development") { - if (inputPrompt && inputPromptNode) { - console.log("InputPrompt and inputPromptNode are both set."); - } - if (successPrompt && successPromptNode) { - console.log("SuccessPrompt and successPromptNode are both set."); - } - if (failurePrompt && failurePromptNode) { - console.log("FailurePrompt and failurePromptNode are both set."); - } - } - - type Step = - | { type: "input" } - | { type: "process" } - | { - type: "success"; - data: TData; - } - | { - type: "failure"; - data: unknown; - }; - - const [step, setStep] = useState({ type: "input" }); - - const { inputGroupProps, hasErrorAndDirty, setAllDisabled, confirm } = - useInputs({ - init: inputs, - }); - - function close() { - if (step.type !== "process") { - onClose(); - if (step.type === "success" && onSuccessAndClose) { - onSuccessAndClose?.(step.data); - } - } else { - console.log("Attempt to close modal dialog when processing."); - } - } - - function onConfirm() { - const result = confirm(); - if (result.type === "ok") { - setStep({ type: "process" }); - setAllDisabled(true); - onProcess(result.values).then( - (d) => { - setStep({ - type: "success", - data: d, - }); - }, - (e: unknown) => { - setStep({ - type: "failure", - data: e, - }); - }, - ); - } - } - - let body: ReactNode; - let buttons: ComponentProps["buttons"]; - - if (step.type === "input" || step.type === "process") { - const isProcessing = step.type === "process"; - - body = ( -
- - -
- ); - buttons = [ - { - key: "cancel", - type: "normal", - props: { - text: "operationDialog.cancel", - color: "secondary", - outline: true, - onClick: close, - disabled: isProcessing, - }, - }, - { - key: "confirm", - type: "loading", - props: { - text: "operationDialog.confirm", - color, - loading: isProcessing, - disabled: hasErrorAndDirty, - onClick: onConfirm, - }, - }, - ]; - } else { - const result = step; - - const promptProps: OperationDialogPromptProps = - result.type === "success" - ? { - message: "operationDialog.success", - customMessage: successPrompt?.(result.data), - customMessageNode: successPromptNode?.(result.data), - } - : { - message: "operationDialog.error", - customMessage: failurePrompt?.(result.data), - customMessageNode: failurePromptNode?.(result.data), - }; - body = ( -
- -
- ); - - buttons = [ - { - key: "ok", - type: "normal", - props: { - text: "operationDialog.ok", - color: "primary", - onClick: close, - }, - }, - ]; - } - - return ( - - - {body} - - - ); -} - -export default OperationDialog; diff --git a/FrontEnd/src/views/common/dialog/index.ts b/FrontEnd/src/views/common/dialog/index.ts deleted file mode 100644 index 59f15791..00000000 --- a/FrontEnd/src/views/common/dialog/index.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { useState } from "react"; - -export { default as Dialog } from "./Dialog"; -export { default as FullPageDialog } from "./FullPageDialog"; -export { default as OperationDialog } from "./OperationDialog"; -export { default as ConfirmDialog } from "./ConfirmDialog"; - -type DialogMap = { - [K in D]: V; -}; - -type DialogKeyMap = DialogMap; - -type DialogPropsMap = DialogMap< - D, - { key: number | string; open: boolean; onClose: () => void } ->; - -export function useDialog( - dialogs: D[], - options?: { - initDialog?: D | null; - onClose?: { - [K in D]?: () => void; - }; - }, -): { - dialog: D | null; - switchDialog: (newDialog: D | null) => void; - dialogPropsMap: DialogPropsMap; - createDialogSwitch: (newDialog: D | null) => () => void; -} { - const [dialog, setDialog] = useState(options?.initDialog ?? null); - - const [dialogKeys, setDialogKeys] = useState>( - () => Object.fromEntries(dialogs.map((d) => [d, 0])) as DialogKeyMap, - ); - - const switchDialog = (newDialog: D | null) => { - if (dialog !== null) { - setDialogKeys({ ...dialogKeys, [dialog]: dialogKeys[dialog] + 1 }); - } - setDialog(newDialog); - }; - - return { - dialog, - switchDialog, - dialogPropsMap: Object.fromEntries( - dialogs.map((d) => [ - d, - { - key: `${d}-${dialogKeys[d]}`, - open: dialog === d, - onClose: () => { - switchDialog(null); - options?.onClose?.[d]?.(); - }, - }, - ]), - ) as DialogPropsMap, - createDialogSwitch: (newDialog: D | null) => () => switchDialog(newDialog), - }; -} -- cgit v1.2.3