From 79df59f61813259d64aa2d4b06115fe7ebc4e760 Mon Sep 17 00:00:00 2001 From: sriram veeraghanta Date: Thu, 9 Nov 2023 17:56:55 +0530 Subject: [PATCH] fix: spliting out the project members from project store and service (#2739) --- .../issue/change-issue-assignee.tsx | 11 +- .../command-palette/shortcuts-modal.tsx | 3 +- web/components/headers/cycle-issues.tsx | 3 +- web/components/headers/module-issues.tsx | 3 +- .../headers/project-archived-issues.tsx | 3 +- web/components/headers/project-issues.tsx | 3 +- .../headers/project-view-issues.tsx | 3 +- .../issues/attachment/attachments.tsx | 9 +- .../issue-layouts/calendar/issue-blocks.tsx | 5 - .../applied-filters/roots/archived-issue.tsx | 3 +- .../applied-filters/roots/cycle-root.tsx | 3 +- .../applied-filters/roots/module-root.tsx | 9 +- .../applied-filters/roots/project-root.tsx | 9 +- .../roots/project-view-root.tsx | 3 +- .../issue-layouts/kanban/roots/cycle-root.tsx | 23 +-- .../kanban/roots/module-root.tsx | 21 +- .../kanban/roots/profile-issues-root.tsx | 12 +- .../kanban/roots/project-root.tsx | 6 +- .../kanban/roots/project-view-root.tsx | 2 +- .../list/roots/archived-issue-root.tsx | 4 +- .../issue-layouts/list/roots/cycle-root.tsx | 4 +- .../issue-layouts/list/roots/module-root.tsx | 4 +- .../list/roots/profile-issues-root.tsx | 4 +- .../issue-layouts/list/roots/project-root.tsx | 4 +- .../list/roots/project-view-root.tsx | 1 - .../issue-layouts/properties/assignee.tsx | 14 +- .../spreadsheet/roots/cycle-root.tsx | 3 +- .../spreadsheet/roots/module-root.tsx | 3 +- .../spreadsheet/roots/project-root.tsx | 3 +- .../spreadsheet/roots/project-view-root.tsx | 3 +- web/components/issues/select/assignee.tsx | 6 +- .../issues/sidebar-select/assignee.tsx | 6 +- web/components/modules/select/lead.tsx | 6 +- web/components/modules/select/members.tsx | 6 +- .../modules/sidebar-select/select-lead.tsx | 6 +- .../modules/sidebar-select/select-members.tsx | 6 +- web/components/pages/pages-view.tsx | 6 +- web/components/project/member-list-item.tsx | 52 +++-- web/components/project/member-list.tsx | 12 +- web/components/project/member-select.tsx | 16 +- .../project/send-project-invitation-modal.tsx | 6 +- web/components/views/form.tsx | 10 +- web/contexts/issue-view.context.tsx | 5 +- web/layouts/auth-layout/project-wrapper.tsx | 3 +- .../projects/[projectId]/pages/[pageId].tsx | 5 +- .../[projectId]/settings/automations.tsx | 5 +- web/services/project/index.ts | 10 +- ...service.ts => project-estimate.service.ts} | 0 ...t.service.ts => project-export.service.ts} | 0 .../project/project-member.service.ts | 109 +++++++++++ ....service.ts => project-publish.service.ts} | 0 ...te.service.ts => project-state.service.ts} | 0 web/services/project/project.service.ts | 74 ------- .../project/project_invitation.service.ts | 35 ---- .../archived-issues/issue_filters.store.ts | 7 +- web/store/editor/mentions.store.ts | 2 +- web/store/issue/issue_filters.store.ts | 6 +- web/store/project/index.ts | 9 +- ...es.store.ts => project-estimates.store.ts} | 0 ..._label_store.ts => project-label.store.ts} | 0 web/store/project/project-members.store.ts | 182 ++++++++++++++++++ ...lish.store.ts => project-publish.store.ts} | 0 ..._state.store.ts => project-state.store.ts} | 0 web/store/project/project.store.ts | 127 +----------- web/store/root.ts | 7 +- web/store/user.store.ts | 6 +- 66 files changed, 496 insertions(+), 415 deletions(-) rename web/services/project/{project_estimate.service.ts => project-estimate.service.ts} (100%) rename web/services/project/{project_export.service.ts => project-export.service.ts} (100%) create mode 100644 web/services/project/project-member.service.ts rename web/services/project/{project_publish.service.ts => project-publish.service.ts} (100%) rename web/services/project/{project_state.service.ts => project-state.service.ts} (100%) delete mode 100644 web/services/project/project_invitation.service.ts rename web/store/project/{project_estimates.store.ts => project-estimates.store.ts} (100%) rename web/store/project/{project_label_store.ts => project-label.store.ts} (100%) create mode 100644 web/store/project/project-members.store.ts rename web/store/project/{project_publish.store.ts => project-publish.store.ts} (100%) rename web/store/project/{project_state.store.ts => project-state.store.ts} (100%) diff --git a/web/components/command-palette/issue/change-issue-assignee.tsx b/web/components/command-palette/issue/change-issue-assignee.tsx index 2d655571c..512428310 100644 --- a/web/components/command-palette/issue/change-issue-assignee.tsx +++ b/web/components/command-palette/issue/change-issue-assignee.tsx @@ -26,15 +26,16 @@ const issueService = new IssueService(); export const ChangeIssueAssignee: FC = observer((props) => { const { setIsPaletteOpen, issue, user } = props; - + // router const router = useRouter(); const { workspaceSlug, projectId, issueId } = router.query; - - const { project: projectStore } = useMobxStore(); - const members = projectId ? projectStore.members?.[projectId.toString()] : undefined; + // store + const { + projectMember: { projectMembers }, + } = useMobxStore(); const options = - members?.map(({ member }) => ({ + projectMembers?.map(({ member }) => ({ value: member.id, query: member.display_name, content: ( diff --git a/web/components/command-palette/shortcuts-modal.tsx b/web/components/command-palette/shortcuts-modal.tsx index 85d2b4fe4..3c7c19969 100644 --- a/web/components/command-palette/shortcuts-modal.tsx +++ b/web/components/command-palette/shortcuts-modal.tsx @@ -1,5 +1,4 @@ -import { FC, useEffect, useState, Dispatch, SetStateAction, Fragment } from "react"; -// headless ui +import { FC, useEffect, useState, Fragment } from "react"; import { Dialog, Transition } from "@headlessui/react"; // icons import { Command, Search, X } from "lucide-react"; diff --git a/web/components/headers/cycle-issues.tsx b/web/components/headers/cycle-issues.tsx index 0fb8913d5..c431b8c00 100644 --- a/web/components/headers/cycle-issues.tsx +++ b/web/components/headers/cycle-issues.tsx @@ -31,6 +31,7 @@ export const CycleIssuesHeader: React.FC = observer(() => { cycle: cycleStore, cycleIssueFilter: cycleIssueFilterStore, project: projectStore, + projectMember: { projectMembers }, projectState: projectStateStore, commandPalette: commandPaletteStore, } = useMobxStore(); @@ -178,7 +179,7 @@ export const CycleIssuesHeader: React.FC = observer(() => { activeLayout ? ISSUE_DISPLAY_FILTERS_BY_LAYOUT.issues[activeLayout] : 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} /> diff --git a/web/components/headers/module-issues.tsx b/web/components/headers/module-issues.tsx index 8364815ca..8e1c20da3 100644 --- a/web/components/headers/module-issues.tsx +++ b/web/components/headers/module-issues.tsx @@ -31,6 +31,7 @@ export const ModuleIssuesHeader: React.FC = observer(() => { module: moduleStore, moduleFilter: moduleFilterStore, project: projectStore, + projectMember: { projectMembers }, projectState: projectStateStore, commandPalette: commandPaletteStore, } = useMobxStore(); @@ -177,7 +178,7 @@ export const ModuleIssuesHeader: React.FC = observer(() => { activeLayout ? ISSUE_DISPLAY_FILTERS_BY_LAYOUT.issues[activeLayout] : 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} /> diff --git a/web/components/headers/project-archived-issues.tsx b/web/components/headers/project-archived-issues.tsx index 7dd06e3a9..3fa1b65b0 100644 --- a/web/components/headers/project-archived-issues.tsx +++ b/web/components/headers/project-archived-issues.tsx @@ -22,6 +22,7 @@ export const ProjectArchivedIssuesHeader: FC = observer(() => { const { project: projectStore, + projectMember: { projectMembers }, archivedIssueFilters: archivedIssueFiltersStore, projectState: projectStateStore, } = useMobxStore(); @@ -119,7 +120,7 @@ export const ProjectArchivedIssuesHeader: FC = observer(() => { activeLayout ? ISSUE_DISPLAY_FILTERS_BY_LAYOUT.archived_issues[activeLayout] : 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} /> diff --git a/web/components/headers/project-issues.tsx b/web/components/headers/project-issues.tsx index e63b348e0..ebc6cc585 100644 --- a/web/components/headers/project-issues.tsx +++ b/web/components/headers/project-issues.tsx @@ -26,6 +26,7 @@ export const ProjectIssuesHeader: React.FC = observer(() => { const { issueFilter: issueFilterStore, project: projectStore, + projectMember: { projectMembers }, projectState: projectStateStore, inbox: inboxStore, commandPalette: commandPaletteStore, @@ -172,7 +173,7 @@ export const ProjectIssuesHeader: React.FC = observer(() => { activeLayout ? ISSUE_DISPLAY_FILTERS_BY_LAYOUT.issues[activeLayout] : 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} /> diff --git a/web/components/headers/project-view-issues.tsx b/web/components/headers/project-view-issues.tsx index dfb3a30b2..55eeac5c2 100644 --- a/web/components/headers/project-view-issues.tsx +++ b/web/components/headers/project-view-issues.tsx @@ -23,6 +23,7 @@ export const ProjectViewIssuesHeader: React.FC = observer(() => { issueFilter: issueFilterStore, projectViewFilters: projectViewFiltersStore, project: projectStore, + projectMember: { projectMembers }, projectState: projectStateStore, projectViews: projectViewsStore, } = useMobxStore(); @@ -163,7 +164,7 @@ export const ProjectViewIssuesHeader: React.FC = observer(() => { activeLayout ? ISSUE_DISPLAY_FILTERS_BY_LAYOUT.issues[activeLayout] : 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} /> diff --git a/web/components/issues/attachment/attachments.tsx b/web/components/issues/attachment/attachments.tsx index 7d8872f9c..ae3b4534d 100644 --- a/web/components/issues/attachment/attachments.tsx +++ b/web/components/issues/attachment/attachments.tsx @@ -1,10 +1,7 @@ import { useState } from "react"; - import Link from "next/link"; import { useRouter } from "next/router"; - import useSWR from "swr"; - // ui import { Tooltip } from "@plane/ui"; import { DeleteAttachmentModal } from "./delete-attachment-modal"; @@ -13,7 +10,7 @@ import { getFileIcon } from "components/icons"; import { AlertCircle, X } from "lucide-react"; // services import { IssueAttachmentService } from "services/issue"; -import { ProjectService } from "services/project"; +import { ProjectMemberService } from "services/project"; // fetch-key import { ISSUE_ATTACHMENTS, PROJECT_MEMBERS } from "constants/fetch-keys"; // helper @@ -25,7 +22,7 @@ import { IIssueAttachment } from "types"; // services const issueAttachmentService = new IssueAttachmentService(); -const projectService = new ProjectService(); +const projectMemberService = new ProjectMemberService(); export const IssueAttachments = () => { const [deleteAttachment, setDeleteAttachment] = useState(null); @@ -44,7 +41,7 @@ export const IssueAttachments = () => { const { data: people } = useSWR( workspaceSlug && projectId ? PROJECT_MEMBERS(projectId as string) : null, workspaceSlug && projectId - ? () => projectService.fetchProjectMembers(workspaceSlug as string, projectId as string) + ? () => projectMemberService.fetchProjectMembers(workspaceSlug as string, projectId as string) : null ); diff --git a/web/components/issues/issue-layouts/calendar/issue-blocks.tsx b/web/components/issues/issue-layouts/calendar/issue-blocks.tsx index 2e270ab7d..931abd081 100644 --- a/web/components/issues/issue-layouts/calendar/issue-blocks.tsx +++ b/web/components/issues/issue-layouts/calendar/issue-blocks.tsx @@ -1,5 +1,3 @@ -import Link from "next/link"; -import { useRouter } from "next/router"; import { observer } from "mobx-react-lite"; import { Draggable } from "@hello-pangea/dnd"; // components @@ -17,9 +15,6 @@ type Props = { export const CalendarIssueBlocks: React.FC = observer((props) => { const { issues, handleIssues, quickActions } = props; - const router = useRouter(); - const { workspaceSlug } = router.query; - return ( <> {issues?.map((issue, index) => ( diff --git a/web/components/issues/issue-layouts/filters/applied-filters/roots/archived-issue.tsx b/web/components/issues/issue-layouts/filters/applied-filters/roots/archived-issue.tsx index d9984c482..32e5a4a21 100644 --- a/web/components/issues/issue-layouts/filters/applied-filters/roots/archived-issue.tsx +++ b/web/components/issues/issue-layouts/filters/applied-filters/roots/archived-issue.tsx @@ -15,6 +15,7 @@ export const ArchivedIssueAppliedFiltersRoot: React.FC = observer(() => { const { archivedIssueFilters: archivedIssueFiltersStore, project: projectStore, + projectMember: { projectMembers }, projectState: projectStateStore, } = useMobxStore(); @@ -77,7 +78,7 @@ export const ArchivedIssueAppliedFiltersRoot: React.FC = observer(() => { handleClearAllFilters={handleClearAllFilters} handleRemoveFilter={handleRemoveFilter} 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() ?? ""]} /> diff --git a/web/components/issues/issue-layouts/filters/applied-filters/roots/cycle-root.tsx b/web/components/issues/issue-layouts/filters/applied-filters/roots/cycle-root.tsx index 407aa6425..2bd0ffdfe 100644 --- a/web/components/issues/issue-layouts/filters/applied-filters/roots/cycle-root.tsx +++ b/web/components/issues/issue-layouts/filters/applied-filters/roots/cycle-root.tsx @@ -13,6 +13,7 @@ export const CycleAppliedFiltersRoot: React.FC = observer(() => { const { project: projectStore, + projectMember: { projectMembers }, cycleIssueFilter: cycleIssueFilterStore, projectState: projectStateStore, } = useMobxStore(); @@ -72,7 +73,7 @@ export const CycleAppliedFiltersRoot: React.FC = observer(() => { handleClearAllFilters={handleClearAllFilters} handleRemoveFilter={handleRemoveFilter} 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() ?? ""]} /> diff --git a/web/components/issues/issue-layouts/filters/applied-filters/roots/module-root.tsx b/web/components/issues/issue-layouts/filters/applied-filters/roots/module-root.tsx index 7875aecd7..6a5cd6944 100644 --- a/web/components/issues/issue-layouts/filters/applied-filters/roots/module-root.tsx +++ b/web/components/issues/issue-layouts/filters/applied-filters/roots/module-root.tsx @@ -12,7 +12,12 @@ export const ModuleAppliedFiltersRoot: React.FC = observer(() => { const router = useRouter(); 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; @@ -69,7 +74,7 @@ export const ModuleAppliedFiltersRoot: React.FC = observer(() => { handleClearAllFilters={handleClearAllFilters} handleRemoveFilter={handleRemoveFilter} 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() ?? ""]} /> diff --git a/web/components/issues/issue-layouts/filters/applied-filters/roots/project-root.tsx b/web/components/issues/issue-layouts/filters/applied-filters/roots/project-root.tsx index acf985051..26f475733 100644 --- a/web/components/issues/issue-layouts/filters/applied-filters/roots/project-root.tsx +++ b/web/components/issues/issue-layouts/filters/applied-filters/roots/project-root.tsx @@ -12,7 +12,12 @@ export const ProjectAppliedFiltersRoot: React.FC = observer(() => { const router = useRouter(); 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; @@ -73,7 +78,7 @@ export const ProjectAppliedFiltersRoot: React.FC = observer(() => { handleClearAllFilters={handleClearAllFilters} handleRemoveFilter={handleRemoveFilter} 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() ?? ""]} /> diff --git a/web/components/issues/issue-layouts/filters/applied-filters/roots/project-view-root.tsx b/web/components/issues/issue-layouts/filters/applied-filters/roots/project-view-root.tsx index baa1ce20d..96a2dab37 100644 --- a/web/components/issues/issue-layouts/filters/applied-filters/roots/project-view-root.tsx +++ b/web/components/issues/issue-layouts/filters/applied-filters/roots/project-view-root.tsx @@ -19,6 +19,7 @@ export const ProjectViewAppliedFiltersRoot: React.FC = observer(() => { const { project: projectStore, + projectMember: { projectMembers }, projectState: projectStateStore, projectViews: projectViewsStore, projectViewFilters: projectViewFiltersStore, @@ -99,7 +100,7 @@ export const ProjectViewAppliedFiltersRoot: React.FC = observer(() => { handleClearAllFilters={handleClearAllFilters} handleRemoveFilter={handleRemoveFilter} 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() ?? ""]} /> {storedFilters && viewDetails && areFiltersDifferent(storedFilters, viewDetails.query_data ?? {}) && ( diff --git a/web/components/issues/issue-layouts/kanban/roots/cycle-root.tsx b/web/components/issues/issue-layouts/kanban/roots/cycle-root.tsx index fdcb430cc..a060ed213 100644 --- a/web/components/issues/issue-layouts/kanban/roots/cycle-root.tsx +++ b/web/components/issues/issue-layouts/kanban/roots/cycle-root.tsx @@ -9,8 +9,6 @@ import { KanBanSwimLanes } from "../swimlanes"; import { KanBan } from "../default"; import { CycleIssueQuickActions } from "components/issues"; import { Spinner } from "@plane/ui"; -// helpers -import { orderArrayBy } from "helpers/array.helper"; // types import { IIssue } from "types"; // constants @@ -25,13 +23,13 @@ export const CycleKanBanLayout: React.FC = observer(() => { // store const { project: projectStore, + projectMember: { projectMembers }, projectState: projectStateStore, cycleIssue: cycleIssueStore, issueFilter: issueFilterStore, cycleIssueKanBanView: cycleIssueKanBanViewStore, issueDetail: issueDetailStore, } = useMobxStore(); - const { currentProjectDetails } = projectStore; const issues = cycleIssueStore?.getIssues; @@ -51,9 +49,9 @@ export const CycleKanBanLayout: React.FC = observer(() => { const [isDragStarted, setIsDragStarted] = useState(false); - const onDragStart = () => { - setIsDragStarted(true); - }; + // const onDragStart = () => { + // setIsDragStarted(true); + // }; const onDragEnd = (result: any) => { setIsDragStarted(false); @@ -102,13 +100,12 @@ export const CycleKanBanLayout: React.FC = observer(() => { const states = projectStateStore?.projectStates || null; const priorities = ISSUE_PRIORITIES || null; const labels = projectStore?.projectLabels || null; - const members = projectStore?.projectMembers || null; const stateGroups = ISSUE_STATE_GROUPS || null; const projects = workspaceSlug ? projectStore?.projects[workspaceSlug.toString()] || null : null; - const estimates = - currentProjectDetails?.estimate !== null - ? projectStore.projectEstimates?.find((e) => e.id === currentProjectDetails?.estimate) || null - : null; + // const estimates = + // currentProjectDetails?.estimate !== null + // ? projectStore.projectEstimates?.find((e) => e.id === currentProjectDetails?.estimate) || null + // : null; return ( <> @@ -141,7 +138,7 @@ export const CycleKanBanLayout: React.FC = observer(() => { stateGroups={stateGroups} priorities={priorities} labels={labels} - members={members?.map((m) => m.member) ?? null} + members={projectMembers?.map((m) => m.member) ?? null} projects={projects} showEmptyGroup={userDisplayFilters?.show_empty_groups || true} isDragStarted={isDragStarted} @@ -168,7 +165,7 @@ export const CycleKanBanLayout: React.FC = observer(() => { stateGroups={stateGroups} priorities={priorities} labels={labels} - members={members?.map((m) => m.member) ?? null} + members={projectMembers?.map((m) => m.member) ?? null} projects={projects} showEmptyGroup={userDisplayFilters?.show_empty_groups || true} isDragStarted={isDragStarted} diff --git a/web/components/issues/issue-layouts/kanban/roots/module-root.tsx b/web/components/issues/issue-layouts/kanban/roots/module-root.tsx index 07b4159b9..7a25f835c 100644 --- a/web/components/issues/issue-layouts/kanban/roots/module-root.tsx +++ b/web/components/issues/issue-layouts/kanban/roots/module-root.tsx @@ -22,13 +22,13 @@ export const ModuleKanBanLayout: React.FC = observer(() => { // store const { project: projectStore, + projectMember: { projectMembers }, projectState: projectStateStore, moduleIssue: moduleIssueStore, issueFilter: issueFilterStore, moduleIssueKanBanView: moduleIssueKanBanViewStore, issueDetail: issueDetailStore, } = useMobxStore(); - const { currentProjectDetails } = projectStore; const issues = moduleIssueStore?.getIssues; @@ -48,9 +48,9 @@ export const ModuleKanBanLayout: React.FC = observer(() => { const [isDragStarted, setIsDragStarted] = useState(false); - const onDragStart = () => { - setIsDragStarted(true); - }; + // const onDragStart = () => { + // setIsDragStarted(true); + // }; const onDragEnd = (result: any) => { setIsDragStarted(false); @@ -98,13 +98,12 @@ export const ModuleKanBanLayout: React.FC = observer(() => { const states = projectStateStore?.projectStates || null; const priorities = ISSUE_PRIORITIES || null; const labels = projectStore?.projectLabels || null; - const members = projectStore?.projectMembers || null; const stateGroups = ISSUE_STATE_GROUPS || null; const projects = workspaceSlug ? projectStore?.projects[workspaceSlug.toString()] || null : null; - const estimates = - currentProjectDetails?.estimate !== null - ? projectStore.projectEstimates?.find((e) => e.id === currentProjectDetails?.estimate) || null - : null; + // const estimates = + // currentProjectDetails?.estimate !== null + // ? projectStore.projectEstimates?.find((e) => e.id === currentProjectDetails?.estimate) || null + // : null; return ( <> @@ -137,7 +136,7 @@ export const ModuleKanBanLayout: React.FC = observer(() => { stateGroups={stateGroups} priorities={priorities} labels={labels} - members={members?.map((m) => m.member) ?? null} + members={projectMembers?.map((m) => m.member) ?? null} projects={projects} showEmptyGroup={userDisplayFilters?.show_empty_groups || true} isDragStarted={isDragStarted} @@ -164,7 +163,7 @@ export const ModuleKanBanLayout: React.FC = observer(() => { stateGroups={stateGroups} priorities={priorities} labels={labels} - members={members?.map((m) => m.member) ?? null} + members={projectMembers?.map((m) => m.member) ?? null} projects={projects} showEmptyGroup={userDisplayFilters?.show_empty_groups || true} isDragStarted={isDragStarted} diff --git a/web/components/issues/issue-layouts/kanban/roots/profile-issues-root.tsx b/web/components/issues/issue-layouts/kanban/roots/profile-issues-root.tsx index 573863ac1..4682f8e26 100644 --- a/web/components/issues/issue-layouts/kanban/roots/profile-issues-root.tsx +++ b/web/components/issues/issue-layouts/kanban/roots/profile-issues-root.tsx @@ -20,6 +20,7 @@ export const ProfileIssuesKanBanLayout: FC = observer(() => { const { workspace: workspaceStore, project: projectStore, + projectMember: { projectMembers }, projectState: projectStateStore, profileIssues: profileIssuesStore, profileIssueFilters: profileIssueFiltersStore, @@ -48,9 +49,9 @@ export const ProfileIssuesKanBanLayout: FC = observer(() => { const [isDragStarted, setIsDragStarted] = useState(false); - const onDragStart = () => { - setIsDragStarted(true); - }; + // const onDragStart = () => { + // setIsDragStarted(true); + // }; const onDragEnd = (result: any) => { setIsDragStarted(false); @@ -89,7 +90,6 @@ export const ProfileIssuesKanBanLayout: FC = observer(() => { const states = projectStateStore?.projectStates || null; const priorities = ISSUE_PRIORITIES || null; const labels = workspaceStore.workspaceLabels || null; - const members = projectStore?.projectMembers || null; const stateGroups = ISSUE_STATE_GROUPS || null; const projects = projectStore?.workspaceProjects || null; @@ -123,7 +123,7 @@ export const ProfileIssuesKanBanLayout: FC = observer(() => { stateGroups={stateGroups} priorities={priorities} labels={labels} - members={members?.map((m) => m.member) ?? null} + members={projectMembers?.map((m) => m.member) ?? null} projects={projects} showEmptyGroup={userDisplayFilters?.show_empty_groups || true} isDragStarted={isDragStarted} @@ -149,7 +149,7 @@ export const ProfileIssuesKanBanLayout: FC = observer(() => { stateGroups={stateGroups} priorities={priorities} labels={labels} - members={members?.map((m) => m.member) ?? null} + members={projectMembers?.map((m) => m.member) ?? null} projects={projects} showEmptyGroup={userDisplayFilters?.show_empty_groups || true} isDragStarted={isDragStarted} diff --git a/web/components/issues/issue-layouts/kanban/roots/project-root.tsx b/web/components/issues/issue-layouts/kanban/roots/project-root.tsx index e8f36d26e..8f34dee71 100644 --- a/web/components/issues/issue-layouts/kanban/roots/project-root.tsx +++ b/web/components/issues/issue-layouts/kanban/roots/project-root.tsx @@ -22,6 +22,7 @@ export const KanBanLayout: React.FC = observer(() => { const { project: projectStore, + projectMember: { projectMembers }, projectState: projectStateStore, issue: issueStore, issueFilter: issueFilterStore, @@ -92,7 +93,6 @@ export const KanBanLayout: React.FC = observer(() => { const states = projectStateStore?.projectStates || null; const priorities = ISSUE_PRIORITIES || null; const labels = projectStore?.projectLabels || null; - const members = projectStore?.projectMembers || null; const stateGroups = ISSUE_STATE_GROUPS || null; const projects = workspaceSlug ? projectStore?.projects?.[workspaceSlug] || null : null; const estimates = @@ -130,7 +130,7 @@ export const KanBanLayout: React.FC = observer(() => { stateGroups={stateGroups} priorities={priorities} labels={labels} - members={members?.map((m) => m.member) ?? null} + members={projectMembers?.map((m) => m.member) ?? null} projects={projects} enableQuickIssueCreate showEmptyGroup={userDisplayFilters?.show_empty_groups || true} @@ -157,7 +157,7 @@ export const KanBanLayout: React.FC = observer(() => { stateGroups={stateGroups} priorities={priorities} labels={labels} - members={members?.map((m) => m.member) ?? null} + members={projectMembers?.map((m) => m.member) ?? null} projects={projects} showEmptyGroup={userDisplayFilters?.show_empty_groups || true} isDragStarted={isDragStarted} diff --git a/web/components/issues/issue-layouts/kanban/roots/project-view-root.tsx b/web/components/issues/issue-layouts/kanban/roots/project-view-root.tsx index 94eb25839..6751f3145 100644 --- a/web/components/issues/issue-layouts/kanban/roots/project-view-root.tsx +++ b/web/components/issues/issue-layouts/kanban/roots/project-view-root.tsx @@ -15,6 +15,7 @@ export interface IViewKanBanLayout {} export const ProjectViewKanBanLayout: React.FC = observer(() => { const { project: projectStore, + projectMember: { projectMembers }, projectState: projectStateStore, issue: issueStore, issueFilter: issueFilterStore, @@ -56,7 +57,6 @@ export const ProjectViewKanBanLayout: React.FC = observer(() => { const states = projectStateStore?.projectStates || null; const priorities = ISSUE_PRIORITIES || null; const labels = projectStore?.projectLabels || null; - const members = projectStore?.projectMembers || null; const stateGroups = ISSUE_STATE_GROUPS || null; const projects = projectStateStore?.projectStates || null; const estimates = null; diff --git a/web/components/issues/issue-layouts/list/roots/archived-issue-root.tsx b/web/components/issues/issue-layouts/list/roots/archived-issue-root.tsx index 253741f9a..396f7b508 100644 --- a/web/components/issues/issue-layouts/list/roots/archived-issue-root.tsx +++ b/web/components/issues/issue-layouts/list/roots/archived-issue-root.tsx @@ -19,6 +19,7 @@ export const ArchivedIssueListLayout: FC = observer(() => { const { project: projectStore, + projectMember: { projectMembers }, projectState: projectStateStore, archivedIssues: archivedIssueStore, archivedIssueFilters: archivedIssueFiltersStore, @@ -42,7 +43,6 @@ export const ArchivedIssueListLayout: FC = observer(() => { const states = projectStateStore?.projectStates || null; const priorities = ISSUE_PRIORITIES || null; const labels = projectStore?.projectLabels || null; - const members = projectStore?.projectMembers || null; const stateGroups = ISSUE_STATE_GROUPS || null; const projects = workspaceSlug ? projectStore?.projects[workspaceSlug.toString()] || null : null; const estimates = @@ -65,7 +65,7 @@ export const ArchivedIssueListLayout: FC = observer(() => { stateGroups={stateGroups} priorities={priorities} labels={labels} - members={members?.map((m) => m.member) ?? null} + members={projectMembers?.map((m) => m.member) ?? null} projects={projects} estimates={estimates?.points ? orderArrayBy(estimates.points, "key") : null} /> diff --git a/web/components/issues/issue-layouts/list/roots/cycle-root.tsx b/web/components/issues/issue-layouts/list/roots/cycle-root.tsx index 1015f1784..608607ab8 100644 --- a/web/components/issues/issue-layouts/list/roots/cycle-root.tsx +++ b/web/components/issues/issue-layouts/list/roots/cycle-root.tsx @@ -21,6 +21,7 @@ export const CycleListLayout: React.FC = observer(() => { // store const { project: projectStore, + projectMember: { projectMembers }, projectState: projectStateStore, issueFilter: issueFilterStore, cycleIssue: cycleIssueStore, @@ -59,7 +60,6 @@ export const CycleListLayout: React.FC = observer(() => { const states = projectStateStore?.projectStates || null; const priorities = ISSUE_PRIORITIES || null; const labels = projectStore?.projectLabels || null; - const members = projectStore?.projectMembers || null; const stateGroups = ISSUE_STATE_GROUPS || null; const projects = workspaceSlug ? projectStore?.projects[workspaceSlug.toString()] || null : null; const estimates = @@ -86,7 +86,7 @@ export const CycleListLayout: React.FC = observer(() => { stateGroups={stateGroups} priorities={priorities} labels={labels} - members={members?.map((m) => m.member) ?? null} + members={projectMembers?.map((m) => m.member) ?? null} projects={projects} estimates={estimates?.points ? orderArrayBy(estimates.points, "key") : null} /> diff --git a/web/components/issues/issue-layouts/list/roots/module-root.tsx b/web/components/issues/issue-layouts/list/roots/module-root.tsx index 8a017e3df..1619112f1 100644 --- a/web/components/issues/issue-layouts/list/roots/module-root.tsx +++ b/web/components/issues/issue-layouts/list/roots/module-root.tsx @@ -21,6 +21,7 @@ export const ModuleListLayout: React.FC = observer(() => { const { project: projectStore, + projectMember: { projectMembers }, projectState: projectStateStore, issueFilter: issueFilterStore, moduleIssue: moduleIssueStore, @@ -59,7 +60,6 @@ export const ModuleListLayout: React.FC = observer(() => { const states = projectStateStore?.projectStates || null; const priorities = ISSUE_PRIORITIES || null; const labels = projectStore?.projectLabels || null; - const members = projectStore?.projectMembers || null; const stateGroups = ISSUE_STATE_GROUPS || null; const projects = workspaceSlug ? projectStore?.projects[workspaceSlug.toString()] || null : null; const estimates = @@ -86,7 +86,7 @@ export const ModuleListLayout: React.FC = observer(() => { stateGroups={stateGroups} priorities={priorities} labels={labels} - members={members?.map((m) => m.member) ?? null} + members={projectMembers?.map((m) => m.member) ?? null} projects={projects} estimates={estimates?.points ? orderArrayBy(estimates.points, "key") : null} /> diff --git a/web/components/issues/issue-layouts/list/roots/profile-issues-root.tsx b/web/components/issues/issue-layouts/list/roots/profile-issues-root.tsx index 30683572f..bfb727843 100644 --- a/web/components/issues/issue-layouts/list/roots/profile-issues-root.tsx +++ b/web/components/issues/issue-layouts/list/roots/profile-issues-root.tsx @@ -18,6 +18,7 @@ export const ProfileIssuesListLayout: FC = observer(() => { workspace: workspaceStore, projectState: projectStateStore, project: projectStore, + projectMember: { projectMembers }, profileIssueFilters: profileIssueFiltersStore, profileIssues: profileIssuesStore, issueDetail: issueDetailStore, @@ -48,7 +49,6 @@ export const ProfileIssuesListLayout: FC = observer(() => { const states = projectStateStore?.projectStates || null; const priorities = ISSUE_PRIORITIES || null; const labels = workspaceStore.workspaceLabels || null; - const members = projectStore?.projectMembers || null; const stateGroups = ISSUE_STATE_GROUPS || null; const projects = projectStore?.workspaceProjects || null; @@ -70,7 +70,7 @@ export const ProfileIssuesListLayout: FC = observer(() => { stateGroups={stateGroups} priorities={priorities} labels={labels} - members={members?.map((m) => m.member) ?? null} + members={projectMembers?.map((m) => m.member) ?? null} projects={projects} estimates={null} /> diff --git a/web/components/issues/issue-layouts/list/roots/project-root.tsx b/web/components/issues/issue-layouts/list/roots/project-root.tsx index eb1771899..beec14008 100644 --- a/web/components/issues/issue-layouts/list/roots/project-root.tsx +++ b/web/components/issues/issue-layouts/list/roots/project-root.tsx @@ -20,6 +20,7 @@ export const ListLayout: FC = observer(() => { // store const { project: projectStore, + projectMember: { projectMembers }, projectState: projectStateStore, issue: issueStore, issueDetail: issueDetailStore, @@ -49,7 +50,6 @@ export const ListLayout: FC = observer(() => { const states = projectStateStore?.projectStates || null; const priorities = ISSUE_PRIORITIES || null; const labels = projectStore?.projectLabels || null; - const members = projectStore?.projectMembers || null; const stateGroups = ISSUE_STATE_GROUPS || null; const projects = workspaceSlug ? projectStore?.projects[workspaceSlug.toString()] || null : null; const estimates = @@ -81,7 +81,7 @@ export const ListLayout: FC = observer(() => { stateGroups={stateGroups} priorities={priorities} labels={labels} - members={members?.map((m) => m.member) ?? null} + members={projectMembers?.map((m) => m.member) ?? null} projects={projects} enableQuickIssueCreate estimates={estimates?.points ? orderArrayBy(estimates.points, "key") : null} diff --git a/web/components/issues/issue-layouts/list/roots/project-view-root.tsx b/web/components/issues/issue-layouts/list/roots/project-view-root.tsx index c98df7ae2..a5dc76352 100644 --- a/web/components/issues/issue-layouts/list/roots/project-view-root.tsx +++ b/web/components/issues/issue-layouts/list/roots/project-view-root.tsx @@ -31,7 +31,6 @@ export const ProjectViewListLayout: React.FC = observer(() => { const states = projectStateStore?.projectStates || null; const priorities = ISSUE_PRIORITIES || null; const labels = projectStore?.projectLabels || null; - const members = projectStore?.projectMembers || null; const stateGroups = ISSUE_STATE_GROUPS || null; const projects = projectStateStore?.projectStates || null; const estimates = null; diff --git a/web/components/issues/issue-layouts/properties/assignee.tsx b/web/components/issues/issue-layouts/properties/assignee.tsx index c3d550055..f7a4f322b 100644 --- a/web/components/issues/issue-layouts/properties/assignee.tsx +++ b/web/components/issues/issue-layouts/properties/assignee.tsx @@ -52,13 +52,13 @@ export const IssuePropertyAssignee: React.FC = observer( const [popperElement, setPopperElement] = useState(null); const [isLoading, setIsLoading] = useState(false); - const fetchProjectMembers = () => { - setIsLoading(true); - if (workspaceSlug && projectId) - workspaceSlug && - projectId && - projectStore.fetchProjectMembers(workspaceSlug, projectId).then(() => setIsLoading(false)); - }; + // const fetchProjectMembers = () => { + // setIsLoading(true); + // if (workspaceSlug && projectId) + // workspaceSlug && + // projectId && + // projectStore.fetchProjectMembers(workspaceSlug, projectId).then(() => setIsLoading(false)); + // }; const getWorkspaceMembers = () => { setIsLoading(true); diff --git a/web/components/issues/issue-layouts/spreadsheet/roots/cycle-root.tsx b/web/components/issues/issue-layouts/spreadsheet/roots/cycle-root.tsx index dbe01878f..f8f400c95 100644 --- a/web/components/issues/issue-layouts/spreadsheet/roots/cycle-root.tsx +++ b/web/components/issues/issue-layouts/spreadsheet/roots/cycle-root.tsx @@ -20,6 +20,7 @@ export const CycleSpreadsheetLayout: React.FC = observer(() => { cycleIssue: cycleIssueStore, issueDetail: issueDetailStore, project: projectStore, + projectMember: { projectMembers }, projectState: projectStateStore, } = useMobxStore(); @@ -59,7 +60,7 @@ export const CycleSpreadsheetLayout: React.FC = observer(() => { displayFilters={issueFilterStore.userDisplayFilters} handleDisplayFilterUpdate={handleDisplayFiltersUpdate} 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} states={projectId ? projectStateStore.states?.[projectId.toString()] : undefined} handleIssueAction={() => {}} diff --git a/web/components/issues/issue-layouts/spreadsheet/roots/module-root.tsx b/web/components/issues/issue-layouts/spreadsheet/roots/module-root.tsx index 0ced88d14..78cd095fa 100644 --- a/web/components/issues/issue-layouts/spreadsheet/roots/module-root.tsx +++ b/web/components/issues/issue-layouts/spreadsheet/roots/module-root.tsx @@ -20,6 +20,7 @@ export const ModuleSpreadsheetLayout: React.FC = observer(() => { moduleIssue: moduleIssueStore, issueDetail: issueDetailStore, project: projectStore, + projectMember: { projectMembers }, projectState: projectStateStore, } = useMobxStore(); @@ -59,7 +60,7 @@ export const ModuleSpreadsheetLayout: React.FC = observer(() => { displayFilters={issueFilterStore.userDisplayFilters} handleDisplayFilterUpdate={handleDisplayFiltersUpdate} 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} states={projectId ? projectStateStore.states?.[projectId.toString()] : undefined} handleIssueAction={() => {}} diff --git a/web/components/issues/issue-layouts/spreadsheet/roots/project-root.tsx b/web/components/issues/issue-layouts/spreadsheet/roots/project-root.tsx index 1a6e4243d..be9c9ea5c 100644 --- a/web/components/issues/issue-layouts/spreadsheet/roots/project-root.tsx +++ b/web/components/issues/issue-layouts/spreadsheet/roots/project-root.tsx @@ -20,6 +20,7 @@ export const ProjectSpreadsheetLayout: React.FC = observer(() => { issueFilter: issueFilterStore, issueDetail: issueDetailStore, project: projectStore, + projectMember: { projectMembers }, projectState: projectStateStore, user: userStore, } = useMobxStore(); @@ -61,7 +62,7 @@ export const ProjectSpreadsheetLayout: React.FC = observer(() => { displayFilters={issueFilterStore.userDisplayFilters} handleDisplayFilterUpdate={handleDisplayFiltersUpdate} 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} states={projectId ? projectStateStore.states?.[projectId.toString()] : undefined} handleIssueAction={() => {}} diff --git a/web/components/issues/issue-layouts/spreadsheet/roots/project-view-root.tsx b/web/components/issues/issue-layouts/spreadsheet/roots/project-view-root.tsx index 3b4d92b58..3e6847b21 100644 --- a/web/components/issues/issue-layouts/spreadsheet/roots/project-view-root.tsx +++ b/web/components/issues/issue-layouts/spreadsheet/roots/project-view-root.tsx @@ -20,6 +20,7 @@ export const ProjectViewSpreadsheetLayout: React.FC = observer(() => { projectViewIssues: projectViewIssueStore, issueDetail: issueDetailStore, project: projectStore, + projectMember: { projectMembers }, projectState: projectStateStore, } = useMobxStore(); @@ -59,7 +60,7 @@ export const ProjectViewSpreadsheetLayout: React.FC = observer(() => { displayFilters={issueFilterStore.userDisplayFilters} handleDisplayFilterUpdate={handleDisplayFiltersUpdate} 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} states={projectId ? projectStateStore.states?.[projectId.toString()] : undefined} handleIssueAction={() => {}} diff --git a/web/components/issues/select/assignee.tsx b/web/components/issues/select/assignee.tsx index 8778c6c62..470452276 100644 --- a/web/components/issues/select/assignee.tsx +++ b/web/components/issues/select/assignee.tsx @@ -1,7 +1,7 @@ import { useRouter } from "next/router"; import useSWR from "swr"; // services -import { ProjectService } from "services/project"; +import { ProjectMemberService } from "services/project"; // ui import { Avatar, AvatarGroup, CustomSearchSelect, UserGroupIcon } from "@plane/ui"; // fetch-keys @@ -13,7 +13,7 @@ export type Props = { onChange: (value: string[]) => void; }; -const projectService = new ProjectService(); +const projectMemberService = new ProjectMemberService(); export const IssueAssigneeSelect: React.FC = ({ projectId, value = [], onChange }) => { const router = useRouter(); @@ -22,7 +22,7 @@ export const IssueAssigneeSelect: React.FC = ({ projectId, value = [], on const { data: members } = useSWR( workspaceSlug && projectId ? PROJECT_MEMBERS(projectId as string) : null, workspaceSlug && projectId - ? () => projectService.fetchProjectMembers(workspaceSlug as string, projectId as string) + ? () => projectMemberService.fetchProjectMembers(workspaceSlug as string, projectId as string) : null ); diff --git a/web/components/issues/sidebar-select/assignee.tsx b/web/components/issues/sidebar-select/assignee.tsx index 4fdb71fa0..a7f698d9f 100644 --- a/web/components/issues/sidebar-select/assignee.tsx +++ b/web/components/issues/sidebar-select/assignee.tsx @@ -2,7 +2,7 @@ import React from "react"; import { useRouter } from "next/router"; import useSWR from "swr"; // services -import { ProjectService } from "services/project"; +import { ProjectMemberService } from "services/project"; // ui import { Avatar, AvatarGroup, CustomSearchSelect } from "@plane/ui"; // fetch-keys @@ -15,7 +15,7 @@ type Props = { }; // services -const projectService = new ProjectService(); +const projectMemberService = new ProjectMemberService(); export const SidebarAssigneeSelect: React.FC = ({ value, onChange, disabled = false }) => { const router = useRouter(); @@ -24,7 +24,7 @@ export const SidebarAssigneeSelect: React.FC = ({ value, onChange, disabl const { data: members } = useSWR( workspaceSlug && projectId ? PROJECT_MEMBERS(projectId as string) : null, workspaceSlug && projectId - ? () => projectService.fetchProjectMembers(workspaceSlug as string, projectId as string) + ? () => projectMemberService.fetchProjectMembers(workspaceSlug as string, projectId as string) : null ); diff --git a/web/components/modules/select/lead.tsx b/web/components/modules/select/lead.tsx index 69ba71bf9..84da54748 100644 --- a/web/components/modules/select/lead.tsx +++ b/web/components/modules/select/lead.tsx @@ -2,7 +2,7 @@ import React from "react"; import { useRouter } from "next/router"; import useSWR from "swr"; // services -import { ProjectService } from "services/project"; +import { ProjectMemberService } from "services/project"; // ui import { Avatar, CustomSearchSelect } from "@plane/ui"; // icons @@ -15,7 +15,7 @@ type Props = { onChange: () => void; }; -const projectService = new ProjectService(); +const projectMemberService = new ProjectMemberService(); export const ModuleLeadSelect: React.FC = ({ value, onChange }) => { const router = useRouter(); @@ -24,7 +24,7 @@ export const ModuleLeadSelect: React.FC = ({ value, onChange }) => { const { data: members } = useSWR( workspaceSlug && projectId ? PROJECT_MEMBERS(projectId as string) : null, workspaceSlug && projectId - ? () => projectService.fetchProjectMembers(workspaceSlug as string, projectId as string) + ? () => projectMemberService.fetchProjectMembers(workspaceSlug as string, projectId as string) : null ); diff --git a/web/components/modules/select/members.tsx b/web/components/modules/select/members.tsx index 17b80a471..212b51cac 100644 --- a/web/components/modules/select/members.tsx +++ b/web/components/modules/select/members.tsx @@ -2,7 +2,7 @@ import React from "react"; import { useRouter } from "next/router"; import useSWR from "swr"; // services -import { ProjectService } from "services/project"; +import { ProjectMemberService } from "services/project"; // ui import { Avatar, AvatarGroup, CustomSearchSelect, UserGroupIcon } from "@plane/ui"; // fetch-keys @@ -13,7 +13,7 @@ type Props = { onChange: () => void; }; -const projectService = new ProjectService(); +const projectMemberService = new ProjectMemberService(); export const ModuleMembersSelect: React.FC = ({ value, onChange }) => { const router = useRouter(); @@ -22,7 +22,7 @@ export const ModuleMembersSelect: React.FC = ({ value, onChange }) => { const { data: members } = useSWR( workspaceSlug && projectId ? PROJECT_MEMBERS(projectId as string) : null, workspaceSlug && projectId - ? () => projectService.fetchProjectMembers(workspaceSlug as string, projectId as string) + ? () => projectMemberService.fetchProjectMembers(workspaceSlug as string, projectId as string) : null ); const options = members?.map((member) => ({ diff --git a/web/components/modules/sidebar-select/select-lead.tsx b/web/components/modules/sidebar-select/select-lead.tsx index 5d7e5f419..a751ce015 100644 --- a/web/components/modules/sidebar-select/select-lead.tsx +++ b/web/components/modules/sidebar-select/select-lead.tsx @@ -2,7 +2,7 @@ import { FC } from "react"; import { useRouter } from "next/router"; import useSWR from "swr"; // services -import { ProjectService } from "services/project"; +import { ProjectMemberService } from "services/project"; // ui import { Avatar, CustomSearchSelect } from "@plane/ui"; // icons @@ -15,7 +15,7 @@ type Props = { onChange: (val: string) => void; }; -const projectService = new ProjectService(); +const projectMemberService = new ProjectMemberService(); export const SidebarLeadSelect: FC = (props) => { const { value, onChange } = props; @@ -26,7 +26,7 @@ export const SidebarLeadSelect: FC = (props) => { const { data: members } = useSWR( workspaceSlug && projectId ? PROJECT_MEMBERS(projectId as string) : null, workspaceSlug && projectId - ? () => projectService.fetchProjectMembers(workspaceSlug as string, projectId as string) + ? () => projectMemberService.fetchProjectMembers(workspaceSlug as string, projectId as string) : null ); diff --git a/web/components/modules/sidebar-select/select-members.tsx b/web/components/modules/sidebar-select/select-members.tsx index 98a57692c..cbb3c3bda 100644 --- a/web/components/modules/sidebar-select/select-members.tsx +++ b/web/components/modules/sidebar-select/select-members.tsx @@ -2,7 +2,7 @@ import React from "react"; import { useRouter } from "next/router"; import useSWR from "swr"; // services -import { ProjectService } from "services/project"; +import { ProjectMemberService } from "services/project"; // ui import { Avatar, AvatarGroup, CustomSearchSelect, UserGroupIcon } from "@plane/ui"; // icons @@ -16,7 +16,7 @@ type Props = { }; // services -const projectService = new ProjectService(); +const projectMemberService = new ProjectMemberService(); export const SidebarMembersSelect: React.FC = ({ value, onChange }) => { const router = useRouter(); @@ -25,7 +25,7 @@ export const SidebarMembersSelect: React.FC = ({ value, onChange }) => { const { data: members } = useSWR( workspaceSlug && projectId ? PROJECT_MEMBERS(projectId as string) : null, workspaceSlug && projectId - ? () => projectService.fetchProjectMembers(workspaceSlug as string, projectId as string) + ? () => projectMemberService.fetchProjectMembers(workspaceSlug as string, projectId as string) : null ); diff --git a/web/components/pages/pages-view.tsx b/web/components/pages/pages-view.tsx index 5aca1de1b..3154f7981 100644 --- a/web/components/pages/pages-view.tsx +++ b/web/components/pages/pages-view.tsx @@ -7,7 +7,7 @@ import { Plus } from "lucide-react"; import { useMobxStore } from "lib/mobx/store-provider"; // services import { PageService } from "services/page.service"; -import { ProjectService } from "services/project"; +import { ProjectMemberService } from "services/project"; // hooks import useToast from "hooks/use-toast"; // components @@ -34,7 +34,7 @@ type Props = { // services const pageService = new PageService(); -const projectService = new ProjectService(); +const projectMemberService = new ProjectMemberService(); export const PagesView: React.FC = observer(({ pages, viewType }) => { // states @@ -55,7 +55,7 @@ export const PagesView: React.FC = observer(({ pages, viewType }) => { const { data: people } = useSWR( workspaceSlug && projectId ? PROJECT_MEMBERS(projectId.toString()) : null, workspaceSlug && projectId - ? () => projectService.fetchProjectMembers(workspaceSlug.toString(), projectId.toString()) + ? () => projectMemberService.fetchProjectMembers(workspaceSlug.toString(), projectId.toString()) : null ); diff --git a/web/components/project/member-list-item.tsx b/web/components/project/member-list-item.tsx index f6b0e833b..84d29079c 100644 --- a/web/components/project/member-list-item.tsx +++ b/web/components/project/member-list-item.tsx @@ -4,8 +4,6 @@ import Link from "next/link"; import useSWR, { mutate } from "swr"; import { observer } from "mobx-react-lite"; import { useMobxStore } from "lib/mobx/store-provider"; -// services -import { ProjectInvitationService } from "services/project"; // hooks import useToast from "hooks/use-toast"; // components @@ -16,11 +14,9 @@ import { CustomSelect, Tooltip } from "@plane/ui"; import { ChevronDown, XCircle } from "lucide-react"; // constants import { ROLE } from "constants/workspace"; +// types import { TUserProjectRole } from "types"; -// services -const projectInvitationService = new ProjectInvitationService(); - type Props = { member: any; }; @@ -34,21 +30,27 @@ export const ProjectMemberListItem: React.FC = observer((props) => { const [selectedRemoveMember, setSelectedRemoveMember] = useState(null); const [selectedInviteRemoveMember, setSelectedInviteRemoveMember] = useState(null); // store - const { user: userStore, project: projectStore } = useMobxStore(); + const { + user: userStore, + projectMember: { + projectMembers, + fetchProjectMembers, + removeMemberFromProject, + updateMember, + deleteProjectInvitation, + }, + } = useMobxStore(); // hooks const { setToastAlert } = useToast(); // fetching project members useSWR( workspaceSlug && projectId ? `PROJECT_MEMBERS_${projectId.toString().toUpperCase()}` : null, - workspaceSlug && projectId - ? () => projectStore.fetchProjectMembers(workspaceSlug.toString(), projectId.toString()) - : null + workspaceSlug && projectId ? () => fetchProjectMembers(workspaceSlug.toString(), projectId.toString()) : null ); // derived values const user = userStore.currentUser; const { currentProjectMemberInfo, currentProjectRole } = userStore; const isAdmin = currentProjectRole === 20; - const projectMembers = projectStore.members?.[projectId?.toString()!]; const currentUser = projectMembers?.find((item) => item.member.id === user?.id); return ( @@ -65,15 +67,11 @@ export const ProjectMemberListItem: React.FC = observer((props) => { // if the user is a member if (selectedRemoveMember) { - await projectStore.removeMemberFromProject( - workspaceSlug.toString(), - projectId.toString(), - selectedRemoveMember.id - ); + await removeMemberFromProject(workspaceSlug.toString(), projectId.toString(), selectedRemoveMember.id); } // if the user is an invite if (selectedInviteRemoveMember) { - await projectInvitationService.deleteProjectInvitation( + await deleteProjectInvitation( workspaceSlug.toString(), projectId.toString(), selectedInviteRemoveMember.id @@ -150,20 +148,18 @@ export const ProjectMemberListItem: React.FC = observer((props) => { onChange={(value: TUserProjectRole | undefined) => { if (!workspaceSlug || !projectId) return; - projectStore - .updateMember(workspaceSlug.toString(), projectId.toString(), member.id, { - role: value, - }) - .catch((err) => { - const error = err.error; - const errorString = Array.isArray(error) ? error[0] : error; + updateMember(workspaceSlug.toString(), projectId.toString(), member.id, { + role: value, + }).catch((err) => { + const error = err.error; + const errorString = Array.isArray(error) ? error[0] : error; - setToastAlert({ - type: "error", - title: "Error!", - message: errorString ?? "An error occurred while updating member role. Please try again.", - }); + setToastAlert({ + type: "error", + title: "Error!", + message: errorString ?? "An error occurred while updating member role. Please try again.", }); + }); }} disabled={ member.memberId === user?.id || diff --git a/web/components/project/member-list.tsx b/web/components/project/member-list.tsx index e24149028..ba2a0198b 100644 --- a/web/components/project/member-list.tsx +++ b/web/components/project/member-list.tsx @@ -4,7 +4,7 @@ import useSWR, { mutate } from "swr"; import { observer } from "mobx-react-lite"; import { useMobxStore } from "lib/mobx/store-provider"; // services -import { ProjectInvitationService } from "services/project"; +import { ProjectMemberService } from "services/project"; // hooks import useUser from "hooks/use-user"; // components @@ -15,7 +15,7 @@ import { Button, Loader } from "@plane/ui"; import { Search } from "lucide-react"; // services -const projectInvitationService = new ProjectInvitationService(); +const projectInvitationService = new ProjectMemberService(); export const ProjectMemberList: React.FC = observer(() => { // router @@ -23,7 +23,10 @@ export const ProjectMemberList: React.FC = observer(() => { const { workspaceSlug, projectId } = router.query; // store - const { project: projectStore } = useMobxStore(); + const { + project: projectStore, + projectMember: { projectMembers, fetchProjectMembers }, + } = useMobxStore(); // states const [inviteModal, setInviteModal] = useState(false); @@ -39,7 +42,6 @@ export const ProjectMemberList: React.FC = observer(() => { ); // derived values - const projectMembers = projectStore.projectMembers; const members = [ ...(projectMembers?.map((item) => ({ @@ -83,7 +85,7 @@ export const ProjectMemberList: React.FC = observer(() => { user={user} onSuccess={() => { mutate(`PROJECT_INVITATIONS_${projectId?.toString()}`); - projectStore.fetchProjectMembers(workspaceSlug?.toString()!, projectId?.toString()!); + fetchProjectMembers(workspaceSlug?.toString()!, projectId?.toString()!); }} /> diff --git a/web/components/project/member-select.tsx b/web/components/project/member-select.tsx index b7d011236..f264a2645 100644 --- a/web/components/project/member-select.tsx +++ b/web/components/project/member-select.tsx @@ -16,24 +16,20 @@ type Props = { export const MemberSelect: React.FC = observer((props) => { const { value, onChange, isDisabled = false } = props; - // router const router = useRouter(); const { workspaceSlug, projectId } = router.query; - // store - const { project: projectStore } = useMobxStore(); + const { + projectMember: { fetchProjectMembers, projectMembers }, + } = useMobxStore(); useSWR( workspaceSlug && projectId ? `PROJECT_MEMBERS_${projectId.toString().toUpperCase()}` : null, - workspaceSlug && projectId - ? () => projectStore.fetchProjectMembers(workspaceSlug.toString(), projectId.toString()) - : null + workspaceSlug && projectId ? () => fetchProjectMembers(workspaceSlug.toString(), projectId.toString()) : null ); - const members = projectStore.members?.[projectId?.toString()!]; - - const options = members?.map((member) => ({ + const options = projectMembers?.map((member) => ({ value: member.member.id, query: member.member.display_name, content: ( @@ -44,7 +40,7 @@ export const MemberSelect: React.FC = observer((props) => { ), })); - const selectedOption = members?.find((m) => m.member.id === value)?.member; + const selectedOption = projectMembers?.find((m) => m.member.id === value)?.member; return ( = observer((props) => { @@ -90,7 +90,7 @@ export const SendProjectInvitationModal: React.FC = observer((props) => { const payload = { ...formData }; - await projectService + await projectMemberService .bulkAddMembersToProject(workspaceSlug.toString(), projectId.toString(), payload, user) .then(() => { setIsOpen(false); diff --git a/web/components/views/form.tsx b/web/components/views/form.tsx index c448726d4..b7f91a467 100644 --- a/web/components/views/form.tsx +++ b/web/components/views/form.tsx @@ -26,7 +26,11 @@ const defaultValues: Partial = { }; export const ProjectViewForm: React.FC = observer(({ handleFormSubmit, handleClose, data, preLoadedData }) => { - const { project: projectStore, projectState: projectStateStore } = useMobxStore(); + const { + project: projectStore, + projectState: projectStateStore, + projectMember: { projectMembers }, + } = useMobxStore(); const { control, @@ -137,7 +141,7 @@ export const ProjectViewForm: React.FC = observer(({ handleFormSubmit, ha }} layoutDisplayFiltersOptions={ISSUE_DISPLAY_FILTERS_BY_LAYOUT.issues.list} labels={projectStore.projectLabels ?? undefined} - members={projectStore.projectMembers?.map((m) => m.member) ?? undefined} + members={projectMembers?.map((m) => m.member) ?? undefined} states={projectStateStore.projectStates ?? undefined} /> @@ -151,7 +155,7 @@ export const ProjectViewForm: React.FC = observer(({ handleFormSubmit, ha handleClearAllFilters={clearAllFilters} handleRemoveFilter={() => {}} labels={projectStore.projectLabels ?? undefined} - members={projectStore.projectMembers?.map((m) => m.member) ?? undefined} + members={projectMembers?.map((m) => m.member) ?? undefined} states={projectStateStore.projectStates ?? undefined} /> diff --git a/web/contexts/issue-view.context.tsx b/web/contexts/issue-view.context.tsx index 7807523e4..c64dcf194 100644 --- a/web/contexts/issue-view.context.tsx +++ b/web/contexts/issue-view.context.tsx @@ -4,7 +4,7 @@ import useSWR, { mutate } from "swr"; // components import ToastAlert from "components/toast-alert"; // services -import { ProjectService } from "services/project"; +import { ProjectService, ProjectMemberService } from "services/project"; import { CycleService } from "services/cycle.service"; import { ModuleService } from "services/module.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"; const projectService = new ProjectService(); +const projectMemberService = new ProjectMemberService(); const cycleService = new CycleService(); const moduleService = new ModuleService(); const viewService = new ViewService(); @@ -218,7 +219,7 @@ export const IssueViewContextProvider: React.FC<{ children: React.ReactNode }> = const { data: myViewProps, mutate: mutateMyViewProps } = useSWR( workspaceSlug && projectId ? USER_PROJECT_VIEW(projectId as string) : null, workspaceSlug && projectId - ? () => projectService.projectMemberMe(workspaceSlug as string, projectId as string) + ? () => projectMemberService.projectMemberMe(workspaceSlug as string, projectId as string) : null ); diff --git a/web/layouts/auth-layout/project-wrapper.tsx b/web/layouts/auth-layout/project-wrapper.tsx index 18dfe1254..225e92f2a 100644 --- a/web/layouts/auth-layout/project-wrapper.tsx +++ b/web/layouts/auth-layout/project-wrapper.tsx @@ -20,7 +20,8 @@ export const ProjectAuthWrapper: FC = observer((props) => { // store const { user: { fetchUserProjectInfo, projectMemberInfo, hasPermissionToProject }, - project: { fetchProjectDetails, fetchProjectLabels, fetchProjectMembers, fetchProjectEstimates, workspaceProjects }, + project: { fetchProjectDetails, fetchProjectLabels, fetchProjectEstimates, workspaceProjects }, + projectMember: { fetchProjectMembers }, projectState: { fetchProjectStates }, cycle: { fetchCycles }, module: { fetchModules }, diff --git a/web/pages/[workspaceSlug]/projects/[projectId]/pages/[pageId].tsx b/web/pages/[workspaceSlug]/projects/[projectId]/pages/[pageId].tsx index ade06b36a..40391234d 100644 --- a/web/pages/[workspaceSlug]/projects/[projectId]/pages/[pageId].tsx +++ b/web/pages/[workspaceSlug]/projects/[projectId]/pages/[pageId].tsx @@ -6,7 +6,7 @@ import { Popover, Transition } from "@headlessui/react"; import { TwitterPicker } from "react-color"; import { DragDropContext, DropResult } from "@hello-pangea/dnd"; // services -import { ProjectService } from "services/project"; +import { ProjectService, ProjectMemberService } from "services/project"; import { PageService } from "services/page.service"; import { IssueLabelService } from "services/issue"; // hooks @@ -45,6 +45,7 @@ import { // services const projectService = new ProjectService(); +const projectMemberService = new ProjectMemberService(); const pageService = new PageService(); const issueLabelService = new IssueLabelService(); @@ -95,7 +96,7 @@ const PageDetailsPage: NextPageWithLayout = () => { const { data: memberDetails } = useSWR( workspaceSlug && projectId ? USER_PROJECT_VIEW(projectId.toString()) : null, workspaceSlug && projectId - ? () => projectService.projectMemberMe(workspaceSlug.toString(), projectId.toString()) + ? () => projectMemberService.projectMemberMe(workspaceSlug.toString(), projectId.toString()) : null ); diff --git a/web/pages/[workspaceSlug]/projects/[projectId]/settings/automations.tsx b/web/pages/[workspaceSlug]/projects/[projectId]/settings/automations.tsx index 01068e469..db070d6c6 100644 --- a/web/pages/[workspaceSlug]/projects/[projectId]/settings/automations.tsx +++ b/web/pages/[workspaceSlug]/projects/[projectId]/settings/automations.tsx @@ -2,7 +2,7 @@ import React, { ReactElement } from "react"; import { useRouter } from "next/router"; import useSWR from "swr"; // services -import { ProjectService } from "services/project"; +import { ProjectService, ProjectMemberService } from "services/project"; // layouts import { AppLayout } from "layouts/app-layout"; import { ProjectSettingLayout } from "layouts/settings-layout"; @@ -21,6 +21,7 @@ import { USER_PROJECT_VIEW } from "constants/fetch-keys"; // services const projectService = new ProjectService(); +const projectMemberService = new ProjectMemberService(); const AutomationSettingsPage: NextPageWithLayout = () => { const router = useRouter(); @@ -34,7 +35,7 @@ const AutomationSettingsPage: NextPageWithLayout = () => { const { data: memberDetails } = useSWR( workspaceSlug && projectId ? USER_PROJECT_VIEW(projectId.toString()) : null, workspaceSlug && projectId - ? () => projectService.projectMemberMe(workspaceSlug.toString(), projectId.toString()) + ? () => projectMemberService.projectMemberMe(workspaceSlug.toString(), projectId.toString()) : null ); diff --git a/web/services/project/index.ts b/web/services/project/index.ts index 538b65e11..18cf1200a 100644 --- a/web/services/project/index.ts +++ b/web/services/project/index.ts @@ -1,6 +1,6 @@ export * from "./project.service"; -export * from "./project_estimate.service"; -export * from "./project_publish.service"; -export * from "./project_state.service"; -export * from "./project_export.service"; -export * from "./project_invitation.service"; +export * from "./project-estimate.service"; +export * from "./project-export.service"; +export * from "./project-member.service"; +export * from "./project-state.service"; +export * from "./project-publish.service"; diff --git a/web/services/project/project_estimate.service.ts b/web/services/project/project-estimate.service.ts similarity index 100% rename from web/services/project/project_estimate.service.ts rename to web/services/project/project-estimate.service.ts diff --git a/web/services/project/project_export.service.ts b/web/services/project/project-export.service.ts similarity index 100% rename from web/services/project/project_export.service.ts rename to web/services/project/project-export.service.ts diff --git a/web/services/project/project-member.service.ts b/web/services/project/project-member.service.ts new file mode 100644 index 000000000..35c7a620a --- /dev/null +++ b/web/services/project/project-member.service.ts @@ -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 { + 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 { + 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 { + 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 { + 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 + ): Promise { + 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 { + 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 { + 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 { + 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 { + return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/invitations/${invitationId}/`) + .then((response) => response?.data) + .catch((error) => { + throw error?.response?.data; + }); + } +} diff --git a/web/services/project/project_publish.service.ts b/web/services/project/project-publish.service.ts similarity index 100% rename from web/services/project/project_publish.service.ts rename to web/services/project/project-publish.service.ts diff --git a/web/services/project/project_state.service.ts b/web/services/project/project-state.service.ts similarity index 100% rename from web/services/project/project_state.service.ts rename to web/services/project/project-state.service.ts diff --git a/web/services/project/project.service.ts b/web/services/project/project.service.ts index 1c824a40c..74d678d23 100644 --- a/web/services/project/project.service.ts +++ b/web/services/project/project.service.ts @@ -5,10 +5,7 @@ import { TrackEventService } from "services/track_event.service"; // types import type { GithubRepositoriesResponse, - IUser, IProject, - IProjectBulkAddFormData, - IProjectMember, ISearchIssueResponse, ProjectPreferences, IProjectViewProps, @@ -110,77 +107,6 @@ export class ProjectService extends APIService { }); } - async fetchProjectMembers(workspaceSlug: string, projectId: string): Promise { - 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 { - 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 { - 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 { - 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 - ): Promise { - 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 { - return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/members/${memberId}/`) - .then((response) => response?.data) - .catch((error) => { - throw error?.response?.data; - }); - } - async setProjectView( workspaceSlug: string, projectId: string, diff --git a/web/services/project/project_invitation.service.ts b/web/services/project/project_invitation.service.ts deleted file mode 100644 index 1fbf6e24c..000000000 --- a/web/services/project/project_invitation.service.ts +++ /dev/null @@ -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 { - 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 { - 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 { - return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/invitations/${invitationId}/`) - .then((response) => response?.data) - .catch((error) => { - throw error?.response?.data; - }); - } -} diff --git a/web/store/archived-issues/issue_filters.store.ts b/web/store/archived-issues/issue_filters.store.ts index edb1549a6..9a555212b 100644 --- a/web/store/archived-issues/issue_filters.store.ts +++ b/web/store/archived-issues/issue_filters.store.ts @@ -3,7 +3,7 @@ import { observable, computed, makeObservable, action, runInAction } from "mobx" import { handleIssueQueryParamsByLayout } from "helpers/issue.helper"; // services import { IssueService } from "services/issue"; -import { ProjectService } from "services/project"; +import { ProjectService, ProjectMemberService } from "services/project"; // types import { RootStore } from "../root"; import { @@ -25,6 +25,7 @@ export interface IArchivedIssueFilterStore { // services projectService: ProjectService; + projectMemberService: ProjectMemberService; issueService: IssueService; // computed @@ -87,6 +88,7 @@ export class ArchivedIssueFilterStore implements IArchivedIssueFilterStore { // services projectService: ProjectService; + projectMemberService: ProjectMemberService; issueService: IssueService; constructor(_rootStore: RootStore) { @@ -111,6 +113,7 @@ export class ArchivedIssueFilterStore implements IArchivedIssueFilterStore { // services this.issueService = new IssueService(); this.projectService = new ProjectService(); + this.projectMemberService = new ProjectMemberService(); } computedFilter = (filters: any, filteredParams: any) => { @@ -222,7 +225,7 @@ export class ArchivedIssueFilterStore implements IArchivedIssueFilterStore { fetchUserProjectFilters = async (workspaceSlug: string, projectId: string) => { 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); runInAction(() => { diff --git a/web/store/editor/mentions.store.ts b/web/store/editor/mentions.store.ts index 11296450f..df4ba152e 100644 --- a/web/store/editor/mentions.store.ts +++ b/web/store/editor/mentions.store.ts @@ -22,7 +22,7 @@ export class MentionsStore implements IMentionsStore { } get mentionSuggestions() { - const projectMembers = this.rootStore.project.projectMembers; + const projectMembers = this.rootStore.projectMember.projectMembers; const suggestions = projectMembers === null diff --git a/web/store/issue/issue_filters.store.ts b/web/store/issue/issue_filters.store.ts index be28cca87..83b7f7bad 100644 --- a/web/store/issue/issue_filters.store.ts +++ b/web/store/issue/issue_filters.store.ts @@ -1,6 +1,6 @@ import { observable, action, computed, makeObservable, runInAction } from "mobx"; // services -import { ProjectService } from "services/project"; +import { ProjectService, ProjectMemberService } from "services/project"; import { IssueService } from "services/issue"; // helpers import { handleIssueQueryParamsByLayout } from "helpers/issue.helper"; @@ -72,6 +72,7 @@ export class IssueFilterStore implements IIssueFilterStore { // services projectService; + projectMemberService; issueService; constructor(_rootStore: RootStore) { @@ -98,6 +99,7 @@ export class IssueFilterStore implements IIssueFilterStore { this.rootStore = _rootStore; this.projectService = new ProjectService(); + this.projectMemberService = new ProjectMemberService(); this.issueService = new IssueService(); } @@ -145,7 +147,7 @@ export class IssueFilterStore implements IIssueFilterStore { fetchUserProjectFilters = async (workspaceSlug: string, projectId: string) => { 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); runInAction(() => { diff --git a/web/store/project/index.ts b/web/store/project/index.ts index ccd0abfaf..35cfda8fc 100644 --- a/web/store/project/index.ts +++ b/web/store/project/index.ts @@ -1,5 +1,6 @@ -export * from "./project_publish.store"; export * from "./project.store"; -export * from "./project_estimates.store"; -export * from "./project_label_store"; -export * from "./project_state.store"; +export * from "./project-estimates.store"; +export * from "./project-label.store"; +export * from "./project-members.store"; +export * from "./project-publish.store"; +export * from "./project-state.store"; diff --git a/web/store/project/project_estimates.store.ts b/web/store/project/project-estimates.store.ts similarity index 100% rename from web/store/project/project_estimates.store.ts rename to web/store/project/project-estimates.store.ts diff --git a/web/store/project/project_label_store.ts b/web/store/project/project-label.store.ts similarity index 100% rename from web/store/project/project_label_store.ts rename to web/store/project/project-label.store.ts diff --git a/web/store/project/project-members.store.ts b/web/store/project/project-members.store.ts new file mode 100644 index 000000000..d75bbeec6 --- /dev/null +++ b/web/store/project/project-members.store.ts @@ -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; + removeMemberFromProject: (workspaceSlug: string, projectId: string, memberId: string) => Promise; + updateMember: ( + workspaceSlug: string, + projectId: string, + memberId: string, + data: Partial + ) => Promise; + + deleteProjectInvitation: (workspaceSlug: string, projectId: string, memberId: string) => Promise; +} + +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) => { + 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; + } + }; +} diff --git a/web/store/project/project_publish.store.ts b/web/store/project/project-publish.store.ts similarity index 100% rename from web/store/project/project_publish.store.ts rename to web/store/project/project-publish.store.ts diff --git a/web/store/project/project_state.store.ts b/web/store/project/project-state.store.ts similarity index 100% rename from web/store/project/project_state.store.ts rename to web/store/project/project-state.store.ts diff --git a/web/store/project/project.store.ts b/web/store/project/project.store.ts index e2ab7f004..9997de5c1 100644 --- a/web/store/project/project.store.ts +++ b/web/store/project/project.store.ts @@ -1,7 +1,7 @@ import { observable, action, computed, makeObservable, runInAction } from "mobx"; // types import { RootStore } from "../root"; -import { IProject, IIssueLabels, IProjectMember, IEstimate } from "types"; +import { IProject, IIssueLabels, IEstimate } from "types"; // services import { ProjectService, ProjectStateService, ProjectEstimateService } from "services/project"; import { IssueService, IssueLabelService } from "services/issue"; @@ -19,9 +19,6 @@ export interface IProjectStore { labels: { [projectId: string]: IIssueLabels[] | null; // project_id: labels } | null; - members: { - [projectId: string]: IProjectMember[] | null; // project_id: members - } | null; estimates: { [projectId: string]: IEstimate[] | null; // project_id: members } | null; @@ -30,7 +27,6 @@ export interface IProjectStore { searchedProjects: IProject[]; workspaceProjects: IProject[] | null; projectLabels: IIssueLabels[] | null; - projectMembers: IProjectMember[] | null; projectEstimates: IEstimate[] | null; joinedProjects: IProject[]; @@ -44,14 +40,11 @@ export interface IProjectStore { getProjectById: (workspaceSlug: string, projectId: string) => IProject | null; getProjectLabelById: (labelId: string) => IIssueLabels | null; - getProjectMemberById: (memberId: string) => IProjectMember | null; - getProjectMemberByUserId: (memberId: string) => IProjectMember | null; getProjectEstimateById: (estimateId: string) => IEstimate | null; fetchProjects: (workspaceSlug: string) => Promise; fetchProjectDetails: (workspaceSlug: string, projectId: string) => Promise; fetchProjectLabels: (workspaceSlug: string, projectId: string) => Promise; - fetchProjectMembers: (workspaceSlug: string, projectId: string) => Promise; fetchProjectEstimates: (workspaceSlug: string, projectId: string) => Promise; addProjectToFavorites: (workspaceSlug: string, projectId: string) => Promise; @@ -65,15 +58,6 @@ export interface IProjectStore { createProject: (workspaceSlug: string, data: any) => Promise; updateProject: (workspaceSlug: string, projectId: string, data: Partial) => Promise; deleteProject: (workspaceSlug: string, projectId: string) => Promise; - - // write operations - removeMemberFromProject: (workspaceSlug: string, projectId: string, memberId: string) => Promise; - updateMember: ( - workspaceSlug: string, - projectId: string, - memberId: string, - data: Partial - ) => Promise; } export class ProjectStore implements IProjectStore { @@ -89,9 +73,6 @@ export class ProjectStore implements IProjectStore { labels: { [projectId: string]: IIssueLabels[]; // projectId: labels } | null = {}; - members: { - [projectId: string]: IProjectMember[]; // projectId: members - } | null = {}; estimates: { [projectId: string]: IEstimate[]; // projectId: estimates } | null = {}; @@ -116,14 +97,12 @@ export class ProjectStore implements IProjectStore { projects: observable.ref, project_details: observable.ref, labels: observable.ref, - members: observable.ref, estimates: observable.ref, // computed searchedProjects: computed, workspaceProjects: computed, projectLabels: computed, - projectMembers: computed, projectEstimates: computed, currentProjectDetails: computed, @@ -139,11 +118,9 @@ export class ProjectStore implements IProjectStore { getProjectById: action, getProjectLabelById: action, - getProjectMemberById: action, getProjectEstimateById: action, fetchProjectLabels: action, - fetchProjectMembers: action, fetchProjectEstimates: action, addProjectToFavorites: action, @@ -154,10 +131,6 @@ export class ProjectStore implements IProjectStore { createProject: action, updateProject: action, leaveProject: action, - - // write operations - removeMemberFromProject: action, - updateMember: action, }); this.rootStore = _rootStore; @@ -209,11 +182,6 @@ export class ProjectStore implements IProjectStore { return this.labels?.[this.projectId] || null; } - get projectMembers() { - if (!this.projectId) return null; - return this.members?.[this.projectId] || null; - } - get projectEstimates() { if (!this.projectId) return null; return this.estimates?.[this.projectId] || null; @@ -281,22 +249,6 @@ export class ProjectStore implements IProjectStore { 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) => { if (!this.projectId) return null; 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) => { try { this.loader = true; @@ -576,58 +505,4 @@ export class ProjectStore implements IProjectStore { 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) => { - 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; - } - }; } diff --git a/web/store/root.ts b/web/store/root.ts index 655549025..3b03bf9c8 100644 --- a/web/store/root.ts +++ b/web/store/root.ts @@ -38,6 +38,8 @@ import { ProjectLabelStore, ProjectEstimatesStore, IProjectEstimateStore, + ProjectMemberStore, + IProjectMemberStore, } from "store/project"; import { IModuleFilterStore, @@ -116,8 +118,8 @@ export class RootStore { user: IUserStore; theme: IThemeStore; appConfig: IAppConfigStore; - commandPalette: ICommandPaletteStore; + workspace: IWorkspaceStore; workspaceFilter: IWorkspaceFilterStore; workspaceMember: IWorkspaceMemberStore; @@ -127,6 +129,8 @@ export class RootStore { projectState: IProjectStateStore; projectLabel: IProjectLabelStore; projectEstimates: IProjectEstimateStore; + projectMember: IProjectMemberStore; + issue: IIssueStore; module: IModuleStore; @@ -191,6 +195,7 @@ export class RootStore { this.projectLabel = new ProjectLabelStore(this); this.projectEstimates = new ProjectEstimatesStore(this); this.projectPublish = new ProjectPublishStore(this); + this.projectMember = new ProjectMemberStore(this); this.module = new ModuleStore(this); this.moduleIssue = new ModuleIssueStore(this); diff --git a/web/store/user.store.ts b/web/store/user.store.ts index 80cafdf44..c1d91904f 100644 --- a/web/store/user.store.ts +++ b/web/store/user.store.ts @@ -1,7 +1,7 @@ // mobx import { action, observable, runInAction, makeObservable, computed } from "mobx"; // services -import { ProjectService } from "services/project"; +import { ProjectMemberService, ProjectService } from "services/project"; import { UserService } from "services/user.service"; import { WorkspaceService } from "services/workspace.service"; // interfaces @@ -81,6 +81,7 @@ class UserStore implements IUserStore { userService; workspaceService; projectService; + projectMemberService; constructor(_rootStore: RootStore) { makeObservable(this, { @@ -115,6 +116,7 @@ class UserStore implements IUserStore { this.userService = new UserService(); this.workspaceService = new WorkspaceService(); this.projectService = new ProjectService(); + this.projectMemberService = new ProjectMemberService(); } get currentWorkspaceMemberInfo() { @@ -219,7 +221,7 @@ class UserStore implements IUserStore { fetchUserProjectInfo = async (workspaceSlug: string, projectId: string) => { try { - const response = await this.projectService.projectMemberMe(workspaceSlug, projectId); + const response = await this.projectMemberService.projectMemberMe(workspaceSlug, projectId); runInAction(() => { this.projectMemberInfo = {