chore: implement project view hook

This commit is contained in:
Aaryan Khandelwal 2023-12-15 17:01:36 +05:30
parent 960f170fd4
commit 4e755289a1
80 changed files with 362 additions and 401 deletions

View File

@ -8,10 +8,9 @@ import { SelectMonthModal } from "components/automation";
// icon // icon
import { ArchiveRestore } from "lucide-react"; import { ArchiveRestore } from "lucide-react";
// constants // constants
import { PROJECT_AUTOMATION_MONTHS } from "constants/project"; import { EUserProjectRoles, PROJECT_AUTOMATION_MONTHS } from "constants/project";
// types // types
import { IProject } from "types"; import { IProject } from "types";
import { EUserWorkspaceRoles } from "constants/workspace";
type Props = { type Props = {
handleChange: (formData: Partial<IProject>) => Promise<void>; handleChange: (formData: Partial<IProject>) => Promise<void>;
@ -29,7 +28,7 @@ export const AutoArchiveAutomation: React.FC<Props> = observer((props) => {
} = useUser(); } = useUser();
const { currentProjectDetails } = useProject(); const { currentProjectDetails } = useProject();
const isAdmin = currentProjectRole === EUserWorkspaceRoles.ADMIN; const isAdmin = currentProjectRole === EUserProjectRoles.ADMIN;
return ( return (
<> <>

View File

@ -9,9 +9,8 @@ import { CustomSelect, CustomSearchSelect, ToggleSwitch, StateGroupIcon, DoubleC
import { ArchiveX } from "lucide-react"; import { ArchiveX } from "lucide-react";
// types // types
import { IProject } from "types"; import { IProject } from "types";
// fetch keys // constants
import { PROJECT_AUTOMATION_MONTHS } from "constants/project"; import { EUserProjectRoles, PROJECT_AUTOMATION_MONTHS } from "constants/project";
import { EUserWorkspaceRoles } from "constants/workspace";
type Props = { type Props = {
handleChange: (formData: Partial<IProject>) => Promise<void>; handleChange: (formData: Partial<IProject>) => Promise<void>;
@ -55,7 +54,7 @@ export const AutoCloseAutomation: React.FC<Props> = observer((props) => {
default_state: defaultState, default_state: defaultState,
}; };
const isAdmin = currentProjectRole === EUserWorkspaceRoles.ADMIN; const isAdmin = currentProjectRole === EUserProjectRoles.ADMIN;
return ( return (
<> <>

View File

@ -12,7 +12,7 @@ import { CycleGanttBlock } from "components/cycles";
// types // types
import { ICycle } from "types"; import { ICycle } from "types";
// constants // constants
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserProjectRoles } from "constants/project";
type Props = { type Props = {
workspaceSlug: string; workspaceSlug: string;
@ -83,7 +83,7 @@ export const CyclesListGanttChartView: FC<Props> = observer((props) => {
}; };
const isAllowed = const isAllowed =
currentProjectRole && [EUserWorkspaceRoles.ADMIN, EUserWorkspaceRoles.MEMBER].includes(currentProjectRole); currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole);
return ( return (
<div className="h-full w-full overflow-y-auto"> <div className="h-full w-full overflow-y-auto">

View File

@ -19,10 +19,9 @@ import { renderEmoji } from "helpers/emoji.helper";
import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions, TIssueLayouts } from "types"; import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions, TIssueLayouts } from "types";
// constants // constants
import { ISSUE_DISPLAY_FILTERS_BY_LAYOUT } from "constants/issue"; import { ISSUE_DISPLAY_FILTERS_BY_LAYOUT } from "constants/issue";
import { EUserWorkspaceRoles } from "constants/workspace";
import { EFilterType } from "store_legacy/issues/types"; import { EFilterType } from "store_legacy/issues/types";
import { EProjectStore } from "store_legacy/command-palette.store"; import { EProjectStore } from "store_legacy/command-palette.store";
import { EUserProjectRoles } from "constants/project";
export const CycleIssuesHeader: React.FC = observer(() => { export const CycleIssuesHeader: React.FC = observer(() => {
// states // states
@ -110,7 +109,7 @@ export const CycleIssuesHeader: React.FC = observer(() => {
const cycleDetails = cycleId ? cycleStore.getCycleById(cycleId.toString()) : undefined; const cycleDetails = cycleId ? cycleStore.getCycleById(cycleId.toString()) : undefined;
const canUserCreateIssue = const canUserCreateIssue =
currentProjectRole && [EUserWorkspaceRoles.ADMIN, EUserWorkspaceRoles.MEMBER].includes(currentProjectRole); currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole);
return ( return (
<> <>

View File

@ -8,7 +8,7 @@ import { useApplication, useProject, useUser } from "hooks/store";
import { Breadcrumbs, Button, ContrastIcon } from "@plane/ui"; import { Breadcrumbs, Button, ContrastIcon } from "@plane/ui";
// helpers // helpers
import { renderEmoji } from "helpers/emoji.helper"; import { renderEmoji } from "helpers/emoji.helper";
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserProjectRoles } from "constants/project";
export const CyclesHeader: FC = observer(() => { export const CyclesHeader: FC = observer(() => {
// router // router
@ -25,7 +25,7 @@ export const CyclesHeader: FC = observer(() => {
const { currentProjectDetails } = useProject(); const { currentProjectDetails } = useProject();
const canUserCreateCycle = const canUserCreateCycle =
currentProjectRole && [EUserWorkspaceRoles.ADMIN, EUserWorkspaceRoles.MEMBER].includes(currentProjectRole); currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole);
return ( return (
<div className="relative z-10 flex h-[3.75rem] w-full flex-shrink-0 flex-row items-center justify-between gap-x-2 gap-y-4 border-b border-custom-border-200 bg-custom-sidebar-background-100 p-4"> <div className="relative z-10 flex h-[3.75rem] w-full flex-shrink-0 flex-row items-center justify-between gap-x-2 gap-y-4 border-b border-custom-border-200 bg-custom-sidebar-background-100 p-4">

View File

@ -19,10 +19,10 @@ import { renderEmoji } from "helpers/emoji.helper";
import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions, TIssueLayouts } from "types"; import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions, TIssueLayouts } from "types";
// constants // constants
import { ISSUE_DISPLAY_FILTERS_BY_LAYOUT } from "constants/issue"; import { ISSUE_DISPLAY_FILTERS_BY_LAYOUT } from "constants/issue";
import { EUserWorkspaceRoles } from "constants/workspace";
// store // store
import { EFilterType } from "store_legacy/issues/types"; import { EFilterType } from "store_legacy/issues/types";
import { EProjectStore } from "store_legacy/command-palette.store"; import { EProjectStore } from "store_legacy/command-palette.store";
import { EUserProjectRoles } from "constants/project";
export const ModuleIssuesHeader: React.FC = observer(() => { export const ModuleIssuesHeader: React.FC = observer(() => {
// states // states
@ -109,7 +109,7 @@ export const ModuleIssuesHeader: React.FC = observer(() => {
const moduleDetails = moduleId ? moduleStore.getModuleById(moduleId.toString()) : undefined; const moduleDetails = moduleId ? moduleStore.getModuleById(moduleId.toString()) : undefined;
const canUserCreateIssue = const canUserCreateIssue =
currentProjectRole && [EUserWorkspaceRoles.ADMIN, EUserWorkspaceRoles.MEMBER].includes(currentProjectRole); currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole);
return ( return (
<> <>

View File

@ -10,7 +10,7 @@ import { Breadcrumbs, Button, Tooltip, DiceIcon } from "@plane/ui";
import { renderEmoji } from "helpers/emoji.helper"; import { renderEmoji } from "helpers/emoji.helper";
// constants // constants
import { MODULE_VIEW_LAYOUTS } from "constants/module"; import { MODULE_VIEW_LAYOUTS } from "constants/module";
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserProjectRoles } from "constants/project";
export const ModulesListHeader: React.FC = observer(() => { export const ModulesListHeader: React.FC = observer(() => {
// router // router
@ -26,7 +26,7 @@ export const ModulesListHeader: React.FC = observer(() => {
const { storedValue: modulesView, setValue: setModulesView } = useLocalStorage("modules_view", "grid"); const { storedValue: modulesView, setValue: setModulesView } = useLocalStorage("modules_view", "grid");
const canUserCreateModule = const canUserCreateModule =
currentProjectRole && [EUserWorkspaceRoles.ADMIN, EUserWorkspaceRoles.MEMBER].includes(currentProjectRole); currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole);
return ( return (
<div className="relative z-10 flex h-[3.75rem] w-full flex-shrink-0 flex-row items-center justify-between gap-x-2 gap-y-4 border-b border-custom-border-200 bg-custom-sidebar-background-100 p-4"> <div className="relative z-10 flex h-[3.75rem] w-full flex-shrink-0 flex-row items-center justify-between gap-x-2 gap-y-4 border-b border-custom-border-200 bg-custom-sidebar-background-100 p-4">

View File

@ -8,7 +8,7 @@ import { Breadcrumbs, Button } from "@plane/ui";
// helpers // helpers
import { renderEmoji } from "helpers/emoji.helper"; import { renderEmoji } from "helpers/emoji.helper";
// constants // constants
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserProjectRoles } from "constants/project";
export const PagesHeader = observer(() => { export const PagesHeader = observer(() => {
// router // router
@ -24,7 +24,7 @@ export const PagesHeader = observer(() => {
const { currentProjectDetails } = useProject(); const { currentProjectDetails } = useProject();
const canUserCreatePage = const canUserCreatePage =
currentProjectRole && [EUserWorkspaceRoles.ADMIN, EUserWorkspaceRoles.MEMBER].includes(currentProjectRole); currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole);
return ( return (
<div className="relative z-10 flex h-[3.75rem] w-full flex-shrink-0 flex-row items-center justify-between gap-x-2 gap-y-4 border-b border-custom-border-200 bg-custom-sidebar-background-100 p-4"> <div className="relative z-10 flex h-[3.75rem] w-full flex-shrink-0 flex-row items-center justify-between gap-x-2 gap-y-4 border-b border-custom-border-200 bg-custom-sidebar-background-100 p-4">

View File

@ -3,7 +3,8 @@ import Link from "next/link";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
import { ArrowLeft, Briefcase, Circle, ExternalLink, Plus } from "lucide-react"; import { ArrowLeft, Briefcase, Circle, ExternalLink, Plus } from "lucide-react";
// mobx store // hooks
import { useApplication, useLabel, useProject, useProjectState, useUser } from "hooks/store";
import { useMobxStore } from "lib/mobx/store-provider"; import { useMobxStore } from "lib/mobx/store-provider";
// components // components
import { DisplayFiltersSelection, FiltersDropdown, FilterSelection, LayoutSelection } from "components/issues"; import { DisplayFiltersSelection, FiltersDropdown, FilterSelection, LayoutSelection } from "components/issues";
@ -14,31 +15,37 @@ import { Breadcrumbs, Button, LayersIcon } from "@plane/ui";
import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions, TIssueLayouts } from "types"; import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions, TIssueLayouts } from "types";
// constants // constants
import { ISSUE_DISPLAY_FILTERS_BY_LAYOUT } from "constants/issue"; import { ISSUE_DISPLAY_FILTERS_BY_LAYOUT } from "constants/issue";
import { EUserWorkspaceRoles } from "constants/workspace";
// helper // helper
import { renderEmoji } from "helpers/emoji.helper"; import { renderEmoji } from "helpers/emoji.helper";
import { EFilterType } from "store_legacy/issues/types"; import { EFilterType } from "store_legacy/issues/types";
import { EProjectStore } from "store_legacy/command-palette.store"; import { EProjectStore } from "store_legacy/command-palette.store";
import { EUserProjectRoles } from "constants/project";
export const ProjectIssuesHeader: React.FC = observer(() => { export const ProjectIssuesHeader: React.FC = observer(() => {
// states
const [analyticsModal, setAnalyticsModal] = useState(false); const [analyticsModal, setAnalyticsModal] = useState(false);
// router
const router = useRouter(); const router = useRouter();
const { workspaceSlug, projectId } = router.query as { workspaceSlug: string; projectId: string }; const { workspaceSlug, projectId } = router.query as { workspaceSlug: string; projectId: string };
// store hooks
const { const {
project: { currentProjectDetails },
projectLabel: { projectLabels },
projectMember: { projectMembers }, projectMember: { projectMembers },
projectState: projectStateStore,
inbox: inboxStore, inbox: inboxStore,
commandPalette: commandPaletteStore,
trackEvent: { setTrackElement },
// issue filters // issue filters
projectIssuesFilter: { issueFilters, updateFilters }, projectIssuesFilter: { issueFilters, updateFilters },
projectIssues: {},
user: { currentProjectRole },
} = useMobxStore(); } = useMobxStore();
const {
commandPalette: { toggleCreateIssueModal },
eventTracker: { setTrackElement },
} = useApplication();
const {
membership: { currentProjectRole },
} = useUser();
const { currentProjectDetails } = useProject();
const { projectStates } = useProjectState();
const {
project: { projectLabels },
} = useLabel();
const activeLayout = issueFilters?.displayFilters?.layout; const activeLayout = issueFilters?.displayFilters?.layout;
@ -90,7 +97,7 @@ export const ProjectIssuesHeader: React.FC = observer(() => {
const deployUrl = process.env.NEXT_PUBLIC_DEPLOY_URL; const deployUrl = process.env.NEXT_PUBLIC_DEPLOY_URL;
const canUserCreateIssue = const canUserCreateIssue =
currentProjectRole && [EUserWorkspaceRoles.ADMIN, EUserWorkspaceRoles.MEMBER].includes(currentProjectRole); currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole);
return ( return (
<> <>
@ -172,9 +179,9 @@ export const ProjectIssuesHeader: React.FC = observer(() => {
layoutDisplayFiltersOptions={ layoutDisplayFiltersOptions={
activeLayout ? ISSUE_DISPLAY_FILTERS_BY_LAYOUT.issues[activeLayout] : undefined activeLayout ? ISSUE_DISPLAY_FILTERS_BY_LAYOUT.issues[activeLayout] : undefined
} }
labels={projectLabels ?? undefined} labels={projectLabels}
members={projectMembers?.map((m) => m.member)} members={projectMembers?.map((m) => m.member)}
states={projectStateStore.states?.[projectId ?? ""] ?? undefined} states={projectStates}
/> />
</FiltersDropdown> </FiltersDropdown>
<FiltersDropdown title="Display" placement="bottom-end"> <FiltersDropdown title="Display" placement="bottom-end">
@ -211,7 +218,7 @@ export const ProjectIssuesHeader: React.FC = observer(() => {
<Button <Button
onClick={() => { onClick={() => {
setTrackElement("PROJECT_PAGE_HEADER"); setTrackElement("PROJECT_PAGE_HEADER");
commandPaletteStore.toggleCreateIssueModal(true, EProjectStore.PROJECT); toggleCreateIssueModal(true, EProjectStore.PROJECT);
}} }}
size="sm" size="sm"
prependIcon={<Plus />} prependIcon={<Plus />}

View File

@ -8,7 +8,7 @@ import { renderEmoji } from "helpers/emoji.helper";
// hooks // hooks
import { useProject, useUser } from "hooks/store"; import { useProject, useUser } from "hooks/store";
// constants // constants
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserProjectRoles } from "constants/project";
export interface IProjectSettingHeader { export interface IProjectSettingHeader {
title: string; title: string;
@ -25,7 +25,7 @@ export const ProjectSettingHeader: FC<IProjectSettingHeader> = observer((props)
} = useUser(); } = useUser();
const { currentProjectDetails } = useProject(); const { currentProjectDetails } = useProject();
if (currentProjectRole && currentProjectRole <= EUserWorkspaceRoles.VIEWER) return null; if (currentProjectRole && currentProjectRole <= EUserProjectRoles.VIEWER) return null;
return ( return (
<div className="relative z-10 flex h-[3.75rem] w-full flex-shrink-0 flex-row items-center justify-between gap-x-2 gap-y-4 border-b border-custom-border-200 bg-custom-sidebar-background-100 p-4"> <div className="relative z-10 flex h-[3.75rem] w-full flex-shrink-0 flex-row items-center justify-between gap-x-2 gap-y-4 border-b border-custom-border-200 bg-custom-sidebar-background-100 p-4">

View File

@ -3,7 +3,7 @@ import { useRouter } from "next/router";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
import { Plus } from "lucide-react"; import { Plus } from "lucide-react";
// hooks // hooks
import { useApplication, useLabel, useProject, useProjectState, useUser } from "hooks/store"; import { useApplication, useLabel, useProject, useProjectState, useProjectView, useUser } from "hooks/store";
import { useMobxStore } from "lib/mobx/store-provider"; import { useMobxStore } from "lib/mobx/store-provider";
// components // components
import { DisplayFiltersSelection, FiltersDropdown, FilterSelection, LayoutSelection } from "components/issues"; import { DisplayFiltersSelection, FiltersDropdown, FilterSelection, LayoutSelection } from "components/issues";
@ -16,10 +16,9 @@ import { renderEmoji } from "helpers/emoji.helper";
import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions, TIssueLayouts } from "types"; import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions, TIssueLayouts } from "types";
// constants // constants
import { ISSUE_DISPLAY_FILTERS_BY_LAYOUT } from "constants/issue"; import { ISSUE_DISPLAY_FILTERS_BY_LAYOUT } from "constants/issue";
import { EUserWorkspaceRoles } from "constants/workspace";
import { EFilterType } from "store_legacy/issues/types"; import { EFilterType } from "store_legacy/issues/types";
import { EProjectStore } from "store_legacy/command-palette.store"; import { EProjectStore } from "store_legacy/command-palette.store";
import { EUserProjectRoles } from "constants/project";
export const ProjectViewIssuesHeader: React.FC = observer(() => { export const ProjectViewIssuesHeader: React.FC = observer(() => {
// router // router
@ -32,7 +31,6 @@ export const ProjectViewIssuesHeader: React.FC = observer(() => {
// store hooks // store hooks
const { const {
projectMember: { projectMembers }, projectMember: { projectMembers },
projectViews: projectViewsStore,
viewIssuesFilter: { issueFilters, updateFilters }, viewIssuesFilter: { issueFilters, updateFilters },
} = useMobxStore(); } = useMobxStore();
const { const {
@ -43,6 +41,7 @@ export const ProjectViewIssuesHeader: React.FC = observer(() => {
membership: { currentProjectRole }, membership: { currentProjectRole },
} = useUser(); } = useUser();
const { currentProjectDetails } = useProject(); const { currentProjectDetails } = useProject();
const { projectViews, getViewById } = useProjectView();
const { projectStates } = useProjectState(); const { projectStates } = useProjectState();
const { const {
project: { projectLabels }, project: { projectLabels },
@ -93,11 +92,10 @@ export const ProjectViewIssuesHeader: React.FC = observer(() => {
[workspaceSlug, projectId, viewId, updateFilters] [workspaceSlug, projectId, viewId, updateFilters]
); );
const viewsList = projectId ? projectViewsStore.viewsList[projectId.toString()] : undefined; const viewDetails = viewId ? getViewById(viewId.toString()) : null;
const viewDetails = viewId ? projectViewsStore.viewDetails[viewId.toString()] : undefined;
const canUserCreateIssue = const canUserCreateIssue =
currentProjectRole && [EUserWorkspaceRoles.ADMIN, EUserWorkspaceRoles.MEMBER].includes(currentProjectRole); currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole);
return ( return (
<div className="relative z-10 flex h-[3.75rem] w-full items-center justify-between gap-x-2 gap-y-4 border-b border-custom-border-200 bg-custom-sidebar-background-100 p-4"> <div className="relative z-10 flex h-[3.75rem] w-full items-center justify-between gap-x-2 gap-y-4 border-b border-custom-border-200 bg-custom-sidebar-background-100 p-4">
@ -142,17 +140,23 @@ export const ProjectViewIssuesHeader: React.FC = observer(() => {
className="ml-1.5" className="ml-1.5"
placement="bottom-start" placement="bottom-start"
> >
{viewsList?.map((view) => ( {projectViews?.map((viewId) => {
<CustomMenu.MenuItem const view = getViewById(viewId);
key={view.id}
onClick={() => router.push(`/${workspaceSlug}/projects/${projectId}/views/${view.id}`)} if (!view) return;
>
<div className="flex items-center gap-1.5"> return (
<PhotoFilterIcon height={12} width={12} /> <CustomMenu.MenuItem
{truncateText(view.name, 40)} key={viewId}
</div> onClick={() => router.push(`/${workspaceSlug}/projects/${projectId}/views/${viewId}`)}
</CustomMenu.MenuItem> >
))} <div className="flex items-center gap-1.5">
<PhotoFilterIcon height={12} width={12} />
{truncateText(view.name, 40)}
</div>
</CustomMenu.MenuItem>
);
})}
</CustomMenu> </CustomMenu>
} }
/> />

View File

@ -8,7 +8,7 @@ import { Breadcrumbs, PhotoFilterIcon, Button } from "@plane/ui";
// helpers // helpers
import { renderEmoji } from "helpers/emoji.helper"; import { renderEmoji } from "helpers/emoji.helper";
// constants // constants
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserProjectRoles } from "constants/project";
export const ProjectViewsHeader: React.FC = observer(() => { export const ProjectViewsHeader: React.FC = observer(() => {
// router // router
@ -24,7 +24,7 @@ export const ProjectViewsHeader: React.FC = observer(() => {
const { currentProjectDetails } = useProject(); const { currentProjectDetails } = useProject();
const canUserCreateIssue = const canUserCreateIssue =
currentProjectRole && [EUserWorkspaceRoles.ADMIN, EUserWorkspaceRoles.MEMBER].includes(currentProjectRole); currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole);
return ( return (
<> <>

View File

@ -3,10 +3,9 @@ import { useRouter } from "next/router";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
import DatePicker from "react-datepicker"; import DatePicker from "react-datepicker";
import { Popover } from "@headlessui/react"; import { Popover } from "@headlessui/react";
// mobx store
import { useMobxStore } from "lib/mobx/store-provider";
// hooks // hooks
import { useUser } from "hooks/store";
import { useMobxStore } from "lib/mobx/store-provider";
import useToast from "hooks/use-toast"; import useToast from "hooks/use-toast";
// components // components
import { import {
@ -22,22 +21,25 @@ import { Button } from "@plane/ui";
import { CheckCircle2, ChevronDown, ChevronUp, Clock, FileStack, Inbox, Trash2, XCircle } from "lucide-react"; import { CheckCircle2, ChevronDown, ChevronUp, Clock, FileStack, Inbox, Trash2, XCircle } from "lucide-react";
// types // types
import type { TInboxStatus } from "types"; import type { TInboxStatus } from "types";
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserProjectRoles } from "constants/project";
export const InboxActionsHeader = observer(() => { export const InboxActionsHeader = observer(() => {
// states
const [date, setDate] = useState(new Date()); const [date, setDate] = useState(new Date());
const [selectDuplicateIssue, setSelectDuplicateIssue] = useState(false); const [selectDuplicateIssue, setSelectDuplicateIssue] = useState(false);
const [acceptIssueModal, setAcceptIssueModal] = useState(false); const [acceptIssueModal, setAcceptIssueModal] = useState(false);
const [declineIssueModal, setDeclineIssueModal] = useState(false); const [declineIssueModal, setDeclineIssueModal] = useState(false);
const [deleteIssueModal, setDeleteIssueModal] = useState(false); const [deleteIssueModal, setDeleteIssueModal] = useState(false);
// router
const router = useRouter(); const router = useRouter();
const { workspaceSlug, projectId, inboxId, inboxIssueId } = router.query; const { workspaceSlug, projectId, inboxId, inboxIssueId } = router.query;
// store hooks
const { inboxIssues: inboxIssuesStore, inboxIssueDetails: inboxIssueDetailsStore } = useMobxStore();
const {
currentUser,
membership: { currentProjectRole },
} = useUser();
const { inboxIssues: inboxIssuesStore, inboxIssueDetails: inboxIssueDetailsStore, user: userStore } = useMobxStore();
const user = userStore?.currentUser;
const userRole = userStore.currentProjectRole;
const issuesList = inboxId ? inboxIssuesStore.inboxIssues[inboxId.toString()] : null; const issuesList = inboxId ? inboxIssuesStore.inboxIssues[inboxId.toString()] : null;
const { setToastAlert } = useToast(); const { setToastAlert } = useToast();
@ -72,7 +74,7 @@ export const InboxActionsHeader = observer(() => {
}, [issue]); }, [issue]);
const issueStatus = issue?.issue_inbox[0].status; const issueStatus = issue?.issue_inbox[0].status;
const isAllowed = !!userRole && userRole >= EUserWorkspaceRoles.MEMBER; const isAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
const today = new Date(); const today = new Date();
const tomorrow = new Date(today); const tomorrow = new Date(today);
@ -228,7 +230,7 @@ export const InboxActionsHeader = observer(() => {
</Button> </Button>
</div> </div>
)} )}
{(isAllowed || user?.id === issue?.created_by) && ( {(isAllowed || currentUser?.id === issue?.created_by) && (
<div className="flex-shrink-0"> <div className="flex-shrink-0">
<Button <Button
variant="neutral-primary" variant="neutral-primary"

View File

@ -16,7 +16,7 @@ import { Loader, StateGroupIcon } from "@plane/ui";
import { renderShortDateWithYearFormat } from "helpers/date-time.helper"; import { renderShortDateWithYearFormat } from "helpers/date-time.helper";
// types // types
import { IInboxIssue, IIssue } from "types"; import { IInboxIssue, IIssue } from "types";
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserProjectRoles } from "constants/project";
const defaultValues: Partial<IInboxIssue> = { const defaultValues: Partial<IInboxIssue> = {
name: "", name: "",
@ -151,7 +151,7 @@ export const InboxMainContent: React.FC = observer(() => {
</div> </div>
); );
const isAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER; const isAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
return ( return (
<> <>

View File

@ -17,7 +17,7 @@ import {
IViewIssuesFilterStore, IViewIssuesFilterStore,
} from "store_legacy/issues"; } from "store_legacy/issues";
// constants // constants
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserProjectRoles } from "constants/project";
type Props = { type Props = {
issuesFilterStore: issuesFilterStore:
@ -50,7 +50,7 @@ export const CalendarChart: React.FC<Props> = observer((props) => {
} = useMobxStore(); } = useMobxStore();
const { enableIssueCreation } = issueStore?.viewFlags || {}; const { enableIssueCreation } = issueStore?.viewFlags || {};
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER; const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
const calendarPayload = calendarStore.calendarPayload; const calendarPayload = calendarStore.calendarPayload;

View File

@ -16,7 +16,7 @@ import emptyIssue from "public/empty-state/issue.svg";
import { ISearchIssueResponse } from "types"; import { ISearchIssueResponse } from "types";
import { EProjectStore } from "store_legacy/command-palette.store"; import { EProjectStore } from "store_legacy/command-palette.store";
// constants // constants
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserProjectRoles } from "constants/project";
type Props = { type Props = {
workspaceSlug: string | undefined; workspaceSlug: string | undefined;
@ -54,7 +54,7 @@ export const CycleEmptyState: React.FC<Props> = observer((props) => {
}); });
}; };
const isEditingAllowed = !!userRole && userRole >= EUserWorkspaceRoles.MEMBER; const isEditingAllowed = !!userRole && userRole >= EUserProjectRoles.MEMBER;
return ( return (
<> <>

View File

@ -15,7 +15,7 @@ import emptyIssue from "public/empty-state/issue.svg";
// types // types
import { ISearchIssueResponse } from "types"; import { ISearchIssueResponse } from "types";
// constants // constants
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserProjectRoles } from "constants/project";
type Props = { type Props = {
workspaceSlug: string | undefined; workspaceSlug: string | undefined;
@ -53,7 +53,7 @@ export const ModuleEmptyState: React.FC<Props> = observer((props) => {
); );
}; };
const isEditingAllowed = !!userRole && userRole >= EUserWorkspaceRoles.MEMBER; const isEditingAllowed = !!userRole && userRole >= EUserProjectRoles.MEMBER;
return ( return (
<> <>

View File

@ -5,7 +5,7 @@ import { useApplication, useUser } from "hooks/store";
// components // components
import { NewEmptyState } from "components/common/new-empty-state"; import { NewEmptyState } from "components/common/new-empty-state";
// constants // constants
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserProjectRoles } from "constants/project";
// assets // assets
import emptyIssue from "public/empty-state/empty_issues.webp"; import emptyIssue from "public/empty-state/empty_issues.webp";
import { EProjectStore } from "store_legacy/command-palette.store"; import { EProjectStore } from "store_legacy/command-palette.store";
@ -20,7 +20,7 @@ export const ProjectEmptyState: React.FC = observer(() => {
membership: { currentProjectRole }, membership: { currentProjectRole },
} = useUser(); } = useUser();
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER; const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
return ( return (
<div className="grid h-full w-full place-items-center"> <div className="grid h-full w-full place-items-center">

View File

@ -17,7 +17,7 @@ import { replaceUnderscoreIfSnakeCase } from "helpers/string.helper";
// types // types
import { IIssueFilterOptions, IIssueLabel, IProject, IState, IUserLite } from "types"; import { IIssueFilterOptions, IIssueLabel, IProject, IState, IUserLite } from "types";
// constants // constants
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserProjectRoles } from "constants/project";
type Props = { type Props = {
appliedFilters: IIssueFilterOptions; appliedFilters: IIssueFilterOptions;
@ -43,7 +43,7 @@ export const AppliedFiltersList: React.FC<Props> = observer((props) => {
if (Object.keys(appliedFilters).length === 0) return null; if (Object.keys(appliedFilters).length === 0) return null;
const isEditingAllowed = currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER; const isEditingAllowed = currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
return ( return (
<div className="flex flex-wrap items-stretch gap-2 bg-custom-background-100"> <div className="flex flex-wrap items-stretch gap-2 bg-custom-background-100">

View File

@ -1,6 +1,7 @@
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
// mobx store // hooks
import { useProjectView } from "hooks/store";
import { useMobxStore } from "lib/mobx/store-provider"; import { useMobxStore } from "lib/mobx/store-provider";
// components // components
import { AppliedFiltersList } from "components/issues"; import { AppliedFiltersList } from "components/issues";
@ -13,22 +14,23 @@ import { IIssueFilterOptions } from "types";
import { EFilterType } from "store_legacy/issues/types"; import { EFilterType } from "store_legacy/issues/types";
export const ProjectViewAppliedFiltersRoot: React.FC = observer(() => { export const ProjectViewAppliedFiltersRoot: React.FC = observer(() => {
// router
const router = useRouter(); const router = useRouter();
const { workspaceSlug, projectId, viewId } = router.query as { const { workspaceSlug, projectId, viewId } = router.query as {
workspaceSlug: string; workspaceSlug: string;
projectId: string; projectId: string;
viewId: string; viewId: string;
}; };
// store hooks
const { const {
projectLabel: { projectLabels }, projectLabel: { projectLabels },
projectState: projectStateStore, projectState: projectStateStore,
projectMember: { projectMembers }, projectMember: { projectMembers },
projectViews: projectViewsStore,
viewIssuesFilter: { issueFilters, updateFilters }, viewIssuesFilter: { issueFilters, updateFilters },
} = useMobxStore(); } = useMobxStore();
const { getViewById, updateView } = useProjectView();
const viewDetails = viewId ? projectViewsStore.viewDetails[viewId.toString()] : undefined; const viewDetails = viewId ? getViewById(viewId.toString()) : null;
const userFilters = issueFilters?.filters; const userFilters = issueFilters?.filters;
// filters whose value not null or empty array // filters whose value not null or empty array
@ -83,7 +85,7 @@ export const ProjectViewAppliedFiltersRoot: React.FC = observer(() => {
const handleUpdateView = () => { const handleUpdateView = () => {
if (!workspaceSlug || !projectId || !viewId || !viewDetails) return; if (!workspaceSlug || !projectId || !viewId || !viewDetails) return;
projectViewsStore.updateView(workspaceSlug.toString(), projectId.toString(), viewId.toString(), { updateView(workspaceSlug.toString(), projectId.toString(), viewId.toString(), {
query_data: { query_data: {
...viewDetails.query_data, ...viewDetails.query_data,
...(appliedFilters ?? {}), ...(appliedFilters ?? {}),

View File

@ -25,7 +25,7 @@ import {
IViewIssuesStore, IViewIssuesStore,
} from "store_legacy/issues"; } from "store_legacy/issues";
import { TUnGroupedIssues } from "store_legacy/issues/types"; import { TUnGroupedIssues } from "store_legacy/issues/types";
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserProjectRoles } from "constants/project";
interface IBaseGanttRoot { interface IBaseGanttRoot {
issueFiltersStore: issueFiltersStore:
@ -70,7 +70,7 @@ export const BaseGanttRoot: React.FC<IBaseGanttRoot> = observer((props: IBaseGan
await issueStore.updateIssue(workspaceSlug.toString(), projectId, issueId, payload, viewId); await issueStore.updateIssue(workspaceSlug.toString(), projectId, issueId, payload, viewId);
}; };
const isAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER; const isAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
return ( return (
<> <>

View File

@ -30,7 +30,7 @@ import { KanBan } from "./default";
import { KanBanSwimLanes } from "./swimlanes"; import { KanBanSwimLanes } from "./swimlanes";
import { EProjectStore } from "store_legacy/command-palette.store"; import { EProjectStore } from "store_legacy/command-palette.store";
import { DeleteIssueModal, IssuePeekOverview } from "components/issues"; import { DeleteIssueModal, IssuePeekOverview } from "components/issues";
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserProjectRoles } from "constants/project";
export interface IBaseKanBanLayout { export interface IBaseKanBanLayout {
issueStore: issueStore:
@ -118,7 +118,7 @@ export const BaseKanBanRoot: React.FC<IBaseKanBanLayout> = observer((props: IBas
const [dragState, setDragState] = useState<KanbanDragState>({}); const [dragState, setDragState] = useState<KanbanDragState>({});
const [deleteIssueModal, setDeleteIssueModal] = useState(false); const [deleteIssueModal, setDeleteIssueModal] = useState(false);
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER; const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
const canEditProperties = useCallback( const canEditProperties = useCallback(
(projectId: string | undefined) => { (projectId: string | undefined) => {

View File

@ -10,7 +10,7 @@ import { IIssue } from "types";
import { EIssueActions } from "../../types"; import { EIssueActions } from "../../types";
import { BaseKanBanRoot } from "../base-kanban-root"; import { BaseKanBanRoot } from "../base-kanban-root";
import { EProjectStore } from "store_legacy/command-palette.store"; import { EProjectStore } from "store_legacy/command-palette.store";
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserProjectRoles } from "constants/project";
export const ProfileIssuesKanBanLayout: React.FC = observer(() => { export const ProfileIssuesKanBanLayout: React.FC = observer(() => {
const router = useRouter(); const router = useRouter();
@ -39,7 +39,7 @@ export const ProfileIssuesKanBanLayout: React.FC = observer(() => {
const canEditPropertiesBasedOnProject = (projectId: string) => { const canEditPropertiesBasedOnProject = (projectId: string) => {
const currentProjectRole = currentWorkspaceUserProjectsRole && currentWorkspaceUserProjectsRole[projectId]; const currentProjectRole = currentWorkspaceUserProjectsRole && currentWorkspaceUserProjectsRole[projectId];
return !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER; return !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
}; };
return ( return (

View File

@ -25,7 +25,7 @@ import { IIssueResponse } from "store_legacy/issues/types";
import { EProjectStore } from "store_legacy/command-palette.store"; import { EProjectStore } from "store_legacy/command-palette.store";
import { IssuePeekOverview } from "components/issues"; import { IssuePeekOverview } from "components/issues";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserProjectRoles } from "constants/project";
enum EIssueActions { enum EIssueActions {
UPDATE = "update", UPDATE = "update",
@ -86,7 +86,7 @@ export const BaseListRoot = observer((props: IBaseListRoot) => {
} = useMobxStore(); } = useMobxStore();
const { currentProjectRole } = userStore; const { currentProjectRole } = userStore;
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER; const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
const issueIds = issueStore?.getIssuesIds || []; const issueIds = issueStore?.getIssuesIds || [];
const issues = issueStore?.getIssues; const issues = issueStore?.getIssues;

View File

@ -12,7 +12,7 @@ import { EIssueActions } from "../../types";
import { BaseListRoot } from "../base-list-root"; import { BaseListRoot } from "../base-list-root";
import { IProjectStore } from "store_legacy/project"; import { IProjectStore } from "store_legacy/project";
import { EProjectStore } from "store_legacy/command-palette.store"; import { EProjectStore } from "store_legacy/command-palette.store";
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserProjectRoles } from "constants/project";
export const ProfileIssuesListLayout: FC = observer(() => { export const ProfileIssuesListLayout: FC = observer(() => {
const router = useRouter(); const router = useRouter();
@ -46,9 +46,9 @@ export const ProfileIssuesListLayout: FC = observer(() => {
console.log( console.log(
projectId, projectId,
currentWorkspaceUserProjectsRole, currentWorkspaceUserProjectsRole,
!!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER
); );
return !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER; return !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
}; };
return ( return (

View File

@ -14,7 +14,7 @@ import { IIssue } from "types";
import { IQuickActionProps } from "../list/list-view-types"; import { IQuickActionProps } from "../list/list-view-types";
import { EProjectStore } from "store_legacy/command-palette.store"; import { EProjectStore } from "store_legacy/command-palette.store";
// constant // constant
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserProjectRoles } from "constants/project";
export const ProjectIssueQuickActions: React.FC<IQuickActionProps> = (props) => { export const ProjectIssueQuickActions: React.FC<IQuickActionProps> = (props) => {
const { issue, handleDelete, handleUpdate, customActionButton } = props; const { issue, handleDelete, handleUpdate, customActionButton } = props;
@ -30,7 +30,7 @@ export const ProjectIssueQuickActions: React.FC<IQuickActionProps> = (props) =>
membership: { currentProjectRole }, membership: { currentProjectRole },
} = useUser(); } = useUser();
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER; const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
const { setToastAlert } = useToast(); const { setToastAlert } = useToast();

View File

@ -16,7 +16,7 @@ import { IIssueUnGroupedStructure } from "store_legacy/issue";
import { EIssueActions } from "../types"; import { EIssueActions } from "../types";
import { EFilterType, TUnGroupedIssues } from "store_legacy/issues/types"; import { EFilterType, TUnGroupedIssues } from "store_legacy/issues/types";
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserProjectRoles } from "constants/project";
type Props = { type Props = {
type?: TStaticViewTypes | null; type?: TStaticViewTypes | null;
@ -62,7 +62,7 @@ export const AllIssueLayoutRoot: React.FC<Props> = observer((props) => {
const currentProjectRole = currentWorkspaceUserProjectsRole && currentWorkspaceUserProjectsRole[projectId]; const currentProjectRole = currentWorkspaceUserProjectsRole && currentWorkspaceUserProjectsRole[projectId];
return !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER; return !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
}; };
const issuesResponse = getIssues; const issuesResponse = getIssues;

View File

@ -18,7 +18,7 @@ import { observer } from "mobx-react-lite";
import { EFilterType, TUnGroupedIssues } from "store_legacy/issues/types"; import { EFilterType, TUnGroupedIssues } from "store_legacy/issues/types";
import { EIssueActions } from "../types"; import { EIssueActions } from "../types";
import { IQuickActionProps } from "../list/list-view-types"; import { IQuickActionProps } from "../list/list-view-types";
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserProjectRoles } from "constants/project";
interface IBaseSpreadsheetRoot { interface IBaseSpreadsheetRoot {
issueFiltersStore: issueFiltersStore:
@ -53,7 +53,7 @@ export const BaseSpreadsheetRoot = observer((props: IBaseSpreadsheetRoot) => {
const { enableInlineEditing, enableQuickAdd, enableIssueCreation } = issueStore?.viewFlags || {}; const { enableInlineEditing, enableQuickAdd, enableIssueCreation } = issueStore?.viewFlags || {};
const { currentProjectRole } = userStore; const { currentProjectRole } = userStore;
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER; const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
const canEditProperties = (projectId: string | undefined) => { const canEditProperties = (projectId: string | undefined) => {
const isEditingAllowedBasedOnProject = const isEditingAllowedBasedOnProject =

View File

@ -27,7 +27,7 @@ import { IIssue, IIssueActivity } from "types";
// fetch-keys // fetch-keys
import { PROJECT_ISSUES_ACTIVITY, SUB_ISSUES } from "constants/fetch-keys"; import { PROJECT_ISSUES_ACTIVITY, SUB_ISSUES } from "constants/fetch-keys";
// constants // constants
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserProjectRoles } from "constants/project";
type Props = { type Props = {
issueDetails: IIssue; issueDetails: IIssue;
@ -151,7 +151,7 @@ export const IssueMainContent: React.FC<Props> = observer((props) => {
); );
}; };
const isAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER; const isAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
return ( return (
<> <>

View File

@ -16,7 +16,7 @@ import { IIssue, IUser } from "types";
// services // services
import { FileService } from "services/file.service"; import { FileService } from "services/file.service";
// constants // constants
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserProjectRoles } from "constants/project";
const fileService = new FileService(); const fileService = new FileService();
@ -48,7 +48,7 @@ export const PeekOverviewIssueDetails: FC<IPeekOverviewIssueDetails> = (props) =
const { const {
membership: { currentProjectRole }, membership: { currentProjectRole },
} = useUser(); } = useUser();
const isAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER; const isAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
// states // states
const [characterLimit, setCharacterLimit] = useState(false); const [characterLimit, setCharacterLimit] = useState(false);
// hooks // hooks

View File

@ -23,7 +23,7 @@ import { LinkModal, LinksList } from "components/core";
// types // types
import { IIssue, TIssuePriorities, ILinkDetails, IIssueLink } from "types"; import { IIssue, TIssuePriorities, ILinkDetails, IIssueLink } from "types";
// constants // constants
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserProjectRoles } from "constants/project";
interface IPeekOverviewProperties { interface IPeekOverviewProperties {
issue: IIssue; issue: IIssue;
@ -295,10 +295,10 @@ export const PeekOverviewProperties: FC<IPeekOverviewProperties> = observer((pro
handleDeleteLink={issueLinkDelete} handleDeleteLink={issueLinkDelete}
handleEditLink={handleEditLink} handleEditLink={handleEditLink}
userAuth={{ userAuth={{
isGuest: currentProjectRole === EUserWorkspaceRoles.GUEST, isGuest: currentProjectRole === EUserProjectRoles.GUEST,
isViewer: currentProjectRole === EUserWorkspaceRoles.VIEWER, isViewer: currentProjectRole === EUserProjectRoles.VIEWER,
isMember: currentProjectRole === EUserWorkspaceRoles.MEMBER, isMember: currentProjectRole === EUserProjectRoles.MEMBER,
isOwner: currentProjectRole === EUserWorkspaceRoles.ADMIN, isOwner: currentProjectRole === EUserProjectRoles.ADMIN,
}} }}
/> />
) : null} ) : null}

View File

@ -12,7 +12,7 @@ import { copyUrlToClipboard } from "helpers/string.helper";
// types // types
import { IIssue, IIssueLink } from "types"; import { IIssue, IIssueLink } from "types";
// constants // constants
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserProjectRoles } from "constants/project";
interface IIssuePeekOverview { interface IIssuePeekOverview {
workspaceSlug: string; workspaceSlug: string;
@ -146,7 +146,7 @@ export const IssuePeekOverview: FC<IIssuePeekOverview> = observer((props) => {
} }
}; };
const userRole = currentProjectRole ?? EUserWorkspaceRoles.GUEST; const userRole = currentProjectRole ?? EUserProjectRoles.GUEST;
return ( return (
<Fragment> <Fragment>

View File

@ -40,7 +40,7 @@ import { copyTextToClipboard } from "helpers/string.helper";
import type { IIssue, IIssueLink, ILinkDetails } from "types"; import type { IIssue, IIssueLink, ILinkDetails } from "types";
// fetch-keys // fetch-keys
import { ISSUE_DETAILS, PROJECT_ISSUES_ACTIVITY } from "constants/fetch-keys"; import { ISSUE_DETAILS, PROJECT_ISSUES_ACTIVITY } from "constants/fetch-keys";
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserProjectRoles } from "constants/project";
type Props = { type Props = {
control: any; control: any;
@ -191,7 +191,7 @@ export const IssueDetailsSidebar: React.FC<Props> = observer((props) => {
setLinkModal(true); setLinkModal(true);
}; };
const isAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER; const isAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
const currentIssueState = projectStates?.find((s) => s.id === issueDetail?.state); const currentIssueState = projectStates?.find((s) => s.id === issueDetail?.state);

View File

@ -22,7 +22,8 @@ import { IUser, IIssue, ISearchIssueResponse } from "types";
import { IssueService } from "services/issue"; import { IssueService } from "services/issue";
// fetch keys // fetch keys
import { SUB_ISSUES } from "constants/fetch-keys"; import { SUB_ISSUES } from "constants/fetch-keys";
import { EUserWorkspaceRoles } from "constants/workspace"; // constants
import { EUserProjectRoles } from "constants/project";
export interface ISubIssuesRoot { export interface ISubIssuesRoot {
parentIssue: IIssue; parentIssue: IIssue;
@ -178,7 +179,7 @@ export const SubIssuesRoot: React.FC<ISubIssuesRoot> = observer((props) => {
[updateIssueStructure, projectId, updateIssue, user, workspaceSlug] [updateIssueStructure, projectId, updateIssue, user, workspaceSlug]
); );
const isEditable = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER; const isEditable = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
const mutateSubIssues = (parentIssueId: string | null) => { const mutateSubIssues = (parentIssueId: string | null) => {
if (parentIssueId) mutate(SUB_ISSUES(parentIssueId)); if (parentIssueId) mutate(SUB_ISSUES(parentIssueId));

View File

@ -15,7 +15,7 @@ import { copyUrlToClipboard } from "helpers/string.helper";
import { renderShortDate, renderShortMonthDate } from "helpers/date-time.helper"; import { renderShortDate, renderShortMonthDate } from "helpers/date-time.helper";
// constants // constants
import { MODULE_STATUS } from "constants/module"; import { MODULE_STATUS } from "constants/module";
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserProjectRoles } from "constants/project";
type Props = { type Props = {
moduleId: string; moduleId: string;
@ -38,7 +38,7 @@ export const ModuleCardItem: React.FC<Props> = observer((props) => {
const { getModuleById, addModuleToFavorites, removeModuleFromFavorites } = useModule(); const { getModuleById, addModuleToFavorites, removeModuleFromFavorites } = useModule();
// derived values // derived values
const moduleDetails = getModuleById(moduleId); const moduleDetails = getModuleById(moduleId);
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER; const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
const handleAddToFavorites = (e: React.MouseEvent<HTMLButtonElement>) => { const handleAddToFavorites = (e: React.MouseEvent<HTMLButtonElement>) => {
e.stopPropagation(); e.stopPropagation();

View File

@ -15,7 +15,7 @@ import { copyUrlToClipboard } from "helpers/string.helper";
import { renderShortDate, renderShortMonthDate } from "helpers/date-time.helper"; import { renderShortDate, renderShortMonthDate } from "helpers/date-time.helper";
// constants // constants
import { MODULE_STATUS } from "constants/module"; import { MODULE_STATUS } from "constants/module";
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserProjectRoles } from "constants/project";
type Props = { type Props = {
moduleId: string; moduleId: string;
@ -38,7 +38,7 @@ export const ModuleListItem: React.FC<Props> = observer((props) => {
const { getModuleById, addModuleToFavorites, removeModuleFromFavorites } = useModule(); const { getModuleById, addModuleToFavorites, removeModuleFromFavorites } = useModule();
// derived values // derived values
const moduleDetails = getModuleById(moduleId); const moduleDetails = getModuleById(moduleId);
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER; const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
const handleAddToFavorites = (e: React.MouseEvent<HTMLButtonElement>) => { const handleAddToFavorites = (e: React.MouseEvent<HTMLButtonElement>) => {
e.stopPropagation(); e.stopPropagation();

View File

@ -9,7 +9,7 @@ import { ModuleCardItem, ModuleListItem, ModulePeekOverview, ModulesListGanttCha
// ui // ui
import { Loader } from "@plane/ui"; import { Loader } from "@plane/ui";
// constants // constants
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserProjectRoles } from "constants/project";
// assets // assets
import emptyModule from "public/empty-state/empty_modules.webp"; import emptyModule from "public/empty-state/empty_modules.webp";
import { NewEmptyState } from "components/common/new-empty-state"; import { NewEmptyState } from "components/common/new-empty-state";
@ -27,7 +27,7 @@ export const ModulesListView: React.FC = observer(() => {
const { storedValue: modulesView } = useLocalStorage("modules_view", "grid"); const { storedValue: modulesView } = useLocalStorage("modules_view", "grid");
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER; const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
if (!projectModules) if (!projectModules)
return ( return (

View File

@ -28,7 +28,7 @@ import { copyUrlToClipboard } from "helpers/string.helper";
import { ILinkDetails, IModule, ModuleLink } from "types"; import { ILinkDetails, IModule, ModuleLink } from "types";
// constant // constant
import { MODULE_STATUS } from "constants/module"; import { MODULE_STATUS } from "constants/module";
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserProjectRoles } from "constants/project";
const defaultValues: Partial<IModule> = { const defaultValues: Partial<IModule> = {
lead: "", lead: "",
@ -255,7 +255,7 @@ export const ModuleDetailsSidebar: React.FC<Props> = observer((props) => {
: `${moduleDetails.total_issues}` : `${moduleDetails.total_issues}`
: `${moduleDetails.completed_issues}/${moduleDetails.total_issues}`; : `${moduleDetails.completed_issues}/${moduleDetails.total_issues}`;
const isEditingAllowed = !!userRole && userRole >= EUserWorkspaceRoles.MEMBER; const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
return ( return (
<> <>
@ -583,10 +583,10 @@ export const ModuleDetailsSidebar: React.FC<Props> = observer((props) => {
handleEditLink={handleEditLink} handleEditLink={handleEditLink}
handleDeleteLink={handleDeleteLink} handleDeleteLink={handleDeleteLink}
userAuth={{ userAuth={{
isGuest: currentProjectRole === EUserWorkspaceRoles.GUEST, isGuest: currentProjectRole === EUserProjectRoles.GUEST,
isViewer: currentProjectRole === EUserWorkspaceRoles.VIEWER, isViewer: currentProjectRole === EUserProjectRoles.VIEWER,
isMember: currentProjectRole === EUserWorkspaceRoles.MEMBER, isMember: currentProjectRole === EUserProjectRoles.MEMBER,
isOwner: currentProjectRole === EUserWorkspaceRoles.ADMIN, isOwner: currentProjectRole === EUserProjectRoles.ADMIN,
}} }}
/> />
</> </>

View File

@ -9,7 +9,7 @@ import { TourRoot } from "components/onboarding";
import { UserGreetingsView } from "components/user"; import { UserGreetingsView } from "components/user";
import { CompletedIssuesGraph, IssuesList, IssuesPieChart, IssuesStats } from "components/workspace"; import { CompletedIssuesGraph, IssuesList, IssuesPieChart, IssuesStats } from "components/workspace";
// constants // constants
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserProjectRoles } from "constants/project";
// images // images
import { NewEmptyState } from "components/common/new-empty-state"; import { NewEmptyState } from "components/common/new-empty-state";
import emptyProject from "public/empty-state/dashboard_empty_project.webp"; import emptyProject from "public/empty-state/dashboard_empty_project.webp";
@ -25,7 +25,13 @@ export const WorkspaceDashboardView = observer(() => {
commandPalette: commandPaletteStore, commandPalette: commandPaletteStore,
eventTracker: { setTrackElement, postHogEventTracker }, eventTracker: { setTrackElement, postHogEventTracker },
} = useApplication(); } = useApplication();
const { currentUser, dashboardInfo: workspaceDashboardInfo, fetchUserDashboardInfo, updateTourCompleted } = useUser(); const {
currentUser,
dashboardInfo: workspaceDashboardInfo,
fetchUserDashboardInfo,
updateTourCompleted,
membership: { currentProjectRole },
} = useUser();
const { workspaceProjects } = useProject(); const { workspaceProjects } = useProject();
// fetch user dashboard info // fetch user dashboard info
useSWR( useSWR(
@ -33,7 +39,7 @@ export const WorkspaceDashboardView = observer(() => {
workspaceSlug ? () => fetchUserDashboardInfo(workspaceSlug.toString(), month) : null workspaceSlug ? () => fetchUserDashboardInfo(workspaceSlug.toString(), month) : null
); );
const isEditingAllowed = !!userStore.currentProjectRole && userStore.currentProjectRole >= EUserWorkspaceRoles.MEMBER; const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
const handleTourCompleted = () => { const handleTourCompleted = () => {
updateTourCompleted() updateTourCompleted()

View File

@ -26,7 +26,7 @@ import { CustomMenu, Tooltip } from "@plane/ui";
// components // components
import { CreateUpdatePageModal, DeletePageModal } from "components/pages"; import { CreateUpdatePageModal, DeletePageModal } from "components/pages";
// constants // constants
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserProjectRoles } from "constants/project";
export interface IPagesListItem { export interface IPagesListItem {
workspaceSlug: string; workspaceSlug: string;
@ -168,11 +168,11 @@ export const PagesListItem: FC<IPagesListItem> = observer((props) => {
const userCanEdit = const userCanEdit =
isCurrentUserOwner || isCurrentUserOwner ||
(currentProjectRole && [EUserWorkspaceRoles.ADMIN, EUserWorkspaceRoles.MEMBER].includes(currentProjectRole)); (currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole));
const userCanChangeAccess = isCurrentUserOwner; const userCanChangeAccess = isCurrentUserOwner;
const userCanArchive = isCurrentUserOwner || currentProjectRole === EUserWorkspaceRoles.ADMIN; const userCanArchive = isCurrentUserOwner || currentProjectRole === EUserProjectRoles.ADMIN;
const userCanDelete = isCurrentUserOwner || currentProjectRole === EUserWorkspaceRoles.ADMIN; const userCanDelete = isCurrentUserOwner || currentProjectRole === EUserProjectRoles.ADMIN;
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER; const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
return ( return (
<> <>

View File

@ -12,7 +12,7 @@ import { Loader } from "@plane/ui";
// images // images
import emptyPage from "public/empty-state/empty_page.png"; import emptyPage from "public/empty-state/empty_page.png";
// constants // constants
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserProjectRoles } from "constants/project";
type IPagesListView = { type IPagesListView = {
pages: string[]; pages: string[];
@ -31,7 +31,7 @@ export const PagesListView: FC<IPagesListView> = observer((props) => {
const router = useRouter(); const router = useRouter();
const { workspaceSlug, projectId } = router.query; const { workspaceSlug, projectId } = router.query;
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER; const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
return ( return (
<> <>

View File

@ -13,7 +13,7 @@ import emptyPage from "public/empty-state/empty_page.png";
// helpers // helpers
import { replaceUnderscoreIfSnakeCase } from "helpers/string.helper"; import { replaceUnderscoreIfSnakeCase } from "helpers/string.helper";
// constants // constants
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserProjectRoles } from "constants/project";
export const RecentPagesList: FC = observer(() => { export const RecentPagesList: FC = observer(() => {
// store hooks // store hooks
@ -25,7 +25,7 @@ export const RecentPagesList: FC = observer(() => {
const isEmpty = recentProjectPages && Object.values(recentProjectPages).every((value) => value.length === 0); const isEmpty = recentProjectPages && Object.values(recentProjectPages).every((value) => value.length === 0);
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER; const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
if (!recentProjectPages) { if (!recentProjectPages) {
return ( return (

View File

@ -9,7 +9,7 @@ import emptyProject from "public/empty-state/empty_project.webp";
// icons // icons
import { NewEmptyState } from "components/common/new-empty-state"; import { NewEmptyState } from "components/common/new-empty-state";
// constants // constants
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserProjectRoles } from "constants/project";
export const ProjectCardList = observer(() => { export const ProjectCardList = observer(() => {
// store hooks // store hooks
@ -22,7 +22,7 @@ export const ProjectCardList = observer(() => {
} = useUser(); } = useUser();
const { workspaceProjects, searchedProjects, getProjectById } = useProject(); const { workspaceProjects, searchedProjects, getProjectById } = useProject();
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER; const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
if (!workspaceProjects) if (!workspaceProjects)
return ( return (

View File

@ -15,7 +15,8 @@ import { ChevronDown, Dot, XCircle } from "lucide-react";
// constants // constants
import { EUserWorkspaceRoles, ROLE } from "constants/workspace"; import { EUserWorkspaceRoles, ROLE } from "constants/workspace";
// types // types
import { IProjectMember, TUserProjectRole } from "types"; import { IProjectMember } from "types";
import { EUserProjectRoles } from "constants/project";
type Props = { type Props = {
member: IProjectMember; member: IProjectMember;
@ -136,7 +137,7 @@ export const ProjectMemberListItem: React.FC<Props> = observer((props) => {
</div> </div>
} }
value={member.role} value={member.role}
onChange={(value: TUserProjectRole | undefined) => { onChange={(value: EUserProjectRoles | undefined) => {
if (!workspaceSlug || !projectId) return; if (!workspaceSlug || !projectId) return;
updateMember(workspaceSlug.toString(), projectId.toString(), member.id, { updateMember(workspaceSlug.toString(), projectId.toString(), member.id, {

View File

@ -15,7 +15,7 @@ import { IProject, IUserLite, IWorkspace } from "types";
// fetch-keys // fetch-keys
import { PROJECT_MEMBERS } from "constants/fetch-keys"; import { PROJECT_MEMBERS } from "constants/fetch-keys";
// constants // constants
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserProjectRoles } from "constants/project";
const defaultValues: Partial<IProject> = { const defaultValues: Partial<IProject> = {
project_lead: null, project_lead: null,
@ -32,7 +32,7 @@ export const ProjectSettingsMemberDefaults: React.FC = observer(() => {
} = useUser(); } = useUser();
const { currentProjectDetails, fetchProjectDetails, updateProject } = useProject(); const { currentProjectDetails, fetchProjectDetails, updateProject } = useProject();
const isAdmin = currentProjectRole === EUserWorkspaceRoles.ADMIN; const isAdmin = currentProjectRole === EUserProjectRoles.ADMIN;
// hooks // hooks
const { setToastAlert } = useToast(); const { setToastAlert } = useToast();
// form info // form info

View File

@ -13,9 +13,10 @@ import { Avatar, Button, CustomSelect, CustomSearchSelect } from "@plane/ui";
// services // services
import { ProjectMemberService } from "services/project"; import { ProjectMemberService } from "services/project";
// types // types
import { IProjectMember, TUserProjectRole } from "types"; import { IProjectMember } from "types";
// constants // constants
import { EUserWorkspaceRoles, ROLE } from "constants/workspace"; import { ROLE } from "constants/workspace";
import { EUserProjectRoles } from "constants/project";
type Props = { type Props = {
isOpen: boolean; isOpen: boolean;
@ -25,7 +26,7 @@ type Props = {
}; };
type member = { type member = {
role: TUserProjectRole; role: EUserProjectRoles;
member_id: string; member_id: string;
}; };
@ -267,8 +268,7 @@ export const SendProjectInvitationModal: React.FC<Props> = observer((props) => {
width="w-full" width="w-full"
> >
{Object.entries(ROLE).map(([key, label]) => { {Object.entries(ROLE).map(([key, label]) => {
if (parseInt(key) > (currentProjectRole ?? EUserWorkspaceRoles.GUEST)) if (parseInt(key) > (currentProjectRole ?? EUserProjectRoles.GUEST)) return null;
return null;
return ( return (
<CustomSelect.Option key={key} value={key}> <CustomSelect.Option key={key} value={key}>

View File

@ -9,7 +9,7 @@ import useToast from "hooks/use-toast";
// types // types
import { IProject } from "types"; import { IProject } from "types";
// constants // constants
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserProjectRoles } from "constants/project";
type Props = {}; type Props = {};
@ -60,7 +60,7 @@ export const ProjectFeaturesList: FC<Props> = observer(() => {
} = useUser(); } = useUser();
const { currentWorkspace } = useWorkspace(); const { currentWorkspace } = useWorkspace();
const { currentProjectDetails, updateProject } = useProject(); const { currentProjectDetails, updateProject } = useProject();
const isAdmin = currentProjectRole === EUserWorkspaceRoles.ADMIN; const isAdmin = currentProjectRole === EUserProjectRoles.ADMIN;
// toast alert // toast alert
const { setToastAlert } = useToast(); const { setToastAlert } = useToast();

View File

@ -2,15 +2,12 @@ import React, { useState } from "react";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
import { Dialog, Transition } from "@headlessui/react"; import { Dialog, Transition } from "@headlessui/react";
import { AlertTriangle } from "lucide-react";
// mobx store
import { useMobxStore } from "lib/mobx/store-provider";
// hooks // hooks
import { useProjectView } from "hooks/store";
import useToast from "hooks/use-toast"; import useToast from "hooks/use-toast";
// ui // ui
import { Button } from "@plane/ui"; import { Button } from "@plane/ui";
// icons
import { AlertTriangle } from "lucide-react";
// types // types
import { IProjectView } from "types"; import { IProjectView } from "types";
@ -22,14 +19,14 @@ type Props = {
export const DeleteProjectViewModal: React.FC<Props> = observer((props) => { export const DeleteProjectViewModal: React.FC<Props> = observer((props) => {
const { data, isOpen, onClose } = props; const { data, isOpen, onClose } = props;
// states
const [isDeleteLoading, setIsDeleteLoading] = useState(false); const [isDeleteLoading, setIsDeleteLoading] = useState(false);
// router
const router = useRouter(); const router = useRouter();
const { workspaceSlug, projectId } = router.query; const { workspaceSlug, projectId } = router.query;
// store hooks
const { projectViews: projectViewsStore } = useMobxStore(); const { deleteView } = useProjectView();
// toast alert
const { setToastAlert } = useToast(); const { setToastAlert } = useToast();
const handleClose = () => { const handleClose = () => {
@ -42,8 +39,7 @@ export const DeleteProjectViewModal: React.FC<Props> = observer((props) => {
setIsDeleteLoading(true); setIsDeleteLoading(true);
await projectViewsStore await deleteView(workspaceSlug.toString(), projectId.toString(), data.id)
.deleteView(workspaceSlug.toString(), projectId.toString(), data.id)
.then(() => { .then(() => {
handleClose(); handleClose();

View File

@ -1,14 +1,14 @@
import { FC, Fragment } from "react"; import { FC, Fragment } from "react";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
import { Dialog, Transition } from "@headlessui/react"; import { Dialog, Transition } from "@headlessui/react";
import { debounce } from "lodash";
// hooks // hooks
import { useMobxStore } from "lib/mobx/store-provider"; import { useProjectView } from "hooks/store";
import useToast from "hooks/use-toast"; import useToast from "hooks/use-toast";
// components // components
import { ProjectViewForm } from "components/views"; import { ProjectViewForm } from "components/views";
// types // types
import { IProjectView } from "types"; import { IProjectView } from "types";
import { debounce } from "lodash";
type Props = { type Props = {
data?: IProjectView | null; data?: IProjectView | null;
@ -21,18 +21,17 @@ type Props = {
export const CreateUpdateProjectViewModal: FC<Props> = observer((props) => { export const CreateUpdateProjectViewModal: FC<Props> = observer((props) => {
const { data, isOpen, onClose, preLoadedData, workspaceSlug, projectId } = props; const { data, isOpen, onClose, preLoadedData, workspaceSlug, projectId } = props;
// store // store hooks
const { projectViews: projectViewsStore } = useMobxStore(); const { createView, updateView } = useProjectView();
// hooks // toast alert
const { setToastAlert } = useToast(); const { setToastAlert } = useToast();
const handleClose = () => { const handleClose = () => {
onClose(); onClose();
}; };
const createView = async (payload: IProjectView) => { const handleCreateView = async (payload: IProjectView) => {
await projectViewsStore await createView(workspaceSlug, projectId, payload)
.createView(workspaceSlug, projectId, payload)
.then(() => { .then(() => {
console.log("after calling store"); console.log("after calling store");
handleClose(); handleClose();
@ -52,9 +51,8 @@ export const CreateUpdateProjectViewModal: FC<Props> = observer((props) => {
); );
}; };
const updateView = async (payload: IProjectView) => { const handleUpdateView = async (payload: IProjectView) => {
await projectViewsStore await updateView(workspaceSlug, projectId, data?.id as string, payload)
.updateView(workspaceSlug, projectId, data?.id as string, payload)
.then(() => handleClose()) .then(() => handleClose())
.catch((err) => .catch((err) =>
setToastAlert({ setToastAlert({
@ -66,8 +64,8 @@ export const CreateUpdateProjectViewModal: FC<Props> = observer((props) => {
}; };
const handleFormSubmit = async (formData: IProjectView) => { const handleFormSubmit = async (formData: IProjectView) => {
if (!data) await createView(formData); if (!data) await handleCreateView(formData);
else await updateView(formData); else await handleUpdateView(formData);
}; };
const debouncedFormSubmit = debounce(handleFormSubmit, 10, { leading: false, trailing: true }); const debouncedFormSubmit = debounce(handleFormSubmit, 10, { leading: false, trailing: true });

View File

@ -4,8 +4,7 @@ import { useRouter } from "next/router";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
import { LinkIcon, PencilIcon, StarIcon, TrashIcon } from "lucide-react"; import { LinkIcon, PencilIcon, StarIcon, TrashIcon } from "lucide-react";
// hooks // hooks
import { useUser } from "hooks/store"; import { useProjectView, useUser } from "hooks/store";
import { useMobxStore } from "lib/mobx/store-provider";
import useToast from "hooks/use-toast"; import useToast from "hooks/use-toast";
// components // components
import { CreateUpdateProjectViewModal, DeleteProjectViewModal } from "components/views"; import { CreateUpdateProjectViewModal, DeleteProjectViewModal } from "components/views";
@ -17,7 +16,7 @@ import { copyUrlToClipboard } from "helpers/string.helper";
// types // types
import { IProjectView } from "types"; import { IProjectView } from "types";
// constants // constants
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserProjectRoles } from "constants/project";
type Props = { type Props = {
view: IProjectView; view: IProjectView;
@ -34,21 +33,21 @@ export const ProjectViewListItem: React.FC<Props> = observer((props) => {
// toast alert // toast alert
const { setToastAlert } = useToast(); const { setToastAlert } = useToast();
// store hooks // store hooks
const { projectViews: projectViewsStore } = useMobxStore();
const { const {
membership: { currentProjectRole }, membership: { currentProjectRole },
} = useUser(); } = useUser();
const { addViewToFavorites, removeViewFromFavorites } = useProjectView();
const handleAddToFavorites = () => { const handleAddToFavorites = () => {
if (!workspaceSlug || !projectId) return; if (!workspaceSlug || !projectId) return;
projectViewsStore.addViewToFavorites(workspaceSlug.toString(), projectId.toString(), view.id); addViewToFavorites(workspaceSlug.toString(), projectId.toString(), view.id);
}; };
const handleRemoveFromFavorites = () => { const handleRemoveFromFavorites = () => {
if (!workspaceSlug || !projectId) return; if (!workspaceSlug || !projectId) return;
projectViewsStore.removeViewFromFavorites(workspaceSlug.toString(), projectId.toString(), view.id); removeViewFromFavorites(workspaceSlug.toString(), projectId.toString(), view.id);
}; };
const handleCopyText = (e: React.MouseEvent<HTMLButtonElement>) => { const handleCopyText = (e: React.MouseEvent<HTMLButtonElement>) => {
@ -65,7 +64,7 @@ export const ProjectViewListItem: React.FC<Props> = observer((props) => {
const totalFilters = calculateTotalFilters(view.query_data ?? {}); const totalFilters = calculateTotalFilters(view.query_data ?? {});
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER; const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
return ( return (
<> <>

View File

@ -1,10 +1,8 @@
import { useState } from "react"; import { useState } from "react";
import { useRouter } from "next/router";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
import { Plus, Search } from "lucide-react"; import { Plus, Search } from "lucide-react";
// hooks // hooks
import { useApplication, useUser } from "hooks/store"; import { useApplication, useProjectView, useUser } from "hooks/store";
import { useMobxStore } from "lib/mobx/store-provider";
// components // components
import { ProjectViewListItem } from "components/views"; import { ProjectViewListItem } from "components/views";
import { NewEmptyState } from "components/common/new-empty-state"; import { NewEmptyState } from "components/common/new-empty-state";
@ -13,28 +11,23 @@ import { Input, Loader } from "@plane/ui";
// assets // assets
import emptyView from "public/empty-state/empty_view.webp"; import emptyView from "public/empty-state/empty_view.webp";
// constants // constants
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserProjectRoles } from "constants/project";
export const ProjectViewsList = observer(() => { export const ProjectViewsList = observer(() => {
// states // states
const [query, setQuery] = useState(""); const [query, setQuery] = useState("");
// router
const router = useRouter();
const { projectId } = router.query;
// store hooks // store hooks
const { projectViews: projectViewsStore } = useMobxStore();
const { const {
commandPalette: { toggleCreateViewModal }, commandPalette: { toggleCreateViewModal },
} = useApplication(); } = useApplication();
const { const {
membership: { currentProjectRole }, membership: { currentProjectRole },
} = useUser(); } = useUser();
const { projectViews, getViewById } = useProjectView();
const viewsList = projectId ? projectViewsStore.viewsList[projectId.toString()] : undefined; const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER; if (!projectViews)
if (!viewsList)
return ( return (
<Loader className="space-y-4 p-4"> <Loader className="space-y-4 p-4">
<Loader.Item height="72px" /> <Loader.Item height="72px" />
@ -44,7 +37,9 @@ export const ProjectViewsList = observer(() => {
</Loader> </Loader>
); );
const filteredViewsList = viewsList.filter((v) => v.name.toLowerCase().includes(query.toLowerCase())); const viewsList = projectViews.map((viewId) => getViewById(viewId));
const filteredViewsList = viewsList.filter((v) => v?.name.toLowerCase().includes(query.toLowerCase()));
return ( return (
<> <>

View File

@ -1,6 +1,13 @@
import { Globe2, Lock, LucideIcon } from "lucide-react"; import { Globe2, Lock, LucideIcon } from "lucide-react";
import { TIssuePriorities } from "types"; import { TIssuePriorities } from "types";
export enum EUserProjectRoles {
GUEST = 5,
VIEWER = 10,
MEMBER = 15,
ADMIN = 20,
}
export const NETWORK_CHOICES: { key: 0 | 2; label: string; icon: LucideIcon }[] = [ export const NETWORK_CHOICES: { key: 0 | 2; label: string; icon: LucideIcon }[] = [
{ {
key: 0, key: 0,
@ -53,7 +60,6 @@ export const PROJECT_AUTOMATION_MONTHS = [
export const STATE_GROUP_KEYS = ["backlog", "unstarted", "started", "completed", "cancelled"]; export const STATE_GROUP_KEYS = ["backlog", "unstarted", "started", "completed", "cancelled"];
export const PROJECT_UNSPLASH_COVERS = [ export const PROJECT_UNSPLASH_COVERS = [
"https://images.unsplash.com/photo-1531045535792-b515d59c3d1f?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=870&q=80", "https://images.unsplash.com/photo-1531045535792-b515d59c3d1f?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=870&q=80",
"https://images.unsplash.com/photo-1693027407934-e3aa8a54c7ae?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=870&q=80", "https://images.unsplash.com/photo-1693027407934-e3aa8a54c7ae?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=870&q=80",

View File

@ -5,6 +5,7 @@ export * from "./use-module";
export * from "./use-page"; export * from "./use-page";
export * from "./use-project-publish"; export * from "./use-project-publish";
export * from "./use-project-state"; export * from "./use-project-state";
export * from "./use-project-view";
export * from "./use-project"; export * from "./use-project";
export * from "./use-user"; export * from "./use-user";
export * from "./use-webhook"; export * from "./use-webhook";

View File

@ -0,0 +1,11 @@
import { useContext } from "react";
// mobx store
import { MobxStoreContext } from "lib/mobx/store-provider";
// types
import { IProjectViewStore } from "store/project-view.store";
export const useProjectView = (): IProjectViewStore => {
const context = useContext(MobxStoreContext);
if (context === undefined) throw new Error("useMobxStore must be used within MobxStoreProvider");
return context.projectView;
};

View File

@ -3,7 +3,16 @@ import { useRouter } from "next/router";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
import useSWR from "swr"; import useSWR from "swr";
// hooks // hooks
import { useApplication, useCycle, useLabel, useModule, useProjectState, useUser } from "hooks/store"; import {
useApplication,
useCycle,
useLabel,
useModule,
useProject,
useProjectState,
useProjectView,
useUser,
} from "hooks/store";
import { useMobxStore } from "lib/mobx/store-provider"; import { useMobxStore } from "lib/mobx/store-provider";
// components // components
import { Spinner } from "@plane/ui"; import { Spinner } from "@plane/ui";
@ -20,10 +29,8 @@ export const ProjectAuthWrapper: FC<IProjectAuthWrapper> = observer((props) => {
const { children } = props; const { children } = props;
// store // store
const { const {
project: { fetchProjectDetails, workspaceProjects },
projectMember: { fetchProjectMembers }, projectMember: { fetchProjectMembers },
projectEstimates: { fetchProjectEstimates }, projectEstimates: { fetchProjectEstimates },
projectViews: { fetchAllViews },
inbox: { fetchInboxesList, isInboxEnabled }, inbox: { fetchInboxesList, isInboxEnabled },
} = useMobxStore(); } = useMobxStore();
const { const {
@ -32,8 +39,10 @@ export const ProjectAuthWrapper: FC<IProjectAuthWrapper> = observer((props) => {
const { const {
membership: { fetchUserProjectInfo, projectMemberInfo, hasPermissionToProject }, membership: { fetchUserProjectInfo, projectMemberInfo, hasPermissionToProject },
} = useUser(); } = useUser();
const { getProjectById, fetchProjectDetails } = useProject();
const { fetchAllCycles } = useCycle(); const { fetchAllCycles } = useCycle();
const { fetchModules } = useModule(); const { fetchModules } = useModule();
const { fetchViews } = useProjectView();
const { fetchProjectStates } = useProjectState(); const { fetchProjectStates } = useProjectState();
const { const {
project: { fetchProjectLabels }, project: { fetchProjectLabels },
@ -85,7 +94,7 @@ export const ProjectAuthWrapper: FC<IProjectAuthWrapper> = observer((props) => {
// fetching project views // fetching project views
useSWR( useSWR(
workspaceSlug && projectId ? `PROJECT_VIEWS_${workspaceSlug}_${projectId}` : null, workspaceSlug && projectId ? `PROJECT_VIEWS_${workspaceSlug}_${projectId}` : null,
workspaceSlug && projectId ? () => fetchAllViews(workspaceSlug.toString(), projectId.toString()) : null workspaceSlug && projectId ? () => fetchViews(workspaceSlug.toString(), projectId.toString()) : null
); );
// fetching project inboxes if inbox is enabled // fetching project inboxes if inbox is enabled
useSWR( useSWR(
@ -99,8 +108,7 @@ export const ProjectAuthWrapper: FC<IProjectAuthWrapper> = observer((props) => {
} }
); );
const projectsList = workspaceSlug ? workspaceProjects : null; const projectExists = projectId ? getProjectById(projectId.toString()) : null;
const projectExists = projectId ? projectsList?.find((project) => project.id === projectId.toString()) : null;
// check if the project member apis is loading // check if the project member apis is loading
if (!projectMemberInfo && projectId && hasPermissionToProject[projectId.toString()] === null) if (!projectMemberInfo && projectId && hasPermissionToProject[projectId.toString()] === null)

View File

@ -9,7 +9,7 @@ import { NotAuthorizedView } from "components/auth-screens";
// ui // ui
import { Button, LayersIcon } from "@plane/ui"; import { Button, LayersIcon } from "@plane/ui";
// constants // constants
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserProjectRoles } from "constants/project";
export interface IProjectSettingLayout { export interface IProjectSettingLayout {
children: ReactNode; children: ReactNode;
@ -25,7 +25,7 @@ export const ProjectSettingLayout: FC<IProjectSettingLayout> = observer((props)
membership: { currentProjectRole }, membership: { currentProjectRole },
} = useUser(); } = useUser();
const restrictViewSettings = currentProjectRole && currentProjectRole <= EUserWorkspaceRoles.VIEWER; const restrictViewSettings = currentProjectRole && currentProjectRole <= EUserProjectRoles.VIEWER;
return restrictViewSettings ? ( return restrictViewSettings ? (
<NotAuthorizedView <NotAuthorizedView

View File

@ -34,7 +34,7 @@ import { IPage, IIssue } from "types";
// fetch-keys // fetch-keys
import { PAGE_DETAILS, PROJECT_ISSUES_LIST } from "constants/fetch-keys"; import { PAGE_DETAILS, PROJECT_ISSUES_LIST } from "constants/fetch-keys";
// constants // constants
import { EUserWorkspaceRoles } from "constants/workspace"; import { EUserProjectRoles } from "constants/project";
// services // services
const fileService = new FileService(); const fileService = new FileService();
@ -362,15 +362,15 @@ const PageDetailsPage: NextPageWithLayout = observer(() => {
const isPageReadOnly = const isPageReadOnly =
pageDetails?.is_locked || pageDetails?.is_locked ||
pageDetails?.archived_at || pageDetails?.archived_at ||
(currentProjectRole && [EUserWorkspaceRoles.VIEWER, EUserWorkspaceRoles.GUEST].includes(currentProjectRole)); (currentProjectRole && [EUserProjectRoles.VIEWER, EUserProjectRoles.GUEST].includes(currentProjectRole));
const isCurrentUserOwner = pageDetails?.owned_by === currentUser?.id; const isCurrentUserOwner = pageDetails?.owned_by === currentUser?.id;
const userCanDuplicate = const userCanDuplicate =
currentProjectRole && [EUserWorkspaceRoles.ADMIN, EUserWorkspaceRoles.MEMBER].includes(currentProjectRole); currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole);
const userCanArchive = isCurrentUserOwner || currentProjectRole === EUserWorkspaceRoles.ADMIN; const userCanArchive = isCurrentUserOwner || currentProjectRole === EUserProjectRoles.ADMIN;
const userCanLock = const userCanLock =
currentProjectRole && [EUserWorkspaceRoles.ADMIN, EUserWorkspaceRoles.MEMBER].includes(currentProjectRole); currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole);
return ( return (
<> <>

View File

@ -14,7 +14,8 @@ import { ProjectSettingHeader } from "components/headers";
// types // types
import { NextPageWithLayout } from "types/app"; import { NextPageWithLayout } from "types/app";
import { IProject } from "types"; import { IProject } from "types";
import { EUserWorkspaceRoles } from "constants/workspace"; // constants
import { EUserProjectRoles } from "constants/project";
const AutomationSettingsPage: NextPageWithLayout = observer(() => { const AutomationSettingsPage: NextPageWithLayout = observer(() => {
// router // router
@ -40,7 +41,7 @@ const AutomationSettingsPage: NextPageWithLayout = observer(() => {
}); });
}; };
const isAdmin = currentProjectRole === EUserWorkspaceRoles.ADMIN; const isAdmin = currentProjectRole === EUserProjectRoles.ADMIN;
return ( return (
<section className={`w-full overflow-y-auto py-8 pr-9 ${isAdmin ? "" : "opacity-60"}`}> <section className={`w-full overflow-y-auto py-8 pr-9 ${isAdmin ? "" : "opacity-60"}`}>

View File

@ -10,14 +10,15 @@ import { ProjectSettingHeader } from "components/headers";
import { EstimatesList } from "components/estimates"; import { EstimatesList } from "components/estimates";
// types // types
import { NextPageWithLayout } from "types/app"; import { NextPageWithLayout } from "types/app";
import { EUserWorkspaceRoles } from "constants/workspace"; // constants
import { EUserProjectRoles } from "constants/project";
const EstimatesSettingsPage: NextPageWithLayout = observer(() => { const EstimatesSettingsPage: NextPageWithLayout = observer(() => {
const { const {
membership: { currentProjectRole }, membership: { currentProjectRole },
} = useUser(); } = useUser();
const isAdmin = currentProjectRole === EUserWorkspaceRoles.ADMIN; const isAdmin = currentProjectRole === EUserProjectRoles.ADMIN;
return ( return (
<div className={`w-full overflow-y-auto py-8 pr-9 ${isAdmin ? "" : "pointer-events-none opacity-60"}`}> <div className={`w-full overflow-y-auto py-8 pr-9 ${isAdmin ? "" : "pointer-events-none opacity-60"}`}>

View File

@ -1,8 +1,8 @@
import { ReactElement } from "react"; import { ReactElement } from "react";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import useSWR from "swr"; import useSWR from "swr";
// mobx store // hooks
import { useMobxStore } from "lib/mobx/store-provider"; import { useProjectView } from "hooks/store";
// layouts // layouts
import { AppLayout } from "layouts/app-layout"; import { AppLayout } from "layouts/app-layout";
// components // components
@ -16,15 +16,16 @@ import emptyView from "public/empty-state/view.svg";
import { NextPageWithLayout } from "types/app"; import { NextPageWithLayout } from "types/app";
const ProjectViewIssuesPage: NextPageWithLayout = () => { const ProjectViewIssuesPage: NextPageWithLayout = () => {
// router
const router = useRouter(); const router = useRouter();
const { workspaceSlug, projectId, viewId } = router.query; const { workspaceSlug, projectId, viewId } = router.query;
// store hooks
const { projectViews: projectViewsStore } = useMobxStore(); const { fetchViewDetails } = useProjectView();
const { error } = useSWR( const { error } = useSWR(
workspaceSlug && projectId && viewId ? `VIEW_DETAILS_${viewId.toString()}` : null, workspaceSlug && projectId && viewId ? `VIEW_DETAILS_${viewId.toString()}` : null,
workspaceSlug && projectId && viewId workspaceSlug && projectId && viewId
? () => projectViewsStore.fetchViewDetails(workspaceSlug.toString(), projectId.toString(), viewId.toString()) ? () => fetchViewDetails(workspaceSlug.toString(), projectId.toString(), viewId.toString())
: null : null
); );

View File

@ -1,8 +1,4 @@
import { ReactElement } from "react"; import { ReactElement } from "react";
import { useRouter } from "next/router";
import useSWR from "swr";
// mobx store
import { useMobxStore } from "lib/mobx/store-provider";
// components // components
import { ProjectViewsHeader } from "components/headers"; import { ProjectViewsHeader } from "components/headers";
import { ProjectViewsList } from "components/views"; import { ProjectViewsList } from "components/views";
@ -11,21 +7,7 @@ import { AppLayout } from "layouts/app-layout";
// types // types
import { NextPageWithLayout } from "types/app"; import { NextPageWithLayout } from "types/app";
const ProjectViewsPage: NextPageWithLayout = () => { const ProjectViewsPage: NextPageWithLayout = () => <ProjectViewsList />;
const router = useRouter();
const { workspaceSlug, projectId } = router.query;
// store
const {
projectViews: { fetchAllViews },
} = useMobxStore();
useSWR(
workspaceSlug && projectId ? `PROJECT_VIEWS_LIST_${workspaceSlug.toString()}_${projectId.toString()}` : null,
workspaceSlug && projectId ? () => fetchAllViews(workspaceSlug.toString(), projectId.toString()) : null
);
return <ProjectViewsList />;
};
ProjectViewsPage.getLayout = function getLayout(page: ReactElement) { ProjectViewsPage.getLayout = function getLayout(page: ReactElement) {
return ( return (

View File

@ -19,11 +19,7 @@ export class CycleService extends APIService {
}); });
} }
async getCyclesWithParams( async getCyclesWithParams(workspaceSlug: string, projectId: string, cycleType?: "current"): Promise<ICycle[]> {
workspaceSlug: string,
projectId: string,
cycleType?: "current"
): Promise<Record<string, ICycle>> {
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/`, { return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/`, {
params: { params: {
cycle_view: cycleType, cycle_view: cycleType,

View File

@ -10,7 +10,7 @@ export class ModuleService extends APIService {
super(API_BASE_URL); super(API_BASE_URL);
} }
async getModules(workspaceSlug: string, projectId: string): Promise<Record<string, IModule>> { async getModules(workspaceSlug: string, projectId: string): Promise<IModule[]> {
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/`) return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/`)
.then((response) => response?.data) .then((response) => response?.data)
.catch((error) => { .catch((error) => {

View File

@ -2,7 +2,7 @@ import { API_BASE_URL } from "helpers/common.helper";
// services // services
import { APIService } from "services/api.service"; import { APIService } from "services/api.service";
// types // types
import { IPage, IPageBlock, RecentPagesResponse, IIssue } from "types"; import { IPage, IPageBlock, IIssue } from "types";
export class PageService extends APIService { export class PageService extends APIService {
constructor() { constructor() {
@ -50,7 +50,7 @@ export class PageService extends APIService {
}); });
} }
async getProjectPages(workspaceSlug: string, projectId: string): Promise<Record<string, IPage>> { async getProjectPages(workspaceSlug: string, projectId: string): Promise<IPage[]> {
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/`) return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/`)
.then((response) => response?.data) .then((response) => response?.data)
.catch((error) => { .catch((error) => {
@ -74,18 +74,6 @@ export class PageService extends APIService {
}); });
} }
async getRecentPages(workspaceSlug: string, projectId: string): Promise<RecentPagesResponse> {
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/`, {
params: {
page_view: "recent",
},
})
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
async getPageDetails(workspaceSlug: string, projectId: string, pageId: string): Promise<IPage> { async getPageDetails(workspaceSlug: string, projectId: string, pageId: string): Promise<IPage> {
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/`) return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/`)
.then((response) => response?.data) .then((response) => response?.data)
@ -189,7 +177,7 @@ export class PageService extends APIService {
}); });
} }
async getArchivedPages(workspaceSlug: string, projectId: string): Promise<Record<string, IPage>> { async getArchivedPages(workspaceSlug: string, projectId: string): Promise<IPage[]> {
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/archived-pages/`) return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/archived-pages/`)
.then((response) => response?.data) .then((response) => response?.data)
.catch((error) => { .catch((error) => {

View File

@ -2,7 +2,7 @@ import { API_BASE_URL } from "helpers/common.helper";
// services // services
import { APIService } from "services/api.service"; import { APIService } from "services/api.service";
// types // types
import type { IProjectBulkAddFormData, IProjectMember, IProjectMemberInvitation } from "types"; import type { IProjectBulkAddFormData, IProjectMember } from "types";
export class ProjectMemberService extends APIService { export class ProjectMemberService extends APIService {
constructor() { constructor() {

View File

@ -36,7 +36,7 @@ export class ProjectService extends APIService {
}); });
} }
async getProjects(workspaceSlug: string): Promise<Record<string, IProject>> { async getProjects(workspaceSlug: string): Promise<IProject[]> {
return this.get(`/api/workspaces/${workspaceSlug}/projects/`) return this.get(`/api/workspaces/${workspaceSlug}/projects/`)
.then((response) => response?.data) .then((response) => response?.data)
.catch((error) => { .catch((error) => {

View File

@ -23,7 +23,7 @@ export class WorkspaceService extends APIService {
super(API_BASE_URL); super(API_BASE_URL);
} }
async userWorkspaces(): Promise<Record<string, IWorkspace>> { async userWorkspaces(): Promise<IWorkspace[]> {
return this.get("/api/users/me/workspaces/") return this.get("/api/users/me/workspaces/")
.then((response) => response?.data) .then((response) => response?.data)
.catch((error) => { .catch((error) => {

View File

@ -15,12 +15,8 @@ export interface ICycleStore {
loader: boolean; loader: boolean;
error: any | null; error: any | null;
// observables // observables
cycleMap: { cycleMap: Record<string, ICycle>;
[cycleId: string]: ICycle; activeCycleMap: Record<string, ICycle>;
};
activeCycleMap: {
[cycleId: string]: ICycle;
};
// computed // computed
projectAllCycles: string[] | null; projectAllCycles: string[] | null;
projectCompletedCycles: string[] | null; projectCompletedCycles: string[] | null;
@ -32,8 +28,8 @@ export interface ICycleStore {
getActiveCycleById: (cycleId: string) => ICycle | null; getActiveCycleById: (cycleId: string) => ICycle | null;
// actions // actions
validateDate: (workspaceSlug: string, projectId: string, payload: CycleDateCheckData) => Promise<any>; validateDate: (workspaceSlug: string, projectId: string, payload: CycleDateCheckData) => Promise<any>;
fetchAllCycles: (workspaceSlug: string, projectId: string) => Promise<Record<string, ICycle>>; fetchAllCycles: (workspaceSlug: string, projectId: string) => Promise<ICycle[]>;
fetchActiveCycle: (workspaceSlug: string, projectId: string) => Promise<Record<string, ICycle>>; fetchActiveCycle: (workspaceSlug: string, projectId: string) => Promise<ICycle[]>;
fetchCycleDetails: (workspaceSlug: string, projectId: string, cycleId: string) => Promise<ICycle>; fetchCycleDetails: (workspaceSlug: string, projectId: string, cycleId: string) => Promise<ICycle>;
createCycle: (workspaceSlug: string, projectId: string, data: Partial<ICycle>) => Promise<ICycle>; createCycle: (workspaceSlug: string, projectId: string, data: Partial<ICycle>) => Promise<ICycle>;
updateCycleDetails: ( updateCycleDetails: (
@ -52,10 +48,8 @@ export class CycleStore implements ICycleStore {
loader: boolean = false; loader: boolean = false;
error: any | null = null; error: any | null = null;
// observables // observables
cycleMap: { cycleMap: Record<string, ICycle> = {};
[cycleId: string]: ICycle; activeCycleMap: Record<string, ICycle> = {};
} = {};
activeCycleMap: { [cycleId: string]: ICycle } = {};
// root store // root store
rootStore; rootStore;
// services // services
@ -196,7 +190,7 @@ export class CycleStore implements ICycleStore {
const cyclesResponse = await this.cycleService.getCyclesWithParams(workspaceSlug, projectId); const cyclesResponse = await this.cycleService.getCyclesWithParams(workspaceSlug, projectId);
runInAction(() => { runInAction(() => {
Object.values(cyclesResponse).forEach((cycle) => { cyclesResponse.forEach((cycle) => {
set(this.cycleMap, [cycle.id], cycle); set(this.cycleMap, [cycle.id], cycle);
}); });
this.loader = false; this.loader = false;
@ -221,7 +215,7 @@ export class CycleStore implements ICycleStore {
const cyclesResponse = await this.cycleService.getCyclesWithParams(workspaceSlug, projectId, "current"); const cyclesResponse = await this.cycleService.getCyclesWithParams(workspaceSlug, projectId, "current");
runInAction(() => { runInAction(() => {
Object.values(cyclesResponse).forEach((cycle) => { cyclesResponse.forEach((cycle) => {
set(this.activeCycleMap, [cycle.id], cycle); set(this.activeCycleMap, [cycle.id], cycle);
}); });
this.loader = false; this.loader = false;

View File

@ -12,15 +12,13 @@ export interface IModuleStore {
loader: boolean; loader: boolean;
error: any | null; error: any | null;
// observables // observables
moduleMap: { moduleMap: Record<string, IModule>;
[moduleId: string]: IModule;
};
// computed // computed
projectModules: string[] | null; projectModules: string[] | null;
// computed actions // computed actions
getModuleById: (moduleId: string) => IModule | null; getModuleById: (moduleId: string) => IModule | null;
// actions // actions
fetchModules: (workspaceSlug: string, projectId: string) => void; fetchModules: (workspaceSlug: string, projectId: string) => Promise<IModule[]>;
fetchModuleDetails: (workspaceSlug: string, projectId: string, moduleId: string) => Promise<IModule>; fetchModuleDetails: (workspaceSlug: string, projectId: string, moduleId: string) => Promise<IModule>;
createModule: (workspaceSlug: string, projectId: string, data: Partial<IModule>) => Promise<IModule>; createModule: (workspaceSlug: string, projectId: string, data: Partial<IModule>) => Promise<IModule>;
updateModuleDetails: ( updateModuleDetails: (
@ -53,9 +51,7 @@ export class ModulesStore implements IModuleStore {
loader: boolean = false; loader: boolean = false;
error: any | null = null; error: any | null = null;
// observables // observables
moduleMap: { moduleMap: Record<string, IModule> = {};
[moduleId: string]: IModule;
} = {};
// root store // root store
rootStore; rootStore;
// services // services
@ -108,7 +104,6 @@ export class ModulesStore implements IModuleStore {
getModuleById = (moduleId: string) => this.moduleMap?.[moduleId] || null; getModuleById = (moduleId: string) => this.moduleMap?.[moduleId] || null;
// actions // actions
fetchModules = async (workspaceSlug: string, projectId: string) => { fetchModules = async (workspaceSlug: string, projectId: string) => {
try { try {
runInAction(() => { runInAction(() => {
@ -119,12 +114,14 @@ export class ModulesStore implements IModuleStore {
const modulesResponse = await this.moduleService.getModules(workspaceSlug, projectId); const modulesResponse = await this.moduleService.getModules(workspaceSlug, projectId);
runInAction(() => { runInAction(() => {
Object.values(modulesResponse).forEach((module) => { modulesResponse.forEach((module) => {
set(this.moduleMap, [module.id], module); set(this.moduleMap, [module.id], module);
}); });
this.loader = false; this.loader = false;
this.error = null; this.error = null;
}); });
return modulesResponse;
} catch (error) { } catch (error) {
console.error("Failed to fetch modules list in module store", error); console.error("Failed to fetch modules list in module store", error);
@ -132,6 +129,8 @@ export class ModulesStore implements IModuleStore {
this.loader = false; this.loader = false;
this.error = error; this.error = error;
}); });
throw error;
} }
}; };

View File

@ -24,8 +24,8 @@ export interface IPageStore {
getUnArchivedPageById: (pageId: string) => IPage | null; getUnArchivedPageById: (pageId: string) => IPage | null;
getArchivedPageById: (pageId: string) => IPage | null; getArchivedPageById: (pageId: string) => IPage | null;
// fetch actions // fetch actions
fetchProjectPages: (workspaceSlug: string, projectId: string) => Promise<Record<string, IPage>>; fetchProjectPages: (workspaceSlug: string, projectId: string) => Promise<IPage[]>;
fetchArchivedProjectPages: (workspaceSlug: string, projectId: string) => Promise<Record<string, IPage>>; fetchArchivedProjectPages: (workspaceSlug: string, projectId: string) => Promise<IPage[]>;
// favorites actions // favorites actions
addToFavorites: (workspaceSlug: string, projectId: string, pageId: string) => Promise<void>; addToFavorites: (workspaceSlug: string, projectId: string, pageId: string) => Promise<void>;
removeFromFavorites: (workspaceSlug: string, projectId: string, pageId: string) => Promise<void>; removeFromFavorites: (workspaceSlug: string, projectId: string, pageId: string) => Promise<void>;
@ -202,10 +202,11 @@ export class PageStore implements IPageStore {
const response = await this.pageService.getProjectPages(workspaceSlug, projectId); const response = await this.pageService.getProjectPages(workspaceSlug, projectId);
runInAction(() => { runInAction(() => {
Object.values(response).forEach((page) => { response.forEach((page) => {
set(this.pages, [page.id], page); set(this.pages, [page.id], page);
}); });
}); });
return response; return response;
} catch (error) { } catch (error) {
throw error; throw error;
@ -223,7 +224,7 @@ export class PageStore implements IPageStore {
const response = await this.pageService.getArchivedPages(workspaceSlug, projectId); const response = await this.pageService.getArchivedPages(workspaceSlug, projectId);
runInAction(() => { runInAction(() => {
Object.values(response).forEach((page) => { response.forEach((page) => {
set(this.archivedPages, [page.id], page); set(this.archivedPages, [page.id], page);
}); });
}); });

View File

@ -1,24 +1,21 @@
import set from "lodash/set"; import { omit, set } from "lodash";
import { observable, action, makeObservable, runInAction } from "mobx"; import { observable, action, makeObservable, runInAction, computed } from "mobx";
// services // services
import { ViewService } from "services/view.service"; import { ViewService } from "services/view.service";
import { RootStore } from "store/root.store"; import { RootStore } from "store/root.store";
// types // types
import { IProjectView } from "types"; import { IProjectView } from "types";
export interface IProjectViewsStore { export interface IProjectViewStore {
// states // states
loader: boolean; loader: boolean;
error: any | null; error: any | null;
// observables // observables
viewId: string | null; viewMap: Record<string, IProjectView>;
viewMap: { // computed
[projectId: string]: { projectViews: string[] | null;
[viewId: string]: IProjectView; // computed actions
}; getViewById: (viewId: string) => IProjectView;
};
// actions // actions
fetchViews: (workspaceSlug: string, projectId: string) => Promise<IProjectView[]>; fetchViews: (workspaceSlug: string, projectId: string) => Promise<IProjectView[]>;
fetchViewDetails: (workspaceSlug: string, projectId: string, viewId: string) => Promise<IProjectView>; fetchViewDetails: (workspaceSlug: string, projectId: string, viewId: string) => Promise<IProjectView>;
@ -34,22 +31,14 @@ export interface IProjectViewsStore {
removeViewFromFavorites: (workspaceSlug: string, projectId: string, viewId: string) => Promise<any>; removeViewFromFavorites: (workspaceSlug: string, projectId: string, viewId: string) => Promise<any>;
} }
export class ProjectViewsStore implements IProjectViewsStore { export class ProjectViewStore implements IProjectViewStore {
// states // states
loader: boolean = false; loader: boolean = false;
error: any | null = null; error: any | null = null;
// observables // observables
viewId: string | null = null; viewMap: Record<string, IProjectView> = {};
viewMap: {
[projectId: string]: {
[viewId: string]: IProjectView;
};
} = {};
// root store // root store
rootStore; rootStore;
// services // services
viewService; viewService;
@ -58,11 +47,12 @@ export class ProjectViewsStore implements IProjectViewsStore {
// states // states
loader: observable.ref, loader: observable.ref,
error: observable.ref, error: observable.ref,
// observables // observables
viewId: observable.ref,
viewMap: observable, viewMap: observable,
// computed
projectViews: computed,
// computed actions
getViewById: action,
// actions // actions
fetchViews: action, fetchViews: action,
fetchViewDetails: action, fetchViewDetails: action,
@ -78,11 +68,19 @@ export class ProjectViewsStore implements IProjectViewsStore {
this.viewService = new ViewService(); this.viewService = new ViewService();
} }
setViewId = (viewId: string | null) => { get projectViews() {
this.viewId = viewId; const projectId = this.rootStore.app.router.projectId;
};
fetchViews = async (workspaceSlug: string, projectId: string): Promise<IProjectView[]> => { if (!projectId) return null;
const viewIds = Object.keys(this.viewMap ?? {})?.filter((viewId) => this.viewMap?.[viewId]?.project === projectId);
return viewIds;
}
getViewById = (viewId: string) => this.viewMap?.[viewId] ?? null;
fetchViews = async (workspaceSlug: string, projectId: string) => {
try { try {
runInAction(() => { runInAction(() => {
this.loader = true; this.loader = true;
@ -92,7 +90,9 @@ export class ProjectViewsStore implements IProjectViewsStore {
runInAction(() => { runInAction(() => {
this.loader = false; this.loader = false;
set(this.viewMap, [projectId], response); response.forEach((view) => {
set(this.viewMap, [view.id], view);
});
}); });
return response; return response;
@ -116,7 +116,7 @@ export class ProjectViewsStore implements IProjectViewsStore {
runInAction(() => { runInAction(() => {
this.loader = false; this.loader = false;
set(this.viewMap, [projectId, viewId], response); set(this.viewMap, [viewId], response);
}); });
return response; return response;
@ -136,7 +136,7 @@ export class ProjectViewsStore implements IProjectViewsStore {
runInAction(() => { runInAction(() => {
this.loader = false; this.loader = false;
set(this.viewMap, [projectId, response.id], response); set(this.viewMap, [response.id], response);
}); });
return response; return response;
@ -156,10 +156,10 @@ export class ProjectViewsStore implements IProjectViewsStore {
data: Partial<IProjectView> data: Partial<IProjectView>
): Promise<IProjectView> => { ): Promise<IProjectView> => {
try { try {
const currentView = this.viewMap[projectId][viewId]; const currentView = this.getViewById(viewId);
runInAction(() => { runInAction(() => {
set(this.viewMap, [projectId, viewId], { ...currentView, ...data }); set(this.viewMap, [viewId], { ...currentView, ...data });
}); });
const response = await this.viewService.patchView(workspaceSlug, projectId, viewId, data); const response = await this.viewService.patchView(workspaceSlug, projectId, viewId, data);
@ -178,10 +178,8 @@ export class ProjectViewsStore implements IProjectViewsStore {
deleteView = async (workspaceSlug: string, projectId: string, viewId: string): Promise<any> => { deleteView = async (workspaceSlug: string, projectId: string, viewId: string): Promise<any> => {
try { try {
if (!this.viewMap?.[projectId]?.[viewId]) return;
runInAction(() => { runInAction(() => {
delete this.viewMap[projectId][viewId]; omit(this.viewMap, [viewId]);
}); });
await this.viewService.deleteView(workspaceSlug, projectId, viewId); await this.viewService.deleteView(workspaceSlug, projectId, viewId);
@ -198,12 +196,12 @@ export class ProjectViewsStore implements IProjectViewsStore {
addViewToFavorites = async (workspaceSlug: string, projectId: string, viewId: string) => { addViewToFavorites = async (workspaceSlug: string, projectId: string, viewId: string) => {
try { try {
const currentView = this.viewMap[projectId][viewId]; const currentView = this.getViewById(viewId);
if (currentView.is_favorite) return; if (currentView?.is_favorite) return;
runInAction(() => { runInAction(() => {
set(this.viewMap, [projectId, viewId, "is_favorite"], true); set(this.viewMap, [viewId, "is_favorite"], true);
}); });
await this.viewService.addViewToFavorites(workspaceSlug, projectId, { await this.viewService.addViewToFavorites(workspaceSlug, projectId, {
@ -213,19 +211,19 @@ export class ProjectViewsStore implements IProjectViewsStore {
console.error("Failed to add view to favorites in view store", error); console.error("Failed to add view to favorites in view store", error);
runInAction(() => { runInAction(() => {
set(this.viewMap, [projectId, viewId, "is_favorite"], false); set(this.viewMap, [viewId, "is_favorite"], false);
}); });
} }
}; };
removeViewFromFavorites = async (workspaceSlug: string, projectId: string, viewId: string) => { removeViewFromFavorites = async (workspaceSlug: string, projectId: string, viewId: string) => {
try { try {
const currentView = this.viewMap[projectId][viewId]; const currentView = this.getViewById(viewId);
if (!currentView.is_favorite) return; if (!currentView?.is_favorite) return;
runInAction(() => { runInAction(() => {
set(this.viewMap, [projectId, viewId, "is_favorite"], false); set(this.viewMap, [viewId, "is_favorite"], false);
}); });
await this.viewService.removeViewFromFavorites(workspaceSlug, projectId, viewId); await this.viewService.removeViewFromFavorites(workspaceSlug, projectId, viewId);
@ -233,7 +231,7 @@ export class ProjectViewsStore implements IProjectViewsStore {
console.error("Failed to remove view from favorites in view store", error); console.error("Failed to remove view from favorites in view store", error);
runInAction(() => { runInAction(() => {
set(this.viewMap, [projectId, viewId, "is_favorite"], true); set(this.viewMap, [viewId, "is_favorite"], true);
}); });
} }
}; };

View File

@ -26,7 +26,7 @@ export interface IProjectStore {
setSearchQuery: (query: string) => void; setSearchQuery: (query: string) => void;
getProjectById: (projectId: string) => IProject | null; getProjectById: (projectId: string) => IProject | null;
fetchProjects: (workspaceSlug: string) => Promise<void>; fetchProjects: (workspaceSlug: string) => Promise<IProject[]>;
fetchProjectDetails: (workspaceSlug: string, projectId: string) => Promise<any>; fetchProjectDetails: (workspaceSlug: string, projectId: string) => Promise<any>;
addProjectToFavorites: (workspaceSlug: string, projectId: string) => Promise<any>; addProjectToFavorites: (workspaceSlug: string, projectId: string) => Promise<any>;
@ -146,11 +146,15 @@ export class ProjectStore implements IProjectStore {
*/ */
fetchProjects = async (workspaceSlug: string) => { fetchProjects = async (workspaceSlug: string) => {
try { try {
const currentProjectMap = await this.projectService.getProjects(workspaceSlug); const projectsResponse = await this.projectService.getProjects(workspaceSlug);
runInAction(() => { runInAction(() => {
this.projectMap = currentProjectMap; projectsResponse.forEach((project) => {
set(this.projectMap, [project.id], project);
});
}); });
return projectsResponse;
} catch (error) { } catch (error) {
console.log("Failed to fetch project from workspace store"); console.log("Failed to fetch project from workspace store");
throw error; throw error;

View File

@ -3,7 +3,7 @@ import { enableStaticRendering } from "mobx-react-lite";
import { AppRootStore, IAppRootStore } from "./application"; import { AppRootStore, IAppRootStore } from "./application";
import { IProjectRootStore, ProjectRootStore } from "./project"; import { IProjectRootStore, ProjectRootStore } from "./project";
import { CycleStore, ICycleStore } from "./cycle.store"; import { CycleStore, ICycleStore } from "./cycle.store";
import { IProjectViewsStore, ProjectViewsStore } from "./project-view.store"; import { IProjectViewStore, ProjectViewStore } from "./project-view.store";
import { IModuleStore, ModulesStore } from "./module.store"; import { IModuleStore, ModulesStore } from "./module.store";
import { IUserStore, UserStore } from "./user"; import { IUserStore, UserStore } from "./user";
import { IWorkspaceRootStore, WorkspaceRootStore } from "./workspace"; import { IWorkspaceRootStore, WorkspaceRootStore } from "./workspace";
@ -22,7 +22,7 @@ export class RootStore {
labelRoot: ILabelRootStore; labelRoot: ILabelRootStore;
cycle: ICycleStore; cycle: ICycleStore;
module: IModuleStore; module: IModuleStore;
projectView: IProjectViewsStore; projectView: IProjectViewStore;
page: IPageStore; page: IPageStore;
issue: IIssueRootStore; issue: IIssueRootStore;
state: IStateStore; state: IStateStore;
@ -38,7 +38,7 @@ export class RootStore {
this.issue = new IssueRootStore(this); this.issue = new IssueRootStore(this);
this.cycle = new CycleStore(this); this.cycle = new CycleStore(this);
this.module = new ModulesStore(this); this.module = new ModulesStore(this);
this.projectView = new ProjectViewsStore(this); this.projectView = new ProjectViewStore(this);
this.page = new PageStore(this); this.page = new PageStore(this);
} }
} }

View File

@ -5,8 +5,10 @@ import { ProjectMemberService } from "services/project";
import { UserService } from "services/user.service"; import { UserService } from "services/user.service";
import { WorkspaceService } from "services/workspace.service"; import { WorkspaceService } from "services/workspace.service";
// interfaces // interfaces
import { IWorkspaceMemberMe, IProjectMember, TUserProjectRole, TUserWorkspaceRole } from "types"; import { IWorkspaceMemberMe, IProjectMember } from "types";
import { RootStore } from "../root.store"; import { RootStore } from "../root.store";
import { EUserProjectRoles } from "constants/project";
import { EUserWorkspaceRoles } from "constants/workspace";
export interface IUserMembershipStore { export interface IUserMembershipStore {
workspaceMemberInfo: { workspaceMemberInfo: {
@ -24,8 +26,8 @@ export interface IUserMembershipStore {
currentProjectMemberInfo: IProjectMember | undefined; currentProjectMemberInfo: IProjectMember | undefined;
currentWorkspaceMemberInfo: IWorkspaceMemberMe | undefined; currentWorkspaceMemberInfo: IWorkspaceMemberMe | undefined;
currentProjectRole: TUserProjectRole | undefined; currentProjectRole: EUserProjectRoles | undefined;
currentWorkspaceRole: TUserWorkspaceRole | undefined; currentWorkspaceRole: EUserWorkspaceRoles | undefined;
hasPermissionToCurrentWorkspace: boolean | undefined; hasPermissionToCurrentWorkspace: boolean | undefined;
hasPermissionToCurrentProject: boolean | undefined; hasPermissionToCurrentProject: boolean | undefined;

View File

@ -22,7 +22,7 @@ export interface IWorkspaceRootStore {
getWorkspaceBySlug: (workspaceSlug: string) => IWorkspace | null; getWorkspaceBySlug: (workspaceSlug: string) => IWorkspace | null;
getWorkspaceById: (workspaceId: string) => IWorkspace | null; getWorkspaceById: (workspaceId: string) => IWorkspace | null;
// actions // actions
fetchWorkspaces: () => Promise<Record<string, IWorkspace>>; fetchWorkspaces: () => Promise<IWorkspace[]>;
createWorkspace: (data: Partial<IWorkspace>) => Promise<IWorkspace>; createWorkspace: (data: Partial<IWorkspace>) => Promise<IWorkspace>;
updateWorkspace: (workspaceSlug: string, data: Partial<IWorkspace>) => Promise<IWorkspace>; updateWorkspace: (workspaceSlug: string, data: Partial<IWorkspace>) => Promise<IWorkspace>;
deleteWorkspace: (workspaceSlug: string) => Promise<void>; deleteWorkspace: (workspaceSlug: string) => Promise<void>;
@ -126,7 +126,9 @@ export class WorkspaceRootStore implements IWorkspaceRootStore {
const workspaceResponse = await this.workspaceService.userWorkspaces(); const workspaceResponse = await this.workspaceService.userWorkspaces();
runInAction(() => { runInAction(() => {
this.workspaces = workspaceResponse; workspaceResponse.forEach((workspace) => {
set(this.workspaces, [workspace.id], workspace);
});
this.loader = false; this.loader = false;
this.error = null; this.error = null;
}); });

View File

@ -7,8 +7,9 @@ import { WorkspaceService } from "services/workspace.service";
import { AuthService } from "services/auth.service"; import { AuthService } from "services/auth.service";
// interfaces // interfaces
import { IUser, IUserSettings } from "types/users"; import { IUser, IUserSettings } from "types/users";
import { IWorkspaceMemberMe, IProjectMember, TUserProjectRole, TUserWorkspaceRole } from "types"; import { IWorkspaceMemberMe, IProjectMember, TUserWorkspaceRole } from "types";
import { RootStore } from "./root"; import { RootStore } from "./root";
import { EUserProjectRoles } from "constants/project";
export interface IUserStore { export interface IUserStore {
loader: boolean; loader: boolean;
@ -37,7 +38,7 @@ export interface IUserStore {
currentProjectMemberInfo: IProjectMember | undefined; currentProjectMemberInfo: IProjectMember | undefined;
currentWorkspaceMemberInfo: IWorkspaceMemberMe | undefined; currentWorkspaceMemberInfo: IWorkspaceMemberMe | undefined;
currentProjectRole: TUserProjectRole | undefined; currentProjectRole: EUserProjectRoles | undefined;
currentWorkspaceRole: TUserWorkspaceRole | undefined; currentWorkspaceRole: TUserWorkspaceRole | undefined;
hasPermissionToCurrentWorkspace: boolean | undefined; hasPermissionToCurrentWorkspace: boolean | undefined;

View File

@ -34,10 +34,6 @@ export interface IRecentPages {
[key: string]: string[]; [key: string]: string[];
} }
export interface RecentPagesResponse {
[key: string]: IPage[];
}
export interface IPageBlock { export interface IPageBlock {
completed_at: Date | null; completed_at: Date | null;
created_at: Date; created_at: Date;

View File

@ -1,6 +1,5 @@
import type { IUserLite, IWorkspace, IWorkspaceLite, IUserMemberLite, TStateGroups, IProjectViewProps } from "."; import { EUserProjectRoles } from "constants/project";
import type { IUserLite, IWorkspace, IWorkspaceLite, TStateGroups } from ".";
export type TUserProjectRole = 5 | 10 | 15 | 20;
export interface IProject { export interface IProject {
archive_in: number; archive_in: number;
@ -34,7 +33,7 @@ export interface IProject {
is_deployed: boolean; is_deployed: boolean;
is_favorite: boolean; is_favorite: boolean;
is_member: boolean; is_member: boolean;
member_role: TUserProjectRole | null; member_role: EUserProjectRoles | null;
members: IProjectMemberLite[]; members: IProjectMemberLite[];
issue_views_view: boolean; issue_views_view: boolean;
module_view: boolean; module_view: boolean;
@ -73,44 +72,12 @@ export interface IProjectMemberLite {
export interface IProjectMember { export interface IProjectMember {
id: string; id: string;
member: IUserMemberLite; member: string;
project: IProjectLite; role: EUserProjectRoles;
workspace: IWorkspaceLite;
comment: string;
role: TUserProjectRole;
preferences: ProjectPreferences;
view_props: IProjectViewProps;
default_props: IProjectViewProps;
created_at: Date;
updated_at: Date;
created_by: string;
updated_by: string;
}
export interface IProjectMemberInvitation {
id: string;
project: IProject;
workspace: IWorkspace;
email: string;
accepted: boolean;
token: string;
message: string;
responded_at: Date;
role: TUserProjectRole;
created_at: Date;
updated_at: Date;
created_by: string;
updated_by: string;
} }
export interface IProjectBulkAddFormData { export interface IProjectBulkAddFormData {
members: { role: TUserProjectRole; member_id: string }[]; members: { role: EUserProjectRoles; member_id: string }[];
} }
export interface IGithubRepository { export interface IGithubRepository {

View File

@ -61,11 +61,10 @@ export interface IUserTheme {
export interface IUserLite { export interface IUserLite {
avatar: string; avatar: string;
created_at: Date;
display_name: string; display_name: string;
email?: string; email?: string;
first_name: string; first_name: string;
readonly id: string; id: string;
is_bot: boolean; is_bot: boolean;
last_name: string; last_name: string;
} }

View File

@ -1,3 +1,4 @@
import { EUserWorkspaceRoles } from "constants/workspace";
import type { IProjectMember, IUser, IUserLite, IWorkspaceViewProps } from "types"; import type { IProjectMember, IUser, IUserLite, IWorkspaceViewProps } from "types";
export type TUserWorkspaceRole = 5 | 10 | 15 | 20; export type TUserWorkspaceRole = 5 | 10 | 15 | 20;
@ -58,15 +59,9 @@ export type Properties = {
}; };
export interface IWorkspaceMember { export interface IWorkspaceMember {
company_role: string | null;
created_at: Date;
created_by: string;
id: string; id: string;
member: IUserLite; member: IUserLite;
role: TUserWorkspaceRole; role: EUserWorkspaceRoles;
updated_at: Date;
updated_by: string;
workspace: IWorkspaceLite;
} }
export interface IWorkspaceMemberMe { export interface IWorkspaceMemberMe {