♻️ front: introduce confirm modal (#50)

This commit is contained in:
Eric Doughty-Papassideris
2024-04-21 22:10:42 +02:00
committed by ericlinagora
parent 7bc6e36207
commit ce1180d25d
7 changed files with 150 additions and 67 deletions
@@ -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<HTMLButtonElement> {
theme?: 'primary' | 'secondary' | 'danger' | 'default' | 'outline' | 'dark' | 'white' | 'green';
theme?: ButtonTheme;
size?: 'md' | 'lg' | 'sm';
icon?: (props: any) => JSX.Element;
iconSize?: 'md' | 'lg';
@@ -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<any> = (props: ConfirmModalProps) => {
const [open, setOpen] = useState(true);
return (
<RecoilRoot>
<button className='dark:text-white' onClick={() => setOpen(true)}>Open</button>
<ConfirmModal
{...props}
open={open}
onClose={(...a) => {
setOpen(false);
action("onClose")(...a);
}}
onOk={action("onOk")}
onCancel={action("onCancel")}
/>
</RecoilRoot>
);
}
export const Default = Template.bind({});
Default.args = {};
@@ -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 <>
<Modal open={props.open} onClose={dialogCloseHandler()}>
<ModalContent
title={props.title}
text={props.text}
theme={props.theme}
icon={props.icon}
buttons={
<>
<Button
className="ml-2"
theme='default'
onClick={dialogCloseHandler(false)}
>
{Languages.t(props.buttonCancelLabel || "general.cancel")}
</Button>
<Button
theme={props.buttonOkTheme || "danger"}
onClick={dialogCloseHandler(true)}
>
{Languages.t(props.buttonOkLabel)}
</Button>
</>
}
/>
</Modal>
</>;
};
@@ -144,7 +144,7 @@ export const Modal = (props: {
</Transition.Root>
);
};
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';
@@ -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: {
/>
}
/>
<Modal open={isConfirmingExpiryRemoval} onClose={() => setIsConfirmingExpiryRemoval(false)}>
<ModalContent
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")
}
theme="danger"
icon={ShieldExclamationIcon}
buttons={
<>
<Button
className="ml-2"
theme='default'
onClick={() => setIsConfirmingExpiryRemoval(false)}
>
{Languages.t("general.cancel")}
</Button>
<Button
theme="danger"
onClick={() => {
setIsConfirmingExpiryRemoval(false)
saveValue(0);
}}
>
{Languages.t("components.public-link-security_expiration_removal_confirm")}
</Button>
</>
}
<ConfirmModal
open={isConfirmingExpiryRemoval}
onClose={() => 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'
/>
</Modal>
</>;
}
@@ -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: {
}
/>
<Modal open={isConfirmingPasswordRemoval} onClose={() => setIsConfirmingPasswordRemoval(false)}>
<ModalContent
title={Languages.t("components.public-link-security_password_removal_title")}
text={Languages.t("components.public-link-security_password_removal_body")}
theme="danger"
icon={ShieldExclamationIcon}
buttons={
<>
<Button
className="ml-2"
theme='default'
onClick={() => setIsConfirmingPasswordRemoval(false)}
>
{Languages.t("general.cancel")}
</Button>
<Button
theme="danger"
onClick={() => {
setIsConfirmingPasswordRemoval(false)
savePassword("");
}}
>
{Languages.t("components.public-link-security_password_removal_confirm")}
</Button>
</>
}
<ConfirmModal
open={isConfirmingPasswordRemoval}
title={Languages.t("components.public-link-security_password_removal_title")}
text={Languages.t("components.public-link-security_password_removal_body")}
theme="danger"
icon={ShieldExclamationIcon}
buttonOkTheme='danger'
buttonOkLabel='components.public-link-security_password_removal_confirm'
onClose={() => setIsConfirmingPasswordRemoval(false)}
onOk={() => savePassword("")}
/>
</Modal>
</>;
}
@@ -31,10 +31,7 @@ export const AccessModal = () => {
open={state.open}
onClose={() => setState({ ...state, open: false })}
>
{!!state.id &&
<AccessModalContent
id={state.id}
/>}
{!!state.id && <AccessModalContent id={state.id} />}
</Modal>
);
};