From 78f0934815a87573289c8e52af2666ea38c93251 Mon Sep 17 00:00:00 2001 From: crupest Date: Tue, 11 Jul 2023 18:45:25 +0800 Subject: Fix dialog typo. --- .../src/views/common/dailog/OperationDialog.tsx | 531 --------------------- 1 file changed, 531 deletions(-) delete mode 100644 FrontEnd/src/views/common/dailog/OperationDialog.tsx (limited to 'FrontEnd/src/views/common/dailog/OperationDialog.tsx') diff --git a/FrontEnd/src/views/common/dailog/OperationDialog.tsx b/FrontEnd/src/views/common/dailog/OperationDialog.tsx deleted file mode 100644 index 71be030a..00000000 --- a/FrontEnd/src/views/common/dailog/OperationDialog.tsx +++ /dev/null @@ -1,531 +0,0 @@ -import { useState } from "react"; -import * as React from "react"; -import { useTranslation } from "react-i18next"; -import { TwitterPicker } from "react-color"; -import classNames from "classnames"; -import moment from "moment"; - -import { convertI18nText, I18nText, UiLogicError } from "@/common"; - -import { PaletteColorType } from "@/palette"; - -import Button from "../button/Button"; -import LoadingButton from "../button/LoadingButton"; -import Dialog from "./Dialog"; - -import "./OperationDialog.css"; - -interface DefaultErrorPromptProps { - error?: string; -} - -const DefaultErrorPrompt: React.FC = (props) => { - const { t } = useTranslation(); - - let result =

{t("operationDialog.error")}

; - - if (props.error != null) { - result = ( - <> - {result} -

{props.error}

- - ); - } - - return result; -}; - -export interface OperationDialogTextInput { - type: "text"; - label?: I18nText; - password?: boolean; - initValue?: string; - textFieldProps?: Omit< - React.InputHTMLAttributes, - "type" | "value" | "onChange" - >; - helperText?: string; -} - -export interface OperationDialogBoolInput { - type: "bool"; - label: I18nText; - initValue?: boolean; - helperText?: string; -} - -export interface OperationDialogSelectInputOption { - value: string; - label: I18nText; - icon?: React.ReactElement; -} - -export interface OperationDialogSelectInput { - type: "select"; - label: I18nText; - options: OperationDialogSelectInputOption[]; - initValue?: string; -} - -export interface OperationDialogColorInput { - type: "color"; - label?: I18nText; - initValue?: string | null; - canBeNull?: boolean; -} - -export interface OperationDialogDateTimeInput { - type: "datetime"; - label?: I18nText; - initValue?: string; - helperText?: string; -} - -export type OperationDialogInput = - | OperationDialogTextInput - | OperationDialogBoolInput - | OperationDialogSelectInput - | OperationDialogColorInput - | OperationDialogDateTimeInput; - -interface OperationInputTypeStringToValueTypeMap { - text: string; - bool: boolean; - select: string; - color: string | null; - datetime: string; -} - -type MapOperationInputTypeStringToValueType = - Type extends keyof OperationInputTypeStringToValueTypeMap - ? OperationInputTypeStringToValueTypeMap[Type] - : never; - -type MapOperationInputInfoValueType = T extends OperationDialogInput - ? MapOperationInputTypeStringToValueType - : T; - -const initValueMapperMap: { - [T in OperationDialogInput as T["type"]]: ( - item: T - ) => MapOperationInputInfoValueType; -} = { - bool: (item) => item.initValue ?? false, - color: (item) => item.initValue ?? null, - datetime: (item) => { - if (item.initValue != null) { - return moment(item.initValue).format("YYYY-MM-DDTHH:mm:ss"); - } else { - return ""; - } - }, - select: (item) => item.initValue ?? item.options[0].value, - text: (item) => item.initValue ?? "", -}; - -type MapOperationInputInfoValueTypeList< - Tuple extends readonly OperationDialogInput[] -> = { - [Index in keyof Tuple]: MapOperationInputInfoValueType; -} & { length: Tuple["length"] }; - -export type OperationInputError = - | { - [index: number]: I18nText | null | undefined; - } - | null - | undefined; - -const isNoError = (error: OperationInputError): boolean => { - if (error == null) return true; - for (const key in error) { - if (error[key] != null) return false; - } - return true; -}; - -export interface OperationDialogProps< - TData, - OperationInputInfoList extends readonly OperationDialogInput[] -> { - open: boolean; - onClose: () => void; - title: I18nText | (() => React.ReactNode); - themeColor?: PaletteColorType; - onProcess: ( - inputs: MapOperationInputInfoValueTypeList - ) => Promise; - inputScheme?: OperationInputInfoList; - inputValidator?: ( - inputs: MapOperationInputInfoValueTypeList - ) => OperationInputError; - inputPrompt?: I18nText | (() => React.ReactNode); - processPrompt?: () => React.ReactNode; - successPrompt?: (data: TData) => React.ReactNode; - failurePrompt?: (error: unknown) => React.ReactNode; - onSuccessAndClose?: (data: TData) => void; -} - -const OperationDialog = < - TData, - OperationInputInfoList extends readonly OperationDialogInput[] ->( - props: OperationDialogProps -): React.ReactElement => { - const inputScheme = (props.inputScheme ?? - []) as readonly OperationDialogInput[]; - - const { t } = useTranslation(); - - type Step = - | { type: "input" } - | { type: "process" } - | { - type: "success"; - data: TData; - } - | { - type: "failure"; - data: unknown; - }; - const [step, setStep] = useState({ type: "input" }); - - type ValueType = boolean | string | null | undefined; - - const [values, setValues] = useState( - inputScheme.map((item) => { - if (item.type in initValueMapperMap) { - return ( - initValueMapperMap[item.type] as ( - i: OperationDialogInput - ) => ValueType - )(item); - } else { - throw new UiLogicError("Unknown input scheme."); - } - }) - ); - const [dirtyList, setDirtyList] = useState(() => - inputScheme.map(() => false) - ); - const [inputError, setInputError] = useState(); - - const close = (): void => { - if (step.type !== "process") { - props.onClose(); - if (step.type === "success" && props.onSuccessAndClose) { - props.onSuccessAndClose(step.data); - } - } else { - console.log("Attempt to close modal when processing."); - } - }; - - const onConfirm = (): void => { - setStep({ type: "process" }); - props - .onProcess( - values.map((v, index) => { - if (inputScheme[index].type === "datetime" && v !== "") - return new Date(v as string).toISOString(); - else return v; - }) as unknown as MapOperationInputInfoValueTypeList - ) - .then( - (d) => { - setStep({ - type: "success", - data: d, - }); - }, - (e: unknown) => { - setStep({ - type: "failure", - data: e, - }); - } - ); - }; - - let body: React.ReactNode; - if (step.type === "input" || step.type === "process") { - const process = step.type === "process"; - - let inputPrompt = - typeof props.inputPrompt === "function" - ? props.inputPrompt() - : convertI18nText(props.inputPrompt, t); - inputPrompt =
{inputPrompt}
; - - const validate = (values: ValueType[]): boolean => { - const { inputValidator } = props; - if (inputValidator != null) { - const result = inputValidator( - values as unknown as MapOperationInputInfoValueTypeList - ); - setInputError(result); - return isNoError(result); - } - return true; - }; - - const updateValue = (index: number, newValue: ValueType): void => { - const oldValues = values; - const newValues = oldValues.slice(); - newValues[index] = newValue; - setValues(newValues); - if (dirtyList[index] === false) { - const newDirtyList = dirtyList.slice(); - newDirtyList[index] = true; - setDirtyList(newDirtyList); - } - validate(newValues); - }; - - const canProcess = isNoError(inputError); - - body = ( - <> -
- {inputPrompt} - {inputScheme.map((item, index) => { - const value = values[index]; - const error: string | null = - dirtyList[index] && inputError != null - ? convertI18nText(inputError[index], t) - : null; - - if (item.type === "text") { - return ( -
- {item.label && ( - - )} - { - const v = e.target.value; - updateValue(index, v); - }} - disabled={process} - /> - {error != null && ( -
- {error} -
- )} - {item.helperText && ( -
- {t(item.helperText)} -
- )} -
- ); - } else if (item.type === "bool") { - return ( -
- { - updateValue(index, event.currentTarget.checked); - }} - disabled={process} - /> - - {error != null && ( -
- {error} -
- )} - {item.helperText && ( -
- {t(item.helperText)} -
- )} -
- ); - } else if (item.type === "select") { - return ( -
- - -
- ); - } else if (item.type === "color") { - return ( -
- {item.canBeNull ? ( - { - if (event.currentTarget.checked) { - updateValue(index, "#007bff"); - } else { - updateValue(index, null); - } - }} - disabled={process} - /> - ) : null} - - {value !== null && ( - updateValue(index, result.hex)} - /> - )} -
- ); - } else if (item.type === "datetime") { - return ( -
- {item.label && ( - - )} - { - const v = e.target.value; - updateValue(index, v); - }} - disabled={process} - /> - {error != null &&
{error}
} -
- ); - } - })} -
-
-
-
- - ); - } else { - let content: React.ReactNode; - const result = step; - if (result.type === "success") { - content = - props.successPrompt?.(result.data) ?? t("operationDialog.success"); - if (typeof content === "string") - content =

{content}

; - } else { - content = props.failurePrompt?.(result.data) ?? ; - if (typeof content === "string") - content = ; - } - body = ( - <> -
{content}
-
-
-
- - ); - } - - const title = - typeof props.title === "function" - ? props.title() - : convertI18nText(props.title, t); - - return ( - -

- {title} -

-
- {body} -
- ); -}; - -export default OperationDialog; -- cgit v1.2.3