From e0bc9ac50fbc9a444fd4573bcfe0c20858b488dc Mon Sep 17 00:00:00 2001 From: Charles Morgan Date: Sun, 18 Oct 2020 04:31:54 -0400 Subject: [PATCH 1/2] Duplicate save/invite button at top Adds the Save / Invite User button at the top also --- .../server/users/EditSubuserModal.tsx | 71 +++++++++++-------- 1 file changed, 40 insertions(+), 31 deletions(-) diff --git a/resources/scripts/components/server/users/EditSubuserModal.tsx b/resources/scripts/components/server/users/EditSubuserModal.tsx index d81d15f08..117869703 100644 --- a/resources/scripts/components/server/users/EditSubuserModal.tsx +++ b/resources/scripts/components/server/users/EditSubuserModal.tsx @@ -41,7 +41,7 @@ const PermissionLabel = styled.label` ${tw`border-neutral-500 bg-neutral-800`}; } } - + &:not(:first-of-type) { ${tw`mt-4 sm:mt-2`}; } @@ -90,11 +90,11 @@ const PermissionTitledBox = memo(({ isEditable, permission, permissions, classNa

{permission}

{isEditable && - values.permissions.includes(p))} - onChange={onCheckboxClicked} - /> + values.permissions.includes(p))} + onChange={onCheckboxClicked} + /> }
} @@ -132,30 +132,39 @@ const EditSubuserModal = forwardRef(({ subuser, ...pr return ( -

- {subuser ? - `${canEditUser ? 'Modify' : 'View'} permissions for ${subuser.email}` - : - 'Create new subuser' - } -

- - {(!user.rootAdmin && loggedInPermissions[0] !== '*') && -
-

- Only permissions which your account is currently assigned may be selected when creating or - modifying other users. -

+
+
+

+ {subuser ? + `${canEditUser ? 'Modify' : 'View'} permissions for ${subuser.email}` + : + 'Create new subuser ' + } +

+
+
+ +
+ + {(!user.rootAdmin && loggedInPermissions[0] !== '*') && +
+

+ Only permissions which your account is currently assigned may be selected when creating or + modifying other users. +

+
} {!subuser && -
- -
+
+ +
}
{Object.keys(permissions).filter(key => key !== 'websocket').map((key, index) => { @@ -190,9 +199,9 @@ const EditSubuserModal = forwardRef(({ subuser, ...pr
{permissions[key].keys[pkey].length > 0 && -

- {permissions[key].keys[pkey]} -

+

+ {permissions[key].keys[pkey]} +

}
@@ -258,7 +267,7 @@ export default ({ subuser, ...props }: Props) => { })} >
- + ); From 0f09dfed92413989a644a0c01bc02f430c481e0b Mon Sep 17 00:00:00 2001 From: Charles Morgan Date: Sat, 31 Oct 2020 17:29:41 -0400 Subject: [PATCH 2/2] Update EditSubuserModal.tsx --- .../server/users/EditSubuserModal.tsx | 282 ++++++------------ 1 file changed, 85 insertions(+), 197 deletions(-) diff --git a/resources/scripts/components/server/users/EditSubuserModal.tsx b/resources/scripts/components/server/users/EditSubuserModal.tsx index 117869703..77a84bc08 100644 --- a/resources/scripts/components/server/users/EditSubuserModal.tsx +++ b/resources/scripts/components/server/users/EditSubuserModal.tsx @@ -1,14 +1,10 @@ -import React, { forwardRef, memo, useCallback, useEffect, useRef } from 'react'; +import React, { useContext, useEffect, useRef } from 'react'; import { Subuser } from '@/state/server/subusers'; -import { Form, Formik, FormikHelpers, useFormikContext } from 'formik'; +import { Form, Formik } from 'formik'; import { array, object, string } from 'yup'; -import Modal, { RequiredModalProps } from '@/components/elements/Modal'; import Field from '@/components/elements/Field'; import { Actions, useStoreActions, useStoreState } from 'easy-peasy'; import { ApplicationStore } from '@/state'; -import TitledGreyBox from '@/components/elements/TitledGreyBox'; -import Checkbox from '@/components/elements/Checkbox'; -import styled from 'styled-components/macro'; import createOrUpdateSubuser from '@/api/server/users/createOrUpdateSubuser'; import { ServerContext } from '@/state/server'; import FlashMessageRender from '@/components/FlashMessageRender'; @@ -17,104 +13,33 @@ import { usePermissions } from '@/plugins/usePermissions'; import { useDeepCompareMemo } from '@/plugins/useDeepCompareMemo'; import tw from 'twin.macro'; import Button from '@/components/elements/Button'; -import Label from '@/components/elements/Label'; -import Input from '@/components/elements/Input'; -import isEqual from 'react-fast-compare'; +import PermissionTitleBox from '@/components/server/users/PermissionTitleBox'; +import asModal from '@/hoc/asModal'; +import PermissionRow from '@/components/server/users/PermissionRow'; +import ModalContext from '@/context/ModalContext'; type Props = { subuser?: Subuser; -} & RequiredModalProps; +}; interface Values { email: string; permissions: string[]; } -const PermissionLabel = styled.label` - ${tw`flex items-center border border-transparent rounded md:p-2 transition-colors duration-75`}; - text-transform: none; +const EditSubuserModal = ({ subuser }: Props) => { + const ref = useRef(null); + const uuid = ServerContext.useStoreState(state => state.server.data!.uuid); + const appendSubuser = ServerContext.useStoreActions(actions => actions.subusers.appendSubuser); + const { clearFlashes, clearAndAddHttpError } = useStoreActions((actions: Actions) => actions.flashes); + const { dismiss, toggleSpinner } = useContext(ModalContext); - &:not(.disabled) { - ${tw`cursor-pointer`}; - - &:hover { - ${tw`border-neutral-500 bg-neutral-800`}; - } - } - - &:not(:first-of-type) { - ${tw`mt-4 sm:mt-2`}; - } - - &.disabled { - ${tw`opacity-50`}; - - & input[type="checkbox"]:not(:checked) { - ${tw`border-0`}; - } - } -`; - -interface TitleProps { - isEditable: boolean; - permission: string; - permissions: string[]; - children: React.ReactNode; - className?: string; -} - -const PermissionTitledBox = memo(({ isEditable, permission, permissions, className, children }: TitleProps) => { - const { values, setFieldValue } = useFormikContext(); - - const onCheckboxClicked = useCallback((e: React.ChangeEvent) => { - console.log(e.currentTarget.checked, [ - ...values.permissions, - ...permissions.filter(p => !values.permissions.includes(p)), - ]); - - if (e.currentTarget.checked) { - setFieldValue('permissions', [ - ...values.permissions, - ...permissions.filter(p => !values.permissions.includes(p)), - ]); - } else { - setFieldValue('permissions', [ - ...values.permissions.filter(p => !permissions.includes(p)), - ]); - } - }, [ permissions, values.permissions ]); - - return ( - -

{permission}

- {isEditable && - values.permissions.includes(p))} - onChange={onCheckboxClicked} - /> - } -
- } - className={className} - > - {children} - - ); -}, isEqual); - -const EditSubuserModal = forwardRef(({ subuser, ...props }, ref) => { - const { isSubmitting } = useFormikContext(); - const [ canEditUser ] = usePermissions(subuser ? [ 'user.update' ] : [ 'user.create' ]); + const isRootAdmin = useStoreState(state => state.user.data!.rootAdmin); const permissions = useStoreState(state => state.permissions.data); - - const user = useStoreState(state => state.user.data!); - // The currently logged in user's permissions. We're going to filter out any permissions // that they should not need. const loggedInPermissions = ServerContext.useStoreState(state => state.server.permissions); + const [ canEditUser ] = usePermissions(subuser ? [ 'user.update' ] : [ 'user.create' ]); // The permissions that can be modified by this user. const editablePermissions = useDeepCompareMemo(() => { @@ -123,120 +48,25 @@ const EditSubuserModal = forwardRef(({ subuser, ...pr const list: string[] = ([] as string[]).concat.apply([], Object.values(cleaned)); - if (user.rootAdmin || (loggedInPermissions.length === 1 && loggedInPermissions[0] === '*')) { + if (isRootAdmin || (loggedInPermissions.length === 1 && loggedInPermissions[0] === '*')) { return list; } return list.filter(key => loggedInPermissions.indexOf(key) >= 0); - }, [ permissions, loggedInPermissions ]); + }, [ isRootAdmin, permissions, loggedInPermissions ]); - return ( - -
-
-

- {subuser ? - `${canEditUser ? 'Modify' : 'View'} permissions for ${subuser.email}` - : - 'Create new subuser ' - } -

-
-
- -
-
- - {(!user.rootAdmin && loggedInPermissions[0] !== '*') && -
-

- Only permissions which your account is currently assigned may be selected when creating or - modifying other users. -

-
- } - {!subuser && -
- -
- } -
- {Object.keys(permissions).filter(key => key !== 'websocket').map((key, index) => { - const group = Object.keys(permissions[key].keys).map(pkey => `${key}.${pkey}`); - - return ( - 0 ? tw`mt-4` : undefined} - > -

- {permissions[key].description} -

- {Object.keys(permissions[key].keys).map(pkey => ( - -
- -
-
- - {permissions[key].keys[pkey].length > 0 && -

- {permissions[key].keys[pkey]} -

- } -
-
- ))} -
- ); - })} -
- -
- -
-
-
- ); -}); - -export default ({ subuser, ...props }: Props) => { - const ref = useRef(null); - const uuid = ServerContext.useStoreState(state => state.server.data!.uuid); - const appendSubuser = ServerContext.useStoreActions(actions => actions.subusers.appendSubuser); - const { clearFlashes, clearAndAddHttpError } = useStoreActions((actions: Actions) => actions.flashes); - - const submit = (values: Values, { setSubmitting }: FormikHelpers) => { + const submit = (values: Values) => { + toggleSpinner(true); clearFlashes('user:edit'); + createOrUpdateSubuser(uuid, values, subuser) .then(subuser => { appendSubuser(subuser); - props.onDismissed(); + dismiss(); }) .catch(error => { console.error(error); - setSubmitting(false); + toggleSpinner(false); clearAndAddHttpError({ key: 'user:edit', error }); if (ref.current) { @@ -245,10 +75,8 @@ export default ({ subuser, ...props }: Props) => { }); }; - useEffect(() => { - return () => { - clearFlashes('user:edit'); - }; + useEffect(() => () => { + clearFlashes('user:edit'); }, []); return ( @@ -267,8 +95,68 @@ export default ({ subuser, ...props }: Props) => { })} >
- +
+

+ {subuser ? `${canEditUser ? 'Modify' : 'View'} permissions for ${subuser.email}` : 'Create new subuser'} +

+
+ +
+
+ + {(!isRootAdmin && loggedInPermissions[0] !== '*') && +
+

+ Only permissions which your account is currently assigned may be selected when creating or + modifying other users. +

+
+ } + {!subuser && +
+ +
+ } +
+ {Object.keys(permissions).filter(key => key !== 'websocket').map((key, index) => ( + `${key}.${pkey}`)} + css={index > 0 ? tw`mt-4` : undefined} + > +

+ {permissions[key].description} +

+ {Object.keys(permissions[key].keys).map(pkey => ( + + ))} +
+ ))} +
+ +
+ +
+
); }; + +export default asModal({ + top: false, +})(EditSubuserModal);