chore: user stores

This commit is contained in:
Aaryan Khandelwal 2023-12-18 12:31:57 +05:30
parent e629977ad6
commit 7dd7de40b7
11 changed files with 90 additions and 64 deletions

View File

@ -4,7 +4,7 @@ import { observer } from "mobx-react-lite";
import { mutate } from "swr";
import { Dialog, Transition } from "@headlessui/react";
// hooks
import { useApplication, useUser, useWorkspace } from "hooks/store";
import { useApplication, useProject, useUser, useWorkspace } from "hooks/store";
import { useMobxStore } from "lib/mobx/store-provider";
import useToast from "hooks/use-toast";
import useLocalStorage from "hooks/use-local-storage";
@ -73,7 +73,6 @@ export const CreateUpdateIssueModal: React.FC<IssuesModalProps> = observer((prop
};
// store hooks
const {
project: projectStore,
projectIssues: projectIssueStore,
viewIssues: projectViewIssueStore,
workspaceProfileIssues: profileIssueStore,
@ -85,6 +84,7 @@ export const CreateUpdateIssueModal: React.FC<IssuesModalProps> = observer((prop
} = useApplication();
const { currentUser } = useUser();
const { currentWorkspace } = useWorkspace();
const { workspaceProjects } = useProject();
const issueStores = {
[EProjectStore.PROJECT]: {
@ -116,8 +116,6 @@ export const CreateUpdateIssueModal: React.FC<IssuesModalProps> = observer((prop
const { store: currentIssueStore, viewId, dataIdToUpdate } = issueStores[currentStore];
const projects = workspaceSlug ? projectStore.projects[workspaceSlug.toString()] : undefined;
const { setValue: setValueInLocalStorage, clearValue: clearLocalStorageValue } = useLocalStorage<any>(
"draftedIssue",
{}
@ -213,9 +211,9 @@ export const CreateUpdateIssueModal: React.FC<IssuesModalProps> = observer((prop
// if data is not present, set active project to the project
// in the url. This has the least priority.
if (projects && projects.length > 0 && !activeProject)
setActiveProject(projects?.find((p) => p.id === projectId)?.id ?? projects?.[0].id ?? null);
}, [data, projectId, projects, isOpen, activeProject]);
if (workspaceProjects && workspaceProjects.length > 0 && !activeProject)
setActiveProject(projectId ?? workspaceProjects?.[0] ?? null);
}, [data, projectId, workspaceProjects, isOpen, activeProject]);
const addIssueToCycle = async (issue: IIssue, cycleId: string) => {
if (!workspaceSlug || !activeProject) return;
@ -382,7 +380,7 @@ export const CreateUpdateIssueModal: React.FC<IssuesModalProps> = observer((prop
if (onSubmit) await onSubmit(payload);
};
if (!projects || projects.length === 0) return null;
if (!workspaceProjects || workspaceProjects.length === 0) return null;
return (
<>

View File

@ -7,6 +7,7 @@ import {
useApplication,
useCycle,
useLabel,
useMember,
useModule,
useProject,
useProjectState,
@ -29,7 +30,6 @@ export const ProjectAuthWrapper: FC<IProjectAuthWrapper> = observer((props) => {
const { children } = props;
// store
const {
projectMember: { fetchProjectMembers },
projectEstimates: { fetchProjectEstimates },
inbox: { fetchInboxesList, isInboxEnabled },
} = useMobxStore();
@ -43,6 +43,9 @@ export const ProjectAuthWrapper: FC<IProjectAuthWrapper> = observer((props) => {
const { fetchAllCycles } = useCycle();
const { fetchModules } = useModule();
const { fetchViews } = useProjectView();
const {
project: { fetchProjectMembers },
} = useMember();
const { fetchProjectStates } = useProjectState();
const {
project: { fetchProjectLabels },

View File

@ -4,8 +4,7 @@ import Link from "next/link";
import useSWR from "swr";
import { observer } from "mobx-react-lite";
// hooks
import { useLabel, useProject, useUser } from "hooks/store";
import { useMobxStore } from "lib/mobx/store-provider";
import { useLabel, useMember, useProject, useUser } from "hooks/store";
// icons
import { Button, Spinner } from "@plane/ui";
@ -16,13 +15,11 @@ export interface IWorkspaceAuthWrapper {
export const WorkspaceAuthWrapper: FC<IWorkspaceAuthWrapper> = observer((props) => {
const { children } = props;
// store hooks
const {
workspaceMember: { fetchWorkspaceMembers, fetchWorkspaceUserProjectsRole },
} = useMobxStore();
const {
membership: { currentWorkspaceMemberInfo, hasPermissionToCurrentWorkspace, fetchUserWorkspaceInfo },
} = useUser();
const { membership } = useUser();
const { fetchProjects } = useProject();
const {
workspace: { fetchWorkspaceMembers },
} = useMember();
const {
workspace: { fetchWorkspaceLabels },
} = useLabel();
@ -32,7 +29,7 @@ export const WorkspaceAuthWrapper: FC<IWorkspaceAuthWrapper> = observer((props)
// fetching user workspace information
useSWR(
workspaceSlug ? `WORKSPACE_MEMBERS_ME_${workspaceSlug}` : null,
workspaceSlug ? () => fetchUserWorkspaceInfo(workspaceSlug.toString()) : null
workspaceSlug ? () => membership.fetchUserWorkspaceInfo(workspaceSlug.toString()) : null
);
// fetching workspace projects
useSWR(
@ -52,21 +49,29 @@ export const WorkspaceAuthWrapper: FC<IWorkspaceAuthWrapper> = observer((props)
// fetch workspace user projects role
useSWR(
workspaceSlug ? `WORKSPACE_PROJECTS_ROLE_${workspaceSlug}` : null,
workspaceSlug ? () => fetchWorkspaceUserProjectsRole(workspaceSlug.toString()) : null
workspaceSlug ? () => membership.fetchUserWorkspaceProjectsRole(workspaceSlug.toString()) : null
);
console.log("workspaceMemberInfo", membership.workspaceMemberInfo);
console.log("currentWorkspaceMemberInfo", membership.currentWorkspaceMemberInfo);
console.log("hasPermissionToCurrentWorkspace", membership.hasPermissionToCurrentWorkspace);
// while data is being loaded
if (!currentWorkspaceMemberInfo && hasPermissionToCurrentWorkspace === undefined) {
if (!membership.currentWorkspaceMemberInfo && membership.hasPermissionToCurrentWorkspace === undefined) {
return (
<div className="grid h-screen place-items-center bg-custom-background-100 p-4">
<div className="flex flex-col items-center gap-3 text-center">
<Spinner />
{/* <Spinner /> */}
Not allowed
</div>
</div>
);
}
// while user does not have access to view that workspace
if (hasPermissionToCurrentWorkspace !== undefined && hasPermissionToCurrentWorkspace === false) {
if (
membership.hasPermissionToCurrentWorkspace !== undefined &&
membership.hasPermissionToCurrentWorkspace === false
) {
return (
<div className={`h-screen w-full overflow-hidden bg-custom-background-100`}>
<div className="grid h-full place-items-center p-4">

View File

@ -1,4 +1,4 @@
import { computed, observable, makeObservable } from "mobx";
import { observable, makeObservable, action } from "mobx";
import { RootStore } from "../root.store";
// types
import { IIssueLabel } from "types";
@ -29,7 +29,7 @@ export class LabelRootStore implements ILabelRootStore {
// observables
labelMap: observable,
// computed actions
getLabelById: computed,
getLabelById: action,
});
// root store

View File

@ -56,7 +56,7 @@ export class ProjectLabelStore implements IProjectLabelStore {
// root store
this.rootStore = _rootStore;
this.labelMap = this.rootStore.labelRoot.labelMap;
this.labelMap = this.rootStore.labelRoot?.labelMap;
// services
this.issueLabelService = new IssueLabelService();
}

View File

@ -31,7 +31,7 @@ export class WorkspaceLabelStore implements IWorkspaceLabelStore {
// root store
this.rootStore = _rootStore;
this.labelMap = this.rootStore.labelRoot.labelMap;
this.labelMap = this.rootStore.labelRoot?.labelMap;
// services
this.issueLabelService = new IssueLabelService();
}

View File

@ -9,8 +9,8 @@ export interface IMemberRootStore {
// observables
memberMap: Record<string, IUserLite>;
// sub-stores
workspaceMember: IWorkspaceMemberStore;
projectMember: IProjectMemberStore;
workspace: IWorkspaceMemberStore;
project: IProjectMemberStore;
}
export class MemberRootStore implements IMemberRootStore {
@ -19,8 +19,8 @@ export class MemberRootStore implements IMemberRootStore {
// root store
rootStore: RootStore;
// sub-stores
workspaceMember: IWorkspaceMemberStore;
projectMember: IProjectMemberStore;
workspace: IWorkspaceMemberStore;
project: IProjectMemberStore;
constructor(_rootStore: RootStore) {
makeObservable(this, {
@ -31,7 +31,7 @@ export class MemberRootStore implements IMemberRootStore {
// root store
this.rootStore = _rootStore;
// sub-stores
this.workspaceMember = new WorkspaceMemberStore(_rootStore);
this.projectMember = new ProjectMemberStore(_rootStore);
this.workspace = new WorkspaceMemberStore(_rootStore);
this.project = new ProjectMemberStore(_rootStore);
}
}

View File

@ -53,7 +53,7 @@ export class ProjectMemberStore implements IProjectMemberStore {
// root store
this.rootStore = _rootStore;
this.memberMap = this.rootStore.memberRoot.memberMap;
this.memberMap = this.rootStore.memberRoot?.memberMap;
// services
this.projectMemberService = new ProjectMemberService();
}

View File

@ -53,7 +53,7 @@ export class WorkspaceMemberStore implements IWorkspaceMemberStore {
// root store
this.rootStore = _rootStore;
this.memberMap = this.rootStore.memberRoot.memberMap;
this.memberMap = this.rootStore.memberRoot?.memberMap;
// services
this.workspaceService = new WorkspaceService();
}

View File

@ -1,16 +1,17 @@
// mobx
import { action, observable, runInAction, makeObservable, computed } from "mobx";
import { set } from "lodash";
// services
import { ProjectMemberService } from "services/project";
import { UserService } from "services/user.service";
import { WorkspaceService } from "services/workspace.service";
// interfaces
import { IWorkspaceMemberMe, IProjectMember } from "types";
import { IWorkspaceMemberMe, IProjectMember, IUserProjectsRole } from "types";
import { RootStore } from "../root.store";
import { EUserProjectRoles } from "constants/project";
import { EUserWorkspaceRoles } from "constants/workspace";
export interface IUserMembershipStore {
// observables
workspaceMemberInfo: {
[workspaceSlug: string]: IWorkspaceMemberMe;
};
@ -23,7 +24,8 @@ export interface IUserMembershipStore {
hasPermissionToProject: {
[projectId: string]: boolean | null;
};
workspaceProjectsRole: { [workspaceSlug: string]: IUserProjectsRole };
// computed
currentProjectMemberInfo: IProjectMember | undefined;
currentWorkspaceMemberInfo: IWorkspaceMemberMe | undefined;
currentProjectRole: EUserProjectRoles | undefined;
@ -31,13 +33,14 @@ export interface IUserMembershipStore {
hasPermissionToCurrentWorkspace: boolean | undefined;
hasPermissionToCurrentProject: boolean | undefined;
// actions
fetchUserWorkspaceInfo: (workspaceSlug: string) => Promise<IWorkspaceMemberMe>;
fetchUserProjectInfo: (workspaceSlug: string, projectId: string) => Promise<IProjectMember>;
leaveWorkspace: (workspaceSlug: string) => Promise<void>;
joinProject: (workspaceSlug: string, projectIds: string[]) => Promise<any>;
leaveProject: (workspaceSlug: string, projectId: string) => Promise<void>;
fetchUserWorkspaceProjectsRole: (workspaceSlug: string) => Promise<IUserProjectsRole>;
}
export class UserMembershipStore implements IUserMembershipStore {
@ -53,6 +56,7 @@ export class UserMembershipStore implements IUserMembershipStore {
hasPermissionToProject: {
[projectId: string]: boolean;
} = {};
workspaceProjectsRole: { [workspaceSlug: string]: IUserProjectsRole } = {};
// stores
router;
// services
@ -62,24 +66,26 @@ export class UserMembershipStore implements IUserMembershipStore {
constructor(_rootStore: RootStore) {
makeObservable(this, {
// observable
workspaceMemberInfo: observable.ref,
hasPermissionToWorkspace: observable.ref,
projectMemberInfo: observable.ref,
hasPermissionToProject: observable.ref,
// action
// observables
workspaceMemberInfo: observable,
hasPermissionToWorkspace: observable,
projectMemberInfo: observable,
hasPermissionToProject: observable,
workspaceProjectsRole: observable,
// computed
currentWorkspaceMemberInfo: computed,
currentWorkspaceRole: computed,
currentProjectMemberInfo: computed,
currentProjectRole: computed,
hasPermissionToCurrentWorkspace: computed,
hasPermissionToCurrentProject: computed,
// actions
fetchUserWorkspaceInfo: action,
fetchUserProjectInfo: action,
leaveWorkspace: action,
joinProject: action,
leaveProject: action,
// computed
currentProjectMemberInfo: computed,
currentWorkspaceMemberInfo: computed,
currentProjectRole: computed,
currentWorkspaceRole: computed,
hasPermissionToCurrentWorkspace: computed,
hasPermissionToCurrentProject: computed,
fetchUserWorkspaceProjectsRole: action,
});
this.router = _rootStore.app.router;
// services
@ -122,23 +128,23 @@ export class UserMembershipStore implements IUserMembershipStore {
try {
const response = await this.workspaceService.workspaceMemberMe(workspaceSlug);
console.log("response", response);
let memberInfo = this.workspaceMemberInfo;
if (!memberInfo) memberInfo = {};
memberInfo[workspaceSlug] = { ...response };
runInAction(() => {
this.workspaceMemberInfo = {
...this.workspaceMemberInfo,
[workspaceSlug]: response,
};
this.hasPermissionToWorkspace = {
...this.hasPermissionToWorkspace,
[workspaceSlug]: true,
};
this.workspaceMemberInfo = memberInfo;
// set(this.workspaceMemberInfo, [workspaceSlug], response);
set(this.hasPermissionToWorkspace, [workspaceSlug], true);
});
// console.log("this.workspaceMemberInfo", this.workspaceMemberInfo);
return response;
} catch (error) {
runInAction(() => {
this.hasPermissionToWorkspace = {
...this.hasPermissionToWorkspace,
[workspaceSlug]: false,
};
set(this.hasPermissionToWorkspace, [workspaceSlug], false);
});
throw error;
}
@ -223,4 +229,17 @@ export class UserMembershipStore implements IUserMembershipStore {
throw error;
}
};
fetchUserWorkspaceProjectsRole = async (workspaceSlug: string) => {
try {
const response = await this.workspaceService.getWorkspaceUserProjectsRole(workspaceSlug);
runInAction(() => {
set(this.workspaceProjectsRole, [workspaceSlug], response);
});
return response;
} catch (error) {
throw error;
}
};
}

View File

@ -1,3 +1,4 @@
import { EUserProjectRoles } from "constants/project";
import { IIssueActivity, IIssueLite, TStateGroups } from ".";
export interface IUser {
@ -162,7 +163,7 @@ export interface IUserProfileProjectSegregation {
}
export interface IUserProjectsRole {
[project_id: string]: number;
[project_id: string]: EUserProjectRoles;
}
// export interface ICurrentUser {