Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ref(collaborators): refactor to remove shared props from context #1076

Merged
merged 40 commits into from
Oct 21, 2022
Merged
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
a0fbcd3
refactor(collaborators): refactors collaborators to remove context
seaerchin Sep 27, 2022
dfcfb55
fix(removecollaborator): renamed variable for clarity
seaerchin Sep 30, 2022
634f196
chore(cøllaboratorhooks): remove extra imports
seaerchin Sep 30, 2022
013f25b
chore(collaboratormodal): rename variable for clarity
seaerchin Sep 30, 2022
22fd9f7
fix(mainsubmodal): add rudimentary validation
seaerchin Sep 30, 2022
b3a3d38
refactor(collaboratormodal): shift constant to own file
seaerchin Sep 30, 2022
d1768f1
chore(collaboratormodal): misc fixes
seaerchin Sep 30, 2022
78d3070
chore(loadingbutton): add code block
seaerchin Oct 19, 2022
d7b72e7
refactor(ack submodal): remove moadl body
seaerchin Oct 19, 2022
9fc4276
refactor(removecollaboratorsubmodal): pass user and onDeleteComplete …
seaerchin Oct 19, 2022
9dd58c9
refactor(collaboratormodal): refactor to manage state between deletio…
seaerchin Oct 19, 2022
f797458
refactor(mainsubmodal): shift unnecessary state downwards into the ma…
seaerchin Oct 19, 2022
d0d111b
chore(utils): tweak apiDataBuilder to be slightly more powerful
seaerchin Oct 19, 2022
a702fc2
chore(collab modal stories): tweak stories to work with api
seaerchin Oct 19, 2022
a009d86
chore(collaboratormodal): rename subfolder to components
seaerchin Oct 19, 2022
57ae7f9
chore(constants): removed unused stuff
seaerchin Oct 19, 2022
e483b2f
refactor(collaborators types): shift collaborator types to types folder
seaerchin Oct 19, 2022
83674e6
chore(collaboratorservice): add types to methods
seaerchin Oct 19, 2022
7272cf0
chore(collaboratorhooks): add types to hooks
seaerchin Oct 19, 2022
0525d67
chore(mocks): update mocks to fit new typings
seaerchin Oct 19, 2022
8ce9d08
chore(mainsubmodal): update to fit new types
seaerchin Oct 19, 2022
ccd4ce8
chore(collaborator hooks): shift into own files for ease of discovery
seaerchin Oct 19, 2022
c58cdb6
chore(types): shift collaborator to error and rename
seaerchin Oct 19, 2022
b6fbb87
chore(dashboard): edit dashboard for testing
seaerchin Oct 19, 2022
769575e
chore(collaboratorhooks): update error import
seaerchin Oct 19, 2022
4933be5
refactor(mainsubmodal): add loading state and fix reset
seaerchin Oct 19, 2022
e0cb508
refactor(ack submodal): add isloading prop
seaerchin Oct 19, 2022
ffc1462
refactor(collaboartor): add loading stae; update import
seaerchin Oct 19, 2022
85061cb
chore(usedeletecollaboratorhook): update erro type
seaerchin Oct 19, 2022
603d27c
fix(collaboratormodal): prevent useres being stuck on delete
seaerchin Oct 20, 2022
d066653
fix(uselistcollaboratorshook): transform data from be into shape
seaerchin Oct 20, 2022
72f8858
fix(mainsubmodal): disable button if field empty
seaerchin Oct 20, 2022
e968c16
chore(mainsubmodal): convert units to rem
seaerchin Oct 20, 2022
d91e8db
fix(mainsubmodal): clean up state on modal close
seaerchin Oct 20, 2022
147a374
chore(mainsubmodal): remove unused variables
seaerchin Oct 20, 2022
251b026
chore(mainsubmodal): remove multiple calls to function
seaerchin Oct 20, 2022
aa5b654
chore(collaboratormodal): fix stories
seaerchin Oct 21, 2022
23746af
fix(mainsubmodal): fixed text sizing and add placeholder
seaerchin Oct 21, 2022
a181a01
fix(collaborator): fixed story typing for constants
seaerchin Oct 21, 2022
d9f0155
chore(mainsubmodal): update text styling
seaerchin Oct 21, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 20 additions & 14 deletions src/components/CollaboratorModal/CollaboratorModal.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import { Button, useDisclosure } from "@chakra-ui/react"
import { ComponentMeta, ComponentStory } from "@storybook/react"
import { CollaboratorModal } from "components/CollaboratorModal/index"
import { MemoryRouter, Route } from "react-router-dom"

