mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
chore: implement project view hook
This commit is contained in:
parent
960f170fd4
commit
4e755289a1
web
components
automation
cycles/gantt-chart
headers
cycle-issues.tsxcycles.tsxmodule-issues.tsxmodules-list.tsxpages.tsxproject-issues.tsxproject-settings.tsxproject-view-issues.tsxproject-views.tsx
inbox
issues
issue-layouts
calendar
empty-states
filters/applied-filters
gantt
kanban
list
quick-action-dropdowns
roots
spreadsheet
peek-overview
sidebar.tsxsub-issues
modules
page-views
pages/pages-list
project
card-list.tsxmember-list-item.tsxproject-settings-member-defaults.tsxsend-project-invitation-modal.tsx
settings
views
constants
hooks/store
layouts
pages/[workspaceSlug]/projects/[projectId]
services
store
store_legacy
types
@ -8,10 +8,9 @@ import { SelectMonthModal } from "components/automation";
|
||||
// icon
|
||||
import { ArchiveRestore } from "lucide-react";
|
||||
// constants
|
||||
import { PROJECT_AUTOMATION_MONTHS } from "constants/project";
|
||||
import { EUserProjectRoles, PROJECT_AUTOMATION_MONTHS } from "constants/project";
|
||||
// types
|
||||
import { IProject } from "types";
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
|
||||
type Props = {
|
||||
handleChange: (formData: Partial<IProject>) => Promise<void>;
|
||||
@ -29,7 +28,7 @@ export const AutoArchiveAutomation: React.FC<Props> = observer((props) => {
|
||||
} = useUser();
|
||||
const { currentProjectDetails } = useProject();
|
||||
|
||||
const isAdmin = currentProjectRole === EUserWorkspaceRoles.ADMIN;
|
||||
const isAdmin = currentProjectRole === EUserProjectRoles.ADMIN;
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -9,9 +9,8 @@ import { CustomSelect, CustomSearchSelect, ToggleSwitch, StateGroupIcon, DoubleC
|
||||
import { ArchiveX } from "lucide-react";
|
||||
// types
|
||||
import { IProject } from "types";
|
||||
// fetch keys
|
||||
import { PROJECT_AUTOMATION_MONTHS } from "constants/project";
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
// constants
|
||||
import { EUserProjectRoles, PROJECT_AUTOMATION_MONTHS } from "constants/project";
|
||||
|
||||
type Props = {
|
||||
handleChange: (formData: Partial<IProject>) => Promise<void>;
|
||||
@ -55,7 +54,7 @@ export const AutoCloseAutomation: React.FC<Props> = observer((props) => {
|
||||
default_state: defaultState,
|
||||
};
|
||||
|
||||
const isAdmin = currentProjectRole === EUserWorkspaceRoles.ADMIN;
|
||||
const isAdmin = currentProjectRole === EUserProjectRoles.ADMIN;
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -12,7 +12,7 @@ import { CycleGanttBlock } from "components/cycles";
|
||||
// types
|
||||
import { ICycle } from "types";
|
||||
// constants
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
type Props = {
|
||||
workspaceSlug: string;
|
||||
@ -83,7 +83,7 @@ export const CyclesListGanttChartView: FC<Props> = observer((props) => {
|
||||
};
|
||||
|
||||
const isAllowed =
|
||||
currentProjectRole && [EUserWorkspaceRoles.ADMIN, EUserWorkspaceRoles.MEMBER].includes(currentProjectRole);
|
||||
currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole);
|
||||
|
||||
return (
|
||||
<div className="h-full w-full overflow-y-auto">
|
||||
|
@ -19,10 +19,9 @@ import { renderEmoji } from "helpers/emoji.helper";
|
||||
import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions, TIssueLayouts } from "types";
|
||||
// constants
|
||||
import { ISSUE_DISPLAY_FILTERS_BY_LAYOUT } from "constants/issue";
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
|
||||
import { EFilterType } from "store_legacy/issues/types";
|
||||
import { EProjectStore } from "store_legacy/command-palette.store";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
export const CycleIssuesHeader: React.FC = observer(() => {
|
||||
// states
|
||||
@ -110,7 +109,7 @@ export const CycleIssuesHeader: React.FC = observer(() => {
|
||||
const cycleDetails = cycleId ? cycleStore.getCycleById(cycleId.toString()) : undefined;
|
||||
|
||||
const canUserCreateIssue =
|
||||
currentProjectRole && [EUserWorkspaceRoles.ADMIN, EUserWorkspaceRoles.MEMBER].includes(currentProjectRole);
|
||||
currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -8,7 +8,7 @@ import { useApplication, useProject, useUser } from "hooks/store";
|
||||
import { Breadcrumbs, Button, ContrastIcon } from "@plane/ui";
|
||||
// helpers
|
||||
import { renderEmoji } from "helpers/emoji.helper";
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
export const CyclesHeader: FC = observer(() => {
|
||||
// router
|
||||
@ -25,7 +25,7 @@ export const CyclesHeader: FC = observer(() => {
|
||||
const { currentProjectDetails } = useProject();
|
||||
|
||||
const canUserCreateCycle =
|
||||
currentProjectRole && [EUserWorkspaceRoles.ADMIN, EUserWorkspaceRoles.MEMBER].includes(currentProjectRole);
|
||||
currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole);
|
||||
|
||||
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">
|
||||
|
@ -19,10 +19,10 @@ import { renderEmoji } from "helpers/emoji.helper";
|
||||
import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions, TIssueLayouts } from "types";
|
||||
// constants
|
||||
import { ISSUE_DISPLAY_FILTERS_BY_LAYOUT } from "constants/issue";
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
// store
|
||||
import { EFilterType } from "store_legacy/issues/types";
|
||||
import { EProjectStore } from "store_legacy/command-palette.store";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
export const ModuleIssuesHeader: React.FC = observer(() => {
|
||||
// states
|
||||
@ -109,7 +109,7 @@ export const ModuleIssuesHeader: React.FC = observer(() => {
|
||||
const moduleDetails = moduleId ? moduleStore.getModuleById(moduleId.toString()) : undefined;
|
||||
|
||||
const canUserCreateIssue =
|
||||
currentProjectRole && [EUserWorkspaceRoles.ADMIN, EUserWorkspaceRoles.MEMBER].includes(currentProjectRole);
|
||||
currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -10,7 +10,7 @@ import { Breadcrumbs, Button, Tooltip, DiceIcon } from "@plane/ui";
|
||||
import { renderEmoji } from "helpers/emoji.helper";
|
||||
// constants
|
||||
import { MODULE_VIEW_LAYOUTS } from "constants/module";
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
export const ModulesListHeader: React.FC = observer(() => {
|
||||
// router
|
||||
@ -26,7 +26,7 @@ export const ModulesListHeader: React.FC = observer(() => {
|
||||
const { storedValue: modulesView, setValue: setModulesView } = useLocalStorage("modules_view", "grid");
|
||||
|
||||
const canUserCreateModule =
|
||||
currentProjectRole && [EUserWorkspaceRoles.ADMIN, EUserWorkspaceRoles.MEMBER].includes(currentProjectRole);
|
||||
currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole);
|
||||
|
||||
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">
|
||||
|
@ -8,7 +8,7 @@ import { Breadcrumbs, Button } from "@plane/ui";
|
||||
// helpers
|
||||
import { renderEmoji } from "helpers/emoji.helper";
|
||||
// constants
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
export const PagesHeader = observer(() => {
|
||||
// router
|
||||
@ -24,7 +24,7 @@ export const PagesHeader = observer(() => {
|
||||
const { currentProjectDetails } = useProject();
|
||||
|
||||
const canUserCreatePage =
|
||||
currentProjectRole && [EUserWorkspaceRoles.ADMIN, EUserWorkspaceRoles.MEMBER].includes(currentProjectRole);
|
||||
currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole);
|
||||
|
||||
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">
|
||||
|
@ -3,7 +3,8 @@ import Link from "next/link";
|
||||
import { useRouter } from "next/router";
|
||||
import { observer } from "mobx-react-lite";
|
||||
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";
|
||||
// components
|
||||
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";
|
||||
// constants
|
||||
import { ISSUE_DISPLAY_FILTERS_BY_LAYOUT } from "constants/issue";
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
// helper
|
||||
import { renderEmoji } from "helpers/emoji.helper";
|
||||
import { EFilterType } from "store_legacy/issues/types";
|
||||
import { EProjectStore } from "store_legacy/command-palette.store";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
export const ProjectIssuesHeader: React.FC = observer(() => {
|
||||
// states
|
||||
const [analyticsModal, setAnalyticsModal] = useState(false);
|
||||
|
||||
// router
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query as { workspaceSlug: string; projectId: string };
|
||||
|
||||
// store hooks
|
||||
const {
|
||||
project: { currentProjectDetails },
|
||||
projectLabel: { projectLabels },
|
||||
projectMember: { projectMembers },
|
||||
projectState: projectStateStore,
|
||||
inbox: inboxStore,
|
||||
commandPalette: commandPaletteStore,
|
||||
trackEvent: { setTrackElement },
|
||||
// issue filters
|
||||
projectIssuesFilter: { issueFilters, updateFilters },
|
||||
projectIssues: {},
|
||||
user: { currentProjectRole },
|
||||
} = 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;
|
||||
|
||||
@ -90,7 +97,7 @@ export const ProjectIssuesHeader: React.FC = observer(() => {
|
||||
const deployUrl = process.env.NEXT_PUBLIC_DEPLOY_URL;
|
||||
|
||||
const canUserCreateIssue =
|
||||
currentProjectRole && [EUserWorkspaceRoles.ADMIN, EUserWorkspaceRoles.MEMBER].includes(currentProjectRole);
|
||||
currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole);
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -172,9 +179,9 @@ export const ProjectIssuesHeader: React.FC = observer(() => {
|
||||
layoutDisplayFiltersOptions={
|
||||
activeLayout ? ISSUE_DISPLAY_FILTERS_BY_LAYOUT.issues[activeLayout] : undefined
|
||||
}
|
||||
labels={projectLabels ?? undefined}
|
||||
labels={projectLabels}
|
||||
members={projectMembers?.map((m) => m.member)}
|
||||
states={projectStateStore.states?.[projectId ?? ""] ?? undefined}
|
||||
states={projectStates}
|
||||
/>
|
||||
</FiltersDropdown>
|
||||
<FiltersDropdown title="Display" placement="bottom-end">
|
||||
@ -211,7 +218,7 @@ export const ProjectIssuesHeader: React.FC = observer(() => {
|
||||
<Button
|
||||
onClick={() => {
|
||||
setTrackElement("PROJECT_PAGE_HEADER");
|
||||
commandPaletteStore.toggleCreateIssueModal(true, EProjectStore.PROJECT);
|
||||
toggleCreateIssueModal(true, EProjectStore.PROJECT);
|
||||
}}
|
||||
size="sm"
|
||||
prependIcon={<Plus />}
|
||||
|
@ -8,7 +8,7 @@ import { renderEmoji } from "helpers/emoji.helper";
|
||||
// hooks
|
||||
import { useProject, useUser } from "hooks/store";
|
||||
// constants
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
export interface IProjectSettingHeader {
|
||||
title: string;
|
||||
@ -25,7 +25,7 @@ export const ProjectSettingHeader: FC<IProjectSettingHeader> = observer((props)
|
||||
} = useUser();
|
||||
const { currentProjectDetails } = useProject();
|
||||
|
||||
if (currentProjectRole && currentProjectRole <= EUserWorkspaceRoles.VIEWER) return null;
|
||||
if (currentProjectRole && currentProjectRole <= EUserProjectRoles.VIEWER) return null;
|
||||
|
||||
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">
|
||||
|
@ -3,7 +3,7 @@ import { useRouter } from "next/router";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { Plus } from "lucide-react";
|
||||
// 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";
|
||||
// components
|
||||
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";
|
||||
// constants
|
||||
import { ISSUE_DISPLAY_FILTERS_BY_LAYOUT } from "constants/issue";
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
|
||||
import { EFilterType } from "store_legacy/issues/types";
|
||||
import { EProjectStore } from "store_legacy/command-palette.store";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
export const ProjectViewIssuesHeader: React.FC = observer(() => {
|
||||
// router
|
||||
@ -32,7 +31,6 @@ export const ProjectViewIssuesHeader: React.FC = observer(() => {
|
||||
// store hooks
|
||||
const {
|
||||
projectMember: { projectMembers },
|
||||
projectViews: projectViewsStore,
|
||||
viewIssuesFilter: { issueFilters, updateFilters },
|
||||
} = useMobxStore();
|
||||
const {
|
||||
@ -43,6 +41,7 @@ export const ProjectViewIssuesHeader: React.FC = observer(() => {
|
||||
membership: { currentProjectRole },
|
||||
} = useUser();
|
||||
const { currentProjectDetails } = useProject();
|
||||
const { projectViews, getViewById } = useProjectView();
|
||||
const { projectStates } = useProjectState();
|
||||
const {
|
||||
project: { projectLabels },
|
||||
@ -93,11 +92,10 @@ export const ProjectViewIssuesHeader: React.FC = observer(() => {
|
||||
[workspaceSlug, projectId, viewId, updateFilters]
|
||||
);
|
||||
|
||||
const viewsList = projectId ? projectViewsStore.viewsList[projectId.toString()] : undefined;
|
||||
const viewDetails = viewId ? projectViewsStore.viewDetails[viewId.toString()] : undefined;
|
||||
const viewDetails = viewId ? getViewById(viewId.toString()) : null;
|
||||
|
||||
const canUserCreateIssue =
|
||||
currentProjectRole && [EUserWorkspaceRoles.ADMIN, EUserWorkspaceRoles.MEMBER].includes(currentProjectRole);
|
||||
currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole);
|
||||
|
||||
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">
|
||||
@ -142,17 +140,23 @@ export const ProjectViewIssuesHeader: React.FC = observer(() => {
|
||||
className="ml-1.5"
|
||||
placement="bottom-start"
|
||||
>
|
||||
{viewsList?.map((view) => (
|
||||
<CustomMenu.MenuItem
|
||||
key={view.id}
|
||||
onClick={() => router.push(`/${workspaceSlug}/projects/${projectId}/views/${view.id}`)}
|
||||
>
|
||||
<div className="flex items-center gap-1.5">
|
||||
<PhotoFilterIcon height={12} width={12} />
|
||||
{truncateText(view.name, 40)}
|
||||
</div>
|
||||
</CustomMenu.MenuItem>
|
||||
))}
|
||||
{projectViews?.map((viewId) => {
|
||||
const view = getViewById(viewId);
|
||||
|
||||
if (!view) return;
|
||||
|
||||
return (
|
||||
<CustomMenu.MenuItem
|
||||
key={viewId}
|
||||
onClick={() => router.push(`/${workspaceSlug}/projects/${projectId}/views/${viewId}`)}
|
||||
>
|
||||
<div className="flex items-center gap-1.5">
|
||||
<PhotoFilterIcon height={12} width={12} />
|
||||
{truncateText(view.name, 40)}
|
||||
</div>
|
||||
</CustomMenu.MenuItem>
|
||||
);
|
||||
})}
|
||||
</CustomMenu>
|
||||
}
|
||||
/>
|
||||
|
@ -8,7 +8,7 @@ import { Breadcrumbs, PhotoFilterIcon, Button } from "@plane/ui";
|
||||
// helpers
|
||||
import { renderEmoji } from "helpers/emoji.helper";
|
||||
// constants
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
export const ProjectViewsHeader: React.FC = observer(() => {
|
||||
// router
|
||||
@ -24,7 +24,7 @@ export const ProjectViewsHeader: React.FC = observer(() => {
|
||||
const { currentProjectDetails } = useProject();
|
||||
|
||||
const canUserCreateIssue =
|
||||
currentProjectRole && [EUserWorkspaceRoles.ADMIN, EUserWorkspaceRoles.MEMBER].includes(currentProjectRole);
|
||||
currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -3,10 +3,9 @@ import { useRouter } from "next/router";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import DatePicker from "react-datepicker";
|
||||
import { Popover } from "@headlessui/react";
|
||||
|
||||
// mobx store
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// hooks
|
||||
import { useUser } from "hooks/store";
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
import useToast from "hooks/use-toast";
|
||||
// components
|
||||
import {
|
||||
@ -22,22 +21,25 @@ import { Button } from "@plane/ui";
|
||||
import { CheckCircle2, ChevronDown, ChevronUp, Clock, FileStack, Inbox, Trash2, XCircle } from "lucide-react";
|
||||
// types
|
||||
import type { TInboxStatus } from "types";
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
export const InboxActionsHeader = observer(() => {
|
||||
// states
|
||||
const [date, setDate] = useState(new Date());
|
||||
const [selectDuplicateIssue, setSelectDuplicateIssue] = useState(false);
|
||||
const [acceptIssueModal, setAcceptIssueModal] = useState(false);
|
||||
const [declineIssueModal, setDeclineIssueModal] = useState(false);
|
||||
const [deleteIssueModal, setDeleteIssueModal] = useState(false);
|
||||
|
||||
// router
|
||||
const router = useRouter();
|
||||
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 { setToastAlert } = useToast();
|
||||
@ -72,7 +74,7 @@ export const InboxActionsHeader = observer(() => {
|
||||
}, [issue]);
|
||||
|
||||
const issueStatus = issue?.issue_inbox[0].status;
|
||||
const isAllowed = !!userRole && userRole >= EUserWorkspaceRoles.MEMBER;
|
||||
const isAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
|
||||
|
||||
const today = new Date();
|
||||
const tomorrow = new Date(today);
|
||||
@ -228,7 +230,7 @@ export const InboxActionsHeader = observer(() => {
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
{(isAllowed || user?.id === issue?.created_by) && (
|
||||
{(isAllowed || currentUser?.id === issue?.created_by) && (
|
||||
<div className="flex-shrink-0">
|
||||
<Button
|
||||
variant="neutral-primary"
|
||||
|
@ -16,7 +16,7 @@ import { Loader, StateGroupIcon } from "@plane/ui";
|
||||
import { renderShortDateWithYearFormat } from "helpers/date-time.helper";
|
||||
// types
|
||||
import { IInboxIssue, IIssue } from "types";
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
const defaultValues: Partial<IInboxIssue> = {
|
||||
name: "",
|
||||
@ -151,7 +151,7 @@ export const InboxMainContent: React.FC = observer(() => {
|
||||
</div>
|
||||
);
|
||||
|
||||
const isAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
|
||||
const isAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -17,7 +17,7 @@ import {
|
||||
IViewIssuesFilterStore,
|
||||
} from "store_legacy/issues";
|
||||
// constants
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
type Props = {
|
||||
issuesFilterStore:
|
||||
@ -50,7 +50,7 @@ export const CalendarChart: React.FC<Props> = observer((props) => {
|
||||
} = useMobxStore();
|
||||
|
||||
const { enableIssueCreation } = issueStore?.viewFlags || {};
|
||||
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
|
||||
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
|
||||
|
||||
const calendarPayload = calendarStore.calendarPayload;
|
||||
|
||||
|
@ -16,7 +16,7 @@ import emptyIssue from "public/empty-state/issue.svg";
|
||||
import { ISearchIssueResponse } from "types";
|
||||
import { EProjectStore } from "store_legacy/command-palette.store";
|
||||
// constants
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
type Props = {
|
||||
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 (
|
||||
<>
|
||||
|
@ -15,7 +15,7 @@ import emptyIssue from "public/empty-state/issue.svg";
|
||||
// types
|
||||
import { ISearchIssueResponse } from "types";
|
||||
// constants
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
type Props = {
|
||||
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 (
|
||||
<>
|
||||
|
@ -5,7 +5,7 @@ import { useApplication, useUser } from "hooks/store";
|
||||
// components
|
||||
import { NewEmptyState } from "components/common/new-empty-state";
|
||||
// constants
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
// assets
|
||||
import emptyIssue from "public/empty-state/empty_issues.webp";
|
||||
import { EProjectStore } from "store_legacy/command-palette.store";
|
||||
@ -20,7 +20,7 @@ export const ProjectEmptyState: React.FC = observer(() => {
|
||||
membership: { currentProjectRole },
|
||||
} = useUser();
|
||||
|
||||
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
|
||||
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
|
||||
|
||||
return (
|
||||
<div className="grid h-full w-full place-items-center">
|
||||
|
@ -17,7 +17,7 @@ import { replaceUnderscoreIfSnakeCase } from "helpers/string.helper";
|
||||
// types
|
||||
import { IIssueFilterOptions, IIssueLabel, IProject, IState, IUserLite } from "types";
|
||||
// constants
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
type Props = {
|
||||
appliedFilters: IIssueFilterOptions;
|
||||
@ -43,7 +43,7 @@ export const AppliedFiltersList: React.FC<Props> = observer((props) => {
|
||||
|
||||
if (Object.keys(appliedFilters).length === 0) return null;
|
||||
|
||||
const isEditingAllowed = currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
|
||||
const isEditingAllowed = currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
|
||||
|
||||
return (
|
||||
<div className="flex flex-wrap items-stretch gap-2 bg-custom-background-100">
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { useRouter } from "next/router";
|
||||
import { observer } from "mobx-react-lite";
|
||||
// mobx store
|
||||
// hooks
|
||||
import { useProjectView } from "hooks/store";
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// components
|
||||
import { AppliedFiltersList } from "components/issues";
|
||||
@ -13,22 +14,23 @@ import { IIssueFilterOptions } from "types";
|
||||
import { EFilterType } from "store_legacy/issues/types";
|
||||
|
||||
export const ProjectViewAppliedFiltersRoot: React.FC = observer(() => {
|
||||
// router
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId, viewId } = router.query as {
|
||||
workspaceSlug: string;
|
||||
projectId: string;
|
||||
viewId: string;
|
||||
};
|
||||
|
||||
// store hooks
|
||||
const {
|
||||
projectLabel: { projectLabels },
|
||||
projectState: projectStateStore,
|
||||
projectMember: { projectMembers },
|
||||
projectViews: projectViewsStore,
|
||||
viewIssuesFilter: { issueFilters, updateFilters },
|
||||
} = useMobxStore();
|
||||
const { getViewById, updateView } = useProjectView();
|
||||
|
||||
const viewDetails = viewId ? projectViewsStore.viewDetails[viewId.toString()] : undefined;
|
||||
const viewDetails = viewId ? getViewById(viewId.toString()) : null;
|
||||
|
||||
const userFilters = issueFilters?.filters;
|
||||
// filters whose value not null or empty array
|
||||
@ -83,7 +85,7 @@ export const ProjectViewAppliedFiltersRoot: React.FC = observer(() => {
|
||||
const handleUpdateView = () => {
|
||||
if (!workspaceSlug || !projectId || !viewId || !viewDetails) return;
|
||||
|
||||
projectViewsStore.updateView(workspaceSlug.toString(), projectId.toString(), viewId.toString(), {
|
||||
updateView(workspaceSlug.toString(), projectId.toString(), viewId.toString(), {
|
||||
query_data: {
|
||||
...viewDetails.query_data,
|
||||
...(appliedFilters ?? {}),
|
||||
|
@ -25,7 +25,7 @@ import {
|
||||
IViewIssuesStore,
|
||||
} from "store_legacy/issues";
|
||||
import { TUnGroupedIssues } from "store_legacy/issues/types";
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
interface IBaseGanttRoot {
|
||||
issueFiltersStore:
|
||||
@ -70,7 +70,7 @@ export const BaseGanttRoot: React.FC<IBaseGanttRoot> = observer((props: IBaseGan
|
||||
await issueStore.updateIssue(workspaceSlug.toString(), projectId, issueId, payload, viewId);
|
||||
};
|
||||
|
||||
const isAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
|
||||
const isAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -30,7 +30,7 @@ import { KanBan } from "./default";
|
||||
import { KanBanSwimLanes } from "./swimlanes";
|
||||
import { EProjectStore } from "store_legacy/command-palette.store";
|
||||
import { DeleteIssueModal, IssuePeekOverview } from "components/issues";
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
export interface IBaseKanBanLayout {
|
||||
issueStore:
|
||||
@ -118,7 +118,7 @@ export const BaseKanBanRoot: React.FC<IBaseKanBanLayout> = observer((props: IBas
|
||||
const [dragState, setDragState] = useState<KanbanDragState>({});
|
||||
const [deleteIssueModal, setDeleteIssueModal] = useState(false);
|
||||
|
||||
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
|
||||
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
|
||||
|
||||
const canEditProperties = useCallback(
|
||||
(projectId: string | undefined) => {
|
||||
|
@ -10,7 +10,7 @@ import { IIssue } from "types";
|
||||
import { EIssueActions } from "../../types";
|
||||
import { BaseKanBanRoot } from "../base-kanban-root";
|
||||
import { EProjectStore } from "store_legacy/command-palette.store";
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
export const ProfileIssuesKanBanLayout: React.FC = observer(() => {
|
||||
const router = useRouter();
|
||||
@ -39,7 +39,7 @@ export const ProfileIssuesKanBanLayout: React.FC = observer(() => {
|
||||
const canEditPropertiesBasedOnProject = (projectId: string) => {
|
||||
const currentProjectRole = currentWorkspaceUserProjectsRole && currentWorkspaceUserProjectsRole[projectId];
|
||||
|
||||
return !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
|
||||
return !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -25,7 +25,7 @@ import { IIssueResponse } from "store_legacy/issues/types";
|
||||
import { EProjectStore } from "store_legacy/command-palette.store";
|
||||
import { IssuePeekOverview } from "components/issues";
|
||||
import { useRouter } from "next/router";
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
enum EIssueActions {
|
||||
UPDATE = "update",
|
||||
@ -86,7 +86,7 @@ export const BaseListRoot = observer((props: IBaseListRoot) => {
|
||||
} = useMobxStore();
|
||||
|
||||
const { currentProjectRole } = userStore;
|
||||
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
|
||||
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
|
||||
|
||||
const issueIds = issueStore?.getIssuesIds || [];
|
||||
const issues = issueStore?.getIssues;
|
||||
|
@ -12,7 +12,7 @@ import { EIssueActions } from "../../types";
|
||||
import { BaseListRoot } from "../base-list-root";
|
||||
import { IProjectStore } from "store_legacy/project";
|
||||
import { EProjectStore } from "store_legacy/command-palette.store";
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
export const ProfileIssuesListLayout: FC = observer(() => {
|
||||
const router = useRouter();
|
||||
@ -46,9 +46,9 @@ export const ProfileIssuesListLayout: FC = observer(() => {
|
||||
console.log(
|
||||
projectId,
|
||||
currentWorkspaceUserProjectsRole,
|
||||
!!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER
|
||||
!!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER
|
||||
);
|
||||
return !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
|
||||
return !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -14,7 +14,7 @@ import { IIssue } from "types";
|
||||
import { IQuickActionProps } from "../list/list-view-types";
|
||||
import { EProjectStore } from "store_legacy/command-palette.store";
|
||||
// constant
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
export const ProjectIssueQuickActions: React.FC<IQuickActionProps> = (props) => {
|
||||
const { issue, handleDelete, handleUpdate, customActionButton } = props;
|
||||
@ -30,7 +30,7 @@ export const ProjectIssueQuickActions: React.FC<IQuickActionProps> = (props) =>
|
||||
membership: { currentProjectRole },
|
||||
} = useUser();
|
||||
|
||||
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
|
||||
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
|
||||
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
|
@ -16,7 +16,7 @@ import { IIssueUnGroupedStructure } from "store_legacy/issue";
|
||||
import { EIssueActions } from "../types";
|
||||
|
||||
import { EFilterType, TUnGroupedIssues } from "store_legacy/issues/types";
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
type Props = {
|
||||
type?: TStaticViewTypes | null;
|
||||
@ -62,7 +62,7 @@ export const AllIssueLayoutRoot: React.FC<Props> = observer((props) => {
|
||||
|
||||
const currentProjectRole = currentWorkspaceUserProjectsRole && currentWorkspaceUserProjectsRole[projectId];
|
||||
|
||||
return !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
|
||||
return !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
|
||||
};
|
||||
|
||||
const issuesResponse = getIssues;
|
||||
|
@ -18,7 +18,7 @@ import { observer } from "mobx-react-lite";
|
||||
import { EFilterType, TUnGroupedIssues } from "store_legacy/issues/types";
|
||||
import { EIssueActions } from "../types";
|
||||
import { IQuickActionProps } from "../list/list-view-types";
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
interface IBaseSpreadsheetRoot {
|
||||
issueFiltersStore:
|
||||
@ -53,7 +53,7 @@ export const BaseSpreadsheetRoot = observer((props: IBaseSpreadsheetRoot) => {
|
||||
const { enableInlineEditing, enableQuickAdd, enableIssueCreation } = issueStore?.viewFlags || {};
|
||||
|
||||
const { currentProjectRole } = userStore;
|
||||
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
|
||||
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
|
||||
|
||||
const canEditProperties = (projectId: string | undefined) => {
|
||||
const isEditingAllowedBasedOnProject =
|
||||
|
@ -27,7 +27,7 @@ import { IIssue, IIssueActivity } from "types";
|
||||
// fetch-keys
|
||||
import { PROJECT_ISSUES_ACTIVITY, SUB_ISSUES } from "constants/fetch-keys";
|
||||
// constants
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
type Props = {
|
||||
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 (
|
||||
<>
|
||||
|
@ -16,7 +16,7 @@ import { IIssue, IUser } from "types";
|
||||
// services
|
||||
import { FileService } from "services/file.service";
|
||||
// constants
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
const fileService = new FileService();
|
||||
|
||||
@ -48,7 +48,7 @@ export const PeekOverviewIssueDetails: FC<IPeekOverviewIssueDetails> = (props) =
|
||||
const {
|
||||
membership: { currentProjectRole },
|
||||
} = useUser();
|
||||
const isAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
|
||||
const isAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
|
||||
// states
|
||||
const [characterLimit, setCharacterLimit] = useState(false);
|
||||
// hooks
|
||||
|
@ -23,7 +23,7 @@ import { LinkModal, LinksList } from "components/core";
|
||||
// types
|
||||
import { IIssue, TIssuePriorities, ILinkDetails, IIssueLink } from "types";
|
||||
// constants
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
interface IPeekOverviewProperties {
|
||||
issue: IIssue;
|
||||
@ -295,10 +295,10 @@ export const PeekOverviewProperties: FC<IPeekOverviewProperties> = observer((pro
|
||||
handleDeleteLink={issueLinkDelete}
|
||||
handleEditLink={handleEditLink}
|
||||
userAuth={{
|
||||
isGuest: currentProjectRole === EUserWorkspaceRoles.GUEST,
|
||||
isViewer: currentProjectRole === EUserWorkspaceRoles.VIEWER,
|
||||
isMember: currentProjectRole === EUserWorkspaceRoles.MEMBER,
|
||||
isOwner: currentProjectRole === EUserWorkspaceRoles.ADMIN,
|
||||
isGuest: currentProjectRole === EUserProjectRoles.GUEST,
|
||||
isViewer: currentProjectRole === EUserProjectRoles.VIEWER,
|
||||
isMember: currentProjectRole === EUserProjectRoles.MEMBER,
|
||||
isOwner: currentProjectRole === EUserProjectRoles.ADMIN,
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
|
@ -12,7 +12,7 @@ import { copyUrlToClipboard } from "helpers/string.helper";
|
||||
// types
|
||||
import { IIssue, IIssueLink } from "types";
|
||||
// constants
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
interface IIssuePeekOverview {
|
||||
workspaceSlug: string;
|
||||
@ -146,7 +146,7 @@ export const IssuePeekOverview: FC<IIssuePeekOverview> = observer((props) => {
|
||||
}
|
||||
};
|
||||
|
||||
const userRole = currentProjectRole ?? EUserWorkspaceRoles.GUEST;
|
||||
const userRole = currentProjectRole ?? EUserProjectRoles.GUEST;
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
|
@ -40,7 +40,7 @@ import { copyTextToClipboard } from "helpers/string.helper";
|
||||
import type { IIssue, IIssueLink, ILinkDetails } from "types";
|
||||
// fetch-keys
|
||||
import { ISSUE_DETAILS, PROJECT_ISSUES_ACTIVITY } from "constants/fetch-keys";
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
type Props = {
|
||||
control: any;
|
||||
@ -191,7 +191,7 @@ export const IssueDetailsSidebar: React.FC<Props> = observer((props) => {
|
||||
setLinkModal(true);
|
||||
};
|
||||
|
||||
const isAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
|
||||
const isAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
|
||||
|
||||
const currentIssueState = projectStates?.find((s) => s.id === issueDetail?.state);
|
||||
|
||||
|
@ -22,7 +22,8 @@ import { IUser, IIssue, ISearchIssueResponse } from "types";
|
||||
import { IssueService } from "services/issue";
|
||||
// fetch keys
|
||||
import { SUB_ISSUES } from "constants/fetch-keys";
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
// constants
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
export interface ISubIssuesRoot {
|
||||
parentIssue: IIssue;
|
||||
@ -178,7 +179,7 @@ export const SubIssuesRoot: React.FC<ISubIssuesRoot> = observer((props) => {
|
||||
[updateIssueStructure, projectId, updateIssue, user, workspaceSlug]
|
||||
);
|
||||
|
||||
const isEditable = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
|
||||
const isEditable = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
|
||||
|
||||
const mutateSubIssues = (parentIssueId: string | null) => {
|
||||
if (parentIssueId) mutate(SUB_ISSUES(parentIssueId));
|
||||
|
@ -15,7 +15,7 @@ import { copyUrlToClipboard } from "helpers/string.helper";
|
||||
import { renderShortDate, renderShortMonthDate } from "helpers/date-time.helper";
|
||||
// constants
|
||||
import { MODULE_STATUS } from "constants/module";
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
type Props = {
|
||||
moduleId: string;
|
||||
@ -38,7 +38,7 @@ export const ModuleCardItem: React.FC<Props> = observer((props) => {
|
||||
const { getModuleById, addModuleToFavorites, removeModuleFromFavorites } = useModule();
|
||||
// derived values
|
||||
const moduleDetails = getModuleById(moduleId);
|
||||
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
|
||||
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
|
||||
|
||||
const handleAddToFavorites = (e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
e.stopPropagation();
|
||||
|
@ -15,7 +15,7 @@ import { copyUrlToClipboard } from "helpers/string.helper";
|
||||
import { renderShortDate, renderShortMonthDate } from "helpers/date-time.helper";
|
||||
// constants
|
||||
import { MODULE_STATUS } from "constants/module";
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
type Props = {
|
||||
moduleId: string;
|
||||
@ -38,7 +38,7 @@ export const ModuleListItem: React.FC<Props> = observer((props) => {
|
||||
const { getModuleById, addModuleToFavorites, removeModuleFromFavorites } = useModule();
|
||||
// derived values
|
||||
const moduleDetails = getModuleById(moduleId);
|
||||
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
|
||||
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
|
||||
|
||||
const handleAddToFavorites = (e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
e.stopPropagation();
|
||||
|
@ -9,7 +9,7 @@ import { ModuleCardItem, ModuleListItem, ModulePeekOverview, ModulesListGanttCha
|
||||
// ui
|
||||
import { Loader } from "@plane/ui";
|
||||
// constants
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
// assets
|
||||
import emptyModule from "public/empty-state/empty_modules.webp";
|
||||
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 isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
|
||||
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
|
||||
|
||||
if (!projectModules)
|
||||
return (
|
||||
|
@ -28,7 +28,7 @@ import { copyUrlToClipboard } from "helpers/string.helper";
|
||||
import { ILinkDetails, IModule, ModuleLink } from "types";
|
||||
// constant
|
||||
import { MODULE_STATUS } from "constants/module";
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
const defaultValues: Partial<IModule> = {
|
||||
lead: "",
|
||||
@ -255,7 +255,7 @@ export const ModuleDetailsSidebar: React.FC<Props> = observer((props) => {
|
||||
: `${moduleDetails.total_issues}`
|
||||
: `${moduleDetails.completed_issues}/${moduleDetails.total_issues}`;
|
||||
|
||||
const isEditingAllowed = !!userRole && userRole >= EUserWorkspaceRoles.MEMBER;
|
||||
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -583,10 +583,10 @@ export const ModuleDetailsSidebar: React.FC<Props> = observer((props) => {
|
||||
handleEditLink={handleEditLink}
|
||||
handleDeleteLink={handleDeleteLink}
|
||||
userAuth={{
|
||||
isGuest: currentProjectRole === EUserWorkspaceRoles.GUEST,
|
||||
isViewer: currentProjectRole === EUserWorkspaceRoles.VIEWER,
|
||||
isMember: currentProjectRole === EUserWorkspaceRoles.MEMBER,
|
||||
isOwner: currentProjectRole === EUserWorkspaceRoles.ADMIN,
|
||||
isGuest: currentProjectRole === EUserProjectRoles.GUEST,
|
||||
isViewer: currentProjectRole === EUserProjectRoles.VIEWER,
|
||||
isMember: currentProjectRole === EUserProjectRoles.MEMBER,
|
||||
isOwner: currentProjectRole === EUserProjectRoles.ADMIN,
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
|
@ -9,7 +9,7 @@ import { TourRoot } from "components/onboarding";
|
||||
import { UserGreetingsView } from "components/user";
|
||||
import { CompletedIssuesGraph, IssuesList, IssuesPieChart, IssuesStats } from "components/workspace";
|
||||
// constants
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
// images
|
||||
import { NewEmptyState } from "components/common/new-empty-state";
|
||||
import emptyProject from "public/empty-state/dashboard_empty_project.webp";
|
||||
@ -25,7 +25,13 @@ export const WorkspaceDashboardView = observer(() => {
|
||||
commandPalette: commandPaletteStore,
|
||||
eventTracker: { setTrackElement, postHogEventTracker },
|
||||
} = useApplication();
|
||||
const { currentUser, dashboardInfo: workspaceDashboardInfo, fetchUserDashboardInfo, updateTourCompleted } = useUser();
|
||||
const {
|
||||
currentUser,
|
||||
dashboardInfo: workspaceDashboardInfo,
|
||||
fetchUserDashboardInfo,
|
||||
updateTourCompleted,
|
||||
membership: { currentProjectRole },
|
||||
} = useUser();
|
||||
const { workspaceProjects } = useProject();
|
||||
// fetch user dashboard info
|
||||
useSWR(
|
||||
@ -33,7 +39,7 @@ export const WorkspaceDashboardView = observer(() => {
|
||||
workspaceSlug ? () => fetchUserDashboardInfo(workspaceSlug.toString(), month) : null
|
||||
);
|
||||
|
||||
const isEditingAllowed = !!userStore.currentProjectRole && userStore.currentProjectRole >= EUserWorkspaceRoles.MEMBER;
|
||||
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
|
||||
|
||||
const handleTourCompleted = () => {
|
||||
updateTourCompleted()
|
||||
|
@ -26,7 +26,7 @@ import { CustomMenu, Tooltip } from "@plane/ui";
|
||||
// components
|
||||
import { CreateUpdatePageModal, DeletePageModal } from "components/pages";
|
||||
// constants
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
export interface IPagesListItem {
|
||||
workspaceSlug: string;
|
||||
@ -168,11 +168,11 @@ export const PagesListItem: FC<IPagesListItem> = observer((props) => {
|
||||
|
||||
const userCanEdit =
|
||||
isCurrentUserOwner ||
|
||||
(currentProjectRole && [EUserWorkspaceRoles.ADMIN, EUserWorkspaceRoles.MEMBER].includes(currentProjectRole));
|
||||
(currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole));
|
||||
const userCanChangeAccess = isCurrentUserOwner;
|
||||
const userCanArchive = isCurrentUserOwner || currentProjectRole === EUserWorkspaceRoles.ADMIN;
|
||||
const userCanDelete = isCurrentUserOwner || currentProjectRole === EUserWorkspaceRoles.ADMIN;
|
||||
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
|
||||
const userCanArchive = isCurrentUserOwner || currentProjectRole === EUserProjectRoles.ADMIN;
|
||||
const userCanDelete = isCurrentUserOwner || currentProjectRole === EUserProjectRoles.ADMIN;
|
||||
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -12,7 +12,7 @@ import { Loader } from "@plane/ui";
|
||||
// images
|
||||
import emptyPage from "public/empty-state/empty_page.png";
|
||||
// constants
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
type IPagesListView = {
|
||||
pages: string[];
|
||||
@ -31,7 +31,7 @@ export const PagesListView: FC<IPagesListView> = observer((props) => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
|
||||
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
|
||||
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -13,7 +13,7 @@ import emptyPage from "public/empty-state/empty_page.png";
|
||||
// helpers
|
||||
import { replaceUnderscoreIfSnakeCase } from "helpers/string.helper";
|
||||
// constants
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
export const RecentPagesList: FC = observer(() => {
|
||||
// store hooks
|
||||
@ -25,7 +25,7 @@ export const RecentPagesList: FC = observer(() => {
|
||||
|
||||
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) {
|
||||
return (
|
||||
|
@ -9,7 +9,7 @@ import emptyProject from "public/empty-state/empty_project.webp";
|
||||
// icons
|
||||
import { NewEmptyState } from "components/common/new-empty-state";
|
||||
// constants
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
export const ProjectCardList = observer(() => {
|
||||
// store hooks
|
||||
@ -22,7 +22,7 @@ export const ProjectCardList = observer(() => {
|
||||
} = useUser();
|
||||
const { workspaceProjects, searchedProjects, getProjectById } = useProject();
|
||||
|
||||
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
|
||||
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
|
||||
|
||||
if (!workspaceProjects)
|
||||
return (
|
||||
|
@ -15,7 +15,8 @@ import { ChevronDown, Dot, XCircle } from "lucide-react";
|
||||
// constants
|
||||
import { EUserWorkspaceRoles, ROLE } from "constants/workspace";
|
||||
// types
|
||||
import { IProjectMember, TUserProjectRole } from "types";
|
||||
import { IProjectMember } from "types";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
type Props = {
|
||||
member: IProjectMember;
|
||||
@ -136,7 +137,7 @@ export const ProjectMemberListItem: React.FC<Props> = observer((props) => {
|
||||
</div>
|
||||
}
|
||||
value={member.role}
|
||||
onChange={(value: TUserProjectRole | undefined) => {
|
||||
onChange={(value: EUserProjectRoles | undefined) => {
|
||||
if (!workspaceSlug || !projectId) return;
|
||||
|
||||
updateMember(workspaceSlug.toString(), projectId.toString(), member.id, {
|
||||
|
@ -15,7 +15,7 @@ import { IProject, IUserLite, IWorkspace } from "types";
|
||||
// fetch-keys
|
||||
import { PROJECT_MEMBERS } from "constants/fetch-keys";
|
||||
// constants
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
const defaultValues: Partial<IProject> = {
|
||||
project_lead: null,
|
||||
@ -32,7 +32,7 @@ export const ProjectSettingsMemberDefaults: React.FC = observer(() => {
|
||||
} = useUser();
|
||||
const { currentProjectDetails, fetchProjectDetails, updateProject } = useProject();
|
||||
|
||||
const isAdmin = currentProjectRole === EUserWorkspaceRoles.ADMIN;
|
||||
const isAdmin = currentProjectRole === EUserProjectRoles.ADMIN;
|
||||
// hooks
|
||||
const { setToastAlert } = useToast();
|
||||
// form info
|
||||
|
@ -13,9 +13,10 @@ import { Avatar, Button, CustomSelect, CustomSearchSelect } from "@plane/ui";
|
||||
// services
|
||||
import { ProjectMemberService } from "services/project";
|
||||
// types
|
||||
import { IProjectMember, TUserProjectRole } from "types";
|
||||
import { IProjectMember } from "types";
|
||||
// constants
|
||||
import { EUserWorkspaceRoles, ROLE } from "constants/workspace";
|
||||
import { ROLE } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
type Props = {
|
||||
isOpen: boolean;
|
||||
@ -25,7 +26,7 @@ type Props = {
|
||||
};
|
||||
|
||||
type member = {
|
||||
role: TUserProjectRole;
|
||||
role: EUserProjectRoles;
|
||||
member_id: string;
|
||||
};
|
||||
|
||||
@ -267,8 +268,7 @@ export const SendProjectInvitationModal: React.FC<Props> = observer((props) => {
|
||||
width="w-full"
|
||||
>
|
||||
{Object.entries(ROLE).map(([key, label]) => {
|
||||
if (parseInt(key) > (currentProjectRole ?? EUserWorkspaceRoles.GUEST))
|
||||
return null;
|
||||
if (parseInt(key) > (currentProjectRole ?? EUserProjectRoles.GUEST)) return null;
|
||||
|
||||
return (
|
||||
<CustomSelect.Option key={key} value={key}>
|
||||
|
@ -9,7 +9,7 @@ import useToast from "hooks/use-toast";
|
||||
// types
|
||||
import { IProject } from "types";
|
||||
// constants
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
type Props = {};
|
||||
|
||||
@ -60,7 +60,7 @@ export const ProjectFeaturesList: FC<Props> = observer(() => {
|
||||
} = useUser();
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { currentProjectDetails, updateProject } = useProject();
|
||||
const isAdmin = currentProjectRole === EUserWorkspaceRoles.ADMIN;
|
||||
const isAdmin = currentProjectRole === EUserProjectRoles.ADMIN;
|
||||
// toast alert
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
|
@ -2,15 +2,12 @@ import React, { useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { Dialog, Transition } from "@headlessui/react";
|
||||
|
||||
// mobx store
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
import { AlertTriangle } from "lucide-react";
|
||||
// hooks
|
||||
import { useProjectView } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { Button } from "@plane/ui";
|
||||
// icons
|
||||
import { AlertTriangle } from "lucide-react";
|
||||
// types
|
||||
import { IProjectView } from "types";
|
||||
|
||||
@ -22,14 +19,14 @@ type Props = {
|
||||
|
||||
export const DeleteProjectViewModal: React.FC<Props> = observer((props) => {
|
||||
const { data, isOpen, onClose } = props;
|
||||
|
||||
// states
|
||||
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
|
||||
|
||||
// router
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
|
||||
const { projectViews: projectViewsStore } = useMobxStore();
|
||||
|
||||
// store hooks
|
||||
const { deleteView } = useProjectView();
|
||||
// toast alert
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const handleClose = () => {
|
||||
@ -42,8 +39,7 @@ export const DeleteProjectViewModal: React.FC<Props> = observer((props) => {
|
||||
|
||||
setIsDeleteLoading(true);
|
||||
|
||||
await projectViewsStore
|
||||
.deleteView(workspaceSlug.toString(), projectId.toString(), data.id)
|
||||
await deleteView(workspaceSlug.toString(), projectId.toString(), data.id)
|
||||
.then(() => {
|
||||
handleClose();
|
||||
|
||||
|
@ -1,14 +1,14 @@
|
||||
import { FC, Fragment } from "react";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { Dialog, Transition } from "@headlessui/react";
|
||||
import { debounce } from "lodash";
|
||||
// hooks
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
import { useProjectView } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
// components
|
||||
import { ProjectViewForm } from "components/views";
|
||||
// types
|
||||
import { IProjectView } from "types";
|
||||
import { debounce } from "lodash";
|
||||
|
||||
type Props = {
|
||||
data?: IProjectView | null;
|
||||
@ -21,18 +21,17 @@ type Props = {
|
||||
|
||||
export const CreateUpdateProjectViewModal: FC<Props> = observer((props) => {
|
||||
const { data, isOpen, onClose, preLoadedData, workspaceSlug, projectId } = props;
|
||||
// store
|
||||
const { projectViews: projectViewsStore } = useMobxStore();
|
||||
// hooks
|
||||
// store hooks
|
||||
const { createView, updateView } = useProjectView();
|
||||
// toast alert
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const handleClose = () => {
|
||||
onClose();
|
||||
};
|
||||
|
||||
const createView = async (payload: IProjectView) => {
|
||||
await projectViewsStore
|
||||
.createView(workspaceSlug, projectId, payload)
|
||||
const handleCreateView = async (payload: IProjectView) => {
|
||||
await createView(workspaceSlug, projectId, payload)
|
||||
.then(() => {
|
||||
console.log("after calling store");
|
||||
handleClose();
|
||||
@ -52,9 +51,8 @@ export const CreateUpdateProjectViewModal: FC<Props> = observer((props) => {
|
||||
);
|
||||
};
|
||||
|
||||
const updateView = async (payload: IProjectView) => {
|
||||
await projectViewsStore
|
||||
.updateView(workspaceSlug, projectId, data?.id as string, payload)
|
||||
const handleUpdateView = async (payload: IProjectView) => {
|
||||
await updateView(workspaceSlug, projectId, data?.id as string, payload)
|
||||
.then(() => handleClose())
|
||||
.catch((err) =>
|
||||
setToastAlert({
|
||||
@ -66,8 +64,8 @@ export const CreateUpdateProjectViewModal: FC<Props> = observer((props) => {
|
||||
};
|
||||
|
||||
const handleFormSubmit = async (formData: IProjectView) => {
|
||||
if (!data) await createView(formData);
|
||||
else await updateView(formData);
|
||||
if (!data) await handleCreateView(formData);
|
||||
else await handleUpdateView(formData);
|
||||
};
|
||||
|
||||
const debouncedFormSubmit = debounce(handleFormSubmit, 10, { leading: false, trailing: true });
|
||||
|
@ -4,8 +4,7 @@ import { useRouter } from "next/router";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { LinkIcon, PencilIcon, StarIcon, TrashIcon } from "lucide-react";
|
||||
// hooks
|
||||
import { useUser } from "hooks/store";
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
import { useProjectView, useUser } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
// components
|
||||
import { CreateUpdateProjectViewModal, DeleteProjectViewModal } from "components/views";
|
||||
@ -17,7 +16,7 @@ import { copyUrlToClipboard } from "helpers/string.helper";
|
||||
// types
|
||||
import { IProjectView } from "types";
|
||||
// constants
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
type Props = {
|
||||
view: IProjectView;
|
||||
@ -34,21 +33,21 @@ export const ProjectViewListItem: React.FC<Props> = observer((props) => {
|
||||
// toast alert
|
||||
const { setToastAlert } = useToast();
|
||||
// store hooks
|
||||
const { projectViews: projectViewsStore } = useMobxStore();
|
||||
const {
|
||||
membership: { currentProjectRole },
|
||||
} = useUser();
|
||||
const { addViewToFavorites, removeViewFromFavorites } = useProjectView();
|
||||
|
||||
const handleAddToFavorites = () => {
|
||||
if (!workspaceSlug || !projectId) return;
|
||||
|
||||
projectViewsStore.addViewToFavorites(workspaceSlug.toString(), projectId.toString(), view.id);
|
||||
addViewToFavorites(workspaceSlug.toString(), projectId.toString(), view.id);
|
||||
};
|
||||
|
||||
const handleRemoveFromFavorites = () => {
|
||||
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>) => {
|
||||
@ -65,7 +64,7 @@ export const ProjectViewListItem: React.FC<Props> = observer((props) => {
|
||||
|
||||
const totalFilters = calculateTotalFilters(view.query_data ?? {});
|
||||
|
||||
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
|
||||
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -1,10 +1,8 @@
|
||||
import { useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { Plus, Search } from "lucide-react";
|
||||
// hooks
|
||||
import { useApplication, useUser } from "hooks/store";
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
import { useApplication, useProjectView, useUser } from "hooks/store";
|
||||
// components
|
||||
import { ProjectViewListItem } from "components/views";
|
||||
import { NewEmptyState } from "components/common/new-empty-state";
|
||||
@ -13,28 +11,23 @@ import { Input, Loader } from "@plane/ui";
|
||||
// assets
|
||||
import emptyView from "public/empty-state/empty_view.webp";
|
||||
// constants
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
export const ProjectViewsList = observer(() => {
|
||||
// states
|
||||
const [query, setQuery] = useState("");
|
||||
// router
|
||||
const router = useRouter();
|
||||
const { projectId } = router.query;
|
||||
// store hooks
|
||||
const { projectViews: projectViewsStore } = useMobxStore();
|
||||
const {
|
||||
commandPalette: { toggleCreateViewModal },
|
||||
} = useApplication();
|
||||
const {
|
||||
membership: { currentProjectRole },
|
||||
} = 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 (!viewsList)
|
||||
if (!projectViews)
|
||||
return (
|
||||
<Loader className="space-y-4 p-4">
|
||||
<Loader.Item height="72px" />
|
||||
@ -44,7 +37,9 @@ export const ProjectViewsList = observer(() => {
|
||||
</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 (
|
||||
<>
|
||||
|
@ -1,6 +1,13 @@
|
||||
import { Globe2, Lock, LucideIcon } from "lucide-react";
|
||||
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 }[] = [
|
||||
{
|
||||
key: 0,
|
||||
@ -53,7 +60,6 @@ export const PROJECT_AUTOMATION_MONTHS = [
|
||||
|
||||
export const STATE_GROUP_KEYS = ["backlog", "unstarted", "started", "completed", "cancelled"];
|
||||
|
||||
|
||||
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-1693027407934-e3aa8a54c7ae?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=870&q=80",
|
||||
|
@ -5,6 +5,7 @@ export * from "./use-module";
|
||||
export * from "./use-page";
|
||||
export * from "./use-project-publish";
|
||||
export * from "./use-project-state";
|
||||
export * from "./use-project-view";
|
||||
export * from "./use-project";
|
||||
export * from "./use-user";
|
||||
export * from "./use-webhook";
|
||||
|
11
web/hooks/store/use-project-view.ts
Normal file
11
web/hooks/store/use-project-view.ts
Normal 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;
|
||||
};
|
@ -3,7 +3,16 @@ import { useRouter } from "next/router";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import useSWR from "swr";
|
||||
// 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";
|
||||
// components
|
||||
import { Spinner } from "@plane/ui";
|
||||
@ -20,10 +29,8 @@ export const ProjectAuthWrapper: FC<IProjectAuthWrapper> = observer((props) => {
|
||||
const { children } = props;
|
||||
// store
|
||||
const {
|
||||
project: { fetchProjectDetails, workspaceProjects },
|
||||
projectMember: { fetchProjectMembers },
|
||||
projectEstimates: { fetchProjectEstimates },
|
||||
projectViews: { fetchAllViews },
|
||||
inbox: { fetchInboxesList, isInboxEnabled },
|
||||
} = useMobxStore();
|
||||
const {
|
||||
@ -32,8 +39,10 @@ export const ProjectAuthWrapper: FC<IProjectAuthWrapper> = observer((props) => {
|
||||
const {
|
||||
membership: { fetchUserProjectInfo, projectMemberInfo, hasPermissionToProject },
|
||||
} = useUser();
|
||||
const { getProjectById, fetchProjectDetails } = useProject();
|
||||
const { fetchAllCycles } = useCycle();
|
||||
const { fetchModules } = useModule();
|
||||
const { fetchViews } = useProjectView();
|
||||
const { fetchProjectStates } = useProjectState();
|
||||
const {
|
||||
project: { fetchProjectLabels },
|
||||
@ -85,7 +94,7 @@ export const ProjectAuthWrapper: FC<IProjectAuthWrapper> = observer((props) => {
|
||||
// fetching project views
|
||||
useSWR(
|
||||
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
|
||||
useSWR(
|
||||
@ -99,8 +108,7 @@ export const ProjectAuthWrapper: FC<IProjectAuthWrapper> = observer((props) => {
|
||||
}
|
||||
);
|
||||
|
||||
const projectsList = workspaceSlug ? workspaceProjects : null;
|
||||
const projectExists = projectId ? projectsList?.find((project) => project.id === projectId.toString()) : null;
|
||||
const projectExists = projectId ? getProjectById(projectId.toString()) : null;
|
||||
|
||||
// check if the project member apis is loading
|
||||
if (!projectMemberInfo && projectId && hasPermissionToProject[projectId.toString()] === null)
|
||||
|
@ -9,7 +9,7 @@ import { NotAuthorizedView } from "components/auth-screens";
|
||||
// ui
|
||||
import { Button, LayersIcon } from "@plane/ui";
|
||||
// constants
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
export interface IProjectSettingLayout {
|
||||
children: ReactNode;
|
||||
@ -25,7 +25,7 @@ export const ProjectSettingLayout: FC<IProjectSettingLayout> = observer((props)
|
||||
membership: { currentProjectRole },
|
||||
} = useUser();
|
||||
|
||||
const restrictViewSettings = currentProjectRole && currentProjectRole <= EUserWorkspaceRoles.VIEWER;
|
||||
const restrictViewSettings = currentProjectRole && currentProjectRole <= EUserProjectRoles.VIEWER;
|
||||
|
||||
return restrictViewSettings ? (
|
||||
<NotAuthorizedView
|
||||
|
@ -34,7 +34,7 @@ import { IPage, IIssue } from "types";
|
||||
// fetch-keys
|
||||
import { PAGE_DETAILS, PROJECT_ISSUES_LIST } from "constants/fetch-keys";
|
||||
// constants
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
// services
|
||||
const fileService = new FileService();
|
||||
@ -362,15 +362,15 @@ const PageDetailsPage: NextPageWithLayout = observer(() => {
|
||||
const isPageReadOnly =
|
||||
pageDetails?.is_locked ||
|
||||
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 userCanDuplicate =
|
||||
currentProjectRole && [EUserWorkspaceRoles.ADMIN, EUserWorkspaceRoles.MEMBER].includes(currentProjectRole);
|
||||
const userCanArchive = isCurrentUserOwner || currentProjectRole === EUserWorkspaceRoles.ADMIN;
|
||||
currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole);
|
||||
const userCanArchive = isCurrentUserOwner || currentProjectRole === EUserProjectRoles.ADMIN;
|
||||
const userCanLock =
|
||||
currentProjectRole && [EUserWorkspaceRoles.ADMIN, EUserWorkspaceRoles.MEMBER].includes(currentProjectRole);
|
||||
currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -14,7 +14,8 @@ import { ProjectSettingHeader } from "components/headers";
|
||||
// types
|
||||
import { NextPageWithLayout } from "types/app";
|
||||
import { IProject } from "types";
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
// constants
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
const AutomationSettingsPage: NextPageWithLayout = observer(() => {
|
||||
// router
|
||||
@ -40,7 +41,7 @@ const AutomationSettingsPage: NextPageWithLayout = observer(() => {
|
||||
});
|
||||
};
|
||||
|
||||
const isAdmin = currentProjectRole === EUserWorkspaceRoles.ADMIN;
|
||||
const isAdmin = currentProjectRole === EUserProjectRoles.ADMIN;
|
||||
|
||||
return (
|
||||
<section className={`w-full overflow-y-auto py-8 pr-9 ${isAdmin ? "" : "opacity-60"}`}>
|
||||
|
@ -10,14 +10,15 @@ import { ProjectSettingHeader } from "components/headers";
|
||||
import { EstimatesList } from "components/estimates";
|
||||
// types
|
||||
import { NextPageWithLayout } from "types/app";
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
// constants
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
const EstimatesSettingsPage: NextPageWithLayout = observer(() => {
|
||||
const {
|
||||
membership: { currentProjectRole },
|
||||
} = useUser();
|
||||
|
||||
const isAdmin = currentProjectRole === EUserWorkspaceRoles.ADMIN;
|
||||
const isAdmin = currentProjectRole === EUserProjectRoles.ADMIN;
|
||||
|
||||
return (
|
||||
<div className={`w-full overflow-y-auto py-8 pr-9 ${isAdmin ? "" : "pointer-events-none opacity-60"}`}>
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { ReactElement } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import useSWR from "swr";
|
||||
// mobx store
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// hooks
|
||||
import { useProjectView } from "hooks/store";
|
||||
// layouts
|
||||
import { AppLayout } from "layouts/app-layout";
|
||||
// components
|
||||
@ -16,15 +16,16 @@ import emptyView from "public/empty-state/view.svg";
|
||||
import { NextPageWithLayout } from "types/app";
|
||||
|
||||
const ProjectViewIssuesPage: NextPageWithLayout = () => {
|
||||
// router
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId, viewId } = router.query;
|
||||
|
||||
const { projectViews: projectViewsStore } = useMobxStore();
|
||||
// store hooks
|
||||
const { fetchViewDetails } = useProjectView();
|
||||
|
||||
const { error } = useSWR(
|
||||
workspaceSlug && projectId && viewId ? `VIEW_DETAILS_${viewId.toString()}` : null,
|
||||
workspaceSlug && projectId && viewId
|
||||
? () => projectViewsStore.fetchViewDetails(workspaceSlug.toString(), projectId.toString(), viewId.toString())
|
||||
? () => fetchViewDetails(workspaceSlug.toString(), projectId.toString(), viewId.toString())
|
||||
: null
|
||||
);
|
||||
|
||||
|
@ -1,8 +1,4 @@
|
||||
import { ReactElement } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import useSWR from "swr";
|
||||
// mobx store
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// components
|
||||
import { ProjectViewsHeader } from "components/headers";
|
||||
import { ProjectViewsList } from "components/views";
|
||||
@ -11,21 +7,7 @@ import { AppLayout } from "layouts/app-layout";
|
||||
// types
|
||||
import { NextPageWithLayout } from "types/app";
|
||||
|
||||
const ProjectViewsPage: NextPageWithLayout = () => {
|
||||
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 />;
|
||||
};
|
||||
const ProjectViewsPage: NextPageWithLayout = () => <ProjectViewsList />;
|
||||
|
||||
ProjectViewsPage.getLayout = function getLayout(page: ReactElement) {
|
||||
return (
|
||||
|
@ -19,11 +19,7 @@ export class CycleService extends APIService {
|
||||
});
|
||||
}
|
||||
|
||||
async getCyclesWithParams(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
cycleType?: "current"
|
||||
): Promise<Record<string, ICycle>> {
|
||||
async getCyclesWithParams(workspaceSlug: string, projectId: string, cycleType?: "current"): Promise<ICycle[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/`, {
|
||||
params: {
|
||||
cycle_view: cycleType,
|
||||
|
@ -10,7 +10,7 @@ export class ModuleService extends APIService {
|
||||
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/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
|
@ -2,7 +2,7 @@ import { API_BASE_URL } from "helpers/common.helper";
|
||||
// services
|
||||
import { APIService } from "services/api.service";
|
||||
// types
|
||||
import { IPage, IPageBlock, RecentPagesResponse, IIssue } from "types";
|
||||
import { IPage, IPageBlock, IIssue } from "types";
|
||||
|
||||
export class PageService extends APIService {
|
||||
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/`)
|
||||
.then((response) => response?.data)
|
||||
.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> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/`)
|
||||
.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/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
|
@ -2,7 +2,7 @@ import { API_BASE_URL } from "helpers/common.helper";
|
||||
// services
|
||||
import { APIService } from "services/api.service";
|
||||
// types
|
||||
import type { IProjectBulkAddFormData, IProjectMember, IProjectMemberInvitation } from "types";
|
||||
import type { IProjectBulkAddFormData, IProjectMember } from "types";
|
||||
|
||||
export class ProjectMemberService extends APIService {
|
||||
constructor() {
|
||||
|
@ -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/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
|
@ -23,7 +23,7 @@ export class WorkspaceService extends APIService {
|
||||
super(API_BASE_URL);
|
||||
}
|
||||
|
||||
async userWorkspaces(): Promise<Record<string, IWorkspace>> {
|
||||
async userWorkspaces(): Promise<IWorkspace[]> {
|
||||
return this.get("/api/users/me/workspaces/")
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
|
@ -15,12 +15,8 @@ export interface ICycleStore {
|
||||
loader: boolean;
|
||||
error: any | null;
|
||||
// observables
|
||||
cycleMap: {
|
||||
[cycleId: string]: ICycle;
|
||||
};
|
||||
activeCycleMap: {
|
||||
[cycleId: string]: ICycle;
|
||||
};
|
||||
cycleMap: Record<string, ICycle>;
|
||||
activeCycleMap: Record<string, ICycle>;
|
||||
// computed
|
||||
projectAllCycles: string[] | null;
|
||||
projectCompletedCycles: string[] | null;
|
||||
@ -32,8 +28,8 @@ export interface ICycleStore {
|
||||
getActiveCycleById: (cycleId: string) => ICycle | null;
|
||||
// actions
|
||||
validateDate: (workspaceSlug: string, projectId: string, payload: CycleDateCheckData) => Promise<any>;
|
||||
fetchAllCycles: (workspaceSlug: string, projectId: string) => Promise<Record<string, ICycle>>;
|
||||
fetchActiveCycle: (workspaceSlug: string, projectId: string) => Promise<Record<string, ICycle>>;
|
||||
fetchAllCycles: (workspaceSlug: string, projectId: string) => Promise<ICycle[]>;
|
||||
fetchActiveCycle: (workspaceSlug: string, projectId: string) => Promise<ICycle[]>;
|
||||
fetchCycleDetails: (workspaceSlug: string, projectId: string, cycleId: string) => Promise<ICycle>;
|
||||
createCycle: (workspaceSlug: string, projectId: string, data: Partial<ICycle>) => Promise<ICycle>;
|
||||
updateCycleDetails: (
|
||||
@ -52,10 +48,8 @@ export class CycleStore implements ICycleStore {
|
||||
loader: boolean = false;
|
||||
error: any | null = null;
|
||||
// observables
|
||||
cycleMap: {
|
||||
[cycleId: string]: ICycle;
|
||||
} = {};
|
||||
activeCycleMap: { [cycleId: string]: ICycle } = {};
|
||||
cycleMap: Record<string, ICycle> = {};
|
||||
activeCycleMap: Record<string, ICycle> = {};
|
||||
// root store
|
||||
rootStore;
|
||||
// services
|
||||
@ -196,7 +190,7 @@ export class CycleStore implements ICycleStore {
|
||||
const cyclesResponse = await this.cycleService.getCyclesWithParams(workspaceSlug, projectId);
|
||||
|
||||
runInAction(() => {
|
||||
Object.values(cyclesResponse).forEach((cycle) => {
|
||||
cyclesResponse.forEach((cycle) => {
|
||||
set(this.cycleMap, [cycle.id], cycle);
|
||||
});
|
||||
this.loader = false;
|
||||
@ -221,7 +215,7 @@ export class CycleStore implements ICycleStore {
|
||||
const cyclesResponse = await this.cycleService.getCyclesWithParams(workspaceSlug, projectId, "current");
|
||||
|
||||
runInAction(() => {
|
||||
Object.values(cyclesResponse).forEach((cycle) => {
|
||||
cyclesResponse.forEach((cycle) => {
|
||||
set(this.activeCycleMap, [cycle.id], cycle);
|
||||
});
|
||||
this.loader = false;
|
||||
|
@ -12,15 +12,13 @@ export interface IModuleStore {
|
||||
loader: boolean;
|
||||
error: any | null;
|
||||
// observables
|
||||
moduleMap: {
|
||||
[moduleId: string]: IModule;
|
||||
};
|
||||
moduleMap: Record<string, IModule>;
|
||||
// computed
|
||||
projectModules: string[] | null;
|
||||
// computed actions
|
||||
getModuleById: (moduleId: string) => IModule | null;
|
||||
// actions
|
||||
fetchModules: (workspaceSlug: string, projectId: string) => void;
|
||||
fetchModules: (workspaceSlug: string, projectId: string) => Promise<IModule[]>;
|
||||
fetchModuleDetails: (workspaceSlug: string, projectId: string, moduleId: string) => Promise<IModule>;
|
||||
createModule: (workspaceSlug: string, projectId: string, data: Partial<IModule>) => Promise<IModule>;
|
||||
updateModuleDetails: (
|
||||
@ -53,9 +51,7 @@ export class ModulesStore implements IModuleStore {
|
||||
loader: boolean = false;
|
||||
error: any | null = null;
|
||||
// observables
|
||||
moduleMap: {
|
||||
[moduleId: string]: IModule;
|
||||
} = {};
|
||||
moduleMap: Record<string, IModule> = {};
|
||||
// root store
|
||||
rootStore;
|
||||
// services
|
||||
@ -108,7 +104,6 @@ export class ModulesStore implements IModuleStore {
|
||||
getModuleById = (moduleId: string) => this.moduleMap?.[moduleId] || null;
|
||||
|
||||
// actions
|
||||
|
||||
fetchModules = async (workspaceSlug: string, projectId: string) => {
|
||||
try {
|
||||
runInAction(() => {
|
||||
@ -119,12 +114,14 @@ export class ModulesStore implements IModuleStore {
|
||||
const modulesResponse = await this.moduleService.getModules(workspaceSlug, projectId);
|
||||
|
||||
runInAction(() => {
|
||||
Object.values(modulesResponse).forEach((module) => {
|
||||
modulesResponse.forEach((module) => {
|
||||
set(this.moduleMap, [module.id], module);
|
||||
});
|
||||
this.loader = false;
|
||||
this.error = null;
|
||||
});
|
||||
|
||||
return modulesResponse;
|
||||
} catch (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.error = error;
|
||||
});
|
||||
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -24,8 +24,8 @@ export interface IPageStore {
|
||||
getUnArchivedPageById: (pageId: string) => IPage | null;
|
||||
getArchivedPageById: (pageId: string) => IPage | null;
|
||||
// fetch actions
|
||||
fetchProjectPages: (workspaceSlug: string, projectId: string) => Promise<Record<string, IPage>>;
|
||||
fetchArchivedProjectPages: (workspaceSlug: string, projectId: string) => Promise<Record<string, IPage>>;
|
||||
fetchProjectPages: (workspaceSlug: string, projectId: string) => Promise<IPage[]>;
|
||||
fetchArchivedProjectPages: (workspaceSlug: string, projectId: string) => Promise<IPage[]>;
|
||||
// favorites actions
|
||||
addToFavorites: (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);
|
||||
|
||||
runInAction(() => {
|
||||
Object.values(response).forEach((page) => {
|
||||
response.forEach((page) => {
|
||||
set(this.pages, [page.id], page);
|
||||
});
|
||||
});
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
@ -223,7 +224,7 @@ export class PageStore implements IPageStore {
|
||||
const response = await this.pageService.getArchivedPages(workspaceSlug, projectId);
|
||||
|
||||
runInAction(() => {
|
||||
Object.values(response).forEach((page) => {
|
||||
response.forEach((page) => {
|
||||
set(this.archivedPages, [page.id], page);
|
||||
});
|
||||
});
|
||||
|
@ -1,24 +1,21 @@
|
||||
import set from "lodash/set";
|
||||
import { observable, action, makeObservable, runInAction } from "mobx";
|
||||
import { omit, set } from "lodash";
|
||||
import { observable, action, makeObservable, runInAction, computed } from "mobx";
|
||||
// services
|
||||
import { ViewService } from "services/view.service";
|
||||
import { RootStore } from "store/root.store";
|
||||
// types
|
||||
import { IProjectView } from "types";
|
||||
|
||||
export interface IProjectViewsStore {
|
||||
export interface IProjectViewStore {
|
||||
// states
|
||||
loader: boolean;
|
||||
error: any | null;
|
||||
|
||||
// observables
|
||||
viewId: string | null;
|
||||
viewMap: {
|
||||
[projectId: string]: {
|
||||
[viewId: string]: IProjectView;
|
||||
};
|
||||
};
|
||||
|
||||
viewMap: Record<string, IProjectView>;
|
||||
// computed
|
||||
projectViews: string[] | null;
|
||||
// computed actions
|
||||
getViewById: (viewId: string) => IProjectView;
|
||||
// actions
|
||||
fetchViews: (workspaceSlug: string, projectId: 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>;
|
||||
}
|
||||
|
||||
export class ProjectViewsStore implements IProjectViewsStore {
|
||||
export class ProjectViewStore implements IProjectViewStore {
|
||||
// states
|
||||
loader: boolean = false;
|
||||
error: any | null = null;
|
||||
|
||||
// observables
|
||||
viewId: string | null = null;
|
||||
viewMap: {
|
||||
[projectId: string]: {
|
||||
[viewId: string]: IProjectView;
|
||||
};
|
||||
} = {};
|
||||
|
||||
viewMap: Record<string, IProjectView> = {};
|
||||
// root store
|
||||
rootStore;
|
||||
|
||||
// services
|
||||
viewService;
|
||||
|
||||
@ -58,11 +47,12 @@ export class ProjectViewsStore implements IProjectViewsStore {
|
||||
// states
|
||||
loader: observable.ref,
|
||||
error: observable.ref,
|
||||
|
||||
// observables
|
||||
viewId: observable.ref,
|
||||
viewMap: observable,
|
||||
|
||||
// computed
|
||||
projectViews: computed,
|
||||
// computed actions
|
||||
getViewById: action,
|
||||
// actions
|
||||
fetchViews: action,
|
||||
fetchViewDetails: action,
|
||||
@ -78,11 +68,19 @@ export class ProjectViewsStore implements IProjectViewsStore {
|
||||
this.viewService = new ViewService();
|
||||
}
|
||||
|
||||
setViewId = (viewId: string | null) => {
|
||||
this.viewId = viewId;
|
||||
};
|
||||
get projectViews() {
|
||||
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 {
|
||||
runInAction(() => {
|
||||
this.loader = true;
|
||||
@ -92,7 +90,9 @@ export class ProjectViewsStore implements IProjectViewsStore {
|
||||
|
||||
runInAction(() => {
|
||||
this.loader = false;
|
||||
set(this.viewMap, [projectId], response);
|
||||
response.forEach((view) => {
|
||||
set(this.viewMap, [view.id], view);
|
||||
});
|
||||
});
|
||||
|
||||
return response;
|
||||
@ -116,7 +116,7 @@ export class ProjectViewsStore implements IProjectViewsStore {
|
||||
|
||||
runInAction(() => {
|
||||
this.loader = false;
|
||||
set(this.viewMap, [projectId, viewId], response);
|
||||
set(this.viewMap, [viewId], response);
|
||||
});
|
||||
|
||||
return response;
|
||||
@ -136,7 +136,7 @@ export class ProjectViewsStore implements IProjectViewsStore {
|
||||
|
||||
runInAction(() => {
|
||||
this.loader = false;
|
||||
set(this.viewMap, [projectId, response.id], response);
|
||||
set(this.viewMap, [response.id], response);
|
||||
});
|
||||
|
||||
return response;
|
||||
@ -156,10 +156,10 @@ export class ProjectViewsStore implements IProjectViewsStore {
|
||||
data: Partial<IProjectView>
|
||||
): Promise<IProjectView> => {
|
||||
try {
|
||||
const currentView = this.viewMap[projectId][viewId];
|
||||
const currentView = this.getViewById(viewId);
|
||||
|
||||
runInAction(() => {
|
||||
set(this.viewMap, [projectId, viewId], { ...currentView, ...data });
|
||||
set(this.viewMap, [viewId], { ...currentView, ...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> => {
|
||||
try {
|
||||
if (!this.viewMap?.[projectId]?.[viewId]) return;
|
||||
|
||||
runInAction(() => {
|
||||
delete this.viewMap[projectId][viewId];
|
||||
omit(this.viewMap, [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) => {
|
||||
try {
|
||||
const currentView = this.viewMap[projectId][viewId];
|
||||
const currentView = this.getViewById(viewId);
|
||||
|
||||
if (currentView.is_favorite) return;
|
||||
if (currentView?.is_favorite) return;
|
||||
|
||||
runInAction(() => {
|
||||
set(this.viewMap, [projectId, viewId, "is_favorite"], true);
|
||||
set(this.viewMap, [viewId, "is_favorite"], true);
|
||||
});
|
||||
|
||||
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);
|
||||
|
||||
runInAction(() => {
|
||||
set(this.viewMap, [projectId, viewId, "is_favorite"], false);
|
||||
set(this.viewMap, [viewId, "is_favorite"], false);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
removeViewFromFavorites = async (workspaceSlug: string, projectId: string, viewId: string) => {
|
||||
try {
|
||||
const currentView = this.viewMap[projectId][viewId];
|
||||
const currentView = this.getViewById(viewId);
|
||||
|
||||
if (!currentView.is_favorite) return;
|
||||
if (!currentView?.is_favorite) return;
|
||||
|
||||
runInAction(() => {
|
||||
set(this.viewMap, [projectId, viewId, "is_favorite"], false);
|
||||
set(this.viewMap, [viewId, "is_favorite"], false);
|
||||
});
|
||||
|
||||
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);
|
||||
|
||||
runInAction(() => {
|
||||
set(this.viewMap, [projectId, viewId, "is_favorite"], true);
|
||||
set(this.viewMap, [viewId, "is_favorite"], true);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -26,7 +26,7 @@ export interface IProjectStore {
|
||||
setSearchQuery: (query: string) => void;
|
||||
getProjectById: (projectId: string) => IProject | null;
|
||||
|
||||
fetchProjects: (workspaceSlug: string) => Promise<void>;
|
||||
fetchProjects: (workspaceSlug: string) => Promise<IProject[]>;
|
||||
fetchProjectDetails: (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) => {
|
||||
try {
|
||||
const currentProjectMap = await this.projectService.getProjects(workspaceSlug);
|
||||
const projectsResponse = await this.projectService.getProjects(workspaceSlug);
|
||||
|
||||
runInAction(() => {
|
||||
this.projectMap = currentProjectMap;
|
||||
projectsResponse.forEach((project) => {
|
||||
set(this.projectMap, [project.id], project);
|
||||
});
|
||||
});
|
||||
|
||||
return projectsResponse;
|
||||
} catch (error) {
|
||||
console.log("Failed to fetch project from workspace store");
|
||||
throw error;
|
||||
|
@ -3,7 +3,7 @@ import { enableStaticRendering } from "mobx-react-lite";
|
||||
import { AppRootStore, IAppRootStore } from "./application";
|
||||
import { IProjectRootStore, ProjectRootStore } from "./project";
|
||||
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 { IUserStore, UserStore } from "./user";
|
||||
import { IWorkspaceRootStore, WorkspaceRootStore } from "./workspace";
|
||||
@ -22,7 +22,7 @@ export class RootStore {
|
||||
labelRoot: ILabelRootStore;
|
||||
cycle: ICycleStore;
|
||||
module: IModuleStore;
|
||||
projectView: IProjectViewsStore;
|
||||
projectView: IProjectViewStore;
|
||||
page: IPageStore;
|
||||
issue: IIssueRootStore;
|
||||
state: IStateStore;
|
||||
@ -38,7 +38,7 @@ export class RootStore {
|
||||
this.issue = new IssueRootStore(this);
|
||||
this.cycle = new CycleStore(this);
|
||||
this.module = new ModulesStore(this);
|
||||
this.projectView = new ProjectViewsStore(this);
|
||||
this.projectView = new ProjectViewStore(this);
|
||||
this.page = new PageStore(this);
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,10 @@ import { ProjectMemberService } from "services/project";
|
||||
import { UserService } from "services/user.service";
|
||||
import { WorkspaceService } from "services/workspace.service";
|
||||
// interfaces
|
||||
import { IWorkspaceMemberMe, IProjectMember, TUserProjectRole, TUserWorkspaceRole } from "types";
|
||||
import { IWorkspaceMemberMe, IProjectMember } from "types";
|
||||
import { RootStore } from "../root.store";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
|
||||
export interface IUserMembershipStore {
|
||||
workspaceMemberInfo: {
|
||||
@ -24,8 +26,8 @@ export interface IUserMembershipStore {
|
||||
|
||||
currentProjectMemberInfo: IProjectMember | undefined;
|
||||
currentWorkspaceMemberInfo: IWorkspaceMemberMe | undefined;
|
||||
currentProjectRole: TUserProjectRole | undefined;
|
||||
currentWorkspaceRole: TUserWorkspaceRole | undefined;
|
||||
currentProjectRole: EUserProjectRoles | undefined;
|
||||
currentWorkspaceRole: EUserWorkspaceRoles | undefined;
|
||||
|
||||
hasPermissionToCurrentWorkspace: boolean | undefined;
|
||||
hasPermissionToCurrentProject: boolean | undefined;
|
||||
|
@ -22,7 +22,7 @@ export interface IWorkspaceRootStore {
|
||||
getWorkspaceBySlug: (workspaceSlug: string) => IWorkspace | null;
|
||||
getWorkspaceById: (workspaceId: string) => IWorkspace | null;
|
||||
// actions
|
||||
fetchWorkspaces: () => Promise<Record<string, IWorkspace>>;
|
||||
fetchWorkspaces: () => Promise<IWorkspace[]>;
|
||||
createWorkspace: (data: Partial<IWorkspace>) => Promise<IWorkspace>;
|
||||
updateWorkspace: (workspaceSlug: string, data: Partial<IWorkspace>) => Promise<IWorkspace>;
|
||||
deleteWorkspace: (workspaceSlug: string) => Promise<void>;
|
||||
@ -126,7 +126,9 @@ export class WorkspaceRootStore implements IWorkspaceRootStore {
|
||||
const workspaceResponse = await this.workspaceService.userWorkspaces();
|
||||
|
||||
runInAction(() => {
|
||||
this.workspaces = workspaceResponse;
|
||||
workspaceResponse.forEach((workspace) => {
|
||||
set(this.workspaces, [workspace.id], workspace);
|
||||
});
|
||||
this.loader = false;
|
||||
this.error = null;
|
||||
});
|
||||
|
@ -7,8 +7,9 @@ import { WorkspaceService } from "services/workspace.service";
|
||||
import { AuthService } from "services/auth.service";
|
||||
// interfaces
|
||||
import { IUser, IUserSettings } from "types/users";
|
||||
import { IWorkspaceMemberMe, IProjectMember, TUserProjectRole, TUserWorkspaceRole } from "types";
|
||||
import { IWorkspaceMemberMe, IProjectMember, TUserWorkspaceRole } from "types";
|
||||
import { RootStore } from "./root";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
export interface IUserStore {
|
||||
loader: boolean;
|
||||
@ -37,7 +38,7 @@ export interface IUserStore {
|
||||
|
||||
currentProjectMemberInfo: IProjectMember | undefined;
|
||||
currentWorkspaceMemberInfo: IWorkspaceMemberMe | undefined;
|
||||
currentProjectRole: TUserProjectRole | undefined;
|
||||
currentProjectRole: EUserProjectRoles | undefined;
|
||||
currentWorkspaceRole: TUserWorkspaceRole | undefined;
|
||||
|
||||
hasPermissionToCurrentWorkspace: boolean | undefined;
|
||||
|
4
web/types/pages.d.ts
vendored
4
web/types/pages.d.ts
vendored
@ -34,10 +34,6 @@ export interface IRecentPages {
|
||||
[key: string]: string[];
|
||||
}
|
||||
|
||||
export interface RecentPagesResponse {
|
||||
[key: string]: IPage[];
|
||||
}
|
||||
|
||||
export interface IPageBlock {
|
||||
completed_at: Date | null;
|
||||
created_at: Date;
|
||||
|
45
web/types/projects.d.ts
vendored
45
web/types/projects.d.ts
vendored
@ -1,6 +1,5 @@
|
||||
import type { IUserLite, IWorkspace, IWorkspaceLite, IUserMemberLite, TStateGroups, IProjectViewProps } from ".";
|
||||
|
||||
export type TUserProjectRole = 5 | 10 | 15 | 20;
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
import type { IUserLite, IWorkspace, IWorkspaceLite, TStateGroups } from ".";
|
||||
|
||||
export interface IProject {
|
||||
archive_in: number;
|
||||
@ -34,7 +33,7 @@ export interface IProject {
|
||||
is_deployed: boolean;
|
||||
is_favorite: boolean;
|
||||
is_member: boolean;
|
||||
member_role: TUserProjectRole | null;
|
||||
member_role: EUserProjectRoles | null;
|
||||
members: IProjectMemberLite[];
|
||||
issue_views_view: boolean;
|
||||
module_view: boolean;
|
||||
@ -73,44 +72,12 @@ export interface IProjectMemberLite {
|
||||
|
||||
export interface IProjectMember {
|
||||
id: string;
|
||||
member: IUserMemberLite;
|
||||
project: IProjectLite;
|
||||
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;
|
||||
member: string;
|
||||
role: EUserProjectRoles;
|
||||
}
|
||||
|
||||
export interface IProjectBulkAddFormData {
|
||||
members: { role: TUserProjectRole; member_id: string }[];
|
||||
members: { role: EUserProjectRoles; member_id: string }[];
|
||||
}
|
||||
|
||||
export interface IGithubRepository {
|
||||
|
3
web/types/users.d.ts
vendored
3
web/types/users.d.ts
vendored
@ -61,11 +61,10 @@ export interface IUserTheme {
|
||||
|
||||
export interface IUserLite {
|
||||
avatar: string;
|
||||
created_at: Date;
|
||||
display_name: string;
|
||||
email?: string;
|
||||
first_name: string;
|
||||
readonly id: string;
|
||||
id: string;
|
||||
is_bot: boolean;
|
||||
last_name: string;
|
||||
}
|
||||
|
9
web/types/workspace.d.ts
vendored
9
web/types/workspace.d.ts
vendored
@ -1,3 +1,4 @@
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import type { IProjectMember, IUser, IUserLite, IWorkspaceViewProps } from "types";
|
||||
|
||||
export type TUserWorkspaceRole = 5 | 10 | 15 | 20;
|
||||
@ -58,15 +59,9 @@ export type Properties = {
|
||||
};
|
||||
|
||||
export interface IWorkspaceMember {
|
||||
company_role: string | null;
|
||||
created_at: Date;
|
||||
created_by: string;
|
||||
id: string;
|
||||
member: IUserLite;
|
||||
role: TUserWorkspaceRole;
|
||||
updated_at: Date;
|
||||
updated_by: string;
|
||||
workspace: IWorkspaceLite;
|
||||
role: EUserWorkspaceRoles;
|
||||
}
|
||||
|
||||
export interface IWorkspaceMemberMe {
|
||||
|
Loading…
Reference in New Issue
Block a user