Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 14 additions & 78 deletions web/components/core/views/all-views.tsx
Original file line number Diff line number Diff line change
@@ -1,94 +1,24 @@
import React, { useCallback, useState } from "react";

import React from "react";
import { useRouter } from "next/router";

import { observer } from "mobx-react-lite";
import useSWR from "swr";

// react-beautiful-dnd
import { DragDropContext, DropResult } from "react-beautiful-dnd";
import StrictModeDroppable from "components/dnd/StrictModeDroppable";
// services
import stateService from "services/project_state.service";
// hooks
import useUser from "hooks/use-user";
import { useProjectMyMembership } from "contexts/project-member.context";
// components
import { AllLists, AllBoards, CalendarView, SpreadsheetView, GanttChartView } from "components/core";
import { CalendarLayout, KanBanLayout } from "components/issues";
// ui
import { EmptyState, Spinner } from "components/ui";
// icons
import { TrashIcon } from "@heroicons/react/24/outline";
// images
import emptyIssue from "public/empty-state/issue.svg";
import emptyIssueArchive from "public/empty-state/issue-archive.svg";
// helpers
import { getStatesList } from "helpers/state.helper";
// types
import { IIssue, IIssueViewProps } from "types";
// fetch-keys
import { STATES_LIST } from "constants/fetch-keys";
// store
// mobx store
import { useMobxStore } from "lib/mobx/store-provider";
import { RootStore } from "store/root";
import { observer } from "mobx-react-lite";

type Props = {
addIssueToDate: (date: string) => void;
addIssueToGroup: (groupTitle: string) => void;
disableUserActions: boolean;
dragDisabled?: boolean;
emptyState: {
title: string;
description?: string;
primaryButton?: {
icon: any;
text: string;
onClick: () => void;
};
secondaryButton?: React.ReactNode;
};
handleIssueAction: (issue: IIssue, action: "copy" | "delete" | "edit") => void;
handleDraftIssueAction?: (issue: IIssue, action: "edit" | "delete") => void;
handleOnDragEnd: (result: DropResult) => Promise<void>;
openIssuesListModal: (() => void) | null;
removeIssue: ((bridgeId: string, issueId: string) => void) | null;
disableAddIssueOption?: boolean;
trashBox: boolean;
setTrashBox: React.Dispatch<React.SetStateAction<boolean>>;
viewProps: IIssueViewProps;
};
// components
import { CalendarLayout, GanttLayout, KanBanLayout } from "components/issues";

