diff --git a/assets/icons/illus/cozy-authentification.svg b/assets/icons/illus/cozy-authentification.svg new file mode 100644 index 0000000000..3ee946131c --- /dev/null +++ b/assets/icons/illus/cozy-authentification.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/ui/eye-closed.svg b/assets/icons/ui/eye-closed.svg index 279c8a2871..8ce79592ed 100644 --- a/assets/icons/ui/eye-closed.svg +++ b/assets/icons/ui/eye-closed.svg @@ -1,7 +1 @@ - - - - - - - + \ No newline at end of file diff --git a/docs/styleguide.config.js b/docs/styleguide.config.js index 3438bd63b6..f555f4e210 100644 --- a/docs/styleguide.config.js +++ b/docs/styleguide.config.js @@ -93,6 +93,7 @@ module.exports = { '../react/NoSsr', '../react/OutlinedInput', '../react/Paper', + '../react/PasswordField', '../react/PieChart', '../react/Progress', '../react/ProgressionBanner', diff --git a/react/CozyDialogs/PermissionDialog.jsx b/react/CozyDialogs/PermissionDialog.jsx new file mode 100644 index 0000000000..514d4d938e --- /dev/null +++ b/react/CozyDialogs/PermissionDialog.jsx @@ -0,0 +1,94 @@ +import React from 'react' +import cx from 'classnames' + +import { makeStyles } from '../styles' +import CozyTheme from '../CozyTheme' +import ConfirmDialog from './ConfirmDialog' +import PropTypes from 'prop-types' +import Icon from '../Icon' +import Paper from '../Paper' + +const useStyles = makeStyles({ + floatingIcon: { + top: '-2.25rem', + width: '4.5rem', + height: '4.5rem' + } +}) + +/** + * Dialog for confirmation actions linked to the Cozy system (permissions, authentication, etc.) + */ +const PermissionDialog = ({ + open, + icon, + title, + content, + actions, + actionsLayout, + onClose +}) => { + const styles = useStyles() + + return ( + + + + + + + + {title} + + } + content={content} + actions={actions} + actionsLayout={actionsLayout} + onClose={onClose} + /> + + ) +} + +PermissionDialog.propTypes = { + /** To open/close the modal */ + open: PropTypes.bool.isRequired, + /** Icon to describe the action to be taken */ + icon: PropTypes.func.isRequired, + /** Title of the modal */ + title: PropTypes.string.isRequired, + /** Content of the modal */ + content: PropTypes.node, + /** Actions of the modal */ + actions: PropTypes.node, + /** Actions can be displayed as "rows" or "columns" */ + actionsLayout: PropTypes.oneOf(['row', 'column']), + /** Triggered function on modal close action */ + onClose: PropTypes.func +} + +export default PermissionDialog diff --git a/react/CozyDialogs/Readme.md b/react/CozyDialogs/Readme.md index 49f4efaca9..0b05a09812 100644 --- a/react/CozyDialogs/Readme.md +++ b/react/CozyDialogs/Readme.md @@ -59,7 +59,8 @@ import { ConfirmDialog, IllustrationDialog, FixedDialog, - FixedActionsDialog + FixedActionsDialog, + PermissionDialog } from 'cozy-ui/transpiled/react/CozyDialogs' import { BreakpointsProvider } from 'cozy-ui/transpiled/react/hooks/useBreakpoints' @@ -77,6 +78,7 @@ import FormLabel from 'cozy-ui/transpiled/react/FormLabel' import BottomSheet, { BottomSheetItem } from 'cozy-ui/transpiled/react/BottomSheet' import Stack from 'cozy-ui/transpiled/react/Stack' +import ToTheCloudIcon from 'cozy-ui/transpiled/react/Icons/ToTheCloud' import CloudIcon from "cozy-ui/transpiled/react/Icons/Cloud" import BackgroundImg from './background.png' @@ -133,7 +135,8 @@ const dialogTitles = { IllustrationDialog: , FixedDialog: 'Fixed Dialog', FixedActionsDialog: 'Fixed Actions Dialog', - Dialog: 'Dialog' + Dialog: 'Dialog', + PermissionDialog: 'Are you sure ?' } const dialogContents = { @@ -141,7 +144,8 @@ const dialogContents = { IllustrationDialog: "An IllustrationDialog contains short content." + content.ada.short, FixedDialog: "A FixedDialog can contain very long content. Actions are at the bottom of the content are not visible to the user if she has not scrolled to the bottom. " + content.ada.long, FixedActionsDialog: "A FixedActionsDialog can contain very long content. Actions are visible even without scrolling. " + content.ada.long, - Dialog: "A normal Dialog should contain short content. " + content.ada.short + Dialog: "A normal Dialog should contain short content. " + content.ada.short, + PermissionDialog: "Content of a confirm dialog, precising what the actions will do, and asking the user if she is sure.", } const dialogActions = { @@ -149,7 +153,8 @@ const dialogActions = { IllustrationDialog: , FixedDialog: , FixedActionsDialog: , - Dialog: + Dialog: , + PermissionDialog: , } const dialogs = [ @@ -157,7 +162,8 @@ const dialogs = [ ConfirmDialog, IllustrationDialog, FixedDialog, - FixedActionsDialog + FixedActionsDialog, + PermissionDialog ] const StateRadio = ({ name, ...props }) => { @@ -326,6 +332,7 @@ const setFlagshipVars = () => { } disableGutters={variant.disableGutters} background={variant.withBackground ? `var(--paperBackgroundColor) repeat-x url(${BackgroundImg})` : undefined} + icon={DialogComponent === PermissionDialog ? CloudIcon : undefined} content={ <> diff --git a/react/CozyDialogs/SpecificDialogs/AuthentificationDialog.jsx b/react/CozyDialogs/SpecificDialogs/AuthentificationDialog.jsx new file mode 100644 index 0000000000..c1b82ec760 --- /dev/null +++ b/react/CozyDialogs/SpecificDialogs/AuthentificationDialog.jsx @@ -0,0 +1,109 @@ +import React, { useMemo, useState } from 'react' +import PropTypes from 'prop-types' + +import PermissionDialog from '../PermissionDialog' +import Buttons from '../../Buttons' +import { useI18n } from '../../I18n' +import Typography from '../../Typography' +import { useClient } from 'cozy-client' +import CozyAuthentificationIcon from '../../Icons/CozyAuthentification' +import PasswordField from '../../PasswordField' + +import withSpecificDialogsLocales from './withSpecificDialogsLocales' + +/** + * Dialog used to authenticate a user in the cozy system. + * The authentication logic is implemented in the applications. + */ +const AuthentificationDialog = ({ + onClose, + onSubmit, + isLoading, + isOIDC, + error +}) => { + const { t } = useI18n() + const client = useClient() + const [password, setPassword] = useState('') + + const handleSubmit = e => { + e.preventDefault() + onSubmit(password) + } + + const onPasswordChange = e => { + setPassword(e.currentTarget.value) + } + + const passphraseResetUrl = useMemo(() => { + const url = new URL('/auth/passphrase_reset', client.getStackClient().uri) + return url.href + }, [client]) + + return ( + + + {t('authentification-dialog.subtitle')} + + + + {t('authentification-dialog.forgotten-password')} + + + } + actions={ + + } + /> + ) +} + +AuthentificationDialog.defaultProps = { + isOIDC: false +} + +AuthentificationDialog.propTypes = { + /** A function call on clicking the close button */ + onClose: PropTypes.func, + /** A function call on submitting the form with the password entered */ + onSubmit: PropTypes.func, + /** Waiting status, e.g. processing of form submission */ + isLoading: PropTypes.bool, + /** Show specific wording for OIDC */ + isOIDC: PropTypes.bool, + /** Error key to display a message */ + error: PropTypes.string +} + +export default withSpecificDialogsLocales(AuthentificationDialog) diff --git a/react/CozyDialogs/SpecificDialogs/Readme.md b/react/CozyDialogs/SpecificDialogs/Readme.md index c7c5f0691b..07cfc328dd 100644 --- a/react/CozyDialogs/SpecificDialogs/Readme.md +++ b/react/CozyDialogs/SpecificDialogs/Readme.md @@ -21,3 +21,61 @@ const [open, setOpen] = useState(isTesting()); { setOpen(true) }} label="Open InstallFlagshipAppDialog" /> ``` + +### Authentification dialog + +Dialog used to authenticate a user in the cozy system. The authentication logic is implemented in the applications. + +```jsx +import { AuthentificationDialog } from 'cozy-ui/transpiled/react/CozyDialogs' +import Button from 'cozy-ui/transpiled/react/Buttons' +import DemoProvider from 'cozy-ui/docs/components/DemoProvider' +import Variants from 'cozy-ui/docs/components/Variants' +import FormControlLabel from 'cozy-ui/transpiled/react/FormControlLabel' +import RadioGroup from 'cozy-ui/transpiled/react/RadioGroup' +import Radio from 'cozy-ui/transpiled/react/Radios' +import FormControl from 'cozy-ui/transpiled/react/FormControl' +import FormLabel from 'cozy-ui/transpiled/react/FormLabel' + +initialState = { showModal: false }; + +const initialVariants = [{ + closable: true, + loading: false, + oidc: false +}] + +const initialErrors = [{ + default: true, + invalid_password: false, + server_error: false +}] + +const onClose = () => setState({ showModal: false }) + +const onAuthentification = () => { + alert('authentification') + setState({ showModal: false }) +}; + + + {variant => ( + + {error => ( + +