import { MOCK_COLLABORATORS, MOCK_USER } from "mocks/constants"
import { handlers } from "mocks/handlers"
import {
addContributorCollaborator,
buildCollaboratorData,
buildCollaboratorRoleData,
buildContributor,
buildLoginData,
buildRemoveContributor,
} from "mocks/utils"
import { CollaboratorData } from "types/collaborators"

Expand All @@ -35,15 +37,26 @@ const collaboratorModalMeta = {
],
} as ComponentMeta<typeof CollaboratorModal>

const Template: ComponentStory<typeof CollaboratorModal> = CollaboratorModal
// TODO!: add stories for the submodals
// the sub modals won't show up on chromatic when changes are made at present.
const Template: ComponentStory<typeof CollaboratorModal> = () => {
const props = useDisclosure({ defaultIsOpen: true })
return (
<>
<Button onClick={props.onOpen}>Open collaborators</Button>
<CollaboratorModal {...props} />
</>
)
}

export const AdminMain = Template.bind({})
AdminMain.parameters = {
msw: {
handlers: [
...handlers,
buildRemoveContributor(null),
buildLoginData(MOCK_USER),
buildCollaboratorData(({
buildCollaboratorData({
collaborators: [
// Email override so that the modal can display the "(You)" text depending on
// the LoggedInUser
Expand All @@ -52,14 +65,12 @@ AdminMain.parameters = {
MOCK_COLLABORATORS.CONTRIBUTOR_1,
MOCK_COLLABORATORS.CONTRIBUTOR_2,
],
} as unknown) as CollaboratorData),
}),
buildCollaboratorRoleData({ role: "ADMIN" }),
buildContributor(),
],
},
}
AdminMain.args = {
siteName: "default",
}

export const ContributorMain = Template.bind({})
ContributorMain.parameters = {
Expand Down Expand Up @@ -87,16 +98,14 @@ ContributorMain.parameters = {
],
},
}
ContributorMain.args = {
siteName: "default",
}

export const AdminAddContributor = Template.bind({})
AdminAddContributor.parameters = {
msw: {
handlers: [
...handlers,
buildLoginData(MOCK_USER),
buildRemoveContributor(null),
buildCollaboratorData(({
collaborators: [
// Email override so that the modal can display the "(You)" text depending on
Expand All @@ -108,11 +117,8 @@ AdminAddContributor.parameters = {
],
} as unknown) as CollaboratorData),
buildCollaboratorRoleData({ role: "ADMIN" }),
addContributorCollaborator(),
buildContributor(true),
],
},
}
AdminAddContributor.args = {
siteName: "default",
}
export default collaboratorModalMeta
166 changes: 41 additions & 125 deletions src/components/CollaboratorModal/CollaboratorModal.tsx
Original file line number Diff line number Diff line change
@@ -1,135 +1,51 @@
import { ModalProps } from "@chakra-ui/react"
import {
Modal,
ModalOverlay,
ModalContent,
ModalFooter,
useDisclosure,
Center,
} from "@chakra-ui/react"
import { Button } from "@opengovsg/design-system-react"
import { CollaboratorModalContext } from "components/CollaboratorModal/CollaboratorModalContext"
import { CollaboratorModalState } from "components/CollaboratorModal/constants"
import {
AcknowledgementSubmodal,
MainSubmodal,
RemoveCollaboratorSubmodal,
} from "components/CollaboratorModal/submodals"
import PropTypes from "prop-types"
} from "components/CollaboratorModal/components"
import { useState } from "react"

import { LOCAL_STORAGE_KEYS } from "constants/localStorage"

import * as CollaboratorHooks from "hooks/collaboratorHooks"
import { useLocalStorage } from "hooks/useLocalStorage"
import { useLoginContext } from "contexts/LoginContext"

