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