From ce1180d25dfa75373d35cc956eb135cd6ce338f9 Mon Sep 17 00:00:00 2001 From: Eric Doughty-Papassideris Date: Sun, 21 Apr 2024 22:10:42 +0200 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20=20front:=20introduce=20co?= =?UTF-8?q?nfirm=20modal=20(#50)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../frontend/src/app/atoms/button/button.tsx | 4 +- .../src/app/atoms/modal/confirm.stories.tsx | 60 +++++++++++++++++++ .../frontend/src/app/atoms/modal/confirm.tsx | 59 ++++++++++++++++++ tdrive/frontend/src/app/atoms/modal/index.tsx | 4 +- .../modals/public-link/expiry-editor-row.tsx | 45 ++++---------- .../public-link/password-editor-row.tsx | 40 ++++--------- .../body/drive/modals/update-access/index.tsx | 5 +- 7 files changed, 150 insertions(+), 67 deletions(-) create mode 100644 tdrive/frontend/src/app/atoms/modal/confirm.stories.tsx create mode 100644 tdrive/frontend/src/app/atoms/modal/confirm.tsx diff --git a/tdrive/frontend/src/app/atoms/button/button.tsx b/tdrive/frontend/src/app/atoms/button/button.tsx index b66b4fbd..1e97516a 100644 --- a/tdrive/frontend/src/app/atoms/button/button.tsx +++ b/tdrive/frontend/src/app/atoms/button/button.tsx @@ -2,8 +2,10 @@ import React from 'react'; import _ from 'lodash'; +export type ButtonTheme = 'primary' | 'secondary' | 'danger' | 'default' | 'outline' | 'dark' | 'white' | 'green'; + interface ButtonProps extends React.ButtonHTMLAttributes { - theme?: 'primary' | 'secondary' | 'danger' | 'default' | 'outline' | 'dark' | 'white' | 'green'; + theme?: ButtonTheme; size?: 'md' | 'lg' | 'sm'; icon?: (props: any) => JSX.Element; iconSize?: 'md' | 'lg'; diff --git a/tdrive/frontend/src/app/atoms/modal/confirm.stories.tsx b/tdrive/frontend/src/app/atoms/modal/confirm.stories.tsx new file mode 100644 index 00000000..4e0d5dd2 --- /dev/null +++ b/tdrive/frontend/src/app/atoms/modal/confirm.stories.tsx @@ -0,0 +1,60 @@ +import React, { useState } from 'react'; +import { action } from '@storybook/addon-actions'; + +import { RecoilRoot } from 'recoil'; +import { ComponentStory } from '@storybook/react'; +import { CheckCircleIcon, ExclamationCircleIcon } from '@heroicons/react/outline'; +import { Title } from '../text'; + +import { ConfirmModal, ConfirmModalProps } from './confirm'; +const icons = { + check: CheckCircleIcon, + exclamation: ExclamationCircleIcon, + none: null, +} +export default { + title: '@atoms/modal/confirm', + component: ConfirmModal, + argTypes: { + theme: { + options: "success danger warning gray".split(' '), + }, + buttonTheme: { + options: "primary secondary danger default outline dark white green", + }, + open: { table: { disable: true } }, + icon: { + options: [...Object.keys(icons)], + mapping: icons, + } + }, + args: { + title: "Very brief description", + text: "Long description no one will probably really read", + buttonOkLabel: 'general.continue', + skipCancelOnClose: false, + } +}; + +const Template: ComponentStory = (props: ConfirmModalProps) => { + const [open, setOpen] = useState(true); + + return ( + + + { + setOpen(false); + action("onClose")(...a); + }} + onOk={action("onOk")} + onCancel={action("onCancel")} + /> + + ); +} + +export const Default = Template.bind({}); +Default.args = {}; \ No newline at end of file diff --git a/tdrive/frontend/src/app/atoms/modal/confirm.tsx b/tdrive/frontend/src/app/atoms/modal/confirm.tsx new file mode 100644 index 00000000..365cef43 --- /dev/null +++ b/tdrive/frontend/src/app/atoms/modal/confirm.tsx @@ -0,0 +1,59 @@ +import React from 'react'; + +import { Modal, ModalContent, ModalContentTheme } from '.'; +import { Button, ButtonTheme } from 'app/atoms/button/button'; + +import Languages from 'features/global/services/languages-service'; + +export type ConfirmModalProps = { + open: boolean; + title: string; + text: string; + theme?: ModalContentTheme; + icon: React.ComponentType; + skipCancelOnClose?: boolean; + buttonOkTheme?: ButtonTheme; + buttonOkLabel: string; + buttonCancelLabel?: string; + onClose: () => void; + onCancel?: () => void; + onOk: () => void; +}; +export const ConfirmModal = (props: ConfirmModalProps) => { + function dialogCloseHandler(confirm?: boolean) { + return () => { + if (confirm === true) + props.onOk(); + else if (confirm === false || !props.skipCancelOnClose) + props.onCancel && props.onCancel(); + props.onClose(); + }; + } + return <> + + + + + + } + /> + + ; +}; \ No newline at end of file diff --git a/tdrive/frontend/src/app/atoms/modal/index.tsx b/tdrive/frontend/src/app/atoms/modal/index.tsx index 5579b1c4..331a27b4 100644 --- a/tdrive/frontend/src/app/atoms/modal/index.tsx +++ b/tdrive/frontend/src/app/atoms/modal/index.tsx @@ -144,7 +144,7 @@ export const Modal = (props: { ); }; - +export type ModalContentTheme = 'success' | 'danger' | 'warning' | 'gray'; export const ModalContent = (props: { title: ReactNode | string; text?: string; @@ -152,7 +152,7 @@ export const ModalContent = (props: { buttons?: ReactNode; children?: ReactNode; icon?: any; - theme?: 'success' | 'danger' | 'warning' | 'gray'; + theme?: ModalContentTheme; }) => { let color = 'blue'; if (props.theme === 'success') color = 'green'; diff --git a/tdrive/frontend/src/app/views/client/body/drive/modals/public-link/expiry-editor-row.tsx b/tdrive/frontend/src/app/views/client/body/drive/modals/public-link/expiry-editor-row.tsx index d41da38e..d988581d 100644 --- a/tdrive/frontend/src/app/views/client/body/drive/modals/public-link/expiry-editor-row.tsx +++ b/tdrive/frontend/src/app/views/client/body/drive/modals/public-link/expiry-editor-row.tsx @@ -12,7 +12,7 @@ import { Input } from 'app/atoms/input/input-text'; import { CheckboxSlider } from 'app/atoms/input/input-checkbox-slider'; import { Button } from 'app/atoms/button/button'; import { ShieldExclamationIcon, CalendarIcon, PencilAltIcon } from '@heroicons/react/outline'; -import { Modal, ModalContent } from 'app/atoms/modal'; +import { ConfirmModal } from 'app/atoms/modal/confirm'; import Styles from './styles'; @@ -153,37 +153,18 @@ export const ExpiryEditorRow = (props: { /> } /> - - setIsConfirmingExpiryRemoval(false)}> - - - - - } + setIsConfirmingExpiryRemoval(false)} + onOk={() => saveValue(0)} + title={Languages.t("components.public-link-security_expiration_removal_title")} + text={props.isLinkPasswordProtected + ? Languages.t("components.public-link-security_expiration_removal_but_password") + : Languages.t("components.public-link-security_expiration_removal_no_password") + } + icon={ShieldExclamationIcon} + buttonOkLabel="components.public-link-security_expiration_removal_confirm" + buttonOkTheme='danger' /> - ; } \ No newline at end of file diff --git a/tdrive/frontend/src/app/views/client/body/drive/modals/public-link/password-editor-row.tsx b/tdrive/frontend/src/app/views/client/body/drive/modals/public-link/password-editor-row.tsx index bc4b4517..1b870d49 100644 --- a/tdrive/frontend/src/app/views/client/body/drive/modals/public-link/password-editor-row.tsx +++ b/tdrive/frontend/src/app/views/client/body/drive/modals/public-link/password-editor-row.tsx @@ -9,7 +9,7 @@ import { Input } from 'app/atoms/input/input-text'; import { CheckboxSlider } from 'app/atoms/input/input-checkbox-slider'; import { Button } from 'app/atoms/button/button'; import { ShieldCheckIcon, PencilAltIcon, ShieldExclamationIcon } from '@heroicons/react/outline'; -import { Modal, ModalContent } from 'app/atoms/modal'; +import { ConfirmModal } from 'app/atoms/modal/confirm'; import Styles from './styles'; @@ -136,33 +136,17 @@ export const PasswordEditorRow = (props: { } /> - setIsConfirmingPasswordRemoval(false)}> - - - - - } + setIsConfirmingPasswordRemoval(false)} + onOk={() => savePassword("")} /> - ; } \ No newline at end of file diff --git a/tdrive/frontend/src/app/views/client/body/drive/modals/update-access/index.tsx b/tdrive/frontend/src/app/views/client/body/drive/modals/update-access/index.tsx index 86c73c43..616517d3 100644 --- a/tdrive/frontend/src/app/views/client/body/drive/modals/update-access/index.tsx +++ b/tdrive/frontend/src/app/views/client/body/drive/modals/update-access/index.tsx @@ -31,10 +31,7 @@ export const AccessModal = () => { open={state.open} onClose={() => setState({ ...state, open: false })} > - {!!state.id && - } + {!!state.id && } ); };