// eslint-disable-next-line import/prefer-default-export
export const CollaboratorModal = ({ siteName }: { siteName: string }) => {
const { isOpen, onOpen, onClose } = useDisclosure()
const [localUser] = useLocalStorage(LOCAL_STORAGE_KEYS.User, { email: "" })
import useRedirectHook from "hooks/useRedirectHook"

const [newCollaboratorEmail, setNewCollaboratorEmail] = useState("")
const [addCollaboratorError, setAddCollaboratorError] = useState("")
const [deleteCollaboratorTarget, setDeleteCollaboratorTarget] = useState(
undefined
)
const [modalState, setModalState] = useState<CollaboratorModalState>(
CollaboratorModalState.Default
)
const [isAcknowledged, setIsAcknowledged] = useState(false)
import { Collaborator } from "types/collaborators"

// Set up hooks
const { data: collaboratorData } = CollaboratorHooks.useListCollaboratorsHook(
siteName
)

const {
data: collaboratorRoleData,
} = CollaboratorHooks.useGetCollaboratorRoleHook(siteName)

const {
mutateAsync: addCollaborator,
} = CollaboratorHooks.useAddCollaboratorHook(
siteName,
setAddCollaboratorError,
setModalState,
isAcknowledged,
setIsAcknowledged
)

const {
mutateAsync: deleteCollaborator,
} = CollaboratorHooks.useDeleteCollaboratorHook(siteName)

// Handlers
const handleAddCollaborator = async () => {
addCollaborator(newCollaboratorEmail)
}
const handleDeleteCollaborator = async (collaboratorId: string) => {
deleteCollaborator(collaboratorId)
}

const renderModalContent = (currModalState: CollaboratorModalState) => {
switch (currModalState) {
case CollaboratorModalState.Acknowledgement:
return <AcknowledgementSubmodal />
case CollaboratorModalState.Default:
return <MainSubmodal />
case CollaboratorModalState.RemoveCollaborator:
return <RemoveCollaboratorSubmodal />

default:
return <MainSubmodal />
}
}

return (
<>
<Center m="36px">
<Button onClick={onOpen}>Manage site collaborators</Button>
</Center>
<CollaboratorModalContext.Provider
value={{
newCollaboratorEmail,
setNewCollaboratorEmail,
addCollaboratorError,
setAddCollaboratorError,
modalState,
setModalState,
isAcknowledged,
setIsAcknowledged,
collaboratorData,
collaboratorRoleData,
addCollaborator,
deleteCollaborator,
handleAddCollaborator,
handleDeleteCollaborator,
isModalOpen: isOpen,
closeModal: onClose,
localUser,
deleteCollaboratorTarget,
setDeleteCollaboratorTarget,
}}
>
<Modal
isOpen={isOpen}
onClose={() => {
setAddCollaboratorError("")
setModalState(CollaboratorModalState.Default)
setDeleteCollaboratorTarget(undefined)
onClose()
}}
>
<ModalOverlay />
<ModalContent>
{renderModalContent(modalState)}
<ModalFooter p="22px" />
</ModalContent>
</Modal>
</CollaboratorModalContext.Provider>
</>
// eslint-disable-next-line import/prefer-default-export
export const CollaboratorModal = (
props: Omit<ModalProps, "children">
): JSX.Element => {
const [deleteCollaboratorTarget, setDeleteCollaboratorTarget] = useState<
Collaborator | undefined
>(undefined)
const { onCloseComplete } = props
const [showDelete, setShowDelete] = useState(false)
const { email } = useLoginContext()
const isUserDeletingThemselves = email === deleteCollaboratorTarget?.email
const { setRedirectToPage } = useRedirectHook()

return showDelete && deleteCollaboratorTarget ? (
<RemoveCollaboratorSubmodal
{...props}
userToDelete={deleteCollaboratorTarget}
onCloseComplete={() => {
setShowDelete(false)
onCloseComplete?.()
}}
onDeleteComplete={() => {
setShowDelete(false)
if (isUserDeletingThemselves) {
setRedirectToPage(`/sites`)
}
}}
/>
) : (
<MainSubmodal
{...props}
onDelete={(user) => {
setShowDelete(true)
setDeleteCollaboratorTarget(user)
}}
/>
)
}

CollaboratorModal.propTypes = {
siteName: PropTypes.string.isRequired,
}
40 changes: 0 additions & 40 deletions src/components/CollaboratorModal/CollaboratorModalContext.tsx

This file was deleted.

Loading