fix: spliting out the project members from project store and service (#2739)

This commit is contained in:
sriram veeraghanta 2023-11-09 17:56:55 +05:30 committed by GitHub
parent 7676aab773
commit 79df59f618
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
66 changed files with 496 additions and 415 deletions

View File

@ -26,15 +26,16 @@ const issueService = new IssueService();
export const ChangeIssueAssignee: FC<Props> = observer((props) => { export const ChangeIssueAssignee: FC<Props> = observer((props) => {
const { setIsPaletteOpen, issue, user } = props; const { setIsPaletteOpen, issue, user } = props;
// router
const router = useRouter(); const router = useRouter();
const { workspaceSlug, projectId, issueId } = router.query; const { workspaceSlug, projectId, issueId } = router.query;
// store
const { project: projectStore } = useMobxStore(); const {
const members = projectId ? projectStore.members?.[projectId.toString()] : undefined; projectMember: { projectMembers },
} = useMobxStore();
const options = const options =
members?.map(({ member }) => ({ projectMembers?.map(({ member }) => ({
value: member.id, value: member.id,
query: member.display_name, query: member.display_name,
content: ( content: (

View File

@ -1,5 +1,4 @@
import { FC, useEffect, useState, Dispatch, SetStateAction, Fragment } from "react"; import { FC, useEffect, useState, Fragment } from "react";
// headless ui
import { Dialog, Transition } from "@headlessui/react"; import { Dialog, Transition } from "@headlessui/react";
// icons // icons
import { Command, Search, X } from "lucide-react"; import { Command, Search, X } from "lucide-react";

View File

@ -31,6 +31,7 @@ export const CycleIssuesHeader: React.FC = observer(() => {
cycle: cycleStore, cycle: cycleStore,
cycleIssueFilter: cycleIssueFilterStore, cycleIssueFilter: cycleIssueFilterStore,
project: projectStore, project: projectStore,
projectMember: { projectMembers },
projectState: projectStateStore, projectState: projectStateStore,
commandPalette: commandPaletteStore, commandPalette: commandPaletteStore,
} = useMobxStore(); } = useMobxStore();
@ -178,7 +179,7 @@ export const CycleIssuesHeader: React.FC = observer(() => {
activeLayout ? ISSUE_DISPLAY_FILTERS_BY_LAYOUT.issues[activeLayout] : undefined activeLayout ? ISSUE_DISPLAY_FILTERS_BY_LAYOUT.issues[activeLayout] : undefined
} }
labels={projectStore.labels?.[projectId?.toString() ?? ""] ?? undefined} labels={projectStore.labels?.[projectId?.toString() ?? ""] ?? undefined}
members={projectStore.members?.[projectId?.toString() ?? ""]?.map((m) => m.member)} members={projectMembers?.map((m) => m.member)}
states={projectStateStore.states?.[projectId?.toString() ?? ""] ?? undefined} states={projectStateStore.states?.[projectId?.toString() ?? ""] ?? undefined}
/> />
</FiltersDropdown> </FiltersDropdown>

View File

@ -31,6 +31,7 @@ export const ModuleIssuesHeader: React.FC = observer(() => {
module: moduleStore, module: moduleStore,
moduleFilter: moduleFilterStore, moduleFilter: moduleFilterStore,
project: projectStore, project: projectStore,
projectMember: { projectMembers },
projectState: projectStateStore, projectState: projectStateStore,
commandPalette: commandPaletteStore, commandPalette: commandPaletteStore,
} = useMobxStore(); } = useMobxStore();
@ -177,7 +178,7 @@ export const ModuleIssuesHeader: React.FC = observer(() => {
activeLayout ? ISSUE_DISPLAY_FILTERS_BY_LAYOUT.issues[activeLayout] : undefined activeLayout ? ISSUE_DISPLAY_FILTERS_BY_LAYOUT.issues[activeLayout] : undefined
} }
labels={projectStore.labels?.[projectId?.toString() ?? ""] ?? undefined} labels={projectStore.labels?.[projectId?.toString() ?? ""] ?? undefined}
members={projectStore.members?.[projectId?.toString() ?? ""]?.map((m) => m.member)} members={projectMembers?.map((m) => m.member)}
states={projectStateStore.states?.[projectId?.toString() ?? ""] ?? undefined} states={projectStateStore.states?.[projectId?.toString() ?? ""] ?? undefined}
/> />
</FiltersDropdown> </FiltersDropdown>

View File

@ -22,6 +22,7 @@ export const ProjectArchivedIssuesHeader: FC = observer(() => {
const { const {
project: projectStore, project: projectStore,
projectMember: { projectMembers },
archivedIssueFilters: archivedIssueFiltersStore, archivedIssueFilters: archivedIssueFiltersStore,
projectState: projectStateStore, projectState: projectStateStore,
} = useMobxStore(); } = useMobxStore();
@ -119,7 +120,7 @@ export const ProjectArchivedIssuesHeader: FC = observer(() => {
activeLayout ? ISSUE_DISPLAY_FILTERS_BY_LAYOUT.archived_issues[activeLayout] : undefined activeLayout ? ISSUE_DISPLAY_FILTERS_BY_LAYOUT.archived_issues[activeLayout] : undefined
} }
labels={projectStore.labels?.[projectId?.toString() ?? ""] ?? undefined} labels={projectStore.labels?.[projectId?.toString() ?? ""] ?? undefined}
members={projectStore.members?.[projectId?.toString() ?? ""]?.map((m) => m.member)} members={projectMembers?.map((m) => m.member)}
states={projectStateStore.states?.[projectId?.toString() ?? ""] ?? undefined} states={projectStateStore.states?.[projectId?.toString() ?? ""] ?? undefined}
/> />
</FiltersDropdown> </FiltersDropdown>

View File

@ -26,6 +26,7 @@ export const ProjectIssuesHeader: React.FC = observer(() => {
const { const {
issueFilter: issueFilterStore, issueFilter: issueFilterStore,
project: projectStore, project: projectStore,
projectMember: { projectMembers },
projectState: projectStateStore, projectState: projectStateStore,
inbox: inboxStore, inbox: inboxStore,
commandPalette: commandPaletteStore, commandPalette: commandPaletteStore,
@ -172,7 +173,7 @@ export const ProjectIssuesHeader: React.FC = observer(() => {
activeLayout ? ISSUE_DISPLAY_FILTERS_BY_LAYOUT.issues[activeLayout] : undefined activeLayout ? ISSUE_DISPLAY_FILTERS_BY_LAYOUT.issues[activeLayout] : undefined
} }
labels={projectStore.labels?.[projectId?.toString() ?? ""] ?? undefined} labels={projectStore.labels?.[projectId?.toString() ?? ""] ?? undefined}
members={projectStore.members?.[projectId?.toString() ?? ""]?.map((m) => m.member)} members={projectMembers?.map((m) => m.member)}
states={projectStateStore.states?.[projectId?.toString() ?? ""] ?? undefined} states={projectStateStore.states?.[projectId?.toString() ?? ""] ?? undefined}
/> />
</FiltersDropdown> </FiltersDropdown>

View File

@ -23,6 +23,7 @@ export const ProjectViewIssuesHeader: React.FC = observer(() => {
issueFilter: issueFilterStore, issueFilter: issueFilterStore,
projectViewFilters: projectViewFiltersStore, projectViewFilters: projectViewFiltersStore,
project: projectStore, project: projectStore,
projectMember: { projectMembers },
projectState: projectStateStore, projectState: projectStateStore,
projectViews: projectViewsStore, projectViews: projectViewsStore,
} = useMobxStore(); } = useMobxStore();
@ -163,7 +164,7 @@ export const ProjectViewIssuesHeader: React.FC = observer(() => {
activeLayout ? ISSUE_DISPLAY_FILTERS_BY_LAYOUT.issues[activeLayout] : undefined activeLayout ? ISSUE_DISPLAY_FILTERS_BY_LAYOUT.issues[activeLayout] : undefined
} }
labels={projectStore.labels?.[projectId?.toString() ?? ""] ?? undefined} labels={projectStore.labels?.[projectId?.toString() ?? ""] ?? undefined}
members={projectStore.members?.[projectId?.toString() ?? ""]?.map((m) => m.member)} members={projectMembers?.map((m) => m.member)}
states={projectStateStore.states?.[projectId?.toString() ?? ""] ?? undefined} states={projectStateStore.states?.[projectId?.toString() ?? ""] ?? undefined}
/> />
</FiltersDropdown> </FiltersDropdown>

View File

@ -1,10 +1,7 @@
import { useState } from "react"; import { useState } from "react";
import Link from "next/link"; import Link from "next/link";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import useSWR from "swr"; import useSWR from "swr";
// ui // ui
import { Tooltip } from "@plane/ui"; import { Tooltip } from "@plane/ui";
import { DeleteAttachmentModal } from "./delete-attachment-modal"; import { DeleteAttachmentModal } from "./delete-attachment-modal";
@ -13,7 +10,7 @@ import { getFileIcon } from "components/icons";
import { AlertCircle, X } from "lucide-react"; import { AlertCircle, X } from "lucide-react";
// services // services
import { IssueAttachmentService } from "services/issue"; import { IssueAttachmentService } from "services/issue";
import { ProjectService } from "services/project"; import { ProjectMemberService } from "services/project";
// fetch-key // fetch-key
import { ISSUE_ATTACHMENTS, PROJECT_MEMBERS } from "constants/fetch-keys"; import { ISSUE_ATTACHMENTS, PROJECT_MEMBERS } from "constants/fetch-keys";
// helper // helper
@ -25,7 +22,7 @@ import { IIssueAttachment } from "types";
// services // services
const issueAttachmentService = new IssueAttachmentService(); const issueAttachmentService = new IssueAttachmentService();
const projectService = new ProjectService(); const projectMemberService = new ProjectMemberService();
export const IssueAttachments = () => { export const IssueAttachments = () => {
const [deleteAttachment, setDeleteAttachment] = useState<IIssueAttachment | null>(null); const [deleteAttachment, setDeleteAttachment] = useState<IIssueAttachment | null>(null);
@ -44,7 +41,7 @@ export const IssueAttachments = () => {
const { data: people } = useSWR( const { data: people } = useSWR(
workspaceSlug && projectId ? PROJECT_MEMBERS(projectId as string) : null, workspaceSlug && projectId ? PROJECT_MEMBERS(projectId as string) : null,
workspaceSlug && projectId workspaceSlug && projectId
? () => projectService.fetchProjectMembers(workspaceSlug as string, projectId as string) ? () => projectMemberService.fetchProjectMembers(workspaceSlug as string, projectId as string)
: null : null
); );

View File

@ -1,5 +1,3 @@
import Link from "next/link";
import { useRouter } from "next/router";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
import { Draggable } from "@hello-pangea/dnd"; import { Draggable } from "@hello-pangea/dnd";
// components // components
@ -17,9 +15,6 @@ type Props = {
export const CalendarIssueBlocks: React.FC<Props> = observer((props) => { export const CalendarIssueBlocks: React.FC<Props> = observer((props) => {
const { issues, handleIssues, quickActions } = props; const { issues, handleIssues, quickActions } = props;
const router = useRouter();
const { workspaceSlug } = router.query;
return ( return (
<> <>
{issues?.map((issue, index) => ( {issues?.map((issue, index) => (

View File

@ -15,6 +15,7 @@ export const ArchivedIssueAppliedFiltersRoot: React.FC = observer(() => {
const { const {
archivedIssueFilters: archivedIssueFiltersStore, archivedIssueFilters: archivedIssueFiltersStore,
project: projectStore, project: projectStore,
projectMember: { projectMembers },
projectState: projectStateStore, projectState: projectStateStore,
} = useMobxStore(); } = useMobxStore();
@ -77,7 +78,7 @@ export const ArchivedIssueAppliedFiltersRoot: React.FC = observer(() => {
handleClearAllFilters={handleClearAllFilters} handleClearAllFilters={handleClearAllFilters}
handleRemoveFilter={handleRemoveFilter} handleRemoveFilter={handleRemoveFilter}
labels={projectStore.labels?.[projectId?.toString() ?? ""] ?? []} labels={projectStore.labels?.[projectId?.toString() ?? ""] ?? []}
members={projectStore.members?.[projectId?.toString() ?? ""]?.map((m) => m.member)} members={projectMembers?.map((m) => m.member)}
states={projectStateStore.states?.[projectId?.toString() ?? ""]} states={projectStateStore.states?.[projectId?.toString() ?? ""]}
/> />
</div> </div>

View File

@ -13,6 +13,7 @@ export const CycleAppliedFiltersRoot: React.FC = observer(() => {
const { const {
project: projectStore, project: projectStore,
projectMember: { projectMembers },
cycleIssueFilter: cycleIssueFilterStore, cycleIssueFilter: cycleIssueFilterStore,
projectState: projectStateStore, projectState: projectStateStore,
} = useMobxStore(); } = useMobxStore();
@ -72,7 +73,7 @@ export const CycleAppliedFiltersRoot: React.FC = observer(() => {
handleClearAllFilters={handleClearAllFilters} handleClearAllFilters={handleClearAllFilters}
handleRemoveFilter={handleRemoveFilter} handleRemoveFilter={handleRemoveFilter}
labels={projectStore.labels?.[projectId?.toString() ?? ""] ?? []} labels={projectStore.labels?.[projectId?.toString() ?? ""] ?? []}
members={projectStore.members?.[projectId?.toString() ?? ""]?.map((m) => m.member)} members={projectMembers?.map((m) => m.member)}
states={projectStateStore.states?.[projectId?.toString() ?? ""]} states={projectStateStore.states?.[projectId?.toString() ?? ""]}
/> />
</div> </div>

View File

@ -12,7 +12,12 @@ export const ModuleAppliedFiltersRoot: React.FC = observer(() => {
const router = useRouter(); const router = useRouter();
const { workspaceSlug, projectId, moduleId } = router.query; const { workspaceSlug, projectId, moduleId } = router.query;
const { project: projectStore, moduleFilter: moduleFilterStore, projectState: projectStateStore } = useMobxStore(); const {
project: projectStore,
moduleFilter: moduleFilterStore,
projectState: projectStateStore,
projectMember: { projectMembers },
} = useMobxStore();
const userFilters = moduleFilterStore.moduleFilters; const userFilters = moduleFilterStore.moduleFilters;
@ -69,7 +74,7 @@ export const ModuleAppliedFiltersRoot: React.FC = observer(() => {
handleClearAllFilters={handleClearAllFilters} handleClearAllFilters={handleClearAllFilters}
handleRemoveFilter={handleRemoveFilter} handleRemoveFilter={handleRemoveFilter}
labels={projectStore.labels?.[projectId?.toString() ?? ""] ?? []} labels={projectStore.labels?.[projectId?.toString() ?? ""] ?? []}
members={projectStore.members?.[projectId?.toString() ?? ""]?.map((m) => m.member)} members={projectMembers?.map((m) => m.member)}
states={projectStateStore.states?.[projectId?.toString() ?? ""]} states={projectStateStore.states?.[projectId?.toString() ?? ""]}
/> />
</div> </div>

View File

@ -12,7 +12,12 @@ export const ProjectAppliedFiltersRoot: React.FC = observer(() => {
const router = useRouter(); const router = useRouter();
const { workspaceSlug, projectId } = router.query; const { workspaceSlug, projectId } = router.query;
const { issueFilter: issueFilterStore, project: projectStore, projectState: projectStateStore } = useMobxStore(); const {
issueFilter: issueFilterStore,
project: projectStore,
projectState: projectStateStore,
projectMember: { projectMembers },
} = useMobxStore();
const userFilters = issueFilterStore.userFilters; const userFilters = issueFilterStore.userFilters;
@ -73,7 +78,7 @@ export const ProjectAppliedFiltersRoot: React.FC = observer(() => {
handleClearAllFilters={handleClearAllFilters} handleClearAllFilters={handleClearAllFilters}
handleRemoveFilter={handleRemoveFilter} handleRemoveFilter={handleRemoveFilter}
labels={projectStore.labels?.[projectId?.toString() ?? ""] ?? []} labels={projectStore.labels?.[projectId?.toString() ?? ""] ?? []}
members={projectStore.members?.[projectId?.toString() ?? ""]?.map((m) => m.member)} members={projectMembers?.map((m) => m.member)}
states={projectStateStore.states?.[projectId?.toString() ?? ""]} states={projectStateStore.states?.[projectId?.toString() ?? ""]}
/> />
</div> </div>

View File

@ -19,6 +19,7 @@ export const ProjectViewAppliedFiltersRoot: React.FC = observer(() => {
const { const {
project: projectStore, project: projectStore,
projectMember: { projectMembers },
projectState: projectStateStore, projectState: projectStateStore,
projectViews: projectViewsStore, projectViews: projectViewsStore,
projectViewFilters: projectViewFiltersStore, projectViewFilters: projectViewFiltersStore,
@ -99,7 +100,7 @@ export const ProjectViewAppliedFiltersRoot: React.FC = observer(() => {
handleClearAllFilters={handleClearAllFilters} handleClearAllFilters={handleClearAllFilters}
handleRemoveFilter={handleRemoveFilter} handleRemoveFilter={handleRemoveFilter}
labels={projectStore.labels?.[projectId?.toString() ?? ""] ?? []} labels={projectStore.labels?.[projectId?.toString() ?? ""] ?? []}
members={projectStore.members?.[projectId?.toString() ?? ""]?.map((m) => m.member)} members={projectMembers?.map((m) => m.member)}
states={projectStateStore.states?.[projectId?.toString() ?? ""]} states={projectStateStore.states?.[projectId?.toString() ?? ""]}
/> />
{storedFilters && viewDetails && areFiltersDifferent(storedFilters, viewDetails.query_data ?? {}) && ( {storedFilters && viewDetails && areFiltersDifferent(storedFilters, viewDetails.query_data ?? {}) && (

View File

@ -9,8 +9,6 @@ import { KanBanSwimLanes } from "../swimlanes";
import { KanBan } from "../default"; import { KanBan } from "../default";
import { CycleIssueQuickActions } from "components/issues"; import { CycleIssueQuickActions } from "components/issues";
import { Spinner } from "@plane/ui"; import { Spinner } from "@plane/ui";
// helpers
import { orderArrayBy } from "helpers/array.helper";
// types // types
import { IIssue } from "types"; import { IIssue } from "types";
// constants // constants
@ -25,13 +23,13 @@ export const CycleKanBanLayout: React.FC = observer(() => {
// store // store
const { const {
project: projectStore, project: projectStore,
projectMember: { projectMembers },
projectState: projectStateStore, projectState: projectStateStore,
cycleIssue: cycleIssueStore, cycleIssue: cycleIssueStore,
issueFilter: issueFilterStore, issueFilter: issueFilterStore,
cycleIssueKanBanView: cycleIssueKanBanViewStore, cycleIssueKanBanView: cycleIssueKanBanViewStore,
issueDetail: issueDetailStore, issueDetail: issueDetailStore,
} = useMobxStore(); } = useMobxStore();
const { currentProjectDetails } = projectStore;
const issues = cycleIssueStore?.getIssues; const issues = cycleIssueStore?.getIssues;
@ -51,9 +49,9 @@ export const CycleKanBanLayout: React.FC = observer(() => {
const [isDragStarted, setIsDragStarted] = useState<boolean>(false); const [isDragStarted, setIsDragStarted] = useState<boolean>(false);
const onDragStart = () => { // const onDragStart = () => {
setIsDragStarted(true); // setIsDragStarted(true);
}; // };
const onDragEnd = (result: any) => { const onDragEnd = (result: any) => {
setIsDragStarted(false); setIsDragStarted(false);
@ -102,13 +100,12 @@ export const CycleKanBanLayout: React.FC = observer(() => {
const states = projectStateStore?.projectStates || null; const states = projectStateStore?.projectStates || null;
const priorities = ISSUE_PRIORITIES || null; const priorities = ISSUE_PRIORITIES || null;
const labels = projectStore?.projectLabels || null; const labels = projectStore?.projectLabels || null;
const members = projectStore?.projectMembers || null;
const stateGroups = ISSUE_STATE_GROUPS || null; const stateGroups = ISSUE_STATE_GROUPS || null;
const projects = workspaceSlug ? projectStore?.projects[workspaceSlug.toString()] || null : null; const projects = workspaceSlug ? projectStore?.projects[workspaceSlug.toString()] || null : null;
const estimates = // const estimates =
currentProjectDetails?.estimate !== null // currentProjectDetails?.estimate !== null
? projectStore.projectEstimates?.find((e) => e.id === currentProjectDetails?.estimate) || null // ? projectStore.projectEstimates?.find((e) => e.id === currentProjectDetails?.estimate) || null
: null; // : null;
return ( return (
<> <>
@ -141,7 +138,7 @@ export const CycleKanBanLayout: React.FC = observer(() => {
stateGroups={stateGroups} stateGroups={stateGroups}
priorities={priorities} priorities={priorities}
labels={labels} labels={labels}
members={members?.map((m) => m.member) ?? null} members={projectMembers?.map((m) => m.member) ?? null}
projects={projects} projects={projects}
showEmptyGroup={userDisplayFilters?.show_empty_groups || true} showEmptyGroup={userDisplayFilters?.show_empty_groups || true}
isDragStarted={isDragStarted} isDragStarted={isDragStarted}
@ -168,7 +165,7 @@ export const CycleKanBanLayout: React.FC = observer(() => {
stateGroups={stateGroups} stateGroups={stateGroups}
priorities={priorities} priorities={priorities}
labels={labels} labels={labels}
members={members?.map((m) => m.member) ?? null} members={projectMembers?.map((m) => m.member) ?? null}
projects={projects} projects={projects}
showEmptyGroup={userDisplayFilters?.show_empty_groups || true} showEmptyGroup={userDisplayFilters?.show_empty_groups || true}
isDragStarted={isDragStarted} isDragStarted={isDragStarted}

View File

@ -22,13 +22,13 @@ export const ModuleKanBanLayout: React.FC = observer(() => {
// store // store
const { const {
project: projectStore, project: projectStore,
projectMember: { projectMembers },
projectState: projectStateStore, projectState: projectStateStore,
moduleIssue: moduleIssueStore, moduleIssue: moduleIssueStore,
issueFilter: issueFilterStore, issueFilter: issueFilterStore,
moduleIssueKanBanView: moduleIssueKanBanViewStore, moduleIssueKanBanView: moduleIssueKanBanViewStore,
issueDetail: issueDetailStore, issueDetail: issueDetailStore,
} = useMobxStore(); } = useMobxStore();
const { currentProjectDetails } = projectStore;
const issues = moduleIssueStore?.getIssues; const issues = moduleIssueStore?.getIssues;
@ -48,9 +48,9 @@ export const ModuleKanBanLayout: React.FC = observer(() => {
const [isDragStarted, setIsDragStarted] = useState<boolean>(false); const [isDragStarted, setIsDragStarted] = useState<boolean>(false);
const onDragStart = () => { // const onDragStart = () => {
setIsDragStarted(true); // setIsDragStarted(true);
}; // };
const onDragEnd = (result: any) => { const onDragEnd = (result: any) => {
setIsDragStarted(false); setIsDragStarted(false);
@ -98,13 +98,12 @@ export const ModuleKanBanLayout: React.FC = observer(() => {
const states = projectStateStore?.projectStates || null; const states = projectStateStore?.projectStates || null;
const priorities = ISSUE_PRIORITIES || null; const priorities = ISSUE_PRIORITIES || null;
const labels = projectStore?.projectLabels || null; const labels = projectStore?.projectLabels || null;
const members = projectStore?.projectMembers || null;
const stateGroups = ISSUE_STATE_GROUPS || null; const stateGroups = ISSUE_STATE_GROUPS || null;
const projects = workspaceSlug ? projectStore?.projects[workspaceSlug.toString()] || null : null; const projects = workspaceSlug ? projectStore?.projects[workspaceSlug.toString()] || null : null;
const estimates = // const estimates =
currentProjectDetails?.estimate !== null // currentProjectDetails?.estimate !== null
? projectStore.projectEstimates?.find((e) => e.id === currentProjectDetails?.estimate) || null // ? projectStore.projectEstimates?.find((e) => e.id === currentProjectDetails?.estimate) || null
: null; // : null;
return ( return (
<> <>
@ -137,7 +136,7 @@ export const ModuleKanBanLayout: React.FC = observer(() => {
stateGroups={stateGroups} stateGroups={stateGroups}
priorities={priorities} priorities={priorities}
labels={labels} labels={labels}
members={members?.map((m) => m.member) ?? null} members={projectMembers?.map((m) => m.member) ?? null}
projects={projects} projects={projects}
showEmptyGroup={userDisplayFilters?.show_empty_groups || true} showEmptyGroup={userDisplayFilters?.show_empty_groups || true}
isDragStarted={isDragStarted} isDragStarted={isDragStarted}
@ -164,7 +163,7 @@ export const ModuleKanBanLayout: React.FC = observer(() => {
stateGroups={stateGroups} stateGroups={stateGroups}
priorities={priorities} priorities={priorities}
labels={labels} labels={labels}
members={members?.map((m) => m.member) ?? null} members={projectMembers?.map((m) => m.member) ?? null}
projects={projects} projects={projects}
showEmptyGroup={userDisplayFilters?.show_empty_groups || true} showEmptyGroup={userDisplayFilters?.show_empty_groups || true}
isDragStarted={isDragStarted} isDragStarted={isDragStarted}

View File

@ -20,6 +20,7 @@ export const ProfileIssuesKanBanLayout: FC = observer(() => {
const { const {
workspace: workspaceStore, workspace: workspaceStore,
project: projectStore, project: projectStore,
projectMember: { projectMembers },
projectState: projectStateStore, projectState: projectStateStore,
profileIssues: profileIssuesStore, profileIssues: profileIssuesStore,
profileIssueFilters: profileIssueFiltersStore, profileIssueFilters: profileIssueFiltersStore,
@ -48,9 +49,9 @@ export const ProfileIssuesKanBanLayout: FC = observer(() => {
const [isDragStarted, setIsDragStarted] = useState<boolean>(false); const [isDragStarted, setIsDragStarted] = useState<boolean>(false);
const onDragStart = () => { // const onDragStart = () => {
setIsDragStarted(true); // setIsDragStarted(true);
}; // };
const onDragEnd = (result: any) => { const onDragEnd = (result: any) => {
setIsDragStarted(false); setIsDragStarted(false);
@ -89,7 +90,6 @@ export const ProfileIssuesKanBanLayout: FC = observer(() => {
const states = projectStateStore?.projectStates || null; const states = projectStateStore?.projectStates || null;
const priorities = ISSUE_PRIORITIES || null; const priorities = ISSUE_PRIORITIES || null;
const labels = workspaceStore.workspaceLabels || null; const labels = workspaceStore.workspaceLabels || null;
const members = projectStore?.projectMembers || null;
const stateGroups = ISSUE_STATE_GROUPS || null; const stateGroups = ISSUE_STATE_GROUPS || null;
const projects = projectStore?.workspaceProjects || null; const projects = projectStore?.workspaceProjects || null;
@ -123,7 +123,7 @@ export const ProfileIssuesKanBanLayout: FC = observer(() => {
stateGroups={stateGroups} stateGroups={stateGroups}
priorities={priorities} priorities={priorities}
labels={labels} labels={labels}
members={members?.map((m) => m.member) ?? null} members={projectMembers?.map((m) => m.member) ?? null}
projects={projects} projects={projects}
showEmptyGroup={userDisplayFilters?.show_empty_groups || true} showEmptyGroup={userDisplayFilters?.show_empty_groups || true}
isDragStarted={isDragStarted} isDragStarted={isDragStarted}
@ -149,7 +149,7 @@ export const ProfileIssuesKanBanLayout: FC = observer(() => {
stateGroups={stateGroups} stateGroups={stateGroups}
priorities={priorities} priorities={priorities}
labels={labels} labels={labels}
members={members?.map((m) => m.member) ?? null} members={projectMembers?.map((m) => m.member) ?? null}
projects={projects} projects={projects}
showEmptyGroup={userDisplayFilters?.show_empty_groups || true} showEmptyGroup={userDisplayFilters?.show_empty_groups || true}
isDragStarted={isDragStarted} isDragStarted={isDragStarted}

View File

@ -22,6 +22,7 @@ export const KanBanLayout: React.FC = observer(() => {
const { const {
project: projectStore, project: projectStore,
projectMember: { projectMembers },
projectState: projectStateStore, projectState: projectStateStore,
issue: issueStore, issue: issueStore,
issueFilter: issueFilterStore, issueFilter: issueFilterStore,
@ -92,7 +93,6 @@ export const KanBanLayout: React.FC = observer(() => {
const states = projectStateStore?.projectStates || null; const states = projectStateStore?.projectStates || null;
const priorities = ISSUE_PRIORITIES || null; const priorities = ISSUE_PRIORITIES || null;
const labels = projectStore?.projectLabels || null; const labels = projectStore?.projectLabels || null;
const members = projectStore?.projectMembers || null;
const stateGroups = ISSUE_STATE_GROUPS || null; const stateGroups = ISSUE_STATE_GROUPS || null;
const projects = workspaceSlug ? projectStore?.projects?.[workspaceSlug] || null : null; const projects = workspaceSlug ? projectStore?.projects?.[workspaceSlug] || null : null;
const estimates = const estimates =
@ -130,7 +130,7 @@ export const KanBanLayout: React.FC = observer(() => {
stateGroups={stateGroups} stateGroups={stateGroups}
priorities={priorities} priorities={priorities}
labels={labels} labels={labels}
members={members?.map((m) => m.member) ?? null} members={projectMembers?.map((m) => m.member) ?? null}
projects={projects} projects={projects}
enableQuickIssueCreate enableQuickIssueCreate
showEmptyGroup={userDisplayFilters?.show_empty_groups || true} showEmptyGroup={userDisplayFilters?.show_empty_groups || true}
@ -157,7 +157,7 @@ export const KanBanLayout: React.FC = observer(() => {
stateGroups={stateGroups} stateGroups={stateGroups}
priorities={priorities} priorities={priorities}
labels={labels} labels={labels}
members={members?.map((m) => m.member) ?? null} members={projectMembers?.map((m) => m.member) ?? null}
projects={projects} projects={projects}
showEmptyGroup={userDisplayFilters?.show_empty_groups || true} showEmptyGroup={userDisplayFilters?.show_empty_groups || true}
isDragStarted={isDragStarted} isDragStarted={isDragStarted}

View File

@ -15,6 +15,7 @@ export interface IViewKanBanLayout {}
export const ProjectViewKanBanLayout: React.FC = observer(() => { export const ProjectViewKanBanLayout: React.FC = observer(() => {
const { const {
project: projectStore, project: projectStore,
projectMember: { projectMembers },
projectState: projectStateStore, projectState: projectStateStore,
issue: issueStore, issue: issueStore,
issueFilter: issueFilterStore, issueFilter: issueFilterStore,
@ -56,7 +57,6 @@ export const ProjectViewKanBanLayout: React.FC = observer(() => {
const states = projectStateStore?.projectStates || null; const states = projectStateStore?.projectStates || null;
const priorities = ISSUE_PRIORITIES || null; const priorities = ISSUE_PRIORITIES || null;
const labels = projectStore?.projectLabels || null; const labels = projectStore?.projectLabels || null;
const members = projectStore?.projectMembers || null;
const stateGroups = ISSUE_STATE_GROUPS || null; const stateGroups = ISSUE_STATE_GROUPS || null;
const projects = projectStateStore?.projectStates || null; const projects = projectStateStore?.projectStates || null;
const estimates = null; const estimates = null;

View File

@ -19,6 +19,7 @@ export const ArchivedIssueListLayout: FC = observer(() => {
const { const {
project: projectStore, project: projectStore,
projectMember: { projectMembers },
projectState: projectStateStore, projectState: projectStateStore,
archivedIssues: archivedIssueStore, archivedIssues: archivedIssueStore,
archivedIssueFilters: archivedIssueFiltersStore, archivedIssueFilters: archivedIssueFiltersStore,
@ -42,7 +43,6 @@ export const ArchivedIssueListLayout: FC = observer(() => {
const states = projectStateStore?.projectStates || null; const states = projectStateStore?.projectStates || null;
const priorities = ISSUE_PRIORITIES || null; const priorities = ISSUE_PRIORITIES || null;
const labels = projectStore?.projectLabels || null; const labels = projectStore?.projectLabels || null;
const members = projectStore?.projectMembers || null;
const stateGroups = ISSUE_STATE_GROUPS || null; const stateGroups = ISSUE_STATE_GROUPS || null;
const projects = workspaceSlug ? projectStore?.projects[workspaceSlug.toString()] || null : null; const projects = workspaceSlug ? projectStore?.projects[workspaceSlug.toString()] || null : null;
const estimates = const estimates =
@ -65,7 +65,7 @@ export const ArchivedIssueListLayout: FC = observer(() => {
stateGroups={stateGroups} stateGroups={stateGroups}
priorities={priorities} priorities={priorities}
labels={labels} labels={labels}
members={members?.map((m) => m.member) ?? null} members={projectMembers?.map((m) => m.member) ?? null}
projects={projects} projects={projects}
estimates={estimates?.points ? orderArrayBy(estimates.points, "key") : null} estimates={estimates?.points ? orderArrayBy(estimates.points, "key") : null}
/> />

View File

@ -21,6 +21,7 @@ export const CycleListLayout: React.FC = observer(() => {
// store // store
const { const {
project: projectStore, project: projectStore,
projectMember: { projectMembers },
projectState: projectStateStore, projectState: projectStateStore,
issueFilter: issueFilterStore, issueFilter: issueFilterStore,
cycleIssue: cycleIssueStore, cycleIssue: cycleIssueStore,
@ -59,7 +60,6 @@ export const CycleListLayout: React.FC = observer(() => {
const states = projectStateStore?.projectStates || null; const states = projectStateStore?.projectStates || null;
const priorities = ISSUE_PRIORITIES || null; const priorities = ISSUE_PRIORITIES || null;
const labels = projectStore?.projectLabels || null; const labels = projectStore?.projectLabels || null;
const members = projectStore?.projectMembers || null;
const stateGroups = ISSUE_STATE_GROUPS || null; const stateGroups = ISSUE_STATE_GROUPS || null;
const projects = workspaceSlug ? projectStore?.projects[workspaceSlug.toString()] || null : null; const projects = workspaceSlug ? projectStore?.projects[workspaceSlug.toString()] || null : null;
const estimates = const estimates =
@ -86,7 +86,7 @@ export const CycleListLayout: React.FC = observer(() => {
stateGroups={stateGroups} stateGroups={stateGroups}
priorities={priorities} priorities={priorities}
labels={labels} labels={labels}
members={members?.map((m) => m.member) ?? null} members={projectMembers?.map((m) => m.member) ?? null}
projects={projects} projects={projects}
estimates={estimates?.points ? orderArrayBy(estimates.points, "key") : null} estimates={estimates?.points ? orderArrayBy(estimates.points, "key") : null}
/> />

View File

@ -21,6 +21,7 @@ export const ModuleListLayout: React.FC = observer(() => {
const { const {
project: projectStore, project: projectStore,
projectMember: { projectMembers },
projectState: projectStateStore, projectState: projectStateStore,
issueFilter: issueFilterStore, issueFilter: issueFilterStore,
moduleIssue: moduleIssueStore, moduleIssue: moduleIssueStore,
@ -59,7 +60,6 @@ export const ModuleListLayout: React.FC = observer(() => {
const states = projectStateStore?.projectStates || null; const states = projectStateStore?.projectStates || null;
const priorities = ISSUE_PRIORITIES || null; const priorities = ISSUE_PRIORITIES || null;
const labels = projectStore?.projectLabels || null; const labels = projectStore?.projectLabels || null;
const members = projectStore?.projectMembers || null;
const stateGroups = ISSUE_STATE_GROUPS || null; const stateGroups = ISSUE_STATE_GROUPS || null;
const projects = workspaceSlug ? projectStore?.projects[workspaceSlug.toString()] || null : null; const projects = workspaceSlug ? projectStore?.projects[workspaceSlug.toString()] || null : null;
const estimates = const estimates =
@ -86,7 +86,7 @@ export const ModuleListLayout: React.FC = observer(() => {
stateGroups={stateGroups} stateGroups={stateGroups}
priorities={priorities} priorities={priorities}
labels={labels} labels={labels}
members={members?.map((m) => m.member) ?? null} members={projectMembers?.map((m) => m.member) ?? null}
projects={projects} projects={projects}
estimates={estimates?.points ? orderArrayBy(estimates.points, "key") : null} estimates={estimates?.points ? orderArrayBy(estimates.points, "key") : null}
/> />

View File

@ -18,6 +18,7 @@ export const ProfileIssuesListLayout: FC = observer(() => {
workspace: workspaceStore, workspace: workspaceStore,
projectState: projectStateStore, projectState: projectStateStore,
project: projectStore, project: projectStore,
projectMember: { projectMembers },
profileIssueFilters: profileIssueFiltersStore, profileIssueFilters: profileIssueFiltersStore,
profileIssues: profileIssuesStore, profileIssues: profileIssuesStore,
issueDetail: issueDetailStore, issueDetail: issueDetailStore,
@ -48,7 +49,6 @@ export const ProfileIssuesListLayout: FC = observer(() => {
const states = projectStateStore?.projectStates || null; const states = projectStateStore?.projectStates || null;
const priorities = ISSUE_PRIORITIES || null; const priorities = ISSUE_PRIORITIES || null;
const labels = workspaceStore.workspaceLabels || null; const labels = workspaceStore.workspaceLabels || null;
const members = projectStore?.projectMembers || null;
const stateGroups = ISSUE_STATE_GROUPS || null; const stateGroups = ISSUE_STATE_GROUPS || null;
const projects = projectStore?.workspaceProjects || null; const projects = projectStore?.workspaceProjects || null;
@ -70,7 +70,7 @@ export const ProfileIssuesListLayout: FC = observer(() => {
stateGroups={stateGroups} stateGroups={stateGroups}
priorities={priorities} priorities={priorities}
labels={labels} labels={labels}
members={members?.map((m) => m.member) ?? null} members={projectMembers?.map((m) => m.member) ?? null}
projects={projects} projects={projects}
estimates={null} estimates={null}
/> />

View File

@ -20,6 +20,7 @@ export const ListLayout: FC = observer(() => {
// store // store
const { const {
project: projectStore, project: projectStore,
projectMember: { projectMembers },
projectState: projectStateStore, projectState: projectStateStore,
issue: issueStore, issue: issueStore,
issueDetail: issueDetailStore, issueDetail: issueDetailStore,
@ -49,7 +50,6 @@ export const ListLayout: FC = observer(() => {
const states = projectStateStore?.projectStates || null; const states = projectStateStore?.projectStates || null;
const priorities = ISSUE_PRIORITIES || null; const priorities = ISSUE_PRIORITIES || null;
const labels = projectStore?.projectLabels || null; const labels = projectStore?.projectLabels || null;
const members = projectStore?.projectMembers || null;
const stateGroups = ISSUE_STATE_GROUPS || null; const stateGroups = ISSUE_STATE_GROUPS || null;
const projects = workspaceSlug ? projectStore?.projects[workspaceSlug.toString()] || null : null; const projects = workspaceSlug ? projectStore?.projects[workspaceSlug.toString()] || null : null;
const estimates = const estimates =
@ -81,7 +81,7 @@ export const ListLayout: FC = observer(() => {
stateGroups={stateGroups} stateGroups={stateGroups}
priorities={priorities} priorities={priorities}
labels={labels} labels={labels}
members={members?.map((m) => m.member) ?? null} members={projectMembers?.map((m) => m.member) ?? null}
projects={projects} projects={projects}
enableQuickIssueCreate enableQuickIssueCreate
estimates={estimates?.points ? orderArrayBy(estimates.points, "key") : null} estimates={estimates?.points ? orderArrayBy(estimates.points, "key") : null}

View File

@ -31,7 +31,6 @@ export const ProjectViewListLayout: React.FC = observer(() => {
const states = projectStateStore?.projectStates || null; const states = projectStateStore?.projectStates || null;
const priorities = ISSUE_PRIORITIES || null; const priorities = ISSUE_PRIORITIES || null;
const labels = projectStore?.projectLabels || null; const labels = projectStore?.projectLabels || null;
const members = projectStore?.projectMembers || null;
const stateGroups = ISSUE_STATE_GROUPS || null; const stateGroups = ISSUE_STATE_GROUPS || null;
const projects = projectStateStore?.projectStates || null; const projects = projectStateStore?.projectStates || null;
const estimates = null; const estimates = null;

View File

@ -52,13 +52,13 @@ export const IssuePropertyAssignee: React.FC<IIssuePropertyAssignee> = observer(
const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null); const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null);
const [isLoading, setIsLoading] = useState<Boolean>(false); const [isLoading, setIsLoading] = useState<Boolean>(false);
const fetchProjectMembers = () => { // const fetchProjectMembers = () => {
setIsLoading(true); // setIsLoading(true);
if (workspaceSlug && projectId) // if (workspaceSlug && projectId)
workspaceSlug && // workspaceSlug &&
projectId && // projectId &&
projectStore.fetchProjectMembers(workspaceSlug, projectId).then(() => setIsLoading(false)); // projectStore.fetchProjectMembers(workspaceSlug, projectId).then(() => setIsLoading(false));
}; // };
const getWorkspaceMembers = () => { const getWorkspaceMembers = () => {
setIsLoading(true); setIsLoading(true);

View File

@ -20,6 +20,7 @@ export const CycleSpreadsheetLayout: React.FC = observer(() => {
cycleIssue: cycleIssueStore, cycleIssue: cycleIssueStore,
issueDetail: issueDetailStore, issueDetail: issueDetailStore,
project: projectStore, project: projectStore,
projectMember: { projectMembers },
projectState: projectStateStore, projectState: projectStateStore,
} = useMobxStore(); } = useMobxStore();
@ -59,7 +60,7 @@ export const CycleSpreadsheetLayout: React.FC = observer(() => {
displayFilters={issueFilterStore.userDisplayFilters} displayFilters={issueFilterStore.userDisplayFilters}
handleDisplayFilterUpdate={handleDisplayFiltersUpdate} handleDisplayFilterUpdate={handleDisplayFiltersUpdate}
issues={issues as IIssueUnGroupedStructure} issues={issues as IIssueUnGroupedStructure}
members={projectId ? projectStore.members?.[projectId.toString()]?.map((m) => m.member) : undefined} members={projectMembers?.map((m) => m.member)}
labels={projectId ? projectStore.labels?.[projectId.toString()] ?? undefined : undefined} labels={projectId ? projectStore.labels?.[projectId.toString()] ?? undefined : undefined}
states={projectId ? projectStateStore.states?.[projectId.toString()] : undefined} states={projectId ? projectStateStore.states?.[projectId.toString()] : undefined}
handleIssueAction={() => {}} handleIssueAction={() => {}}

View File

@ -20,6 +20,7 @@ export const ModuleSpreadsheetLayout: React.FC = observer(() => {
moduleIssue: moduleIssueStore, moduleIssue: moduleIssueStore,
issueDetail: issueDetailStore, issueDetail: issueDetailStore,
project: projectStore, project: projectStore,
projectMember: { projectMembers },
projectState: projectStateStore, projectState: projectStateStore,
} = useMobxStore(); } = useMobxStore();
@ -59,7 +60,7 @@ export const ModuleSpreadsheetLayout: React.FC = observer(() => {
displayFilters={issueFilterStore.userDisplayFilters} displayFilters={issueFilterStore.userDisplayFilters}
handleDisplayFilterUpdate={handleDisplayFiltersUpdate} handleDisplayFilterUpdate={handleDisplayFiltersUpdate}
issues={issues as IIssueUnGroupedStructure} issues={issues as IIssueUnGroupedStructure}
members={projectId ? projectStore.members?.[projectId.toString()]?.map((m) => m.member) : undefined} members={projectMembers?.map((m) => m.member)}
labels={projectId ? projectStore.labels?.[projectId.toString()] ?? undefined : undefined} labels={projectId ? projectStore.labels?.[projectId.toString()] ?? undefined : undefined}
states={projectId ? projectStateStore.states?.[projectId.toString()] : undefined} states={projectId ? projectStateStore.states?.[projectId.toString()] : undefined}
handleIssueAction={() => {}} handleIssueAction={() => {}}

View File

@ -20,6 +20,7 @@ export const ProjectSpreadsheetLayout: React.FC = observer(() => {
issueFilter: issueFilterStore, issueFilter: issueFilterStore,
issueDetail: issueDetailStore, issueDetail: issueDetailStore,
project: projectStore, project: projectStore,
projectMember: { projectMembers },
projectState: projectStateStore, projectState: projectStateStore,
user: userStore, user: userStore,
} = useMobxStore(); } = useMobxStore();
@ -61,7 +62,7 @@ export const ProjectSpreadsheetLayout: React.FC = observer(() => {
displayFilters={issueFilterStore.userDisplayFilters} displayFilters={issueFilterStore.userDisplayFilters}
handleDisplayFilterUpdate={handleDisplayFiltersUpdate} handleDisplayFilterUpdate={handleDisplayFiltersUpdate}
issues={issues as IIssueUnGroupedStructure} issues={issues as IIssueUnGroupedStructure}
members={projectId ? projectStore.members?.[projectId.toString()]?.map((m) => m.member) : undefined} members={projectMembers?.map((m) => m.member)}
labels={projectId ? projectStore.labels?.[projectId.toString()] ?? undefined : undefined} labels={projectId ? projectStore.labels?.[projectId.toString()] ?? undefined : undefined}
states={projectId ? projectStateStore.states?.[projectId.toString()] : undefined} states={projectId ? projectStateStore.states?.[projectId.toString()] : undefined}
handleIssueAction={() => {}} handleIssueAction={() => {}}

View File

@ -20,6 +20,7 @@ export const ProjectViewSpreadsheetLayout: React.FC = observer(() => {
projectViewIssues: projectViewIssueStore, projectViewIssues: projectViewIssueStore,
issueDetail: issueDetailStore, issueDetail: issueDetailStore,
project: projectStore, project: projectStore,
projectMember: { projectMembers },
projectState: projectStateStore, projectState: projectStateStore,
} = useMobxStore(); } = useMobxStore();
@ -59,7 +60,7 @@ export const ProjectViewSpreadsheetLayout: React.FC = observer(() => {
displayFilters={issueFilterStore.userDisplayFilters} displayFilters={issueFilterStore.userDisplayFilters}
handleDisplayFilterUpdate={handleDisplayFiltersUpdate} handleDisplayFilterUpdate={handleDisplayFiltersUpdate}
issues={issues as IIssueUnGroupedStructure} issues={issues as IIssueUnGroupedStructure}
members={projectId ? projectStore.members?.[projectId.toString()]?.map((m) => m.member) : undefined} members={projectMembers?.map((m) => m.member)}
labels={projectId ? projectStore.labels?.[projectId.toString()] ?? undefined : undefined} labels={projectId ? projectStore.labels?.[projectId.toString()] ?? undefined : undefined}
states={projectId ? projectStateStore.states?.[projectId.toString()] : undefined} states={projectId ? projectStateStore.states?.[projectId.toString()] : undefined}
handleIssueAction={() => {}} handleIssueAction={() => {}}

View File

@ -1,7 +1,7 @@
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import useSWR from "swr"; import useSWR from "swr";
// services // services
import { ProjectService } from "services/project"; import { ProjectMemberService } from "services/project";
// ui // ui
import { Avatar, AvatarGroup, CustomSearchSelect, UserGroupIcon } from "@plane/ui"; import { Avatar, AvatarGroup, CustomSearchSelect, UserGroupIcon } from "@plane/ui";
// fetch-keys // fetch-keys
@ -13,7 +13,7 @@ export type Props = {
onChange: (value: string[]) => void; onChange: (value: string[]) => void;
}; };
const projectService = new ProjectService(); const projectMemberService = new ProjectMemberService();
export const IssueAssigneeSelect: React.FC<Props> = ({ projectId, value = [], onChange }) => { export const IssueAssigneeSelect: React.FC<Props> = ({ projectId, value = [], onChange }) => {
const router = useRouter(); const router = useRouter();
@ -22,7 +22,7 @@ export const IssueAssigneeSelect: React.FC<Props> = ({ projectId, value = [], on
const { data: members } = useSWR( const { data: members } = useSWR(
workspaceSlug && projectId ? PROJECT_MEMBERS(projectId as string) : null, workspaceSlug && projectId ? PROJECT_MEMBERS(projectId as string) : null,
workspaceSlug && projectId workspaceSlug && projectId
? () => projectService.fetchProjectMembers(workspaceSlug as string, projectId as string) ? () => projectMemberService.fetchProjectMembers(workspaceSlug as string, projectId as string)
: null : null
); );

View File

@ -2,7 +2,7 @@ import React from "react";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import useSWR from "swr"; import useSWR from "swr";
// services // services
import { ProjectService } from "services/project"; import { ProjectMemberService } from "services/project";
// ui // ui
import { Avatar, AvatarGroup, CustomSearchSelect } from "@plane/ui"; import { Avatar, AvatarGroup, CustomSearchSelect } from "@plane/ui";
// fetch-keys // fetch-keys
@ -15,7 +15,7 @@ type Props = {
}; };
// services // services
const projectService = new ProjectService(); const projectMemberService = new ProjectMemberService();
export const SidebarAssigneeSelect: React.FC<Props> = ({ value, onChange, disabled = false }) => { export const SidebarAssigneeSelect: React.FC<Props> = ({ value, onChange, disabled = false }) => {
const router = useRouter(); const router = useRouter();
@ -24,7 +24,7 @@ export const SidebarAssigneeSelect: React.FC<Props> = ({ value, onChange, disabl
const { data: members } = useSWR( const { data: members } = useSWR(
workspaceSlug && projectId ? PROJECT_MEMBERS(projectId as string) : null, workspaceSlug && projectId ? PROJECT_MEMBERS(projectId as string) : null,
workspaceSlug && projectId workspaceSlug && projectId
? () => projectService.fetchProjectMembers(workspaceSlug as string, projectId as string) ? () => projectMemberService.fetchProjectMembers(workspaceSlug as string, projectId as string)
: null : null
); );

View File

@ -2,7 +2,7 @@ import React from "react";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import useSWR from "swr"; import useSWR from "swr";
// services // services
import { ProjectService } from "services/project"; import { ProjectMemberService } from "services/project";
// ui // ui
import { Avatar, CustomSearchSelect } from "@plane/ui"; import { Avatar, CustomSearchSelect } from "@plane/ui";
// icons // icons
@ -15,7 +15,7 @@ type Props = {
onChange: () => void; onChange: () => void;
}; };
const projectService = new ProjectService(); const projectMemberService = new ProjectMemberService();
export const ModuleLeadSelect: React.FC<Props> = ({ value, onChange }) => { export const ModuleLeadSelect: React.FC<Props> = ({ value, onChange }) => {
const router = useRouter(); const router = useRouter();
@ -24,7 +24,7 @@ export const ModuleLeadSelect: React.FC<Props> = ({ value, onChange }) => {
const { data: members } = useSWR( const { data: members } = useSWR(
workspaceSlug && projectId ? PROJECT_MEMBERS(projectId as string) : null, workspaceSlug && projectId ? PROJECT_MEMBERS(projectId as string) : null,
workspaceSlug && projectId workspaceSlug && projectId
? () => projectService.fetchProjectMembers(workspaceSlug as string, projectId as string) ? () => projectMemberService.fetchProjectMembers(workspaceSlug as string, projectId as string)
: null : null
); );

View File

@ -2,7 +2,7 @@ import React from "react";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import useSWR from "swr"; import useSWR from "swr";
// services // services
import { ProjectService } from "services/project"; import { ProjectMemberService } from "services/project";
// ui // ui
import { Avatar, AvatarGroup, CustomSearchSelect, UserGroupIcon } from "@plane/ui"; import { Avatar, AvatarGroup, CustomSearchSelect, UserGroupIcon } from "@plane/ui";
// fetch-keys // fetch-keys
@ -13,7 +13,7 @@ type Props = {
onChange: () => void; onChange: () => void;
}; };
const projectService = new ProjectService(); const projectMemberService = new ProjectMemberService();
export const ModuleMembersSelect: React.FC<Props> = ({ value, onChange }) => { export const ModuleMembersSelect: React.FC<Props> = ({ value, onChange }) => {
const router = useRouter(); const router = useRouter();
@ -22,7 +22,7 @@ export const ModuleMembersSelect: React.FC<Props> = ({ value, onChange }) => {
const { data: members } = useSWR( const { data: members } = useSWR(
workspaceSlug && projectId ? PROJECT_MEMBERS(projectId as string) : null, workspaceSlug && projectId ? PROJECT_MEMBERS(projectId as string) : null,
workspaceSlug && projectId workspaceSlug && projectId
? () => projectService.fetchProjectMembers(workspaceSlug as string, projectId as string) ? () => projectMemberService.fetchProjectMembers(workspaceSlug as string, projectId as string)
: null : null
); );
const options = members?.map((member) => ({ const options = members?.map((member) => ({

View File

@ -2,7 +2,7 @@ import { FC } from "react";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import useSWR from "swr"; import useSWR from "swr";
// services // services
import { ProjectService } from "services/project"; import { ProjectMemberService } from "services/project";
// ui // ui
import { Avatar, CustomSearchSelect } from "@plane/ui"; import { Avatar, CustomSearchSelect } from "@plane/ui";
// icons // icons
@ -15,7 +15,7 @@ type Props = {
onChange: (val: string) => void; onChange: (val: string) => void;
}; };
const projectService = new ProjectService(); const projectMemberService = new ProjectMemberService();
export const SidebarLeadSelect: FC<Props> = (props) => { export const SidebarLeadSelect: FC<Props> = (props) => {
const { value, onChange } = props; const { value, onChange } = props;
@ -26,7 +26,7 @@ export const SidebarLeadSelect: FC<Props> = (props) => {
const { data: members } = useSWR( const { data: members } = useSWR(
workspaceSlug && projectId ? PROJECT_MEMBERS(projectId as string) : null, workspaceSlug && projectId ? PROJECT_MEMBERS(projectId as string) : null,
workspaceSlug && projectId workspaceSlug && projectId
? () => projectService.fetchProjectMembers(workspaceSlug as string, projectId as string) ? () => projectMemberService.fetchProjectMembers(workspaceSlug as string, projectId as string)
: null : null
); );

View File

@ -2,7 +2,7 @@ import React from "react";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import useSWR from "swr"; import useSWR from "swr";
// services // services
import { ProjectService } from "services/project"; import { ProjectMemberService } from "services/project";
// ui // ui
import { Avatar, AvatarGroup, CustomSearchSelect, UserGroupIcon } from "@plane/ui"; import { Avatar, AvatarGroup, CustomSearchSelect, UserGroupIcon } from "@plane/ui";
// icons // icons
@ -16,7 +16,7 @@ type Props = {
}; };
// services // services
const projectService = new ProjectService(); const projectMemberService = new ProjectMemberService();
export const SidebarMembersSelect: React.FC<Props> = ({ value, onChange }) => { export const SidebarMembersSelect: React.FC<Props> = ({ value, onChange }) => {
const router = useRouter(); const router = useRouter();
@ -25,7 +25,7 @@ export const SidebarMembersSelect: React.FC<Props> = ({ value, onChange }) => {
const { data: members } = useSWR( const { data: members } = useSWR(
workspaceSlug && projectId ? PROJECT_MEMBERS(projectId as string) : null, workspaceSlug && projectId ? PROJECT_MEMBERS(projectId as string) : null,
workspaceSlug && projectId workspaceSlug && projectId
? () => projectService.fetchProjectMembers(workspaceSlug as string, projectId as string) ? () => projectMemberService.fetchProjectMembers(workspaceSlug as string, projectId as string)
: null : null
); );

View File

@ -7,7 +7,7 @@ import { Plus } from "lucide-react";
import { useMobxStore } from "lib/mobx/store-provider"; import { useMobxStore } from "lib/mobx/store-provider";
// services // services
import { PageService } from "services/page.service"; import { PageService } from "services/page.service";
import { ProjectService } from "services/project"; import { ProjectMemberService } from "services/project";
// hooks // hooks
import useToast from "hooks/use-toast"; import useToast from "hooks/use-toast";
// components // components
@ -34,7 +34,7 @@ type Props = {
// services // services
const pageService = new PageService(); const pageService = new PageService();
const projectService = new ProjectService(); const projectMemberService = new ProjectMemberService();
export const PagesView: React.FC<Props> = observer(({ pages, viewType }) => { export const PagesView: React.FC<Props> = observer(({ pages, viewType }) => {
// states // states
@ -55,7 +55,7 @@ export const PagesView: React.FC<Props> = observer(({ pages, viewType }) => {
const { data: people } = useSWR( const { data: people } = useSWR(
workspaceSlug && projectId ? PROJECT_MEMBERS(projectId.toString()) : null, workspaceSlug && projectId ? PROJECT_MEMBERS(projectId.toString()) : null,
workspaceSlug && projectId workspaceSlug && projectId
? () => projectService.fetchProjectMembers(workspaceSlug.toString(), projectId.toString()) ? () => projectMemberService.fetchProjectMembers(workspaceSlug.toString(), projectId.toString())
: null : null
); );

View File

@ -4,8 +4,6 @@ import Link from "next/link";
import useSWR, { mutate } from "swr"; import useSWR, { mutate } from "swr";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
import { useMobxStore } from "lib/mobx/store-provider"; import { useMobxStore } from "lib/mobx/store-provider";
// services
import { ProjectInvitationService } from "services/project";
// hooks // hooks
import useToast from "hooks/use-toast"; import useToast from "hooks/use-toast";
// components // components
@ -16,11 +14,9 @@ import { CustomSelect, Tooltip } from "@plane/ui";
import { ChevronDown, XCircle } from "lucide-react"; import { ChevronDown, XCircle } from "lucide-react";
// constants // constants
import { ROLE } from "constants/workspace"; import { ROLE } from "constants/workspace";
// types
import { TUserProjectRole } from "types"; import { TUserProjectRole } from "types";
// services
const projectInvitationService = new ProjectInvitationService();
type Props = { type Props = {
member: any; member: any;
}; };
@ -34,21 +30,27 @@ export const ProjectMemberListItem: React.FC<Props> = observer((props) => {
const [selectedRemoveMember, setSelectedRemoveMember] = useState<any | null>(null); const [selectedRemoveMember, setSelectedRemoveMember] = useState<any | null>(null);
const [selectedInviteRemoveMember, setSelectedInviteRemoveMember] = useState<any | null>(null); const [selectedInviteRemoveMember, setSelectedInviteRemoveMember] = useState<any | null>(null);
// store // store
const { user: userStore, project: projectStore } = useMobxStore(); const {
user: userStore,
projectMember: {
projectMembers,
fetchProjectMembers,
removeMemberFromProject,
updateMember,
deleteProjectInvitation,
},
} = useMobxStore();
// hooks // hooks
const { setToastAlert } = useToast(); const { setToastAlert } = useToast();
// fetching project members // fetching project members
useSWR( useSWR(
workspaceSlug && projectId ? `PROJECT_MEMBERS_${projectId.toString().toUpperCase()}` : null, workspaceSlug && projectId ? `PROJECT_MEMBERS_${projectId.toString().toUpperCase()}` : null,
workspaceSlug && projectId workspaceSlug && projectId ? () => fetchProjectMembers(workspaceSlug.toString(), projectId.toString()) : null
? () => projectStore.fetchProjectMembers(workspaceSlug.toString(), projectId.toString())
: null
); );
// derived values // derived values
const user = userStore.currentUser; const user = userStore.currentUser;
const { currentProjectMemberInfo, currentProjectRole } = userStore; const { currentProjectMemberInfo, currentProjectRole } = userStore;
const isAdmin = currentProjectRole === 20; const isAdmin = currentProjectRole === 20;
const projectMembers = projectStore.members?.[projectId?.toString()!];
const currentUser = projectMembers?.find((item) => item.member.id === user?.id); const currentUser = projectMembers?.find((item) => item.member.id === user?.id);
return ( return (
@ -65,15 +67,11 @@ export const ProjectMemberListItem: React.FC<Props> = observer((props) => {
// if the user is a member // if the user is a member
if (selectedRemoveMember) { if (selectedRemoveMember) {
await projectStore.removeMemberFromProject( await removeMemberFromProject(workspaceSlug.toString(), projectId.toString(), selectedRemoveMember.id);
workspaceSlug.toString(),
projectId.toString(),
selectedRemoveMember.id
);
} }
// if the user is an invite // if the user is an invite
if (selectedInviteRemoveMember) { if (selectedInviteRemoveMember) {
await projectInvitationService.deleteProjectInvitation( await deleteProjectInvitation(
workspaceSlug.toString(), workspaceSlug.toString(),
projectId.toString(), projectId.toString(),
selectedInviteRemoveMember.id selectedInviteRemoveMember.id
@ -150,20 +148,18 @@ export const ProjectMemberListItem: React.FC<Props> = observer((props) => {
onChange={(value: TUserProjectRole | undefined) => { onChange={(value: TUserProjectRole | undefined) => {
if (!workspaceSlug || !projectId) return; if (!workspaceSlug || !projectId) return;
projectStore updateMember(workspaceSlug.toString(), projectId.toString(), member.id, {
.updateMember(workspaceSlug.toString(), projectId.toString(), member.id, { role: value,
role: value, }).catch((err) => {
}) const error = err.error;
.catch((err) => { const errorString = Array.isArray(error) ? error[0] : error;
const error = err.error;
const errorString = Array.isArray(error) ? error[0] : error;
setToastAlert({ setToastAlert({
type: "error", type: "error",
title: "Error!", title: "Error!",
message: errorString ?? "An error occurred while updating member role. Please try again.", message: errorString ?? "An error occurred while updating member role. Please try again.",
});
}); });
});
}} }}
disabled={ disabled={
member.memberId === user?.id || member.memberId === user?.id ||

View File

@ -4,7 +4,7 @@ import useSWR, { mutate } from "swr";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
import { useMobxStore } from "lib/mobx/store-provider"; import { useMobxStore } from "lib/mobx/store-provider";
// services // services
import { ProjectInvitationService } from "services/project"; import { ProjectMemberService } from "services/project";
// hooks // hooks
import useUser from "hooks/use-user"; import useUser from "hooks/use-user";
// components // components
@ -15,7 +15,7 @@ import { Button, Loader } from "@plane/ui";
import { Search } from "lucide-react"; import { Search } from "lucide-react";
// services // services
const projectInvitationService = new ProjectInvitationService(); const projectInvitationService = new ProjectMemberService();
export const ProjectMemberList: React.FC = observer(() => { export const ProjectMemberList: React.FC = observer(() => {
// router // router
@ -23,7 +23,10 @@ export const ProjectMemberList: React.FC = observer(() => {
const { workspaceSlug, projectId } = router.query; const { workspaceSlug, projectId } = router.query;
// store // store
const { project: projectStore } = useMobxStore(); const {
project: projectStore,
projectMember: { projectMembers, fetchProjectMembers },
} = useMobxStore();
// states // states
const [inviteModal, setInviteModal] = useState(false); const [inviteModal, setInviteModal] = useState(false);
@ -39,7 +42,6 @@ export const ProjectMemberList: React.FC = observer(() => {
); );
// derived values // derived values
const projectMembers = projectStore.projectMembers;
const members = [ const members = [
...(projectMembers?.map((item) => ({ ...(projectMembers?.map((item) => ({
@ -83,7 +85,7 @@ export const ProjectMemberList: React.FC = observer(() => {
user={user} user={user}
onSuccess={() => { onSuccess={() => {
mutate(`PROJECT_INVITATIONS_${projectId?.toString()}`); mutate(`PROJECT_INVITATIONS_${projectId?.toString()}`);
projectStore.fetchProjectMembers(workspaceSlug?.toString()!, projectId?.toString()!); fetchProjectMembers(workspaceSlug?.toString()!, projectId?.toString()!);
}} }}
/> />

View File

@ -16,24 +16,20 @@ type Props = {
export const MemberSelect: React.FC<Props> = observer((props) => { export const MemberSelect: React.FC<Props> = observer((props) => {
const { value, onChange, isDisabled = false } = props; const { value, onChange, isDisabled = false } = props;
// router // router
const router = useRouter(); const router = useRouter();
const { workspaceSlug, projectId } = router.query; const { workspaceSlug, projectId } = router.query;
// store // store
const { project: projectStore } = useMobxStore(); const {
projectMember: { fetchProjectMembers, projectMembers },
} = useMobxStore();
useSWR( useSWR(
workspaceSlug && projectId ? `PROJECT_MEMBERS_${projectId.toString().toUpperCase()}` : null, workspaceSlug && projectId ? `PROJECT_MEMBERS_${projectId.toString().toUpperCase()}` : null,
workspaceSlug && projectId workspaceSlug && projectId ? () => fetchProjectMembers(workspaceSlug.toString(), projectId.toString()) : null
? () => projectStore.fetchProjectMembers(workspaceSlug.toString(), projectId.toString())
: null
); );
const members = projectStore.members?.[projectId?.toString()!]; const options = projectMembers?.map((member) => ({
const options = members?.map((member) => ({
value: member.member.id, value: member.member.id,
query: member.member.display_name, query: member.member.display_name,
content: ( content: (
@ -44,7 +40,7 @@ export const MemberSelect: React.FC<Props> = observer((props) => {
), ),
})); }));
const selectedOption = members?.find((m) => m.member.id === value)?.member; const selectedOption = projectMembers?.find((m) => m.member.id === value)?.member;
return ( return (
<CustomSearchSelect <CustomSearchSelect

View File

@ -10,7 +10,7 @@ import { useMobxStore } from "lib/mobx/store-provider";
// ui // ui
import { Avatar, Button, CustomSelect, CustomSearchSelect } from "@plane/ui"; import { Avatar, Button, CustomSelect, CustomSearchSelect } from "@plane/ui";
// services // services
import { ProjectService } from "services/project"; import { ProjectMemberService } from "services/project";
import { WorkspaceService } from "services/workspace.service"; import { WorkspaceService } from "services/workspace.service";
// hooks // hooks
import useToast from "hooks/use-toast"; import useToast from "hooks/use-toast";
@ -48,7 +48,7 @@ const defaultValues: FormValues = {
}; };
// services // services
const projectService = new ProjectService(); const projectMemberService = new ProjectMemberService();
const workspaceService = new WorkspaceService(); const workspaceService = new WorkspaceService();
export const SendProjectInvitationModal: React.FC<Props> = observer((props) => { export const SendProjectInvitationModal: React.FC<Props> = observer((props) => {
@ -90,7 +90,7 @@ export const SendProjectInvitationModal: React.FC<Props> = observer((props) => {
const payload = { ...formData }; const payload = { ...formData };
await projectService await projectMemberService
.bulkAddMembersToProject(workspaceSlug.toString(), projectId.toString(), payload, user) .bulkAddMembersToProject(workspaceSlug.toString(), projectId.toString(), payload, user)
.then(() => { .then(() => {
setIsOpen(false); setIsOpen(false);

View File

@ -26,7 +26,11 @@ const defaultValues: Partial<IProjectView> = {
}; };
export const ProjectViewForm: React.FC<Props> = observer(({ handleFormSubmit, handleClose, data, preLoadedData }) => { export const ProjectViewForm: React.FC<Props> = observer(({ handleFormSubmit, handleClose, data, preLoadedData }) => {
const { project: projectStore, projectState: projectStateStore } = useMobxStore(); const {
project: projectStore,
projectState: projectStateStore,
projectMember: { projectMembers },
} = useMobxStore();
const { const {
control, control,
@ -137,7 +141,7 @@ export const ProjectViewForm: React.FC<Props> = observer(({ handleFormSubmit, ha
}} }}
layoutDisplayFiltersOptions={ISSUE_DISPLAY_FILTERS_BY_LAYOUT.issues.list} layoutDisplayFiltersOptions={ISSUE_DISPLAY_FILTERS_BY_LAYOUT.issues.list}
labels={projectStore.projectLabels ?? undefined} labels={projectStore.projectLabels ?? undefined}
members={projectStore.projectMembers?.map((m) => m.member) ?? undefined} members={projectMembers?.map((m) => m.member) ?? undefined}
states={projectStateStore.projectStates ?? undefined} states={projectStateStore.projectStates ?? undefined}
/> />
</FiltersDropdown> </FiltersDropdown>
@ -151,7 +155,7 @@ export const ProjectViewForm: React.FC<Props> = observer(({ handleFormSubmit, ha
handleClearAllFilters={clearAllFilters} handleClearAllFilters={clearAllFilters}
handleRemoveFilter={() => {}} handleRemoveFilter={() => {}}
labels={projectStore.projectLabels ?? undefined} labels={projectStore.projectLabels ?? undefined}
members={projectStore.projectMembers?.map((m) => m.member) ?? undefined} members={projectMembers?.map((m) => m.member) ?? undefined}
states={projectStateStore.projectStates ?? undefined} states={projectStateStore.projectStates ?? undefined}
/> />
</div> </div>

View File

@ -4,7 +4,7 @@ import useSWR, { mutate } from "swr";
// components // components
import ToastAlert from "components/toast-alert"; import ToastAlert from "components/toast-alert";
// services // services
import { ProjectService } from "services/project"; import { ProjectService, ProjectMemberService } from "services/project";
import { CycleService } from "services/cycle.service"; import { CycleService } from "services/cycle.service";
import { ModuleService } from "services/module.service"; import { ModuleService } from "services/module.service";
import { ViewService } from "services/view.service"; import { ViewService } from "services/view.service";
@ -16,6 +16,7 @@ import { IIssueFilterOptions, IProjectMember, IUser, IIssueDisplayFilterOptions,
import { CYCLE_DETAILS, MODULE_DETAILS, USER_PROJECT_VIEW, VIEW_DETAILS } from "constants/fetch-keys"; import { CYCLE_DETAILS, MODULE_DETAILS, USER_PROJECT_VIEW, VIEW_DETAILS } from "constants/fetch-keys";
const projectService = new ProjectService(); const projectService = new ProjectService();
const projectMemberService = new ProjectMemberService();
const cycleService = new CycleService(); const cycleService = new CycleService();
const moduleService = new ModuleService(); const moduleService = new ModuleService();
const viewService = new ViewService(); const viewService = new ViewService();
@ -218,7 +219,7 @@ export const IssueViewContextProvider: React.FC<{ children: React.ReactNode }> =
const { data: myViewProps, mutate: mutateMyViewProps } = useSWR( const { data: myViewProps, mutate: mutateMyViewProps } = useSWR(
workspaceSlug && projectId ? USER_PROJECT_VIEW(projectId as string) : null, workspaceSlug && projectId ? USER_PROJECT_VIEW(projectId as string) : null,
workspaceSlug && projectId workspaceSlug && projectId
? () => projectService.projectMemberMe(workspaceSlug as string, projectId as string) ? () => projectMemberService.projectMemberMe(workspaceSlug as string, projectId as string)
: null : null
); );

View File

@ -20,7 +20,8 @@ export const ProjectAuthWrapper: FC<IProjectAuthWrapper> = observer((props) => {
// store // store
const { const {
user: { fetchUserProjectInfo, projectMemberInfo, hasPermissionToProject }, user: { fetchUserProjectInfo, projectMemberInfo, hasPermissionToProject },
project: { fetchProjectDetails, fetchProjectLabels, fetchProjectMembers, fetchProjectEstimates, workspaceProjects }, project: { fetchProjectDetails, fetchProjectLabels, fetchProjectEstimates, workspaceProjects },
projectMember: { fetchProjectMembers },
projectState: { fetchProjectStates }, projectState: { fetchProjectStates },
cycle: { fetchCycles }, cycle: { fetchCycles },
module: { fetchModules }, module: { fetchModules },

View File

@ -6,7 +6,7 @@ import { Popover, Transition } from "@headlessui/react";
import { TwitterPicker } from "react-color"; import { TwitterPicker } from "react-color";
import { DragDropContext, DropResult } from "@hello-pangea/dnd"; import { DragDropContext, DropResult } from "@hello-pangea/dnd";
// services // services
import { ProjectService } from "services/project"; import { ProjectService, ProjectMemberService } from "services/project";
import { PageService } from "services/page.service"; import { PageService } from "services/page.service";
import { IssueLabelService } from "services/issue"; import { IssueLabelService } from "services/issue";
// hooks // hooks
@ -45,6 +45,7 @@ import {
// services // services
const projectService = new ProjectService(); const projectService = new ProjectService();
const projectMemberService = new ProjectMemberService();
const pageService = new PageService(); const pageService = new PageService();
const issueLabelService = new IssueLabelService(); const issueLabelService = new IssueLabelService();
@ -95,7 +96,7 @@ const PageDetailsPage: NextPageWithLayout = () => {
const { data: memberDetails } = useSWR( const { data: memberDetails } = useSWR(
workspaceSlug && projectId ? USER_PROJECT_VIEW(projectId.toString()) : null, workspaceSlug && projectId ? USER_PROJECT_VIEW(projectId.toString()) : null,
workspaceSlug && projectId workspaceSlug && projectId
? () => projectService.projectMemberMe(workspaceSlug.toString(), projectId.toString()) ? () => projectMemberService.projectMemberMe(workspaceSlug.toString(), projectId.toString())
: null : null
); );

View File

@ -2,7 +2,7 @@ import React, { ReactElement } from "react";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import useSWR from "swr"; import useSWR from "swr";
// services // services
import { ProjectService } from "services/project"; import { ProjectService, ProjectMemberService } from "services/project";
// layouts // layouts
import { AppLayout } from "layouts/app-layout"; import { AppLayout } from "layouts/app-layout";
import { ProjectSettingLayout } from "layouts/settings-layout"; import { ProjectSettingLayout } from "layouts/settings-layout";
@ -21,6 +21,7 @@ import { USER_PROJECT_VIEW } from "constants/fetch-keys";
// services // services
const projectService = new ProjectService(); const projectService = new ProjectService();
const projectMemberService = new ProjectMemberService();
const AutomationSettingsPage: NextPageWithLayout = () => { const AutomationSettingsPage: NextPageWithLayout = () => {
const router = useRouter(); const router = useRouter();
@ -34,7 +35,7 @@ const AutomationSettingsPage: NextPageWithLayout = () => {
const { data: memberDetails } = useSWR( const { data: memberDetails } = useSWR(
workspaceSlug && projectId ? USER_PROJECT_VIEW(projectId.toString()) : null, workspaceSlug && projectId ? USER_PROJECT_VIEW(projectId.toString()) : null,
workspaceSlug && projectId workspaceSlug && projectId
? () => projectService.projectMemberMe(workspaceSlug.toString(), projectId.toString()) ? () => projectMemberService.projectMemberMe(workspaceSlug.toString(), projectId.toString())
: null : null
); );

View File

@ -1,6 +1,6 @@
export * from "./project.service"; export * from "./project.service";
export * from "./project_estimate.service"; export * from "./project-estimate.service";
export * from "./project_publish.service"; export * from "./project-export.service";
export * from "./project_state.service"; export * from "./project-member.service";
export * from "./project_export.service"; export * from "./project-state.service";
export * from "./project_invitation.service"; export * from "./project-publish.service";

View File

@ -0,0 +1,109 @@
import { API_BASE_URL } from "helpers/common.helper";
// services
import { APIService } from "services/api.service";
import { TrackEventService } from "services/track_event.service";
// types
import type { IUser, IProjectBulkAddFormData, IProjectMember, IProjectMemberInvitation } from "types";
const trackEventService = new TrackEventService();
export class ProjectMemberService extends APIService {
constructor() {
super(API_BASE_URL);
}
async fetchProjectMembers(workspaceSlug: string, projectId: string): Promise<IProjectMember[]> {
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/members/`)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
async bulkAddMembersToProject(
workspaceSlug: string,
projectId: string,
data: IProjectBulkAddFormData,
user: IUser | undefined
): Promise<any> {
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/members/`, data)
.then((response) => {
trackEventService.trackProjectEvent(
{
workspaceId: response?.data?.workspace?.id,
workspaceSlug,
projectId,
projectName: response?.data?.project?.name,
memberEmail: response?.data?.member?.email,
},
"PROJECT_MEMBER_INVITE",
user as IUser
);
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async projectMemberMe(workspaceSlug: string, projectId: string): Promise<IProjectMember> {
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/project-members/me/`)
.then((response) => response?.data)
.catch((error) => {
throw error?.response;
});
}
async getProjectMember(workspaceSlug: string, projectId: string, memberId: string): Promise<IProjectMember> {
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/members/${memberId}/`)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
async updateProjectMember(
workspaceSlug: string,
projectId: string,
memberId: string,
data: Partial<IProjectMember>
): Promise<IProjectMember> {
return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/members/${memberId}/`, data)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
async deleteProjectMember(workspaceSlug: string, projectId: string, memberId: string): Promise<any> {
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/members/${memberId}/`)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
async fetchProjectInvitations(workspaceSlug: string, projectId: string): Promise<IProjectMemberInvitation[]> {
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/invitations/`)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
async updateProjectInvitation(workspaceSlug: string, projectId: string, invitationId: string): Promise<any> {
return this.put(`/api/workspaces/${workspaceSlug}/projects/${projectId}/invitations/${invitationId}/`)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
async deleteProjectInvitation(workspaceSlug: string, projectId: string, invitationId: string): Promise<any> {
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/invitations/${invitationId}/`)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
}

View File

@ -5,10 +5,7 @@ import { TrackEventService } from "services/track_event.service";
// types // types
import type { import type {
GithubRepositoriesResponse, GithubRepositoriesResponse,
IUser,
IProject, IProject,
IProjectBulkAddFormData,
IProjectMember,
ISearchIssueResponse, ISearchIssueResponse,
ProjectPreferences, ProjectPreferences,
IProjectViewProps, IProjectViewProps,
@ -110,77 +107,6 @@ export class ProjectService extends APIService {
}); });
} }
async fetchProjectMembers(workspaceSlug: string, projectId: string): Promise<IProjectMember[]> {
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/members/`)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
async bulkAddMembersToProject(
workspaceSlug: string,
projectId: string,
data: IProjectBulkAddFormData,
user: IUser | undefined
): Promise<any> {
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/members/`, data)
.then((response) => {
trackEventService.trackProjectEvent(
{
workspaceId: response?.data?.workspace?.id,
workspaceSlug,
projectId,
projectName: response?.data?.project?.name,
memberEmail: response?.data?.member?.email,
},
"PROJECT_MEMBER_INVITE",
user as IUser
);
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async projectMemberMe(workspaceSlug: string, projectId: string): Promise<IProjectMember> {
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/project-members/me/`)
.then((response) => response?.data)
.catch((error) => {
throw error?.response;
});
}
async getProjectMember(workspaceSlug: string, projectId: string, memberId: string): Promise<IProjectMember> {
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/members/${memberId}/`)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
async updateProjectMember(
workspaceSlug: string,
projectId: string,
memberId: string,
data: Partial<IProjectMember>
): Promise<IProjectMember> {
return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/members/${memberId}/`, data)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
async deleteProjectMember(workspaceSlug: string, projectId: string, memberId: string): Promise<any> {
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/members/${memberId}/`)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
async setProjectView( async setProjectView(
workspaceSlug: string, workspaceSlug: string,
projectId: string, projectId: string,

View File

@ -1,35 +0,0 @@
import { API_BASE_URL } from "helpers/common.helper";
// services
import { APIService } from "services/api.service";
// types
import { IProjectMemberInvitation } from "types";
export class ProjectInvitationService extends APIService {
constructor() {
super(API_BASE_URL);
}
async fetchProjectInvitations(workspaceSlug: string, projectId: string): Promise<IProjectMemberInvitation[]> {
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/invitations/`)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
async updateProjectInvitation(workspaceSlug: string, projectId: string, invitationId: string): Promise<any> {
return this.put(`/api/workspaces/${workspaceSlug}/projects/${projectId}/invitations/${invitationId}/`)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
async deleteProjectInvitation(workspaceSlug: string, projectId: string, invitationId: string): Promise<any> {
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/invitations/${invitationId}/`)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
}

View File

@ -3,7 +3,7 @@ import { observable, computed, makeObservable, action, runInAction } from "mobx"
import { handleIssueQueryParamsByLayout } from "helpers/issue.helper"; import { handleIssueQueryParamsByLayout } from "helpers/issue.helper";
// services // services
import { IssueService } from "services/issue"; import { IssueService } from "services/issue";
import { ProjectService } from "services/project"; import { ProjectService, ProjectMemberService } from "services/project";
// types // types
import { RootStore } from "../root"; import { RootStore } from "../root";
import { import {
@ -25,6 +25,7 @@ export interface IArchivedIssueFilterStore {
// services // services
projectService: ProjectService; projectService: ProjectService;
projectMemberService: ProjectMemberService;
issueService: IssueService; issueService: IssueService;
// computed // computed
@ -87,6 +88,7 @@ export class ArchivedIssueFilterStore implements IArchivedIssueFilterStore {
// services // services
projectService: ProjectService; projectService: ProjectService;
projectMemberService: ProjectMemberService;
issueService: IssueService; issueService: IssueService;
constructor(_rootStore: RootStore) { constructor(_rootStore: RootStore) {
@ -111,6 +113,7 @@ export class ArchivedIssueFilterStore implements IArchivedIssueFilterStore {
// services // services
this.issueService = new IssueService(); this.issueService = new IssueService();
this.projectService = new ProjectService(); this.projectService = new ProjectService();
this.projectMemberService = new ProjectMemberService();
} }
computedFilter = (filters: any, filteredParams: any) => { computedFilter = (filters: any, filteredParams: any) => {
@ -222,7 +225,7 @@ export class ArchivedIssueFilterStore implements IArchivedIssueFilterStore {
fetchUserProjectFilters = async (workspaceSlug: string, projectId: string) => { fetchUserProjectFilters = async (workspaceSlug: string, projectId: string) => {
try { try {
const memberResponse = await this.projectService.projectMemberMe(workspaceSlug, projectId); const memberResponse = await this.projectMemberService.projectMemberMe(workspaceSlug, projectId);
const issueProperties = await this.issueService.getIssueDisplayProperties(workspaceSlug, projectId); const issueProperties = await this.issueService.getIssueDisplayProperties(workspaceSlug, projectId);
runInAction(() => { runInAction(() => {

View File

@ -22,7 +22,7 @@ export class MentionsStore implements IMentionsStore {
} }
get mentionSuggestions() { get mentionSuggestions() {
const projectMembers = this.rootStore.project.projectMembers; const projectMembers = this.rootStore.projectMember.projectMembers;
const suggestions = const suggestions =
projectMembers === null projectMembers === null

View File

@ -1,6 +1,6 @@
import { observable, action, computed, makeObservable, runInAction } from "mobx"; import { observable, action, computed, makeObservable, runInAction } from "mobx";
// services // services
import { ProjectService } from "services/project"; import { ProjectService, ProjectMemberService } from "services/project";
import { IssueService } from "services/issue"; import { IssueService } from "services/issue";
// helpers // helpers
import { handleIssueQueryParamsByLayout } from "helpers/issue.helper"; import { handleIssueQueryParamsByLayout } from "helpers/issue.helper";
@ -72,6 +72,7 @@ export class IssueFilterStore implements IIssueFilterStore {
// services // services
projectService; projectService;
projectMemberService;
issueService; issueService;
constructor(_rootStore: RootStore) { constructor(_rootStore: RootStore) {
@ -98,6 +99,7 @@ export class IssueFilterStore implements IIssueFilterStore {
this.rootStore = _rootStore; this.rootStore = _rootStore;
this.projectService = new ProjectService(); this.projectService = new ProjectService();
this.projectMemberService = new ProjectMemberService();
this.issueService = new IssueService(); this.issueService = new IssueService();
} }
@ -145,7 +147,7 @@ export class IssueFilterStore implements IIssueFilterStore {
fetchUserProjectFilters = async (workspaceSlug: string, projectId: string) => { fetchUserProjectFilters = async (workspaceSlug: string, projectId: string) => {
try { try {
const memberResponse = await this.projectService.projectMemberMe(workspaceSlug, projectId); const memberResponse = await this.projectMemberService.projectMemberMe(workspaceSlug, projectId);
const issueProperties = await this.issueService.getIssueDisplayProperties(workspaceSlug, projectId); const issueProperties = await this.issueService.getIssueDisplayProperties(workspaceSlug, projectId);
runInAction(() => { runInAction(() => {

View File

@ -1,5 +1,6 @@
export * from "./project_publish.store";
export * from "./project.store"; export * from "./project.store";
export * from "./project_estimates.store"; export * from "./project-estimates.store";
export * from "./project_label_store"; export * from "./project-label.store";
export * from "./project_state.store"; export * from "./project-members.store";
export * from "./project-publish.store";
export * from "./project-state.store";

View File

@ -0,0 +1,182 @@
import { observable, action, computed, makeObservable, runInAction } from "mobx";
// types
import { RootStore } from "../root";
import { IProjectMember } from "types";
// services
import { ProjectMemberService } from "services/project";
export interface IProjectMemberStore {
// observables
members: {
[projectId: string]: IProjectMember[] | null; // project_id: members
};
// computed
projectMembers: IProjectMember[] | null;
// actions
getProjectMemberById: (memberId: string) => IProjectMember | null;
getProjectMemberByUserId: (memberId: string) => IProjectMember | null;
fetchProjectMembers: (workspaceSlug: string, projectId: string) => Promise<void>;
removeMemberFromProject: (workspaceSlug: string, projectId: string, memberId: string) => Promise<void>;
updateMember: (
workspaceSlug: string,
projectId: string,
memberId: string,
data: Partial<IProjectMember>
) => Promise<IProjectMember>;
deleteProjectInvitation: (workspaceSlug: string, projectId: string, memberId: string) => Promise<void>;
}
export class ProjectMemberStore implements IProjectMemberStore {
members: {
[projectId: string]: IProjectMember[]; // projectId: members
} = {};
// root store
rootStore;
// service
projectMemberService;
constructor(_rootStore: RootStore) {
makeObservable(this, {
// observable
members: observable.ref,
// computed
projectMembers: computed,
// action
getProjectMemberById: action,
fetchProjectMembers: action,
removeMemberFromProject: action,
updateMember: action,
});
this.rootStore = _rootStore;
this.projectMemberService = new ProjectMemberService();
}
/**
* Computed value of current members in the project
*/
get projectMembers() {
if (!this.rootStore.project.projectId) return null;
return this.members[this.rootStore.project.projectId] || null;
}
/**
* Get all project information using membership id
* @param memberId
* @returns
*/
getProjectMemberById = (memberId: string) => {
if (!this.rootStore.project.projectId) return null;
const members = this.projectMembers;
if (!members) return null;
const memberInfo: IProjectMember | null = members.find((member) => member.id === memberId) || null;
return memberInfo;
};
/**
* Get user information from the project members using user id
* @param memberId
* @returns
*/
getProjectMemberByUserId = (memberId: string) => {
if (!this.rootStore.project.projectId) return null;
const members = this.projectMembers;
if (!members) return null;
const memberInfo: IProjectMember | null = members.find((member) => member.member.id === memberId) || null;
return memberInfo;
};
/**
* fetch the project members info using workspace id and project id
* @param workspaceSlug
* @param projectId
*/
fetchProjectMembers = async (workspaceSlug: string, projectId: string) => {
try {
const membersResponse = await this.projectMemberService.fetchProjectMembers(workspaceSlug, projectId);
const _members = {
...this.members,
[projectId]: membersResponse,
};
runInAction(() => {
this.members = _members;
});
} catch (error) {
console.error(error);
throw error;
}
};
/**
* Remove user from the project
* @param workspaceSlug
* @param projectId
* @param memberId
*/
removeMemberFromProject = async (workspaceSlug: string, projectId: string, memberId: string) => {
const originalMembers = this.projectMembers || [];
try {
runInAction(() => {
this.members = {
...this.members,
[projectId]: this.projectMembers?.filter((member) => member.id !== memberId) || [],
};
});
await this.projectMemberService.deleteProjectMember(workspaceSlug, projectId, memberId);
await this.fetchProjectMembers(workspaceSlug, projectId);
} catch (error) {
console.log("Failed to delete project from project store");
// revert back to original members in case of error
runInAction(() => {
this.members = {
...this.members,
[projectId]: originalMembers,
};
});
}
};
/**
* Update member information
* @param workspaceSlug
* @param projectId
* @param memberId
* @param data
* @returns
*/
updateMember = async (workspaceSlug: string, projectId: string, memberId: string, data: Partial<IProjectMember>) => {
const originalMembers = this.projectMembers || [];
try {
runInAction(() => {
this.members = {
...this.members,
[projectId]: (this.projectMembers || [])?.map((member) =>
member.id === memberId ? { ...member, ...data } : member
),
};
});
const response = await this.projectMemberService.updateProjectMember(workspaceSlug, projectId, memberId, data);
await this.fetchProjectMembers(workspaceSlug, projectId);
return response;
} catch (error) {
console.log("Failed to update project member from project store");
// revert back to original members in case of error
runInAction(() => {
this.members = {
...this.members,
[projectId]: originalMembers,
};
});
throw error;
}
};
deleteProjectInvitation = async () => {
try {
} catch (error) {
throw error;
}
};
}

View File

@ -1,7 +1,7 @@
import { observable, action, computed, makeObservable, runInAction } from "mobx"; import { observable, action, computed, makeObservable, runInAction } from "mobx";
// types // types
import { RootStore } from "../root"; import { RootStore } from "../root";
import { IProject, IIssueLabels, IProjectMember, IEstimate } from "types"; import { IProject, IIssueLabels, IEstimate } from "types";
// services // services
import { ProjectService, ProjectStateService, ProjectEstimateService } from "services/project"; import { ProjectService, ProjectStateService, ProjectEstimateService } from "services/project";
import { IssueService, IssueLabelService } from "services/issue"; import { IssueService, IssueLabelService } from "services/issue";
@ -19,9 +19,6 @@ export interface IProjectStore {
labels: { labels: {
[projectId: string]: IIssueLabels[] | null; // project_id: labels [projectId: string]: IIssueLabels[] | null; // project_id: labels
} | null; } | null;
members: {
[projectId: string]: IProjectMember[] | null; // project_id: members
} | null;
estimates: { estimates: {
[projectId: string]: IEstimate[] | null; // project_id: members [projectId: string]: IEstimate[] | null; // project_id: members
} | null; } | null;
@ -30,7 +27,6 @@ export interface IProjectStore {
searchedProjects: IProject[]; searchedProjects: IProject[];
workspaceProjects: IProject[] | null; workspaceProjects: IProject[] | null;
projectLabels: IIssueLabels[] | null; projectLabels: IIssueLabels[] | null;
projectMembers: IProjectMember[] | null;
projectEstimates: IEstimate[] | null; projectEstimates: IEstimate[] | null;
joinedProjects: IProject[]; joinedProjects: IProject[];
@ -44,14 +40,11 @@ export interface IProjectStore {
getProjectById: (workspaceSlug: string, projectId: string) => IProject | null; getProjectById: (workspaceSlug: string, projectId: string) => IProject | null;
getProjectLabelById: (labelId: string) => IIssueLabels | null; getProjectLabelById: (labelId: string) => IIssueLabels | null;
getProjectMemberById: (memberId: string) => IProjectMember | null;
getProjectMemberByUserId: (memberId: string) => IProjectMember | null;
getProjectEstimateById: (estimateId: string) => IEstimate | null; getProjectEstimateById: (estimateId: string) => IEstimate | null;
fetchProjects: (workspaceSlug: string) => Promise<void>; fetchProjects: (workspaceSlug: string) => Promise<void>;
fetchProjectDetails: (workspaceSlug: string, projectId: string) => Promise<any>; fetchProjectDetails: (workspaceSlug: string, projectId: string) => Promise<any>;
fetchProjectLabels: (workspaceSlug: string, projectId: string) => Promise<void>; fetchProjectLabels: (workspaceSlug: string, projectId: string) => Promise<void>;
fetchProjectMembers: (workspaceSlug: string, projectId: string) => Promise<void>;
fetchProjectEstimates: (workspaceSlug: string, projectId: string) => Promise<any>; fetchProjectEstimates: (workspaceSlug: string, projectId: string) => Promise<any>;
addProjectToFavorites: (workspaceSlug: string, projectId: string) => Promise<any>; addProjectToFavorites: (workspaceSlug: string, projectId: string) => Promise<any>;
@ -65,15 +58,6 @@ export interface IProjectStore {
createProject: (workspaceSlug: string, data: any) => Promise<any>; createProject: (workspaceSlug: string, data: any) => Promise<any>;
updateProject: (workspaceSlug: string, projectId: string, data: Partial<IProject>) => Promise<any>; updateProject: (workspaceSlug: string, projectId: string, data: Partial<IProject>) => Promise<any>;
deleteProject: (workspaceSlug: string, projectId: string) => Promise<void>; deleteProject: (workspaceSlug: string, projectId: string) => Promise<void>;
// write operations
removeMemberFromProject: (workspaceSlug: string, projectId: string, memberId: string) => Promise<void>;
updateMember: (
workspaceSlug: string,
projectId: string,
memberId: string,
data: Partial<IProjectMember>
) => Promise<IProjectMember>;
} }
export class ProjectStore implements IProjectStore { export class ProjectStore implements IProjectStore {
@ -89,9 +73,6 @@ export class ProjectStore implements IProjectStore {
labels: { labels: {
[projectId: string]: IIssueLabels[]; // projectId: labels [projectId: string]: IIssueLabels[]; // projectId: labels
} | null = {}; } | null = {};
members: {
[projectId: string]: IProjectMember[]; // projectId: members
} | null = {};
estimates: { estimates: {
[projectId: string]: IEstimate[]; // projectId: estimates [projectId: string]: IEstimate[]; // projectId: estimates
} | null = {}; } | null = {};
@ -116,14 +97,12 @@ export class ProjectStore implements IProjectStore {
projects: observable.ref, projects: observable.ref,
project_details: observable.ref, project_details: observable.ref,
labels: observable.ref, labels: observable.ref,
members: observable.ref,
estimates: observable.ref, estimates: observable.ref,
// computed // computed
searchedProjects: computed, searchedProjects: computed,
workspaceProjects: computed, workspaceProjects: computed,
projectLabels: computed, projectLabels: computed,
projectMembers: computed,
projectEstimates: computed, projectEstimates: computed,
currentProjectDetails: computed, currentProjectDetails: computed,
@ -139,11 +118,9 @@ export class ProjectStore implements IProjectStore {
getProjectById: action, getProjectById: action,
getProjectLabelById: action, getProjectLabelById: action,
getProjectMemberById: action,
getProjectEstimateById: action, getProjectEstimateById: action,
fetchProjectLabels: action, fetchProjectLabels: action,
fetchProjectMembers: action,
fetchProjectEstimates: action, fetchProjectEstimates: action,
addProjectToFavorites: action, addProjectToFavorites: action,
@ -154,10 +131,6 @@ export class ProjectStore implements IProjectStore {
createProject: action, createProject: action,
updateProject: action, updateProject: action,
leaveProject: action, leaveProject: action,
// write operations
removeMemberFromProject: action,
updateMember: action,
}); });
this.rootStore = _rootStore; this.rootStore = _rootStore;
@ -209,11 +182,6 @@ export class ProjectStore implements IProjectStore {
return this.labels?.[this.projectId] || null; return this.labels?.[this.projectId] || null;
} }
get projectMembers() {
if (!this.projectId) return null;
return this.members?.[this.projectId] || null;
}
get projectEstimates() { get projectEstimates() {
if (!this.projectId) return null; if (!this.projectId) return null;
return this.estimates?.[this.projectId] || null; return this.estimates?.[this.projectId] || null;
@ -281,22 +249,6 @@ export class ProjectStore implements IProjectStore {
return labelInfo; return labelInfo;
}; };
getProjectMemberById = (memberId: string) => {
if (!this.projectId) return null;
const members = this.projectMembers;
if (!members) return null;
const memberInfo: IProjectMember | null = members.find((member) => member.id === memberId) || null;
return memberInfo;
};
getProjectMemberByUserId = (memberId: string) => {
if (!this.projectId) return null;
const members = this.projectMembers;
if (!members) return null;
const memberInfo: IProjectMember | null = members.find((member) => member.member.id === memberId) || null;
return memberInfo;
};
getProjectEstimateById = (estimateId: string) => { getProjectEstimateById = (estimateId: string) => {
if (!this.projectId) return null; if (!this.projectId) return null;
const estimates = this.projectEstimates; const estimates = this.projectEstimates;
@ -327,29 +279,6 @@ export class ProjectStore implements IProjectStore {
} }
}; };
fetchProjectMembers = async (workspaceSlug: string, projectId: string) => {
try {
this.loader = true;
this.error = null;
const membersResponse = await this.projectService.fetchProjectMembers(workspaceSlug, projectId);
const _members = {
...this.members,
[projectId]: membersResponse,
};
runInAction(() => {
this.members = _members;
this.loader = false;
this.error = null;
});
} catch (error) {
console.error(error);
this.loader = false;
this.error = error;
}
};
fetchProjectEstimates = async (workspaceSlug: string, projectId: string) => { fetchProjectEstimates = async (workspaceSlug: string, projectId: string) => {
try { try {
this.loader = true; this.loader = true;
@ -576,58 +505,4 @@ export class ProjectStore implements IProjectStore {
console.log("Failed to delete project from project store"); console.log("Failed to delete project from project store");
} }
}; };
removeMemberFromProject = async (workspaceSlug: string, projectId: string, memberId: string) => {
const originalMembers = this.projectMembers || [];
runInAction(() => {
this.members = {
...this.members,
[projectId]: this.projectMembers?.filter((member) => member.id !== memberId) || [],
};
});
try {
await this.projectService.deleteProjectMember(workspaceSlug, projectId, memberId);
await this.fetchProjectMembers(workspaceSlug, projectId);
} catch (error) {
console.log("Failed to delete project from project store");
// revert back to original members in case of error
runInAction(() => {
this.members = {
...this.members,
[projectId]: originalMembers,
};
});
}
};
updateMember = async (workspaceSlug: string, projectId: string, memberId: string, data: Partial<IProjectMember>) => {
const originalMembers = this.projectMembers || [];
runInAction(() => {
this.members = {
...this.members,
[projectId]: (this.projectMembers || [])?.map((member) =>
member.id === memberId ? { ...member, ...data } : member
),
};
});
try {
const response = await this.projectService.updateProjectMember(workspaceSlug, projectId, memberId, data);
await this.fetchProjectMembers(workspaceSlug, projectId);
return response;
} catch (error) {
console.log("Failed to update project member from project store");
// revert back to original members in case of error
runInAction(() => {
this.members = {
...this.members,
[projectId]: originalMembers,
};
});
throw error;
}
};
} }

View File

@ -38,6 +38,8 @@ import {
ProjectLabelStore, ProjectLabelStore,
ProjectEstimatesStore, ProjectEstimatesStore,
IProjectEstimateStore, IProjectEstimateStore,
ProjectMemberStore,
IProjectMemberStore,
} from "store/project"; } from "store/project";
import { import {
IModuleFilterStore, IModuleFilterStore,
@ -116,8 +118,8 @@ export class RootStore {
user: IUserStore; user: IUserStore;
theme: IThemeStore; theme: IThemeStore;
appConfig: IAppConfigStore; appConfig: IAppConfigStore;
commandPalette: ICommandPaletteStore; commandPalette: ICommandPaletteStore;
workspace: IWorkspaceStore; workspace: IWorkspaceStore;
workspaceFilter: IWorkspaceFilterStore; workspaceFilter: IWorkspaceFilterStore;
workspaceMember: IWorkspaceMemberStore; workspaceMember: IWorkspaceMemberStore;
@ -127,6 +129,8 @@ export class RootStore {
projectState: IProjectStateStore; projectState: IProjectStateStore;
projectLabel: IProjectLabelStore; projectLabel: IProjectLabelStore;
projectEstimates: IProjectEstimateStore; projectEstimates: IProjectEstimateStore;
projectMember: IProjectMemberStore;
issue: IIssueStore; issue: IIssueStore;
module: IModuleStore; module: IModuleStore;
@ -191,6 +195,7 @@ export class RootStore {
this.projectLabel = new ProjectLabelStore(this); this.projectLabel = new ProjectLabelStore(this);
this.projectEstimates = new ProjectEstimatesStore(this); this.projectEstimates = new ProjectEstimatesStore(this);
this.projectPublish = new ProjectPublishStore(this); this.projectPublish = new ProjectPublishStore(this);
this.projectMember = new ProjectMemberStore(this);
this.module = new ModuleStore(this); this.module = new ModuleStore(this);
this.moduleIssue = new ModuleIssueStore(this); this.moduleIssue = new ModuleIssueStore(this);

View File

@ -1,7 +1,7 @@
// mobx // mobx
import { action, observable, runInAction, makeObservable, computed } from "mobx"; import { action, observable, runInAction, makeObservable, computed } from "mobx";
// services // services
import { ProjectService } from "services/project"; import { ProjectMemberService, ProjectService } from "services/project";
import { UserService } from "services/user.service"; import { UserService } from "services/user.service";
import { WorkspaceService } from "services/workspace.service"; import { WorkspaceService } from "services/workspace.service";
// interfaces // interfaces
@ -81,6 +81,7 @@ class UserStore implements IUserStore {
userService; userService;
workspaceService; workspaceService;
projectService; projectService;
projectMemberService;
constructor(_rootStore: RootStore) { constructor(_rootStore: RootStore) {
makeObservable(this, { makeObservable(this, {
@ -115,6 +116,7 @@ class UserStore implements IUserStore {
this.userService = new UserService(); this.userService = new UserService();
this.workspaceService = new WorkspaceService(); this.workspaceService = new WorkspaceService();
this.projectService = new ProjectService(); this.projectService = new ProjectService();
this.projectMemberService = new ProjectMemberService();
} }
get currentWorkspaceMemberInfo() { get currentWorkspaceMemberInfo() {
@ -219,7 +221,7 @@ class UserStore implements IUserStore {
fetchUserProjectInfo = async (workspaceSlug: string, projectId: string) => { fetchUserProjectInfo = async (workspaceSlug: string, projectId: string) => {
try { try {
const response = await this.projectService.projectMemberMe(workspaceSlug, projectId); const response = await this.projectMemberService.projectMemberMe(workspaceSlug, projectId);
runInAction(() => { runInAction(() => {
this.projectMemberInfo = { this.projectMemberInfo = {