♻️ front: introduce confirm modal (#50)
This commit is contained in:
committed by
ericlinagora
parent
7bc6e36207
commit
ce1180d25d
@@ -2,8 +2,10 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
|
||||||
|
export type ButtonTheme = 'primary' | 'secondary' | 'danger' | 'default' | 'outline' | 'dark' | 'white' | 'green';
|
||||||
|
|
||||||
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
||||||
theme?: 'primary' | 'secondary' | 'danger' | 'default' | 'outline' | 'dark' | 'white' | 'green';
|
theme?: ButtonTheme;
|
||||||
size?: 'md' | 'lg' | 'sm';
|
size?: 'md' | 'lg' | 'sm';
|
||||||
icon?: (props: any) => JSX.Element;
|
icon?: (props: any) => JSX.Element;
|
||||||
iconSize?: 'md' | 'lg';
|
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>
|
</Transition.Root>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
export type ModalContentTheme = 'success' | 'danger' | 'warning' | 'gray';
|
||||||
export const ModalContent = (props: {
|
export const ModalContent = (props: {
|
||||||
title: ReactNode | string;
|
title: ReactNode | string;
|
||||||
text?: string;
|
text?: string;
|
||||||
@@ -152,7 +152,7 @@ export const ModalContent = (props: {
|
|||||||
buttons?: ReactNode;
|
buttons?: ReactNode;
|
||||||
children?: ReactNode;
|
children?: ReactNode;
|
||||||
icon?: any;
|
icon?: any;
|
||||||
theme?: 'success' | 'danger' | 'warning' | 'gray';
|
theme?: ModalContentTheme;
|
||||||
}) => {
|
}) => {
|
||||||
let color = 'blue';
|
let color = 'blue';
|
||||||
if (props.theme === 'success') color = 'green';
|
if (props.theme === 'success') color = 'green';
|
||||||
|
|||||||
+13
-32
@@ -12,7 +12,7 @@ import { Input } from 'app/atoms/input/input-text';
|
|||||||
import { CheckboxSlider } from 'app/atoms/input/input-checkbox-slider';
|
import { CheckboxSlider } from 'app/atoms/input/input-checkbox-slider';
|
||||||
import { Button } from 'app/atoms/button/button';
|
import { Button } from 'app/atoms/button/button';
|
||||||
import { ShieldExclamationIcon, CalendarIcon, PencilAltIcon } from '@heroicons/react/outline';
|
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';
|
import Styles from './styles';
|
||||||
|
|
||||||
@@ -153,37 +153,18 @@ export const ExpiryEditorRow = (props: {
|
|||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
<ConfirmModal
|
||||||
<Modal open={isConfirmingExpiryRemoval} onClose={() => setIsConfirmingExpiryRemoval(false)}>
|
open={isConfirmingExpiryRemoval}
|
||||||
<ModalContent
|
onClose={() => setIsConfirmingExpiryRemoval(false)}
|
||||||
title={Languages.t("components.public-link-security_expiration_removal_title")}
|
onOk={() => saveValue(0)}
|
||||||
text={props.isLinkPasswordProtected
|
title={Languages.t("components.public-link-security_expiration_removal_title")}
|
||||||
? Languages.t("components.public-link-security_expiration_removal_but_password")
|
text={props.isLinkPasswordProtected
|
||||||
: Languages.t("components.public-link-security_expiration_removal_no_password")
|
? Languages.t("components.public-link-security_expiration_removal_but_password")
|
||||||
}
|
: Languages.t("components.public-link-security_expiration_removal_no_password")
|
||||||
theme="danger"
|
}
|
||||||
icon={ShieldExclamationIcon}
|
icon={ShieldExclamationIcon}
|
||||||
buttons={
|
buttonOkLabel="components.public-link-security_expiration_removal_confirm"
|
||||||
<>
|
buttonOkTheme='danger'
|
||||||
<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>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</Modal>
|
|
||||||
</>;
|
</>;
|
||||||
}
|
}
|
||||||
+12
-28
@@ -9,7 +9,7 @@ import { Input } from 'app/atoms/input/input-text';
|
|||||||
import { CheckboxSlider } from 'app/atoms/input/input-checkbox-slider';
|
import { CheckboxSlider } from 'app/atoms/input/input-checkbox-slider';
|
||||||
import { Button } from 'app/atoms/button/button';
|
import { Button } from 'app/atoms/button/button';
|
||||||
import { ShieldCheckIcon, PencilAltIcon, ShieldExclamationIcon } from '@heroicons/react/outline';
|
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';
|
import Styles from './styles';
|
||||||
|
|
||||||
@@ -136,33 +136,17 @@ export const PasswordEditorRow = (props: {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Modal open={isConfirmingPasswordRemoval} onClose={() => setIsConfirmingPasswordRemoval(false)}>
|
<ConfirmModal
|
||||||
<ModalContent
|
open={isConfirmingPasswordRemoval}
|
||||||
title={Languages.t("components.public-link-security_password_removal_title")}
|
title={Languages.t("components.public-link-security_password_removal_title")}
|
||||||
text={Languages.t("components.public-link-security_password_removal_body")}
|
text={Languages.t("components.public-link-security_password_removal_body")}
|
||||||
theme="danger"
|
theme="danger"
|
||||||
icon={ShieldExclamationIcon}
|
icon={ShieldExclamationIcon}
|
||||||
buttons={
|
buttonOkTheme='danger'
|
||||||
<>
|
buttonOkLabel='components.public-link-security_password_removal_confirm'
|
||||||
<Button
|
|
||||||
className="ml-2"
|
onClose={() => setIsConfirmingPasswordRemoval(false)}
|
||||||
theme='default'
|
onOk={() => savePassword("")}
|
||||||
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>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</Modal>
|
|
||||||
</>;
|
</>;
|
||||||
}
|
}
|
||||||
@@ -31,10 +31,7 @@ export const AccessModal = () => {
|
|||||||
open={state.open}
|
open={state.open}
|
||||||
onClose={() => setState({ ...state, open: false })}
|
onClose={() => setState({ ...state, open: false })}
|
||||||
>
|
>
|
||||||
{!!state.id &&
|
{!!state.id && <AccessModalContent id={state.id} />}
|
||||||
<AccessModalContent
|
|
||||||
id={state.id}
|
|
||||||
/>}
|
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user