export const AllViews: React.FC<Props> = observer(({ trashBox, setTrashBox }) => {
export const AllViews: React.FC = observer(() => {
const router = useRouter();
const { workspaceSlug, projectId, cycleId, moduleId } = router.query as {
const { workspaceSlug, projectId } = router.query as {
workspaceSlug: string;
projectId: string;
cycleId: string;
moduleId: string;
};

const [myIssueProjectId, setMyIssueProjectId] = useState<string | null>(null);

const { issue: issueStore, project: projectStore, issueFilter: issueFilterStore } = useMobxStore();

const { data: stateGroups } = useSWR(
workspaceSlug && projectId ? STATES_LIST(projectId as string) : null,
workspaceSlug ? () => stateService.getStates(workspaceSlug as string, projectId as string) : null
);
const states = getStatesList(stateGroups);

const handleMyIssueOpen = (issue: IIssue) => {
setMyIssueProjectId(issue.project);
};

const handleTrashBox = useCallback(
(isDragging: boolean) => {
if (isDragging && !trashBox) setTrashBox(true);
},
[trashBox, setTrashBox]
);

useSWR(workspaceSlug && projectId ? `PROJECT_ISSUES` : null, async () => {
if (workspaceSlug && projectId) {
await issueFilterStore.fetchUserProjectFilters(workspaceSlug, projectId);
Expand All @@ -105,7 +35,13 @@ export const AllViews: React.FC<Props> = observer(({ trashBox, setTrashBox }) =>

return (
<div className="relative w-full h-full overflow-auto">
{activeLayout === "kanban" ? <KanBanLayout /> : activeLayout === "calendar" ? <CalendarLayout /> : null}
{activeLayout === "kanban" ? (
<KanBanLayout />
) : activeLayout === "calendar" ? (
<CalendarLayout />
) : activeLayout === "gantt_chart" ? (
<GanttLayout />
) : null}
</div>
);
});
5 changes: 1 addition & 4 deletions web/components/cycles/gantt-chart/cycle-issues-layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { useRouter } from "next/router";
import useIssuesView from "hooks/use-issues-view";
import useUser from "hooks/use-user";
import useGanttChartCycleIssues from "hooks/gantt-chart/cycle-issues-view";
import { updateGanttIssue } from "components/gantt-chart/hooks/block-update";
import useProjectDetails from "hooks/use-project-details";
// components
import { GanttChartRoot, renderIssueBlocksStructure } from "components/gantt-chart";
Expand Down Expand Up @@ -47,9 +46,7 @@ export const CycleIssuesGanttChartView: React.FC<Props> = ({ disableUserActions
title="Issues"
loaderTitle="Issues"
blocks={ganttIssues ? renderIssueBlocksStructure(ganttIssues as IIssue[]) : null}
blockUpdateHandler={(block, payload) =>
updateGanttIssue(block, payload, mutateGanttIssues, user, workspaceSlug?.toString())
}
blockUpdateHandler={(block, payload) => {}}
SidebarBlockRender={IssueGanttSidebarBlock}
BlockRender={IssueGanttBlock}
enableBlockLeftResize={isAllowed}
Expand Down
40 changes: 0 additions & 40 deletions web/components/gantt-chart/hooks/block-update.tsx

This file was deleted.

12 changes: 5 additions & 7 deletions web/components/headers/project-issues.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ export const ProjectIssuesHeader: React.FC = observer(() => {

const { issueFilter: issueFilterStore } = useMobxStore();

const activeLayout = issueFilterStore.userDisplayFilters.layout;

const handleLayoutChange = useCallback(
(layout: TIssueLayouts) => {
if (!workspaceSlug || !projectId) return;
Expand Down Expand Up @@ -72,25 +74,21 @@ export const ProjectIssuesHeader: React.FC = observer(() => {
<LayoutSelection
layouts={["list", "kanban", "calendar", "spreadsheet", "gantt_chart"]}
onChange={(layout) => handleLayoutChange(layout)}
selectedLayout={issueFilterStore.userDisplayFilters.layout ?? "list"}
selectedLayout={activeLayout}
/>
<FiltersDropdown title="Filters">
<FilterSelection
filters={issueFilterStore.userFilters}
handleFiltersUpdate={handleFiltersUpdate}
layoutDisplayFiltersOptions={
ISSUE_DISPLAY_FILTERS_BY_LAYOUT.issues[issueFilterStore.userDisplayFilters.layout ?? "list"]
}
layoutDisplayFiltersOptions={activeLayout ? ISSUE_DISPLAY_FILTERS_BY_LAYOUT.issues[activeLayout] : undefined}
projectId={projectId?.toString() ?? ""}
/>
</FiltersDropdown>
<FiltersDropdown title="View">
<DisplayFiltersSelection
displayFilters={issueFilterStore.userDisplayFilters}
handleDisplayFiltersUpdate={handleDisplayFiltersUpdate}
layoutDisplayFiltersOptions={
ISSUE_DISPLAY_FILTERS_BY_LAYOUT.issues[issueFilterStore.userDisplayFilters.layout ?? "list"]
}
layoutDisplayFiltersOptions={activeLayout ? ISSUE_DISPLAY_FILTERS_BY_LAYOUT.issues[activeLayout] : undefined}
/>
</FiltersDropdown>
</div>
Expand Down
1 change: 0 additions & 1 deletion web/components/issues/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ export * from "./activity";
export * from "./delete-issue-modal";
export * from "./description-form";
export * from "./form";
export * from "./gantt-chart";
export * from "./issue-layouts";
export * from "./main-content";
export * from "./modal";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export * from "./blocks";
export * from "./layout";
export * from "./root";
Original file line number Diff line number Diff line change
@@ -1,63 +1,59 @@
import { useRouter } from "next/router";
import { observer } from "mobx-react-lite";

// mobx store
import { useMobxStore } from "lib/mobx/store-provider";
// hooks
import useIssuesView from "hooks/use-issues-view";
import useUser from "hooks/use-user";
import useGanttChartIssues from "hooks/gantt-chart/issue-view";
import { updateGanttIssue } from "components/gantt-chart/hooks/block-update";
import useProjectDetails from "hooks/use-project-details";
// components
import { GanttChartRoot, renderIssueBlocksStructure } from "components/gantt-chart";
import { IssueGanttBlock, IssueGanttSidebarBlock, IssuePeekOverview } from "components/issues";
// types
import { IIssue } from "types";
import { IIssueUnGroupedStructure } from "store/issue";

type Props = {
disableUserActions: boolean;
};

export const IssueGanttChartView: React.FC<Props> = ({ disableUserActions }) => {
export const GanttLayout: React.FC = observer(() => {
const router = useRouter();
const { workspaceSlug, projectId } = router.query;

const { displayFilters } = useIssuesView();

const { user } = useUser();
const { projectDetails } = useProjectDetails();

const { ganttIssues, mutateGanttIssues } = useGanttChartIssues(
workspaceSlug as string,
projectId as string
);
const { issue: issueStore, issueFilter: issueFilterStore } = useMobxStore();

const appliedDisplayFilters = issueFilterStore.userDisplayFilters;

const issues = issueStore.getIssues;

const isAllowed = projectDetails?.member_role === 20 || projectDetails?.member_role === 15;

console.log("issues", issues);
console.log("appliedFilters", issueFilterStore.appliedFilters);

return (
<>
<IssuePeekOverview
handleMutation={() => mutateGanttIssues()}
projectId={projectId?.toString() ?? ""}
workspaceSlug={workspaceSlug?.toString() ?? ""}
readOnly={disableUserActions}
readOnly={!isAllowed}
/>
<div className="w-full h-full">
<GanttChartRoot
border={false}
title="Issues"
loaderTitle="Issues"
blocks={ganttIssues ? renderIssueBlocksStructure(ganttIssues as IIssue[]) : null}
blockUpdateHandler={(block, payload) =>
updateGanttIssue(block, payload, mutateGanttIssues, user, workspaceSlug?.toString())
}
blocks={issues ? renderIssueBlocksStructure(issues as IIssueUnGroupedStructure) : null}
blockUpdateHandler={(block, payload) => {
// TODO: update mutation logic
// updateGanttIssue(block, payload, mutateGanttIssues, user, workspaceSlug?.toString())
}}
BlockRender={IssueGanttBlock}
SidebarBlockRender={IssueGanttSidebarBlock}
enableBlockLeftResize={isAllowed}
enableBlockRightResize={isAllowed}
enableBlockMove={isAllowed}
enableReorder={displayFilters.order_by === "sort_order" && isAllowed}
enableReorder={appliedDisplayFilters.order_by === "sort_order" && isAllowed}
bottomSpacing
/>
</div>
</>
);
};
});
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,19 @@ import { ILayoutDisplayFiltersOptions } from "constants/issue";
type Props = {
displayFilters: IIssueDisplayFilterOptions;
handleDisplayFiltersUpdate: (updatedDisplayFilter: Partial<IIssueDisplayFilterOptions>) => void;
layoutDisplayFiltersOptions: ILayoutDisplayFiltersOptions;
layoutDisplayFiltersOptions: ILayoutDisplayFiltersOptions | undefined;
};

export const DisplayFiltersSelection: React.FC<Props> = observer((props) => {
const { displayFilters, handleDisplayFiltersUpdate, layoutDisplayFiltersOptions } = props;

const isDisplayFilterEnabled = (displayFilter: keyof IIssueDisplayFilterOptions) =>
Object.keys(layoutDisplayFiltersOptions.display_filters).includes(displayFilter);
Object.keys(layoutDisplayFiltersOptions?.display_filters ?? {}).includes(displayFilter);

return (
<div className="w-full h-full overflow-hidden overflow-y-auto relative px-2.5 divide-y divide-custom-border-200">
{/* display properties */}
{layoutDisplayFiltersOptions.display_properties && (
{layoutDisplayFiltersOptions?.display_properties && (
<div className="py-2">
<FilterDisplayProperties />
</div>
Expand All @@ -41,7 +41,7 @@ export const DisplayFiltersSelection: React.FC<Props> = observer((props) => {
<FilterGroupBy
selectedGroupBy={displayFilters.group_by}
selectedSubGroupBy={displayFilters.sub_group_by}
groupByOptions={layoutDisplayFiltersOptions.display_filters.group_by ?? []}
groupByOptions={layoutDisplayFiltersOptions?.display_filters.group_by ?? []}
handleUpdate={(val) =>
handleDisplayFiltersUpdate({
group_by: val,
Expand All @@ -62,7 +62,7 @@ export const DisplayFiltersSelection: React.FC<Props> = observer((props) => {
sub_group_by: val,
})
}
subGroupByOptions={layoutDisplayFiltersOptions.display_filters.sub_group_by ?? []}
subGroupByOptions={layoutDisplayFiltersOptions?.display_filters.sub_group_by ?? []}
/>
</div>
)}
Expand Down Expand Up @@ -96,7 +96,7 @@ export const DisplayFiltersSelection: React.FC<Props> = observer((props) => {
)}

{/* Options */}
{layoutDisplayFiltersOptions.extra_options.access && (
{layoutDisplayFiltersOptions?.extra_options.access && (
<div className="py-2">
<FilterExtraOptions
selectedExtraOptions={{
Expand All @@ -108,7 +108,7 @@ export const DisplayFiltersSelection: React.FC<Props> = observer((props) => {
[key]: val,
})
}
enabledExtraOptions={layoutDisplayFiltersOptions.extra_options.values}
enabledExtraOptions={layoutDisplayFiltersOptions?.extra_options.values}
/>
</div>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import { DATE_FILTER_OPTIONS } from "constants/filters";
type Props = {
filters: IIssueFilterOptions;
handleFiltersUpdate: (key: keyof IIssueFilterOptions, value: string | string[]) => void;
layoutDisplayFiltersOptions: ILayoutDisplayFiltersOptions;
layoutDisplayFiltersOptions: ILayoutDisplayFiltersOptions | undefined;
projectId: string;
};

Expand Down Expand Up @@ -125,7 +125,7 @@ export const FilterSelection: React.FC<Props> = observer((props) => {
return filterDetails.currentLength > 5;
};

const isFilterEnabled = (filter: keyof IIssueFilterOptions) => layoutDisplayFiltersOptions.filters.includes(filter);
const isFilterEnabled = (filter: keyof IIssueFilterOptions) => layoutDisplayFiltersOptions?.filters.includes(filter);

return (
<div className="w-full h-full flex flex-col overflow-hidden">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { ISSUE_LAYOUTS } from "constants/issue";
type Props = {
layouts: TIssueLayouts[];
onChange: (layout: TIssueLayouts) => void;
selectedLayout: TIssueLayouts;
selectedLayout: TIssueLayouts | undefined;
};

export const LayoutSelection: React.FC<Props> = (props) => {
Expand Down
Loading