From b1880a41f23566bc389001d3aacf0a9c5d6e2f62 Mon Sep 17 00:00:00 2001 From: Joshua Shoemaker Date: Fri, 20 Oct 2023 10:51:53 -0500 Subject: [PATCH] refact: session to redux not working yet --- frontend/components/project/Main.tsx | 28 +++++++--- frontend/components/settings/User.tsx | 21 +++++--- frontend/pages/index.tsx | 1 + .../redux/features/session/sessionSlice.ts | 53 +++++++++++++++++++ frontend/redux/features/session/types.ts | 9 ++++ frontend/redux/serialize.ts | 9 ++++ frontend/redux/store.ts | 2 + 7 files changed, 108 insertions(+), 15 deletions(-) create mode 100644 frontend/redux/features/session/sessionSlice.ts create mode 100644 frontend/redux/features/session/types.ts create mode 100644 frontend/redux/serialize.ts diff --git a/frontend/components/project/Main.tsx b/frontend/components/project/Main.tsx index 65ba38e..8957b17 100644 --- a/frontend/components/project/Main.tsx +++ b/frontend/components/project/Main.tsx @@ -2,23 +2,28 @@ import { Popover, Transition } from '@headlessui/react' import { ChevronDownIcon, FolderArrowDownIcon, FolderOpenIcon, FolderPlusIcon } from '@heroicons/react/20/solid' -import { Fragment, useState } from 'react' +import { Fragment, useEffect, useState } from 'react' import { useNavigation } from '../../context/Navigation/provider' import { mainPages } from '../../context/Navigation/types' -import { useProject } from '../../context/Project/provider' +// import { useProject } from '../../context/Project/provider' import { GetAllLocalProjects } from '../../wailsjs/wailsjs/go/ipc/Channel' import { entities } from '../../wailsjs/wailsjs/go/models' import NewProjectModal from './NewProjectModal' import ProjectListModal from './ProjectListModal' - +import { useDispatch, useSelector } from 'react-redux' +import { RootState } from '../../redux/store' +import { createNewProject, requestSelectProjectByName } from '../../redux/features/session/sessionSlice' const MainProject = () => { + const dispatch = useDispatch() + const { currentSession } = useSelector((state: RootState) => state.session) + const [isNewProjectModalOpen, setIsNewProjectModalOpen] = useState(false) const [isProjectListModal, setIsProjectListModal] = useState(false) const [canPopoverBeOpen, setCanPopoverBeOpen] = useState(true) const [availableProjects, setAvailableProjects] = useState([]) - const { createNewProject, requestSelectProjectByName } = useProject() + // const { createNewProject, requestSelectProjectByName } = useProject() const { setSelectedMainPage } = useNavigation() const buttonOptions = [ @@ -57,18 +62,25 @@ const MainProject = () => { const onCreateNewProjectHandler = async (projectName: string) => { setIsNewProjectModalOpen(false) setCanPopoverBeOpen(true) - await createNewProject(projectName) - setSelectedMainPage(mainPages.WORKSPACE) + dispatch(createNewProject(projectName)) + // setSelectedMainPage(mainPages.WORKSPACE) } const onSelectProjectHandler = async (name: string) => { - const successfulResponse = await requestSelectProjectByName(name) + // const successfulResponse = await requestSelectProjectByName(name) + dispatch(requestSelectProjectByName(name)) setIsProjectListModal(false) setCanPopoverBeOpen(true) - if (successfulResponse) setSelectedMainPage(mainPages.WORKSPACE) + // if (successfulResponse) setSelectedMainPage(mainPages.WORKSPACE) + // setSelectedMainPage(mainPages.WORKSPACE) } + useEffect(() => { + console.log('useEffect: ', currentSession?.project?.id) + if (currentSession?.project?.id) setSelectedMainPage(mainPages.WORKSPACE) + }, [currentSession?.project?.id]) + return
{isNewProjectModalOpen ? : ''} diff --git a/frontend/components/settings/User.tsx b/frontend/components/settings/User.tsx index 874b360..142a5fc 100644 --- a/frontend/components/settings/User.tsx +++ b/frontend/components/settings/User.tsx @@ -1,13 +1,19 @@ import Search from '../utils/Search' -import { useProject } from '../../context/Project/provider' +// import { useProject } from '../../context/Project/provider' import { EnvelopeIcon } from '@heroicons/react/24/outline' import UserAvatar from '../utils/UserAvatar' -import { useRef, useState } from 'react' +import { useEffect, useRef, useState } from 'react' import { useNavigation } from '../../context/Navigation/provider' import { mainPages } from '../../context/Navigation/types' +import { useDispatch, useSelector } from 'react-redux' +import { RootState } from '../../redux/store' +import { requestUpdateCurrentUser } from '../../redux/features/session/sessionSlice' const User = () => { - const { currentSession, requestUpdateCurrentUser, requestChooseUserAvatar } = useProject() + const dispatch = useDispatch() + const { currentSession } = useSelector((state: RootState) => state.session) + + // const { requestUpdateCurrentUser, requestChooseUserAvatar } = useProject() const { setSelectedMainPage } = useNavigation() const firstNameRef = useRef(null) @@ -16,19 +22,20 @@ const User = () => { const [avatarPath, setAvatarPath] = useState(currentSession?.user?.avatarPath || '') const onSaveButtonClickHandler = async () => { - await requestUpdateCurrentUser({ + dispatch(requestUpdateCurrentUser({ localId: currentSession?.user?.localId, firstName: firstNameRef?.current?.value, lastName: lastNameRef?.current?.value, email: emailRef?.current?.value, avatarPath: avatarPath || '' - }) + })) setSelectedMainPage(mainPages.WORKSPACE) } const onAvatarSelectButtonClickHandler = async () => { - const chosenAvatarPath = await requestChooseUserAvatar() - setAvatarPath(chosenAvatarPath) + // TODO: needs to have requestChooseUserAvatar method made in the slice + // const chosenAvatarPath = await requestChooseUserAvatar() + // setAvatarPath(chosenAvatarPath) } const onAvatarRemoveButtonClickHandler = () => { diff --git a/frontend/pages/index.tsx b/frontend/pages/index.tsx index 7f7a1dd..60ff073 100644 --- a/frontend/pages/index.tsx +++ b/frontend/pages/index.tsx @@ -14,6 +14,7 @@ const Home: NextPage = () => { const { selectedMainPage } = useNavigation() const renderSelectedMainPage = () => { + console.log('selectedMainPage: ', selectedMainPage) if (selectedMainPage === mainPages.SELECTPROJECT) return else if (selectedMainPage === mainPages.EDITUSER) return else if ((selectedMainPage === mainPages.WORKSPACE) && currentSession?.project?.id) { diff --git a/frontend/redux/features/session/sessionSlice.ts b/frontend/redux/features/session/sessionSlice.ts new file mode 100644 index 0000000..c11b251 --- /dev/null +++ b/frontend/redux/features/session/sessionSlice.ts @@ -0,0 +1,53 @@ +import { createSlice } from '@reduxjs/toolkit' +import type { PayloadAction } from '@reduxjs/toolkit' +import { entities } from '../../../wailsjs/wailsjs/go/models' +import { CreateNewProject, GetCurrentSession, RequestChangeSessionProjectByName, RequestChooseUserAvatar, RequestUpdateCurrentUser } from '../../../wailsjs/wailsjs/go/ipc/Channel' +import { UserProps } from './types' +import { serialize } from '../../serialize' + +const initialState = { + currentSession: serialize(new entities.Session()) as entities.Session, +} + +export const sessionSlice = createSlice({ + name: 'session', + initialState, + reducers: { + updateSession: (state, action: PayloadAction) => { + GetCurrentSession().then(response => { + if (response) state.currentSession = response + }).catch(console.error) + }, + createNewProject: (state, action: PayloadAction)=> { + const newProjectName = action.payload + CreateNewProject(newProjectName).then(createdSession => { + if (createdSession) state.currentSession = serialize(createdSession) + }).catch(console.error) + }, + requestUpdateCurrentUser: (state, action: PayloadAction) => { + const userProps = action.payload + RequestUpdateCurrentUser(new entities.User(userProps)).then(updatedUser => { + state.currentSession.user = serialize(updatedUser) + }).catch(console.error) + }, + requestSelectProjectByName: (state, action: PayloadAction) => { + const projectName = action.payload + console.log('projectName: ', projectName) + RequestChangeSessionProjectByName(projectName).then(success => { + if (success) GetCurrentSession().then(response => { + console.log(response) + if (response) state.currentSession = serialize(response) + }).catch(console.error) + }).catch(console.error) + } + } +}) + +export const { + updateSession, + createNewProject, + requestUpdateCurrentUser, + requestSelectProjectByName +} = sessionSlice.actions + +export default sessionSlice.reducer diff --git a/frontend/redux/features/session/types.ts b/frontend/redux/features/session/types.ts new file mode 100644 index 0000000..84c3466 --- /dev/null +++ b/frontend/redux/features/session/types.ts @@ -0,0 +1,9 @@ +export type UserProps = { + id?: string, + localId?: string, + firstName?: string, + lastName?: string, + avatarPath?: string, + authToken?: string, + email?: string +} \ No newline at end of file diff --git a/frontend/redux/serialize.ts b/frontend/redux/serialize.ts new file mode 100644 index 0000000..1f3e015 --- /dev/null +++ b/frontend/redux/serialize.ts @@ -0,0 +1,9 @@ +const serialize = (value: unknown) => { + return JSON.parse(JSON.stringify(value)) +} + +const deserialize = (value: Record, constructor: any): any => { + return constructor(value) +} + +export { serialize, deserialize } \ No newline at end of file diff --git a/frontend/redux/store.ts b/frontend/redux/store.ts index 43c0517..c38e9db 100644 --- a/frontend/redux/store.ts +++ b/frontend/redux/store.ts @@ -2,11 +2,13 @@ import { configureStore } from '@reduxjs/toolkit' import { setupListeners } from '@reduxjs/toolkit/dist/query' import notificationQueueSlice from './features/notifications/notificationQueueSlice' import stageSlice from './features/stage/stageSlice' +import sessionSlice from './features/session/sessionSlice' export const store = configureStore({ reducer: { notificationQueue: notificationQueueSlice, stage: stageSlice, + session: sessionSlice, }, middleware: (getDefaultMiddleware) => getDefaultMiddleware(), })