forked from github/plane
fix: store level fixes (#2597)
This commit is contained in:
parent
d46eb9c59a
commit
8c620c4f96
@ -24,19 +24,15 @@ type Props = {
|
||||
|
||||
export const EstimateListItem: React.FC<Props> = observer((props) => {
|
||||
const { estimate, editEstimate, deleteEstimate } = props;
|
||||
|
||||
// router
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
|
||||
// store
|
||||
const { project: projectStore } = useMobxStore();
|
||||
|
||||
const { currentProjectDetails } = projectStore;
|
||||
// hooks
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
// derived values
|
||||
const projectDetails = projectStore.project_details?.[projectId?.toString()!];
|
||||
|
||||
const handleUseEstimate = async () => {
|
||||
if (!workspaceSlug || !projectId) return;
|
||||
|
||||
@ -63,7 +59,7 @@ export const EstimateListItem: React.FC<Props> = observer((props) => {
|
||||
<div>
|
||||
<h6 className="flex w-[40vw] items-center gap-2 truncate text-sm font-medium">
|
||||
{estimate.name}
|
||||
{projectDetails?.estimate && projectDetails?.estimate === estimate.id && (
|
||||
{currentProjectDetails?.estimate && currentProjectDetails?.estimate === estimate.id && (
|
||||
<span className="rounded bg-green-500/20 px-2 py-0.5 text-xs text-green-500">In use</span>
|
||||
)}
|
||||
</h6>
|
||||
@ -72,7 +68,7 @@ export const EstimateListItem: React.FC<Props> = observer((props) => {
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
{projectDetails?.estimate !== estimate?.id && estimate?.points?.length > 0 && (
|
||||
{currentProjectDetails?.estimate !== estimate?.id && estimate?.points?.length > 0 && (
|
||||
<Button variant="neutral-primary" onClick={handleUseEstimate}>
|
||||
Use
|
||||
</Button>
|
||||
@ -88,7 +84,7 @@ export const EstimateListItem: React.FC<Props> = observer((props) => {
|
||||
<span>Edit estimate</span>
|
||||
</div>
|
||||
</CustomMenu.MenuItem>
|
||||
{projectDetails?.estimate !== estimate.id && (
|
||||
{currentProjectDetails?.estimate !== estimate.id && (
|
||||
<CustomMenu.MenuItem
|
||||
onClick={() => {
|
||||
deleteEstimate(estimate.id);
|
||||
|
@ -1,6 +1,5 @@
|
||||
import React, { useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
|
||||
// store
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
@ -25,18 +24,15 @@ export const EstimatesList: React.FC = observer(() => {
|
||||
|
||||
// store
|
||||
const { project: projectStore } = useMobxStore();
|
||||
|
||||
const { currentProjectDetails } = projectStore;
|
||||
// states
|
||||
const [estimateFormOpen, setEstimateFormOpen] = useState(false);
|
||||
const [estimateToDelete, setEstimateToDelete] = useState<string | null>(null);
|
||||
const [estimateToUpdate, setEstimateToUpdate] = useState<IEstimate | undefined>();
|
||||
|
||||
// hooks
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
// derived values
|
||||
const estimatesList = projectStore.projectEstimates;
|
||||
const projectDetails = projectStore.project_details?.[projectId?.toString()!];
|
||||
|
||||
const editEstimate = (estimate: IEstimate) => {
|
||||
setEstimateFormOpen(true);
|
||||
@ -88,7 +84,7 @@ export const EstimatesList: React.FC = observer(() => {
|
||||
>
|
||||
Add Estimate
|
||||
</Button>
|
||||
{projectDetails?.estimate && (
|
||||
{currentProjectDetails?.estimate && (
|
||||
<Button variant="neutral-primary" onClick={disableEstimates}>
|
||||
Disable Estimates
|
||||
</Button>
|
||||
|
@ -29,10 +29,10 @@ const moduleViewOptions: { type: "list" | "grid" | "gantt_chart"; icon: any }[]
|
||||
export const ModulesListHeader: React.FC = observer(() => {
|
||||
// router
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
|
||||
const { workspaceSlug } = router.query;
|
||||
// store
|
||||
const { project: projectStore } = useMobxStore();
|
||||
const projectDetails = projectId ? projectStore.project_details[projectId.toString()] : undefined;
|
||||
const { currentProjectDetails } = projectStore;
|
||||
|
||||
const { storedValue: modulesView, setValue: setModulesView } = useLocalStorage("modules_view", "grid");
|
||||
|
||||
@ -52,7 +52,7 @@ export const ModulesListHeader: React.FC = observer(() => {
|
||||
</Link>
|
||||
}
|
||||
/>
|
||||
<BreadcrumbItem title={`${truncateText(projectDetails?.name ?? "Project", 32)} Modules`} />
|
||||
<BreadcrumbItem title={`${truncateText(currentProjectDetails?.name ?? "Project", 32)} Modules`} />
|
||||
</Breadcrumbs>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -17,10 +17,10 @@ export interface IProjectSettingHeader {
|
||||
export const ProjectSettingHeader: FC<IProjectSettingHeader> = observer((props) => {
|
||||
const { title } = props;
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
const { workspaceSlug } = router.query;
|
||||
// store
|
||||
const { project: projectStore } = useMobxStore();
|
||||
const projectDetails = projectId ? projectStore.project_details[projectId.toString()] : null;
|
||||
const { currentProjectDetails } = projectStore;
|
||||
|
||||
return (
|
||||
<div
|
||||
@ -31,9 +31,9 @@ export const ProjectSettingHeader: FC<IProjectSettingHeader> = observer((props)
|
||||
<Breadcrumbs onBack={() => router.back()}>
|
||||
<BreadcrumbItem
|
||||
link={
|
||||
<Link href={`/${workspaceSlug}/projects/${projectDetails?.id}/issues`}>
|
||||
<Link href={`/${workspaceSlug}/projects/${currentProjectDetails?.id}/issues`}>
|
||||
<a className={`border-r-2 border-custom-sidebar-border-200 px-3 text-sm `}>
|
||||
<p className="truncate">{`${truncateText(projectDetails?.name ?? "Project", 32)}`}</p>
|
||||
<p className="truncate">{`${truncateText(currentProjectDetails?.name ?? "Project", 32)}`}</p>
|
||||
</a>
|
||||
</Link>
|
||||
}
|
||||
|
@ -18,6 +18,10 @@ import { ISSUE_STATE_GROUPS, ISSUE_PRIORITIES } from "constants/issue";
|
||||
export interface ICycleKanBanLayout {}
|
||||
|
||||
export const CycleKanBanLayout: React.FC = observer(() => {
|
||||
// router
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, cycleId } = router.query;
|
||||
// store
|
||||
const {
|
||||
project: projectStore,
|
||||
cycleIssue: cycleIssueStore,
|
||||
@ -25,9 +29,7 @@ export const CycleKanBanLayout: React.FC = observer(() => {
|
||||
cycleIssueKanBanView: cycleIssueKanBanViewStore,
|
||||
issueDetail: issueDetailStore,
|
||||
} = useMobxStore();
|
||||
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId, cycleId } = router.query;
|
||||
const { currentProjectDetails } = projectStore;
|
||||
|
||||
const issues = cycleIssueStore?.getIssues;
|
||||
|
||||
@ -83,8 +85,6 @@ export const CycleKanBanLayout: React.FC = observer(() => {
|
||||
cycleIssueKanBanViewStore.handleKanBanToggle(toggle, value);
|
||||
};
|
||||
|
||||
const projectDetails = projectId ? projectStore.project_details[projectId.toString()] : null;
|
||||
|
||||
const states = projectStore?.projectStates || null;
|
||||
const priorities = ISSUE_PRIORITIES || null;
|
||||
const labels = projectStore?.projectLabels || null;
|
||||
@ -92,8 +92,8 @@ export const CycleKanBanLayout: React.FC = observer(() => {
|
||||
const stateGroups = ISSUE_STATE_GROUPS || null;
|
||||
const projects = workspaceSlug ? projectStore?.projects[workspaceSlug.toString()] || null : null;
|
||||
const estimates =
|
||||
projectDetails?.estimate !== null
|
||||
? projectStore.projectEstimates?.find((e) => e.id === projectDetails?.estimate) || null
|
||||
currentProjectDetails?.estimate !== null
|
||||
? projectStore.projectEstimates?.find((e) => e.id === currentProjectDetails?.estimate) || null
|
||||
: null;
|
||||
|
||||
return (
|
||||
|
@ -18,6 +18,9 @@ import { ISSUE_STATE_GROUPS, ISSUE_PRIORITIES } from "constants/issue";
|
||||
export interface IModuleKanBanLayout {}
|
||||
|
||||
export const ModuleKanBanLayout: React.FC = observer(() => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, moduleId } = router.query;
|
||||
// store
|
||||
const {
|
||||
project: projectStore,
|
||||
moduleIssue: moduleIssueStore,
|
||||
@ -25,9 +28,7 @@ export const ModuleKanBanLayout: React.FC = observer(() => {
|
||||
moduleIssueKanBanView: moduleIssueKanBanViewStore,
|
||||
issueDetail: issueDetailStore,
|
||||
} = useMobxStore();
|
||||
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId, moduleId } = router.query;
|
||||
const { currentProjectDetails } = projectStore;
|
||||
|
||||
const issues = moduleIssueStore?.getIssues;
|
||||
|
||||
@ -83,8 +84,6 @@ export const ModuleKanBanLayout: React.FC = observer(() => {
|
||||
moduleIssueKanBanViewStore.handleKanBanToggle(toggle, value);
|
||||
};
|
||||
|
||||
const projectDetails = projectId ? projectStore.project_details[projectId.toString()] : null;
|
||||
|
||||
const states = projectStore?.projectStates || null;
|
||||
const priorities = ISSUE_PRIORITIES || null;
|
||||
const labels = projectStore?.projectLabels || null;
|
||||
@ -92,8 +91,8 @@ export const ModuleKanBanLayout: React.FC = observer(() => {
|
||||
const stateGroups = ISSUE_STATE_GROUPS || null;
|
||||
const projects = workspaceSlug ? projectStore?.projects[workspaceSlug.toString()] || null : null;
|
||||
const estimates =
|
||||
projectDetails?.estimate !== null
|
||||
? projectStore.projectEstimates?.find((e) => e.id === projectDetails?.estimate) || null
|
||||
currentProjectDetails?.estimate !== null
|
||||
? projectStore.projectEstimates?.find((e) => e.id === currentProjectDetails?.estimate) || null
|
||||
: null;
|
||||
|
||||
return (
|
||||
|
@ -19,7 +19,7 @@ export interface IKanBanLayout {}
|
||||
|
||||
export const KanBanLayout: React.FC = observer(() => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
const { workspaceSlug } = router.query;
|
||||
|
||||
const {
|
||||
project: projectStore,
|
||||
@ -28,6 +28,7 @@ export const KanBanLayout: React.FC = observer(() => {
|
||||
issueKanBanView: issueKanBanViewStore,
|
||||
issueDetail: issueDetailStore,
|
||||
} = useMobxStore();
|
||||
const { currentProjectDetails } = projectStore;
|
||||
|
||||
const issues = issueStore?.getIssues;
|
||||
|
||||
@ -74,8 +75,6 @@ export const KanBanLayout: React.FC = observer(() => {
|
||||
issueKanBanViewStore.handleKanBanToggle(toggle, value);
|
||||
};
|
||||
|
||||
const projectDetails = projectId ? projectStore.project_details[projectId.toString()] : null;
|
||||
|
||||
const states = projectStore?.projectStates || null;
|
||||
const priorities = ISSUE_PRIORITIES || null;
|
||||
const labels = projectStore?.projectLabels || null;
|
||||
@ -83,8 +82,8 @@ export const KanBanLayout: React.FC = observer(() => {
|
||||
const stateGroups = ISSUE_STATE_GROUPS || null;
|
||||
const projects = workspaceSlug ? projectStore?.projects[workspaceSlug.toString()] || null : null;
|
||||
const estimates =
|
||||
projectDetails?.estimate !== null
|
||||
? projectStore.projectEstimates?.find((e) => e.id === projectDetails?.estimate) || null
|
||||
currentProjectDetails?.estimate !== null
|
||||
? projectStore.projectEstimates?.find((e) => e.id === currentProjectDetails?.estimate) || null
|
||||
: null;
|
||||
|
||||
return (
|
||||
|
@ -17,14 +17,15 @@ export interface ICycleListLayout {}
|
||||
|
||||
export const CycleListLayout: React.FC = observer(() => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId, cycleId } = router.query;
|
||||
|
||||
const { workspaceSlug, cycleId } = router.query;
|
||||
// store
|
||||
const {
|
||||
project: projectStore,
|
||||
issueFilter: issueFilterStore,
|
||||
cycleIssue: cycleIssueStore,
|
||||
issueDetail: issueDetailStore,
|
||||
} = useMobxStore();
|
||||
const { currentProjectDetails } = projectStore;
|
||||
|
||||
const issues = cycleIssueStore?.getIssues;
|
||||
|
||||
@ -54,8 +55,6 @@ export const CycleListLayout: React.FC = observer(() => {
|
||||
[cycleIssueStore, issueDetailStore, cycleId, workspaceSlug]
|
||||
);
|
||||
|
||||
const projectDetails = projectId ? projectStore.project_details[projectId.toString()] : null;
|
||||
|
||||
const states = projectStore?.projectStates || null;
|
||||
const priorities = ISSUE_PRIORITIES || null;
|
||||
const labels = projectStore?.projectLabels || null;
|
||||
@ -63,8 +62,8 @@ export const CycleListLayout: React.FC = observer(() => {
|
||||
const stateGroups = ISSUE_STATE_GROUPS || null;
|
||||
const projects = workspaceSlug ? projectStore?.projects[workspaceSlug.toString()] || null : null;
|
||||
const estimates =
|
||||
projectDetails?.estimate !== null
|
||||
? projectStore.projectEstimates?.find((e) => e.id === projectDetails?.estimate) || null
|
||||
currentProjectDetails?.estimate !== null
|
||||
? projectStore.projectEstimates?.find((e) => e.id === currentProjectDetails?.estimate) || null
|
||||
: null;
|
||||
|
||||
return (
|
||||
|
@ -17,7 +17,7 @@ export interface IModuleListLayout {}
|
||||
|
||||
export const ModuleListLayout: React.FC = observer(() => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId, moduleId } = router.query;
|
||||
const { workspaceSlug, moduleId } = router.query;
|
||||
|
||||
const {
|
||||
project: projectStore,
|
||||
@ -25,6 +25,7 @@ export const ModuleListLayout: React.FC = observer(() => {
|
||||
moduleIssue: moduleIssueStore,
|
||||
issueDetail: issueDetailStore,
|
||||
} = useMobxStore();
|
||||
const { currentProjectDetails } = projectStore;
|
||||
|
||||
const issues = moduleIssueStore?.getIssues;
|
||||
|
||||
@ -54,8 +55,6 @@ export const ModuleListLayout: React.FC = observer(() => {
|
||||
[moduleIssueStore, issueDetailStore, moduleId, workspaceSlug]
|
||||
);
|
||||
|
||||
const projectDetails = projectId ? projectStore.project_details[projectId.toString()] : null;
|
||||
|
||||
const states = projectStore?.projectStates || null;
|
||||
const priorities = ISSUE_PRIORITIES || null;
|
||||
const labels = projectStore?.projectLabels || null;
|
||||
@ -63,8 +62,8 @@ export const ModuleListLayout: React.FC = observer(() => {
|
||||
const stateGroups = ISSUE_STATE_GROUPS || null;
|
||||
const projects = workspaceSlug ? projectStore?.projects[workspaceSlug.toString()] || null : null;
|
||||
const estimates =
|
||||
projectDetails?.estimate !== null
|
||||
? projectStore.projectEstimates?.find((e) => e.id === projectDetails?.estimate) || null
|
||||
currentProjectDetails?.estimate !== null
|
||||
? projectStore.projectEstimates?.find((e) => e.id === currentProjectDetails?.estimate) || null
|
||||
: null;
|
||||
|
||||
return (
|
||||
|
@ -15,14 +15,15 @@ import { ISSUE_STATE_GROUPS, ISSUE_PRIORITIES } from "constants/issue";
|
||||
|
||||
export const ListLayout: FC = observer(() => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
|
||||
const { workspaceSlug } = router.query;
|
||||
// store
|
||||
const {
|
||||
project: projectStore,
|
||||
issue: issueStore,
|
||||
issueDetail: issueDetailStore,
|
||||
issueFilter: issueFilterStore,
|
||||
} = useMobxStore();
|
||||
const { currentProjectDetails } = projectStore;
|
||||
|
||||
const issues = issueStore?.getIssues;
|
||||
|
||||
@ -43,8 +44,6 @@ export const ListLayout: FC = observer(() => {
|
||||
[issueStore, issueDetailStore, workspaceSlug]
|
||||
);
|
||||
|
||||
const projectDetails = projectId ? projectStore.project_details[projectId.toString()] : null;
|
||||
|
||||
const states = projectStore?.projectStates || null;
|
||||
const priorities = ISSUE_PRIORITIES || null;
|
||||
const labels = projectStore?.projectLabels || null;
|
||||
@ -52,8 +51,8 @@ export const ListLayout: FC = observer(() => {
|
||||
const stateGroups = ISSUE_STATE_GROUPS || null;
|
||||
const projects = workspaceSlug ? projectStore?.projects[workspaceSlug.toString()] || null : null;
|
||||
const estimates =
|
||||
projectDetails?.estimate !== null
|
||||
? projectStore.projectEstimates?.find((e) => e.id === projectDetails?.estimate) || null
|
||||
currentProjectDetails?.estimate !== null
|
||||
? projectStore.projectEstimates?.find((e) => e.id === currentProjectDetails?.estimate) || null
|
||||
: null;
|
||||
|
||||
return (
|
||||
|
@ -31,7 +31,8 @@ export const PeekOverviewIssueDetails: FC<IPeekOverviewIssueDetails> = (props) =
|
||||
const { workspaceSlug, issue, issueReactions, user, issueUpdate, issueReactionCreate, issueReactionRemove } = props;
|
||||
// store
|
||||
const { user: userStore } = useMobxStore();
|
||||
const isAllowed = [5, 10].includes(userStore.projectMemberInfo?.role || 0);
|
||||
const { currentProjectRole } = userStore;
|
||||
const isAllowed = [5, 10].includes(currentProjectRole || 0);
|
||||
// states
|
||||
const [isSubmitting, setIsSubmitting] = useState<"submitting" | "submitted" | "saved">("saved");
|
||||
const [characterLimit, setCharacterLimit] = useState(false);
|
||||
|
@ -9,12 +9,12 @@ import { ModuleGanttBlock, ModuleGanttSidebarBlock } from "components/modules";
|
||||
import { IModule } from "types";
|
||||
|
||||
export const ModulesListGanttChartView: React.FC = observer(() => {
|
||||
// router
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
|
||||
const { workspaceSlug } = router.query;
|
||||
// store
|
||||
const { project: projectStore, module: moduleStore } = useMobxStore();
|
||||
|
||||
const projectDetails = projectId ? projectStore.project_details[projectId.toString()] : undefined;
|
||||
const { currentProjectDetails } = projectStore;
|
||||
const modules = moduleStore.projectModules;
|
||||
|
||||
const handleModuleUpdate = (module: IModule, payload: IBlockUpdateData) => {
|
||||
@ -36,7 +36,7 @@ export const ModulesListGanttChartView: React.FC = observer(() => {
|
||||
}))
|
||||
: [];
|
||||
|
||||
const isAllowed = projectDetails?.member_role === 20 || projectDetails?.member_role === 15;
|
||||
const isAllowed = currentProjectDetails?.member_role === 20 || currentProjectDetails?.member_role === 15;
|
||||
|
||||
return (
|
||||
<div className="w-full h-full overflow-y-auto">
|
||||
|
@ -26,32 +26,28 @@ type Props = {
|
||||
|
||||
export const ProjectMemberListItem: React.FC<Props> = observer((props) => {
|
||||
const { member } = props;
|
||||
|
||||
// router
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
|
||||
// states
|
||||
const [selectedRemoveMember, setSelectedRemoveMember] = useState<any | null>(null);
|
||||
const [selectedInviteRemoveMember, setSelectedInviteRemoveMember] = useState<any | null>(null);
|
||||
|
||||
// store
|
||||
const { user: userStore, project: projectStore } = useMobxStore();
|
||||
|
||||
// hooks
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
// fetching project members
|
||||
useSWR(
|
||||
workspaceSlug && projectId ? `PROJECT_MEMBERS_${projectId.toString().toUpperCase()}` : null,
|
||||
workspaceSlug && projectId
|
||||
? () => projectStore.fetchProjectMembers(workspaceSlug.toString(), projectId.toString())
|
||||
: null
|
||||
);
|
||||
|
||||
// derived values
|
||||
const user = userStore.currentUser;
|
||||
const memberDetails = userStore.projectMemberInfo;
|
||||
const isAdmin = memberDetails?.role === 20;
|
||||
const isOwner = memberDetails?.role === 20;
|
||||
const { currentProjectRole } = userStore;
|
||||
const isAdmin = currentProjectRole === 20;
|
||||
const isOwner = currentProjectRole === 20;
|
||||
const projectMembers = projectStore.members?.[projectId?.toString()!];
|
||||
const currentUser = projectMembers?.find((item) => item.member.id === user?.id);
|
||||
|
||||
|
@ -25,20 +25,16 @@ export const ProjectSettingsMemberDefaults: React.FC = observer(() => {
|
||||
// router
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
|
||||
// store
|
||||
const { user: userStore, project: projectStore } = useMobxStore();
|
||||
|
||||
const { currentProjectDetails } = projectStore;
|
||||
const { currentProjectRole } = userStore;
|
||||
const isAdmin = currentProjectRole === 20;
|
||||
// hooks
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
// derived values
|
||||
const memberDetails = userStore.projectMemberInfo;
|
||||
const isAdmin = memberDetails?.role === 20;
|
||||
const projectDetails = projectStore.project_details[projectId?.toString()!];
|
||||
|
||||
// form info
|
||||
const { reset, control } = useForm<IProject>({ defaultValues });
|
||||
|
||||
// fetching user members
|
||||
useSWR(
|
||||
workspaceSlug && projectId ? PROJECT_MEMBERS(projectId.toString()) : null,
|
||||
workspaceSlug && projectId
|
||||
@ -47,23 +43,23 @@ export const ProjectSettingsMemberDefaults: React.FC = observer(() => {
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!projectDetails) return;
|
||||
if (!currentProjectDetails) return;
|
||||
|
||||
reset({
|
||||
...projectDetails,
|
||||
default_assignee: projectDetails.default_assignee?.id ?? projectDetails.default_assignee,
|
||||
project_lead: (projectDetails.project_lead as IUserLite)?.id ?? projectDetails.project_lead,
|
||||
workspace: (projectDetails.workspace as IWorkspace).id,
|
||||
...currentProjectDetails,
|
||||
default_assignee: currentProjectDetails.default_assignee?.id ?? currentProjectDetails.default_assignee,
|
||||
project_lead: (currentProjectDetails.project_lead as IUserLite)?.id ?? currentProjectDetails.project_lead,
|
||||
workspace: (currentProjectDetails.workspace as IWorkspace).id,
|
||||
});
|
||||
}, [projectDetails, reset]);
|
||||
}, [currentProjectDetails, reset]);
|
||||
|
||||
const submitChanges = async (formData: Partial<IProject>) => {
|
||||
if (!workspaceSlug || !projectId) return;
|
||||
|
||||
reset({
|
||||
...projectDetails,
|
||||
default_assignee: projectDetails.default_assignee?.id ?? projectDetails.default_assignee,
|
||||
project_lead: (projectDetails.project_lead as IUserLite)?.id ?? projectDetails.project_lead,
|
||||
...currentProjectDetails,
|
||||
default_assignee: currentProjectDetails?.default_assignee?.id ?? currentProjectDetails?.default_assignee,
|
||||
project_lead: (currentProjectDetails?.project_lead as IUserLite)?.id ?? currentProjectDetails?.project_lead,
|
||||
...formData,
|
||||
});
|
||||
|
||||
@ -96,7 +92,7 @@ export const ProjectSettingsMemberDefaults: React.FC = observer(() => {
|
||||
<div className="flex flex-col gap-2 w-1/2">
|
||||
<h4 className="text-sm">Project Lead</h4>
|
||||
<div className="">
|
||||
{projectDetails ? (
|
||||
{currentProjectDetails ? (
|
||||
<Controller
|
||||
control={control}
|
||||
name="project_lead"
|
||||
@ -121,7 +117,7 @@ export const ProjectSettingsMemberDefaults: React.FC = observer(() => {
|
||||
<div className="flex flex-col gap-2 w-1/2">
|
||||
<h4 className="text-sm">Default Assignee</h4>
|
||||
<div className="">
|
||||
{projectDetails ? (
|
||||
{currentProjectDetails ? (
|
||||
<Controller
|
||||
control={control}
|
||||
name="default_assignee"
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { FC } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { ContrastIcon, FileText, Inbox, Layers } from "lucide-react";
|
||||
@ -18,7 +19,6 @@ const PROJECT_FEATURES_LIST = [
|
||||
title: "Cycles",
|
||||
description: "Cycles are enabled for all the projects in this workspace. Access them from the sidebar.",
|
||||
icon: <ContrastIcon className="h-4 w-4 text-purple-500 flex-shrink-0 rotate-180" />,
|
||||
|
||||
property: "cycle_view",
|
||||
},
|
||||
{
|
||||
@ -67,32 +67,30 @@ const getEventType = (feature: string, toggle: boolean): MiscellaneousEventType
|
||||
// services
|
||||
const trackEventService = new TrackEventService();
|
||||
|
||||
export const ProjectFeaturesList: React.FC<Props> = observer((props) => {
|
||||
const {} = props;
|
||||
|
||||
export const ProjectFeaturesList: FC<Props> = observer(() => {
|
||||
// router
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
|
||||
// store
|
||||
const { project: projectStore, user: userStore } = useMobxStore();
|
||||
|
||||
const projectDetails = projectId ? projectStore.project_details[projectId.toString()] : undefined;
|
||||
const user = userStore.currentUser ?? undefined;
|
||||
const isAdmin = userStore.projectMemberInfo?.role === 20;
|
||||
|
||||
const { currentUser, currentProjectRole } = userStore;
|
||||
const { currentProjectDetails } = projectStore;
|
||||
const isAdmin = currentProjectRole === 20;
|
||||
// hooks
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const handleSubmit = async (formData: Partial<IProject>) => {
|
||||
if (!workspaceSlug || !projectId || !projectDetails) return;
|
||||
|
||||
if (!workspaceSlug || !projectId || !currentProjectDetails) return;
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
title: "Success!",
|
||||
message: "Project feature updated successfully.",
|
||||
});
|
||||
|
||||
projectStore.updateProject(workspaceSlug.toString(), projectId.toString(), formData);
|
||||
};
|
||||
|
||||
if (!currentUser) return <></>;
|
||||
|
||||
return (
|
||||
<div>
|
||||
{PROJECT_FEATURES_LIST.map((feature) => (
|
||||
@ -108,21 +106,21 @@ export const ProjectFeaturesList: React.FC<Props> = observer((props) => {
|
||||
</div>
|
||||
</div>
|
||||
<ToggleSwitch
|
||||
value={projectDetails?.[feature.property as keyof IProject]}
|
||||
value={currentProjectDetails?.[feature.property as keyof IProject]}
|
||||
onChange={() => {
|
||||
trackEventService.trackMiscellaneousEvent(
|
||||
{
|
||||
workspaceId: (projectDetails?.workspace as any)?.id,
|
||||
workspaceId: (currentProjectDetails?.workspace as any)?.id,
|
||||
workspaceSlug,
|
||||
projectId,
|
||||
projectIdentifier: projectDetails?.identifier,
|
||||
projectName: projectDetails?.name,
|
||||
projectIdentifier: currentProjectDetails?.identifier,
|
||||
projectName: currentProjectDetails?.name,
|
||||
},
|
||||
getEventType(feature.title, !projectDetails?.[feature.property as keyof IProject]),
|
||||
user
|
||||
getEventType(feature.title, !currentProjectDetails?.[feature.property as keyof IProject]),
|
||||
currentUser
|
||||
);
|
||||
handleSubmit({
|
||||
[feature.property]: !projectDetails?.[feature.property as keyof IProject],
|
||||
[feature.property]: !currentProjectDetails?.[feature.property as keyof IProject],
|
||||
});
|
||||
}}
|
||||
disabled={!isAdmin}
|
||||
|
@ -1,9 +1,6 @@
|
||||
import React, { useState } from "react";
|
||||
|
||||
import { useRouter } from "next/router";
|
||||
|
||||
import useSWR from "swr";
|
||||
|
||||
// store
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
@ -22,10 +19,9 @@ export const ProjectSettingStateList: React.FC = observer(() => {
|
||||
// router
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
|
||||
// store
|
||||
const { project: projectStore } = useMobxStore();
|
||||
|
||||
const { currentProjectDetails } = projectStore;
|
||||
// state
|
||||
const [activeGroup, setActiveGroup] = useState<StateGroup>(null);
|
||||
const [selectedState, setSelectedState] = useState<string | null>(null);
|
||||
@ -47,7 +43,6 @@ export const ProjectSettingStateList: React.FC = observer(() => {
|
||||
|
||||
// derived values
|
||||
const states = projectStore.projectStatesByGroups;
|
||||
const projectDetails = projectStore.project_details[projectId?.toString()!] ?? null;
|
||||
const orderedStateGroups = orderStateGroups(states!);
|
||||
const statesList = getStatesList(orderedStateGroups);
|
||||
|
||||
@ -60,7 +55,7 @@ export const ProjectSettingStateList: React.FC = observer(() => {
|
||||
/>
|
||||
|
||||
<div className="space-y-8 py-6">
|
||||
{states && projectDetails && orderedStateGroups ? (
|
||||
{states && currentProjectDetails && orderedStateGroups ? (
|
||||
Object.keys(orderedStateGroups || {}).map((key) => {
|
||||
if (orderedStateGroups[key].length !== 0)
|
||||
return (
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { useState } from "react";
|
||||
import { useState, FC } from "react";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/router";
|
||||
// mobx store
|
||||
@ -35,20 +35,19 @@ type Props = {
|
||||
// services
|
||||
const workspaceService = new WorkspaceService();
|
||||
|
||||
export const WorkspaceMembersListItem: React.FC<Props> = (props) => {
|
||||
export const WorkspaceMembersListItem: FC<Props> = (props) => {
|
||||
const { member } = props;
|
||||
|
||||
const [removeMemberModal, setRemoveMemberModal] = useState(false);
|
||||
|
||||
// router
|
||||
const router = useRouter();
|
||||
const { workspaceSlug } = router.query;
|
||||
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
// store
|
||||
const { workspace: workspaceStore, user: userStore } = useMobxStore();
|
||||
|
||||
const user = userStore.workspaceMemberInfo;
|
||||
const isAdmin = userStore.workspaceMemberInfo?.role === 20;
|
||||
const { currentWorkspaceMemberInfo, currentWorkspaceRole } = userStore;
|
||||
const isAdmin = currentWorkspaceRole === 20;
|
||||
// states
|
||||
const [removeMemberModal, setRemoveMemberModal] = useState(false);
|
||||
// hooks
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const handleRemoveMember = async () => {
|
||||
if (!workspaceSlug) return;
|
||||
@ -83,7 +82,7 @@ export const WorkspaceMembersListItem: React.FC<Props> = (props) => {
|
||||
});
|
||||
};
|
||||
|
||||
if (!user) return null;
|
||||
if (!currentWorkspaceMemberInfo) return null;
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -141,12 +140,12 @@ export const WorkspaceMembersListItem: React.FC<Props> = (props) => {
|
||||
<div className="flex item-center gap-1 px-2 py-0.5 rounded">
|
||||
<span
|
||||
className={`flex items-center text-xs font-medium rounded ${
|
||||
member.memberId !== user.member ? "" : "text-custom-sidebar-text-400"
|
||||
member.memberId !== currentWorkspaceMemberInfo.member ? "" : "text-custom-sidebar-text-400"
|
||||
}`}
|
||||
>
|
||||
{ROLE[member.role as keyof typeof ROLE]}
|
||||
</span>
|
||||
{member.memberId !== user.member && (
|
||||
{member.memberId !== currentWorkspaceMemberInfo.member && (
|
||||
<span className="grid place-items-center">
|
||||
<ChevronDown className="h-3 w-3" />
|
||||
</span>
|
||||
@ -155,7 +154,7 @@ export const WorkspaceMembersListItem: React.FC<Props> = (props) => {
|
||||
}
|
||||
value={member.role}
|
||||
onChange={(value: 5 | 10 | 15 | 20 | undefined) => {
|
||||
if (!workspaceSlug) return;
|
||||
if (!workspaceSlug || !value) return;
|
||||
|
||||
workspaceStore
|
||||
.updateMember(workspaceSlug.toString(), member.id, {
|
||||
@ -170,12 +169,15 @@ export const WorkspaceMembersListItem: React.FC<Props> = (props) => {
|
||||
});
|
||||
}}
|
||||
disabled={
|
||||
member.memberId === user.member || !member.status || (user.role !== 20 && user.role < member.role)
|
||||
member.memberId === currentWorkspaceMemberInfo.member ||
|
||||
!member.status ||
|
||||
Boolean(currentWorkspaceRole && currentWorkspaceRole !== 20 && currentWorkspaceRole < member.role)
|
||||
}
|
||||
placement="bottom-end"
|
||||
>
|
||||
{Object.keys(ROLE).map((key) => {
|
||||
if (user.role !== 20 && user.role < parseInt(key)) return null;
|
||||
if (currentWorkspaceRole && currentWorkspaceRole !== 20 && currentWorkspaceRole < parseInt(key))
|
||||
return null;
|
||||
|
||||
return (
|
||||
<CustomSelect.Option key={key} value={parseInt(key, 10)}>
|
||||
@ -185,7 +187,11 @@ export const WorkspaceMembersListItem: React.FC<Props> = (props) => {
|
||||
})}
|
||||
</CustomSelect>
|
||||
{isAdmin && (
|
||||
<Tooltip tooltipContent={member.memberId === user.member ? "Leave workspace" : "Remove member"}>
|
||||
<Tooltip
|
||||
tooltipContent={
|
||||
member.memberId === currentWorkspaceMemberInfo.member ? "Leave workspace" : "Remove member"
|
||||
}
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setRemoveMemberModal(true)}
|
||||
|
@ -15,12 +15,11 @@ const workspaceService = new WorkspaceService();
|
||||
export const WorkspaceMembersList: React.FC = observer(() => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug } = router.query;
|
||||
|
||||
// store
|
||||
const { workspace: workspaceStore, user: userStore } = useMobxStore();
|
||||
|
||||
const workspaceMembers = workspaceStore.workspaceMembers;
|
||||
const user = userStore.workspaceMemberInfo;
|
||||
|
||||
const user = userStore.currentWorkspaceMemberInfo;
|
||||
// fetching workspace invitations
|
||||
const { data: workspaceInvitations } = useSWR(
|
||||
workspaceSlug ? `WORKSPACE_INVITATIONS_${workspaceSlug.toString()}` : null,
|
||||
workspaceSlug ? () => workspaceService.workspaceInvitations(workspaceSlug.toString()) : null
|
||||
|
@ -30,16 +30,20 @@ const defaultValues: Partial<IWorkspace> = {
|
||||
const fileService = new FileService();
|
||||
|
||||
export const WorkspaceDetails: React.FC = observer(() => {
|
||||
// states
|
||||
const [deleteWorkspaceModal, setDeleteWorkspaceModal] = useState(false);
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const [isImageUploading, setIsImageUploading] = useState(false);
|
||||
const [isImageRemoving, setIsImageRemoving] = useState(false);
|
||||
const [isImageUploadModalOpen, setIsImageUploadModalOpen] = useState(false);
|
||||
|
||||
// store
|
||||
const { workspace: workspaceStore, user: userStore } = useMobxStore();
|
||||
const activeWorkspace = workspaceStore.currentWorkspace;
|
||||
|
||||
const { currentWorkspaceRole } = userStore;
|
||||
const isAdmin = currentWorkspaceRole === 20;
|
||||
// hooks
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
// form info
|
||||
const {
|
||||
handleSubmit,
|
||||
control,
|
||||
@ -103,8 +107,6 @@ export const WorkspaceDetails: React.FC = observer(() => {
|
||||
if (activeWorkspace) reset({ ...activeWorkspace });
|
||||
}, [activeWorkspace, reset]);
|
||||
|
||||
const isAdmin = userStore.workspaceMemberInfo?.role === 20;
|
||||
|
||||
if (!activeWorkspace)
|
||||
return (
|
||||
<div className="grid place-items-center h-full w-full px-4 sm:px-0">
|
||||
|
@ -16,6 +16,7 @@ export const WorkspaceAuthWrapper: FC<IWorkspaceAuthWrapper> = observer((props)
|
||||
const { children } = props;
|
||||
// store
|
||||
const { user: userStore, project: projectStore, workspace: workspaceStore } = useMobxStore();
|
||||
const { currentWorkspaceMemberInfo, hasPermissionToCurrentWorkspace } = userStore;
|
||||
// router
|
||||
const router = useRouter();
|
||||
const { workspaceSlug } = router.query;
|
||||
@ -43,11 +44,7 @@ export const WorkspaceAuthWrapper: FC<IWorkspaceAuthWrapper> = observer((props)
|
||||
);
|
||||
|
||||
// while data is being loaded
|
||||
if (
|
||||
!userStore.workspaceMemberInfo &&
|
||||
workspaceSlug &&
|
||||
userStore.hasPermissionToWorkspace[workspaceSlug.toString()] === null
|
||||
) {
|
||||
if (!currentWorkspaceMemberInfo && hasPermissionToCurrentWorkspace === undefined) {
|
||||
return (
|
||||
<div className="grid h-screen place-items-center p-4 bg-custom-background-100">
|
||||
<div className="flex flex-col items-center gap-3 text-center">
|
||||
@ -57,11 +54,7 @@ export const WorkspaceAuthWrapper: FC<IWorkspaceAuthWrapper> = observer((props)
|
||||
);
|
||||
}
|
||||
// while user does not have access to view that workspace
|
||||
if (
|
||||
userStore.hasPermissionToWorkspace !== null &&
|
||||
workspaceSlug &&
|
||||
userStore.hasPermissionToWorkspace[workspaceSlug.toString()] === false
|
||||
) {
|
||||
if (hasPermissionToCurrentWorkspace !== undefined && 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">
|
||||
|
@ -27,6 +27,7 @@ const ProjectCyclesPage: NextPage = observer(() => {
|
||||
const [createModal, setCreateModal] = useState(false);
|
||||
// store
|
||||
const { project: projectStore, cycle: cycleStore } = useMobxStore();
|
||||
const { currentProjectDetails } = projectStore;
|
||||
// router
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId, peekCycle } = router.query as {
|
||||
@ -78,19 +79,18 @@ const ProjectCyclesPage: NextPage = observer(() => {
|
||||
}
|
||||
}, [projectId, cycleStore, handleCurrentView, handleCurrentLayout]);
|
||||
|
||||
const projectDetails = projectId ? projectStore.project_details[projectId] : null;
|
||||
const cycleView = cycleStore?.cycleView;
|
||||
const cycleLayout = cycleStore?.cycleLayout;
|
||||
|
||||
return (
|
||||
<AppLayout header={<CyclesHeader name={projectDetails?.name} />} withProjectWrapper>
|
||||
<AppLayout header={<CyclesHeader name={currentProjectDetails?.name} />} withProjectWrapper>
|
||||
<CycleCreateUpdateModal
|
||||
workspaceSlug={workspaceSlug}
|
||||
projectId={projectId}
|
||||
isOpen={createModal}
|
||||
handleClose={() => setCreateModal(false)}
|
||||
/>
|
||||
{projectDetails?.total_cycles === 0 ? (
|
||||
{currentProjectDetails?.total_cycles === 0 ? (
|
||||
<div className="h-full grid place-items-center">
|
||||
<EmptyState
|
||||
title="Plan your project with cycles"
|
||||
|
@ -20,14 +20,14 @@ import { useMobxStore } from "lib/mobx/store-provider";
|
||||
import { observer } from "mobx-react-lite";
|
||||
|
||||
const GeneralSettings: NextPage = observer(() => {
|
||||
// store
|
||||
const { project: projectStore } = useMobxStore();
|
||||
const { currentProjectDetails } = projectStore;
|
||||
// states
|
||||
const [selectProject, setSelectedProject] = useState<string | null>(null);
|
||||
// router
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
// derived values
|
||||
const projectDetails = projectId ? projectStore.project_details[projectId.toString()] : null;
|
||||
// api call to fetch project details
|
||||
useSWR(
|
||||
workspaceSlug && projectId ? "PROJECT_DETAILS" : null,
|
||||
@ -39,30 +39,34 @@ const GeneralSettings: NextPage = observer(() => {
|
||||
// const currentNetwork = NETWORK_CHOICES.find((n) => n.key === projectDetails?.network);
|
||||
// const selectedNetwork = NETWORK_CHOICES.find((n) => n.key === watch("network"));
|
||||
|
||||
const isAdmin = projectDetails?.member_role === 20;
|
||||
const isAdmin = currentProjectDetails?.member_role === 20;
|
||||
|
||||
return (
|
||||
<AppLayout header={<ProjectSettingHeader title="General Settings" />} withProjectWrapper>
|
||||
<ProjectSettingLayout>
|
||||
{projectDetails && (
|
||||
{currentProjectDetails && (
|
||||
<DeleteProjectModal
|
||||
project={projectDetails}
|
||||
project={currentProjectDetails}
|
||||
isOpen={Boolean(selectProject)}
|
||||
onClose={() => setSelectedProject(null)}
|
||||
/>
|
||||
)}
|
||||
|
||||
<div className={`pr-9 py-8 w-full overflow-y-auto ${isAdmin ? "" : "opacity-60"}`}>
|
||||
{projectDetails && workspaceSlug ? (
|
||||
<ProjectDetailsForm project={projectDetails} workspaceSlug={workspaceSlug.toString()} isAdmin={isAdmin} />
|
||||
{currentProjectDetails && workspaceSlug ? (
|
||||
<ProjectDetailsForm
|
||||
project={currentProjectDetails}
|
||||
workspaceSlug={workspaceSlug.toString()}
|
||||
isAdmin={isAdmin}
|
||||
/>
|
||||
) : (
|
||||
<ProjectDetailsFormLoader />
|
||||
)}
|
||||
|
||||
{isAdmin && (
|
||||
<DeleteProjectSection
|
||||
projectDetails={projectDetails}
|
||||
handleDelete={() => setSelectedProject(projectDetails.id ?? null)}
|
||||
projectDetails={currentProjectDetails}
|
||||
handleDelete={() => setSelectedProject(currentProjectDetails.id ?? null)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
@ -41,6 +41,8 @@ export interface IProjectStore {
|
||||
joinedProjects: IProject[];
|
||||
favoriteProjects: IProject[];
|
||||
|
||||
currentProjectDetails: IProject | undefined;
|
||||
|
||||
// actions
|
||||
setProjectId: (projectId: string) => void;
|
||||
setSearchQuery: (query: string) => void;
|
||||
@ -137,6 +139,8 @@ export class ProjectStore implements IProjectStore {
|
||||
projectMembers: computed,
|
||||
projectEstimates: computed,
|
||||
|
||||
currentProjectDetails: computed,
|
||||
|
||||
joinedProjects: computed,
|
||||
favoriteProjects: computed,
|
||||
|
||||
@ -198,6 +202,11 @@ export class ProjectStore implements IProjectStore {
|
||||
return this.projects?.[this.rootStore.workspace.workspaceSlug];
|
||||
}
|
||||
|
||||
get currentProjectDetails() {
|
||||
if (!this.projectId) return;
|
||||
return this.project_details[this.projectId];
|
||||
}
|
||||
|
||||
get joinedProjects() {
|
||||
if (!this.rootStore.workspace.workspaceSlug) return [];
|
||||
return this.projects?.[this.rootStore.workspace.workspaceSlug]?.filter((p) => p.is_member);
|
||||
|
@ -98,10 +98,7 @@ import {
|
||||
InboxStore,
|
||||
} from "store/inbox";
|
||||
|
||||
import {
|
||||
IMentionsStore,
|
||||
MentionsStore
|
||||
} from "store/editor"
|
||||
import { IMentionsStore, MentionsStore } from "store/editor";
|
||||
|
||||
enableStaticRendering(typeof window === "undefined");
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// mobx
|
||||
import { action, observable, runInAction, makeObservable } from "mobx";
|
||||
import { action, observable, runInAction, makeObservable, computed } from "mobx";
|
||||
// services
|
||||
import { ProjectService } from "services/project";
|
||||
import { UserService } from "services/user.service";
|
||||
@ -7,6 +7,7 @@ import { WorkspaceService } from "services/workspace.service";
|
||||
// interfaces
|
||||
import { IUser, IUserSettings } from "types/users";
|
||||
import { IWorkspaceMemberMe, IProjectMember } from "types";
|
||||
import { RootStore } from "./root";
|
||||
|
||||
export interface IUserStore {
|
||||
loader: boolean;
|
||||
@ -17,16 +18,28 @@ export interface IUserStore {
|
||||
|
||||
dashboardInfo: any;
|
||||
|
||||
workspaceMemberInfo: IWorkspaceMemberMe | null;
|
||||
workspaceMemberInfo: {
|
||||
[workspaceSlug: string]: IWorkspaceMemberMe;
|
||||
};
|
||||
hasPermissionToWorkspace: {
|
||||
[workspaceSlug: string]: boolean | null;
|
||||
};
|
||||
|
||||
projectMemberInfo: IProjectMember | null;
|
||||
projectMemberInfo: {
|
||||
[projectId: string]: IProjectMember;
|
||||
};
|
||||
hasPermissionToProject: {
|
||||
[projectId: string]: boolean | null;
|
||||
};
|
||||
|
||||
currentProjectMemberInfo: IProjectMember | undefined;
|
||||
currentWorkspaceMemberInfo: IWorkspaceMemberMe | undefined;
|
||||
currentProjectRole: number | undefined;
|
||||
currentWorkspaceRole: number | undefined;
|
||||
|
||||
hasPermissionToCurrentWorkspace: boolean | undefined;
|
||||
hasPermissionToCurrentProject: boolean | undefined;
|
||||
|
||||
fetchCurrentUser: () => Promise<IUser>;
|
||||
fetchCurrentUserSettings: () => Promise<IUserSettings>;
|
||||
|
||||
@ -48,14 +61,18 @@ class UserStore implements IUserStore {
|
||||
|
||||
dashboardInfo: any = null;
|
||||
|
||||
workspaceMemberInfo: IWorkspaceMemberMe | null = null;
|
||||
workspaceMemberInfo: {
|
||||
[workspaceSlug: string]: IWorkspaceMemberMe;
|
||||
} = {};
|
||||
hasPermissionToWorkspace: {
|
||||
[workspaceSlug: string]: boolean | null;
|
||||
[workspaceSlug: string]: boolean;
|
||||
} = {};
|
||||
|
||||
projectMemberInfo: IProjectMember | null = null;
|
||||
projectMemberInfo: {
|
||||
[projectId: string]: IProjectMember;
|
||||
} = {};
|
||||
hasPermissionToProject: {
|
||||
[projectId: string]: boolean | null;
|
||||
[projectId: string]: boolean;
|
||||
} = {};
|
||||
// root store
|
||||
rootStore;
|
||||
@ -64,7 +81,7 @@ class UserStore implements IUserStore {
|
||||
workspaceService;
|
||||
projectService;
|
||||
|
||||
constructor(_rootStore: any) {
|
||||
constructor(_rootStore: RootStore) {
|
||||
makeObservable(this, {
|
||||
// observable
|
||||
loader: observable.ref,
|
||||
@ -78,7 +95,19 @@ class UserStore implements IUserStore {
|
||||
// action
|
||||
fetchCurrentUser: action,
|
||||
fetchCurrentUserSettings: action,
|
||||
fetchUserDashboardInfo: action,
|
||||
fetchUserWorkspaceInfo: action,
|
||||
fetchUserProjectInfo: action,
|
||||
updateTourCompleted: action,
|
||||
updateCurrentUser: action,
|
||||
updateCurrentUserTheme: action,
|
||||
// computed
|
||||
currentProjectMemberInfo: computed,
|
||||
currentWorkspaceMemberInfo: computed,
|
||||
currentProjectRole: computed,
|
||||
currentWorkspaceRole: computed,
|
||||
hasPermissionToCurrentWorkspace: computed,
|
||||
hasPermissionToCurrentProject: computed,
|
||||
});
|
||||
this.rootStore = _rootStore;
|
||||
this.userService = new UserService();
|
||||
@ -86,6 +115,36 @@ class UserStore implements IUserStore {
|
||||
this.projectService = new ProjectService();
|
||||
}
|
||||
|
||||
get currentWorkspaceMemberInfo() {
|
||||
if (!this.rootStore.workspace.workspaceSlug) return;
|
||||
return this.workspaceMemberInfo[this.rootStore.workspace.workspaceSlug];
|
||||
}
|
||||
|
||||
get currentWorkspaceRole() {
|
||||
if (!this.rootStore.workspace.workspaceSlug) return;
|
||||
return this.workspaceMemberInfo[this.rootStore.workspace.workspaceSlug].role;
|
||||
}
|
||||
|
||||
get currentProjectMemberInfo() {
|
||||
if (!this.rootStore.project.projectId) return;
|
||||
return this.projectMemberInfo[this.rootStore.project.projectId];
|
||||
}
|
||||
|
||||
get currentProjectRole() {
|
||||
if (!this.rootStore.project.projectId) return;
|
||||
return this.projectMemberInfo[this.rootStore.project.projectId].role;
|
||||
}
|
||||
|
||||
get hasPermissionToCurrentWorkspace() {
|
||||
if (!this.rootStore.workspace.workspaceSlug) return;
|
||||
return this.hasPermissionToWorkspace[this.rootStore.workspace.workspaceSlug];
|
||||
}
|
||||
|
||||
get hasPermissionToCurrentProject() {
|
||||
if (!this.rootStore.project.projectId) return;
|
||||
return this.hasPermissionToProject[this.rootStore.project.projectId];
|
||||
}
|
||||
|
||||
fetchCurrentUser = async () => {
|
||||
try {
|
||||
const response = await this.userService.currentUser();
|
||||
@ -132,10 +191,13 @@ class UserStore implements IUserStore {
|
||||
|
||||
fetchUserWorkspaceInfo = async (workspaceSlug: string) => {
|
||||
try {
|
||||
const response = await this.workspaceService.workspaceMemberMe(workspaceSlug.toString());
|
||||
const response = await this.workspaceService.workspaceMemberMe(workspaceSlug);
|
||||
|
||||
runInAction(() => {
|
||||
this.workspaceMemberInfo = response;
|
||||
this.workspaceMemberInfo = {
|
||||
...this.workspaceMemberInfo,
|
||||
[workspaceSlug]: response,
|
||||
};
|
||||
this.hasPermissionToWorkspace = {
|
||||
...this.hasPermissionToWorkspace,
|
||||
[workspaceSlug]: true,
|
||||
@ -158,7 +220,10 @@ class UserStore implements IUserStore {
|
||||
const response = await this.projectService.projectMemberMe(workspaceSlug, projectId);
|
||||
|
||||
runInAction(() => {
|
||||
this.projectMemberInfo = response;
|
||||
this.projectMemberInfo = {
|
||||
...this.projectMemberInfo,
|
||||
[projectId]: response,
|
||||
};
|
||||
this.hasPermissionToProject = {
|
||||
...this.hasPermissionToProject,
|
||||
[projectId]: true,
|
||||
|
Loading…
Reference in New Issue
Block a user