mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
refactor: layout roots (#2517)
This commit is contained in:
parent
05a76c5ee3
commit
38421e8106
@ -1,11 +1,15 @@
|
||||
import { useCallback } from "react";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/router";
|
||||
import { observer } from "mobx-react-lite";
|
||||
|
||||
// mobx store
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// components
|
||||
import { DisplayFiltersSelection, FiltersDropdown, FilterSelection, LayoutSelection } from "components/issues";
|
||||
// ui
|
||||
import { BreadcrumbItem, Breadcrumbs, CustomMenu, PhotoFilterIcon } from "@plane/ui";
|
||||
// helpers
|
||||
import { truncateText } from "helpers/string.helper";
|
||||
// types
|
||||
import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions, TIssueLayouts } from "types";
|
||||
// constants
|
||||
@ -19,6 +23,7 @@ export const ProjectViewIssuesHeader: React.FC = observer(() => {
|
||||
issueFilter: issueFilterStore,
|
||||
projectViewFilters: projectViewFiltersStore,
|
||||
project: projectStore,
|
||||
projectViews: projectViewsStore,
|
||||
} = useMobxStore();
|
||||
|
||||
const storedFilters = viewId ? projectViewFiltersStore.storedFilters[viewId.toString()] : undefined;
|
||||
@ -82,32 +87,78 @@ export const ProjectViewIssuesHeader: React.FC = observer(() => {
|
||||
[issueFilterStore, projectId, workspaceSlug]
|
||||
);
|
||||
|
||||
const projectDetails =
|
||||
workspaceSlug && projectId
|
||||
? projectStore.getProjectById(workspaceSlug.toString(), projectId.toString())
|
||||
: undefined;
|
||||
|
||||
const viewsList = projectId ? projectViewsStore.viewsList[projectId.toString()] : undefined;
|
||||
const viewDetails = viewId ? projectViewsStore.viewDetails[viewId.toString()] : undefined;
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-2">
|
||||
<LayoutSelection
|
||||
layouts={["list", "kanban", "calendar", "spreadsheet", "gantt_chart"]}
|
||||
onChange={(layout) => handleLayoutChange(layout)}
|
||||
selectedLayout={activeLayout}
|
||||
/>
|
||||
<FiltersDropdown title="Filters">
|
||||
<FilterSelection
|
||||
filters={storedFilters ?? {}}
|
||||
handleFiltersUpdate={handleFiltersUpdate}
|
||||
layoutDisplayFiltersOptions={activeLayout ? ISSUE_DISPLAY_FILTERS_BY_LAYOUT.issues[activeLayout] : undefined}
|
||||
labels={projectStore.labels?.[projectId?.toString() ?? ""] ?? undefined}
|
||||
members={projectStore.members?.[projectId?.toString() ?? ""]?.map((m) => m.member)}
|
||||
states={projectStore.states?.[projectId?.toString() ?? ""] ?? undefined}
|
||||
<div className="relative w-full flex items-center z-10 justify-between gap-x-2 gap-y-4 border-b border-custom-border-200 bg-custom-sidebar-background-100 p-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<Breadcrumbs onBack={() => router.back()}>
|
||||
<BreadcrumbItem
|
||||
link={
|
||||
<Link href={`/${workspaceSlug}/projects/${projectDetails?.id}/cycles`}>
|
||||
<a className={`border-r-2 border-custom-sidebar-border-200 px-3 text-sm `}>
|
||||
<p className="truncate">{`${projectDetails?.name ?? "Project"} Views`}</p>
|
||||
</a>
|
||||
</Link>
|
||||
}
|
||||
/>
|
||||
</Breadcrumbs>
|
||||
<CustomMenu
|
||||
label={
|
||||
<>
|
||||
<PhotoFilterIcon height={12} width={12} />
|
||||
{viewDetails?.name && truncateText(viewDetails.name, 40)}
|
||||
</>
|
||||
}
|
||||
className="ml-1.5"
|
||||
placement="bottom-start"
|
||||
>
|
||||
{viewsList?.map((view) => (
|
||||
<CustomMenu.MenuItem
|
||||
key={view.id}
|
||||
onClick={() => router.push(`/${workspaceSlug}/projects/${projectId}/views/${view.id}`)}
|
||||
>
|
||||
{truncateText(view.name, 40)}
|
||||
</CustomMenu.MenuItem>
|
||||
))}
|
||||
</CustomMenu>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<LayoutSelection
|
||||
layouts={["list", "kanban", "calendar", "spreadsheet", "gantt_chart"]}
|
||||
onChange={(layout) => handleLayoutChange(layout)}
|
||||
selectedLayout={activeLayout}
|
||||
/>
|
||||
</FiltersDropdown>
|
||||
<FiltersDropdown title="Display">
|
||||
<DisplayFiltersSelection
|
||||
displayFilters={issueFilterStore.userDisplayFilters}
|
||||
displayProperties={issueFilterStore.userDisplayProperties}
|
||||
handleDisplayFiltersUpdate={handleDisplayFiltersUpdate}
|
||||
handleDisplayPropertiesUpdate={handleDisplayPropertiesUpdate}
|
||||
layoutDisplayFiltersOptions={activeLayout ? ISSUE_DISPLAY_FILTERS_BY_LAYOUT.issues[activeLayout] : undefined}
|
||||
/>
|
||||
</FiltersDropdown>
|
||||
<FiltersDropdown title="Filters">
|
||||
<FilterSelection
|
||||
filters={storedFilters ?? {}}
|
||||
handleFiltersUpdate={handleFiltersUpdate}
|
||||
layoutDisplayFiltersOptions={
|
||||
activeLayout ? ISSUE_DISPLAY_FILTERS_BY_LAYOUT.issues[activeLayout] : undefined
|
||||
}
|
||||
labels={projectStore.labels?.[projectId?.toString() ?? ""] ?? undefined}
|
||||
members={projectStore.members?.[projectId?.toString() ?? ""]?.map((m) => m.member)}
|
||||
states={projectStore.states?.[projectId?.toString() ?? ""] ?? undefined}
|
||||
/>
|
||||
</FiltersDropdown>
|
||||
<FiltersDropdown title="Display">
|
||||
<DisplayFiltersSelection
|
||||
displayFilters={issueFilterStore.userDisplayFilters}
|
||||
displayProperties={issueFilterStore.userDisplayProperties}
|
||||
handleDisplayFiltersUpdate={handleDisplayFiltersUpdate}
|
||||
handleDisplayPropertiesUpdate={handleDisplayPropertiesUpdate}
|
||||
layoutDisplayFiltersOptions={
|
||||
activeLayout ? ISSUE_DISPLAY_FILTERS_BY_LAYOUT.issues[activeLayout] : undefined
|
||||
}
|
||||
/>
|
||||
</FiltersDropdown>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
@ -1,7 +1,10 @@
|
||||
import { FC, useState } from "react";
|
||||
import { useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
// icons
|
||||
import { ArrowLeft, Link, Plus } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { ArrowLeft, Plus } from "lucide-react";
|
||||
// mobx store
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// components
|
||||
import { CreateUpdateProjectViewModal } from "components/views";
|
||||
// components
|
||||
@ -11,18 +14,20 @@ import { PrimaryButton } from "components/ui";
|
||||
// helpers
|
||||
import { truncateText } from "helpers/string.helper";
|
||||
|
||||
interface IProjectViewsHeader {
|
||||
title: string | undefined;
|
||||
}
|
||||
|
||||
export const ProjectViewsHeader: FC<IProjectViewsHeader> = (props) => {
|
||||
const { title } = props;
|
||||
export const ProjectViewsHeader: React.FC = observer(() => {
|
||||
// router
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
// states
|
||||
const [createViewModal, setCreateViewModal] = useState(false);
|
||||
|
||||
const { project: projectStore } = useMobxStore();
|
||||
|
||||
const projectDetails =
|
||||
workspaceSlug && projectId
|
||||
? projectStore.getProjectById(workspaceSlug.toString(), projectId.toString())
|
||||
: undefined;
|
||||
|
||||
return (
|
||||
<>
|
||||
{workspaceSlug && projectId && (
|
||||
@ -43,7 +48,7 @@ export const ProjectViewsHeader: FC<IProjectViewsHeader> = (props) => {
|
||||
className="grid h-8 w-8 place-items-center rounded border border-custom-border-200"
|
||||
onClick={() => router.back()}
|
||||
>
|
||||
<ArrowLeft fontSize={14} strokeWidth={2} />
|
||||
<ArrowLeft className="h-3 w-3" strokeWidth={2} />
|
||||
</button>
|
||||
</div>
|
||||
<div>
|
||||
@ -57,20 +62,13 @@ export const ProjectViewsHeader: FC<IProjectViewsHeader> = (props) => {
|
||||
</Link>
|
||||
}
|
||||
/>
|
||||
<BreadcrumbItem title={`${truncateText(title ?? "Project", 32)} Cycles`} />
|
||||
<BreadcrumbItem title={`${truncateText(projectDetails?.name ?? "Project", 32)} Views`} />
|
||||
</Breadcrumbs>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="flex items-center gap-2 flex-shrink-0">
|
||||
<div>
|
||||
<PrimaryButton
|
||||
type="button"
|
||||
className="flex items-center gap-2"
|
||||
onClick={() => {
|
||||
const e = new KeyboardEvent("keydown", { key: "v" });
|
||||
document.dispatchEvent(e);
|
||||
}}
|
||||
>
|
||||
<PrimaryButton type="button" className="flex items-center gap-2" onClick={() => setCreateViewModal(true)}>
|
||||
<Plus size={14} strokeWidth={2} />
|
||||
Create View
|
||||
</PrimaryButton>
|
||||
@ -79,4 +77,4 @@ export const ProjectViewsHeader: FC<IProjectViewsHeader> = (props) => {
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
@ -1,10 +1,9 @@
|
||||
import React from "react";
|
||||
// next imports
|
||||
import React, { useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
// swr
|
||||
import useSWR from "swr";
|
||||
// mobx react lite
|
||||
import { observer } from "mobx-react-lite";
|
||||
import useSWR from "swr";
|
||||
// mobx store
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// components
|
||||
import {
|
||||
CycleAppliedFiltersRoot,
|
||||
@ -14,59 +13,63 @@ import {
|
||||
CycleListLayout,
|
||||
CycleSpreadsheetLayout,
|
||||
} from "components/issues";
|
||||
// mobx store
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
import { TransferIssues, TransferIssuesModal } from "components/cycles";
|
||||
// helpers
|
||||
import { getDateRangeStatus } from "helpers/date-time.helper";
|
||||
|
||||
export const CycleLayoutRoot: React.FC = observer(() => {
|
||||
const [transferIssuesModal, setTransferIssuesModal] = useState(false);
|
||||
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId, cycleId } = router.query as {
|
||||
workspaceSlug: string;
|
||||
projectId: string;
|
||||
cycleId: string;
|
||||
};
|
||||
const { workspaceSlug, projectId, cycleId } = router.query;
|
||||
|
||||
const {
|
||||
project: projectStore,
|
||||
issueFilter: issueFilterStore,
|
||||
cycle: cycleStore,
|
||||
cycleIssue: cycleIssueStore,
|
||||
cycleIssueFilter: cycleIssueFilterStore,
|
||||
} = useMobxStore();
|
||||
|
||||
useSWR(workspaceSlug && projectId && cycleId ? `CYCLE_ISSUES` : null, async () => {
|
||||
useSWR(workspaceSlug && projectId && cycleId ? `CYCLE_FILTERS_AND_ISSUES_${cycleId.toString()}` : null, async () => {
|
||||
if (workspaceSlug && projectId && cycleId) {
|
||||
// fetching the project display filters and display properties
|
||||
await issueFilterStore.fetchUserProjectFilters(workspaceSlug, projectId);
|
||||
await issueFilterStore.fetchUserProjectFilters(workspaceSlug.toString(), projectId.toString());
|
||||
// fetching the cycle filters
|
||||
await cycleIssueFilterStore.fetchCycleFilters(workspaceSlug, projectId, cycleId);
|
||||
|
||||
// fetching the project state, labels and members
|
||||
await projectStore.fetchProjectStates(workspaceSlug, projectId);
|
||||
await projectStore.fetchProjectLabels(workspaceSlug, projectId);
|
||||
await projectStore.fetchProjectMembers(workspaceSlug, projectId);
|
||||
await cycleIssueFilterStore.fetchCycleFilters(workspaceSlug.toString(), projectId.toString(), cycleId.toString());
|
||||
|
||||
// fetching the cycle issues
|
||||
await cycleIssueStore.fetchIssues(workspaceSlug, projectId, cycleId);
|
||||
await cycleIssueStore.fetchIssues(workspaceSlug.toString(), projectId.toString(), cycleId.toString());
|
||||
}
|
||||
});
|
||||
|
||||
const activeLayout = issueFilterStore.userDisplayFilters.layout;
|
||||
|
||||
const cycleDetails = cycleId ? cycleStore.cycle_details[cycleId.toString()] : undefined;
|
||||
const cycleStatus =
|
||||
cycleDetails?.start_date && cycleDetails?.end_date
|
||||
? getDateRangeStatus(cycleDetails?.start_date, cycleDetails?.end_date)
|
||||
: "draft";
|
||||
|
||||
return (
|
||||
<div className="relative w-full h-full flex flex-col overflow-hidden">
|
||||
<CycleAppliedFiltersRoot />
|
||||
<div className="w-full h-full overflow-auto">
|
||||
{activeLayout === "list" ? (
|
||||
<CycleListLayout />
|
||||
) : activeLayout === "kanban" ? (
|
||||
<CycleKanBanLayout />
|
||||
) : activeLayout === "calendar" ? (
|
||||
<CycleCalendarLayout />
|
||||
) : activeLayout === "gantt_chart" ? (
|
||||
<CycleGanttLayout />
|
||||
) : activeLayout === "spreadsheet" ? (
|
||||
<CycleSpreadsheetLayout />
|
||||
) : null}
|
||||
<>
|
||||
<TransferIssuesModal handleClose={() => setTransferIssuesModal(false)} isOpen={transferIssuesModal} />
|
||||
<div className="relative w-full h-full flex flex-col overflow-hidden">
|
||||
{cycleStatus === "completed" && <TransferIssues handleClick={() => setTransferIssuesModal(true)} />}
|
||||
<CycleAppliedFiltersRoot />
|
||||
<div className="w-full h-full overflow-auto">
|
||||
{activeLayout === "list" ? (
|
||||
<CycleListLayout />
|
||||
) : activeLayout === "kanban" ? (
|
||||
<CycleKanBanLayout />
|
||||
) : activeLayout === "calendar" ? (
|
||||
<CycleCalendarLayout />
|
||||
) : activeLayout === "gantt_chart" ? (
|
||||
<CycleGanttLayout />
|
||||
) : activeLayout === "spreadsheet" ? (
|
||||
<CycleSpreadsheetLayout />
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
@ -2,15 +2,12 @@ import React, { useCallback } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import useSWR from "swr";
|
||||
|
||||
// mobx store
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// components
|
||||
import { GlobalViewsAppliedFiltersRoot, SpreadsheetView } from "components/issues";
|
||||
// types
|
||||
import { IIssue, IIssueDisplayFilterOptions, TStaticViewTypes } from "types";
|
||||
// fetch-keys
|
||||
import { GLOBAL_VIEW_ISSUES } from "constants/fetch-keys";
|
||||
|
||||
type Props = {
|
||||
type?: TStaticViewTypes;
|
||||
@ -35,7 +32,7 @@ export const GlobalViewLayoutRoot: React.FC<Props> = observer((props) => {
|
||||
const storedFilters = globalViewId ? globalViewFiltersStore.storedFilters[globalViewId.toString()] : undefined;
|
||||
|
||||
useSWR(
|
||||
workspaceSlug && globalViewId && viewDetails ? GLOBAL_VIEW_ISSUES(globalViewId.toString()) : null,
|
||||
workspaceSlug && globalViewId && viewDetails ? `GLOBAL_VIEW_ISSUES_${globalViewId.toString()}` : null,
|
||||
workspaceSlug && globalViewId && viewDetails
|
||||
? () => {
|
||||
globalViewIssuesStore.fetchViewIssues(workspaceSlug.toString(), globalViewId.toString(), storedFilters ?? {});
|
||||
@ -44,7 +41,7 @@ export const GlobalViewLayoutRoot: React.FC<Props> = observer((props) => {
|
||||
);
|
||||
|
||||
useSWR(
|
||||
workspaceSlug && type ? GLOBAL_VIEW_ISSUES(type) : null,
|
||||
workspaceSlug && type ? `GLOBAL_VIEW_ISSUES_${type.toString()}` : null,
|
||||
workspaceSlug && type
|
||||
? () => {
|
||||
globalViewIssuesStore.fetchStaticIssues(workspaceSlug.toString(), type);
|
||||
|
@ -24,28 +24,25 @@ export const ModuleLayoutRoot: React.FC = observer(() => {
|
||||
};
|
||||
|
||||
const {
|
||||
project: projectStore,
|
||||
issueFilter: issueFilterStore,
|
||||
moduleIssue: moduleIssueStore,
|
||||
moduleFilter: moduleIssueFilterStore,
|
||||
} = useMobxStore();
|
||||
|
||||
useSWR(workspaceSlug && projectId && moduleId ? `MODULE_INFORMATION_${moduleId.toString()}` : null, async () => {
|
||||
if (workspaceSlug && projectId && moduleId) {
|
||||
// fetching the project display filters and display properties
|
||||
await issueFilterStore.fetchUserProjectFilters(workspaceSlug, projectId);
|
||||
// fetching the module filters
|
||||
await moduleIssueFilterStore.fetchModuleFilters(workspaceSlug, projectId, moduleId);
|
||||
useSWR(
|
||||
workspaceSlug && projectId && moduleId ? `MODULE_FILTERS_AND_ISSUES_${moduleId.toString()}` : null,
|
||||
async () => {
|
||||
if (workspaceSlug && projectId && moduleId) {
|
||||
// fetching the project display filters and display properties
|
||||
await issueFilterStore.fetchUserProjectFilters(workspaceSlug, projectId);
|
||||
// fetching the module filters
|
||||
await moduleIssueFilterStore.fetchModuleFilters(workspaceSlug, projectId, moduleId);
|
||||
|
||||
// fetching the project state, labels and members
|
||||
await projectStore.fetchProjectStates(workspaceSlug, projectId);
|
||||
await projectStore.fetchProjectLabels(workspaceSlug, projectId);
|
||||
await projectStore.fetchProjectMembers(workspaceSlug, projectId);
|
||||
|
||||
// fetching the module issues
|
||||
await moduleIssueStore.fetchIssues(workspaceSlug, projectId, moduleId);
|
||||
// fetching the module issues
|
||||
await moduleIssueStore.fetchIssues(workspaceSlug, projectId, moduleId);
|
||||
}
|
||||
}
|
||||
});
|
||||
);
|
||||
|
||||
const activeLayout = issueFilterStore.userDisplayFilters.layout;
|
||||
|
||||
|
@ -18,24 +18,15 @@ export const ProjectLayoutRoot: React.FC = observer(() => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
|
||||
const { issue: issueStore, project: projectStore, issueFilter: issueFilterStore } = useMobxStore();
|
||||
const { issue: issueStore, issueFilter: issueFilterStore } = useMobxStore();
|
||||
|
||||
useSWR(
|
||||
workspaceSlug && projectId ? `REVALIDATE_PROJECT_ISSUES_${projectId.toString()}` : null,
|
||||
async () => {
|
||||
if (workspaceSlug && projectId) {
|
||||
await issueFilterStore.fetchUserProjectFilters(workspaceSlug.toString(), projectId.toString());
|
||||
useSWR(workspaceSlug && projectId ? `PROJECT_FILTERS_AND_ISSUES_${projectId.toString()}` : null, async () => {
|
||||
if (workspaceSlug && projectId) {
|
||||
await issueFilterStore.fetchUserProjectFilters(workspaceSlug.toString(), projectId.toString());
|
||||
|
||||
await projectStore.fetchProjectStates(workspaceSlug.toString(), projectId.toString());
|
||||
await projectStore.fetchProjectLabels(workspaceSlug.toString(), projectId.toString());
|
||||
await projectStore.fetchProjectMembers(workspaceSlug.toString(), projectId.toString());
|
||||
await projectStore.fetchProjectEstimates(workspaceSlug.toString(), projectId.toString());
|
||||
|
||||
await issueStore.fetchIssues(workspaceSlug.toString(), projectId.toString());
|
||||
}
|
||||
},
|
||||
{ revalidateOnFocus: false }
|
||||
);
|
||||
await issueStore.fetchIssues(workspaceSlug.toString(), projectId.toString());
|
||||
}
|
||||
});
|
||||
|
||||
const activeLayout = issueFilterStore.userDisplayFilters.layout;
|
||||
|
||||
|
@ -20,34 +20,31 @@ export const ProjectViewLayoutRoot: React.FC = observer(() => {
|
||||
const { workspaceSlug, projectId, viewId } = router.query;
|
||||
|
||||
const {
|
||||
project: projectStore,
|
||||
issueFilter: issueFilterStore,
|
||||
projectViews: projectViewsStore,
|
||||
projectViewIssues: projectViewIssuesStore,
|
||||
projectViewFilters: projectViewFiltersStore,
|
||||
} = useMobxStore();
|
||||
|
||||
useSWR(workspaceSlug && projectId && viewId ? `PROJECT_VIEW_INFORMATION_${viewId.toString()}` : null, async () => {
|
||||
if (workspaceSlug && projectId && viewId) {
|
||||
// fetching the project display filters and display properties
|
||||
await issueFilterStore.fetchUserProjectFilters(workspaceSlug.toString(), projectId.toString());
|
||||
useSWR(
|
||||
workspaceSlug && projectId && viewId ? `PROJECT_VIEW_FILTERS_AND_ISSUES_${viewId.toString()}` : null,
|
||||
async () => {
|
||||
if (workspaceSlug && projectId && viewId) {
|
||||
// fetching the project display filters and display properties
|
||||
await issueFilterStore.fetchUserProjectFilters(workspaceSlug.toString(), projectId.toString());
|
||||
|
||||
// fetching the project state, labels and members
|
||||
await projectStore.fetchProjectStates(workspaceSlug.toString(), projectId.toString());
|
||||
await projectStore.fetchProjectLabels(workspaceSlug.toString(), projectId.toString());
|
||||
await projectStore.fetchProjectMembers(workspaceSlug.toString(), projectId.toString());
|
||||
|
||||
// fetching the view details
|
||||
await projectViewsStore.fetchViewDetails(workspaceSlug.toString(), projectId.toString(), viewId.toString());
|
||||
// fetching the view issues
|
||||
await projectViewIssuesStore.fetchViewIssues(
|
||||
workspaceSlug.toString(),
|
||||
projectId.toString(),
|
||||
viewId.toString(),
|
||||
projectViewFiltersStore.storedFilters[viewId.toString()] ?? {}
|
||||
);
|
||||
// fetching the view details
|
||||
await projectViewsStore.fetchViewDetails(workspaceSlug.toString(), projectId.toString(), viewId.toString());
|
||||
// fetching the view issues
|
||||
await projectViewIssuesStore.fetchViewIssues(
|
||||
workspaceSlug.toString(),
|
||||
projectId.toString(),
|
||||
viewId.toString(),
|
||||
projectViewFiltersStore.storedFilters[viewId.toString()] ?? {}
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
);
|
||||
|
||||
const activeLayout = issueFilterStore.userDisplayFilters.layout;
|
||||
|
||||
|
@ -65,6 +65,7 @@ export const ProjectAuthWrapper: FC<IProjectAuthWrapper> = observer((props) => {
|
||||
? () => projectStore.fetchProjectStates(workspaceSlug.toString(), projectId.toString())
|
||||
: null
|
||||
);
|
||||
// TODO: fetch project estimates
|
||||
// fetching project cycles
|
||||
useSWR(
|
||||
workspaceSlug && projectId ? `PROJECT_ALL_CYCLES_${workspaceSlug}_${projectId}` : null,
|
||||
|
@ -10,18 +10,15 @@ import { AppLayout } from "layouts/app-layout";
|
||||
// components
|
||||
import { CycleIssuesHeader } from "components/headers";
|
||||
import { ExistingIssuesListModal } from "components/core";
|
||||
import { CycleDetailsSidebar, TransferIssues, TransferIssuesModal } from "components/cycles";
|
||||
import { CycleDetailsSidebar } from "components/cycles";
|
||||
import { CycleLayoutRoot } from "components/issues/issue-layouts";
|
||||
// ui
|
||||
import { EmptyState } from "components/common";
|
||||
// assets
|
||||
import emptyCycle from "public/empty-state/cycle.svg";
|
||||
// helpers
|
||||
import { getDateRangeStatus } from "helpers/date-time.helper";
|
||||
|
||||
const SingleCycle: React.FC = () => {
|
||||
const [cycleIssuesListModal, setCycleIssuesListModal] = useState(false);
|
||||
const [transferIssuesModal, setTransferIssuesModal] = useState(false);
|
||||
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId, cycleId } = router.query;
|
||||
@ -31,18 +28,13 @@ const SingleCycle: React.FC = () => {
|
||||
const { storedValue } = useLocalStorage("cycle_sidebar_collapsed", "false");
|
||||
const isSidebarCollapsed = storedValue ? (storedValue === "true" ? true : false) : false;
|
||||
|
||||
const { data: cycleDetails, error } = useSWR(
|
||||
const { error } = useSWR(
|
||||
workspaceSlug && projectId && cycleId ? `CURRENT_CYCLE_DETAILS_${cycleId.toString()}` : null,
|
||||
workspaceSlug && projectId && cycleId
|
||||
? () => cycleStore.fetchCycleWithId(workspaceSlug.toString(), projectId.toString(), cycleId.toString())
|
||||
: null
|
||||
);
|
||||
|
||||
const cycleStatus =
|
||||
cycleDetails?.start_date && cycleDetails?.end_date
|
||||
? getDateRangeStatus(cycleDetails?.start_date, cycleDetails?.end_date)
|
||||
: "draft";
|
||||
|
||||
// TODO: add this function to bulk add issues to cycle
|
||||
// const handleAddIssuesToCycle = async (data: ISearchIssueResponse[]) => {
|
||||
// if (!workspaceSlug || !projectId) return;
|
||||
@ -83,13 +75,9 @@ const SingleCycle: React.FC = () => {
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
<TransferIssuesModal handleClose={() => setTransferIssuesModal(false)} isOpen={transferIssuesModal} />
|
||||
<div className="relative w-full h-full flex overflow-auto">
|
||||
<div className={`flex flex-col h-full w-full ${isSidebarCollapsed ? "" : "mr-[24rem]"} duration-300`}>
|
||||
{cycleStatus === "completed" && <TransferIssues handleClick={() => setTransferIssuesModal(true)} />}
|
||||
<div className="h-full w-full">
|
||||
<CycleLayoutRoot />
|
||||
</div>
|
||||
<div className={`h-full w-full ${isSidebarCollapsed ? "" : "mr-[24rem]"} duration-300`}>
|
||||
<CycleLayoutRoot />
|
||||
</div>
|
||||
{cycleId && <CycleDetailsSidebar isOpen={!isSidebarCollapsed} cycleId={cycleId.toString()} />}
|
||||
</div>
|
||||
|
@ -1,7 +1,3 @@
|
||||
import { useRouter } from "next/router";
|
||||
import useSWR from "swr";
|
||||
// mobx
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// components
|
||||
import { ProjectLayoutRoot } from "components/issues";
|
||||
import { ProjectIssuesHeader } from "components/headers";
|
||||
@ -10,27 +6,12 @@ import type { NextPage } from "next";
|
||||
// layouts
|
||||
import { AppLayout } from "layouts/app-layout";
|
||||
|
||||
const ProjectIssues: NextPage = () => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
|
||||
const { issueFilter: issueFilterStore } = useMobxStore();
|
||||
|
||||
// TODO: update the fetch keys
|
||||
useSWR(
|
||||
workspaceSlug && projectId ? "REVALIDATE_USER_PROJECT_FILTERS" : null,
|
||||
workspaceSlug && projectId
|
||||
? () => issueFilterStore.fetchUserProjectFilters(workspaceSlug.toString(), projectId.toString())
|
||||
: null
|
||||
);
|
||||
|
||||
return (
|
||||
<AppLayout header={<ProjectIssuesHeader />} withProjectWrapper>
|
||||
<div className="h-full w-full flex flex-col">
|
||||
<ProjectLayoutRoot />
|
||||
</div>
|
||||
</AppLayout>
|
||||
);
|
||||
};
|
||||
const ProjectIssues: NextPage = () => (
|
||||
<AppLayout header={<ProjectIssuesHeader />} withProjectWrapper>
|
||||
<div className="h-full w-full">
|
||||
<ProjectLayoutRoot />
|
||||
</div>
|
||||
</AppLayout>
|
||||
);
|
||||
|
||||
export default ProjectIssues;
|
||||
|
@ -1,90 +1,34 @@
|
||||
import { useRouter } from "next/router";
|
||||
import Link from "next/link";
|
||||
|
||||
import useSWR from "swr";
|
||||
|
||||
// services
|
||||
import { ProjectService } from "services/project";
|
||||
import { ViewService } from "services/view.service";
|
||||
// mobx store
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// layouts
|
||||
import { ProjectAuthorizationWrapper } from "layouts/auth-layout-legacy";
|
||||
import { AppLayout } from "layouts/app-layout";
|
||||
// components
|
||||
import { ProjectViewLayoutRoot } from "components/issues";
|
||||
// ui
|
||||
import { BreadcrumbItem, Breadcrumbs, CustomMenu, PhotoFilterIcon } from "@plane/ui";
|
||||
import { EmptyState } from "components/common";
|
||||
// icons
|
||||
// images
|
||||
import emptyView from "public/empty-state/view.svg";
|
||||
// helpers
|
||||
import { truncateText } from "helpers/string.helper";
|
||||
// fetch-keys
|
||||
import { PROJECT_DETAILS, VIEWS_LIST, VIEW_DETAILS } from "constants/fetch-keys";
|
||||
import { ProjectViewIssuesHeader } from "components/headers";
|
||||
// ui
|
||||
import { EmptyState } from "components/common";
|
||||
// assets
|
||||
import emptyView from "public/empty-state/view.svg";
|
||||
// types
|
||||
import { NextPage } from "next";
|
||||
|
||||
// services
|
||||
const projectService = new ProjectService();
|
||||
const viewService = new ViewService();
|
||||
|
||||
const SingleView: React.FC = () => {
|
||||
const ProjectViewIssues: NextPage = () => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId, viewId } = router.query;
|
||||
|
||||
const { data: activeProject } = useSWR(
|
||||
workspaceSlug && projectId ? PROJECT_DETAILS(projectId as string) : null,
|
||||
workspaceSlug && projectId ? () => projectService.getProject(workspaceSlug as string, projectId as string) : null
|
||||
);
|
||||
const { projectViews: projectViewsStore } = useMobxStore();
|
||||
|
||||
const { data: views } = useSWR(
|
||||
workspaceSlug && projectId ? VIEWS_LIST(projectId as string) : null,
|
||||
workspaceSlug && projectId ? () => viewService.getViews(workspaceSlug as string, projectId as string) : null
|
||||
);
|
||||
|
||||
const { data: viewDetails, error } = useSWR(
|
||||
workspaceSlug && projectId && viewId ? VIEW_DETAILS(viewId as string) : null,
|
||||
const { error } = useSWR(
|
||||
workspaceSlug && projectId && viewId ? `VIEW_DETAILS_${viewId.toString()}` : null,
|
||||
workspaceSlug && projectId && viewId
|
||||
? () => viewService.getViewDetails(workspaceSlug as string, projectId as string, viewId as string)
|
||||
? () => projectViewsStore.fetchViewDetails(workspaceSlug.toString(), projectId.toString(), viewId.toString())
|
||||
: null
|
||||
);
|
||||
|
||||
return (
|
||||
<ProjectAuthorizationWrapper
|
||||
breadcrumbs={
|
||||
<Breadcrumbs onBack={() => router.back()}>
|
||||
<BreadcrumbItem
|
||||
link={
|
||||
<Link href={`/${workspaceSlug}/projects/${activeProject?.id}/cycles`}>
|
||||
<a className={`border-r-2 border-custom-sidebar-border-200 px-3 text-sm `}>
|
||||
<p className="truncate">{`${activeProject?.name ?? "Project"} Views`}</p>
|
||||
</a>
|
||||
</Link>
|
||||
}
|
||||
/>
|
||||
</Breadcrumbs>
|
||||
}
|
||||
left={
|
||||
<CustomMenu
|
||||
label={
|
||||
<>
|
||||
<PhotoFilterIcon height={12} width={12} />
|
||||
{viewDetails?.name && truncateText(viewDetails.name, 40)}
|
||||
</>
|
||||
}
|
||||
className="ml-1.5"
|
||||
width="auto"
|
||||
>
|
||||
{views?.map((view) => (
|
||||
<CustomMenu.MenuItem
|
||||
key={view.id}
|
||||
onClick={() => router.push(`/${workspaceSlug}/projects/${projectId}/views/${view.id}`)}
|
||||
>
|
||||
{truncateText(view.name, 40)}
|
||||
</CustomMenu.MenuItem>
|
||||
))}
|
||||
</CustomMenu>
|
||||
}
|
||||
right={<ProjectViewIssuesHeader />}
|
||||
>
|
||||
<AppLayout header={<ProjectViewIssuesHeader />} withProjectWrapper>
|
||||
{error ? (
|
||||
<EmptyState
|
||||
image={emptyView}
|
||||
@ -98,8 +42,8 @@ const SingleView: React.FC = () => {
|
||||
) : (
|
||||
<ProjectViewLayoutRoot />
|
||||
)}
|
||||
</ProjectAuthorizationWrapper>
|
||||
</AppLayout>
|
||||
);
|
||||
};
|
||||
|
||||
export default SingleView;
|
||||
export default ProjectViewIssues;
|
||||
|
@ -2,7 +2,7 @@ import React from "react";
|
||||
import type { NextPage } from "next";
|
||||
import { useRouter } from "next/router";
|
||||
import useSWR from "swr";
|
||||
// hooks
|
||||
// mobx store
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// components
|
||||
import { ProjectViewsHeader } from "components/headers";
|
||||
@ -14,14 +14,7 @@ const ProjectViews: NextPage = () => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
|
||||
const { project: projectStore, projectViews: projectViewsStore } = useMobxStore();
|
||||
|
||||
useSWR(
|
||||
workspaceSlug && projectId ? `PROJECT_DETAILS_${projectId.toString()}` : null,
|
||||
workspaceSlug && projectId
|
||||
? () => projectStore.fetchProjectDetails(workspaceSlug.toString(), projectId.toString())
|
||||
: null
|
||||
);
|
||||
const { projectViews: projectViewsStore } = useMobxStore();
|
||||
|
||||
useSWR(
|
||||
workspaceSlug && projectId ? `PROJECT_VIEWS_LIST_${workspaceSlug.toString()}_${projectId.toString()}` : null,
|
||||
@ -30,13 +23,8 @@ const ProjectViews: NextPage = () => {
|
||||
: null
|
||||
);
|
||||
|
||||
const projectDetails =
|
||||
workspaceSlug && projectId
|
||||
? projectStore.getProjectById(workspaceSlug.toString(), projectId.toString())
|
||||
: undefined;
|
||||
|
||||
return (
|
||||
<AppLayout header={<ProjectViewsHeader title={projectDetails?.name} />}>
|
||||
<AppLayout header={<ProjectViewsHeader />}>
|
||||
<ProjectViewsList />
|
||||
</AppLayout>
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user