From 8aebf0bbd2a5326fc1f97a1785c8591b9478c839 Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal <65252264+aaryan610@users.noreply.github.com> Date: Fri, 13 Oct 2023 12:00:54 +0530 Subject: [PATCH] refactor: folder structure, remove junk code (#2423) * refactor: folder structure * chore: ad order by target date option * refactor: remove old layout components * refactor: inbox folder structure --- .../core/views/board-view/all-boards.tsx | 145 ----- .../core/views/board-view/board-header.tsx | 214 ------- web/components/core/views/board-view/index.ts | 5 - .../board-view/inline-create-issue-form.tsx | 62 --- .../core/views/board-view/single-board.tsx | 293 ---------- .../core/views/board-view/single-issue.tsx | 527 ------------------ .../views/calendar-view/calendar-header.tsx | 133 ----- .../core/views/calendar-view/calendar.tsx | 203 ------- .../core/views/calendar-view/index.ts | 5 - .../inline-create-issue-form.tsx | 102 ---- .../core/views/calendar-view/single-date.tsx | 126 ----- .../core/views/calendar-view/single-issue.tsx | 389 ------------- .../core/views/gantt-chart-view/index.tsx | 30 - .../inline-create-issue-form.tsx | 62 --- web/components/core/views/index.ts | 5 - .../core/views/list-view/all-lists.tsx | 104 ---- web/components/core/views/list-view/index.ts | 4 - .../list-view/inline-create-issue-form.tsx | 62 --- .../core/views/list-view/single-issue.tsx | 482 ---------------- .../core/views/list-view/single-list.tsx | 349 ------------ .../gantt-chart/cycle-issues-layout.tsx | 61 -- web/components/cycles/gantt-chart/index.ts | 1 - web/components/gantt-chart/chart/index.tsx | 57 +- web/components/headers/global-issues.tsx | 2 +- ...-action-headers.tsx => action-headers.tsx} | 0 web/components/inbox/index.ts | 13 +- ...-issue-activity.tsx => issue-activity.tsx} | 0 .../{inbox-issue-card.tsx => issue-card.tsx} | 0 ...nbox-main-content.tsx => main-content.tsx} | 0 .../inbox/{ => modals}/accept-issue-modal.tsx | 0 .../{ => modals}/decline-issue-modal.tsx | 0 .../inbox/{ => modals}/delete-issue-modal.tsx | 0 web/components/inbox/modals/index.ts | 4 + .../inbox/{ => modals}/select-duplicate.tsx | 7 +- .../issue-layouts/calendar/index.tsx | 6 - .../filters-preview/assignees.tsx | 73 --- .../filters-preview/created-by.tsx | 63 --- .../filters-preview/helpers/clear.tsx | 17 - .../filters-preview/helpers/content.tsx | 26 - .../filters-preview/helpers/header.tsx | 12 - .../issue-layouts/filters-preview/index.tsx | 69 --- .../issue-layouts/filters-preview/labels.tsx | 73 --- .../filters-preview/priority.tsx | 79 --- .../filters-preview/start-date.tsx | 56 -- .../filters-preview/state-group.tsx | 129 ----- .../issue-layouts/filters-preview/state.tsx | 66 --- .../filters-preview/target-date.tsx | 56 -- web/components/issue-layouts/gantt/index.tsx | 6 - web/components/issue-layouts/index.ts | 0 .../issue-layouts/kanban/content.tsx | 45 -- .../issue-layouts/kanban/header.tsx | 18 - web/components/issue-layouts/kanban/index.tsx | 75 --- .../issue-layouts/list/group-header.tsx | 31 -- web/components/issue-layouts/list/index.ts | 4 - web/components/issue-layouts/list/item.tsx | 246 -------- web/components/issue-layouts/list/list.tsx | 14 - web/components/issue-layouts/list/root.tsx | 47 -- .../issue-layouts/properties/index.ts | 1 - .../properties/priority-select.tsx | 62 --- web/components/issue-layouts/root.tsx | 89 --- .../issue-layouts/spreadsheet/index.tsx | 6 - .../issues/issue-layouts/calendar/index.ts | 5 +- .../calendar/{ => roots}/cycle-root.tsx | 0 .../issue-layouts/calendar/roots/index.ts | 4 + .../calendar/{ => roots}/module-root.tsx | 0 .../{root.tsx => roots/project-root.tsx} | 0 .../{ => roots}/project-view-root.tsx | 0 .../filters/applied-filters/index.ts | 6 +- .../{ => roots}/cycle-root.tsx | 0 .../global-view-root.tsx} | 0 .../filters/applied-filters/roots/index.ts | 5 + .../{ => roots}/module-root.tsx | 0 .../{root.tsx => roots/project-root.tsx} | 2 +- .../{ => roots}/project-view-root.tsx | 0 .../display-filters-selection.tsx | 1 + .../header/display-filters/order-by.tsx | 5 +- .../filters/header/helpers/dropdown.tsx | 2 +- web/components/issues/issue-layouts/index.ts | 12 +- .../{ => roots}/cycle-layout-root.tsx | 4 +- .../global-view-layout-root.tsx} | 6 +- .../issues/issue-layouts/roots/index.ts | 5 + .../module-layout-root.tsx} | 6 +- .../roots/project-layout-root.tsx} | 10 +- .../project-view-layout-root.tsx} | 6 +- web/components/modules/gantt-chart/index.ts | 1 - .../gantt-chart/module-issues-layout.tsx | 51 -- web/components/search-listbox/index.tsx | 165 ------ web/components/search-listbox/types.d.ts | 15 - web/components/views/gantt-chart.tsx | 55 -- web/components/views/index.ts | 1 - web/components/workspace/views/header.tsx | 17 +- web/constants/issue.ts | 3 +- web/layouts/app-layout/layout.tsx | 21 +- .../projects/[projectId]/cycles/[cycleId].tsx | 2 - .../projects/[projectId]/issues/index.tsx | 4 +- .../[projectId]/modules/[moduleId].tsx | 6 +- .../projects/[projectId]/views/[viewId].tsx | 4 +- .../workspace-views/[globalViewId].tsx | 4 +- .../workspace-views/all-issues.tsx | 4 +- .../workspace-views/assigned.tsx | 4 +- .../workspace-views/created.tsx | 4 +- .../workspace-views/subscribed.tsx | 4 +- web/pages/calender/index.tsx | 19 - 103 files changed, 112 insertions(+), 5167 deletions(-) delete mode 100644 web/components/core/views/board-view/all-boards.tsx delete mode 100644 web/components/core/views/board-view/board-header.tsx delete mode 100644 web/components/core/views/board-view/index.ts delete mode 100644 web/components/core/views/board-view/inline-create-issue-form.tsx delete mode 100644 web/components/core/views/board-view/single-board.tsx delete mode 100644 web/components/core/views/board-view/single-issue.tsx delete mode 100644 web/components/core/views/calendar-view/calendar-header.tsx delete mode 100644 web/components/core/views/calendar-view/calendar.tsx delete mode 100644 web/components/core/views/calendar-view/index.ts delete mode 100644 web/components/core/views/calendar-view/inline-create-issue-form.tsx delete mode 100644 web/components/core/views/calendar-view/single-date.tsx delete mode 100644 web/components/core/views/calendar-view/single-issue.tsx delete mode 100644 web/components/core/views/gantt-chart-view/index.tsx delete mode 100644 web/components/core/views/gantt-chart-view/inline-create-issue-form.tsx delete mode 100644 web/components/core/views/list-view/all-lists.tsx delete mode 100644 web/components/core/views/list-view/index.ts delete mode 100644 web/components/core/views/list-view/inline-create-issue-form.tsx delete mode 100644 web/components/core/views/list-view/single-issue.tsx delete mode 100644 web/components/core/views/list-view/single-list.tsx delete mode 100644 web/components/cycles/gantt-chart/cycle-issues-layout.tsx rename web/components/inbox/{inbox-action-headers.tsx => action-headers.tsx} (100%) rename web/components/inbox/{inbox-issue-activity.tsx => issue-activity.tsx} (100%) rename web/components/inbox/{inbox-issue-card.tsx => issue-card.tsx} (100%) rename web/components/inbox/{inbox-main-content.tsx => main-content.tsx} (100%) rename web/components/inbox/{ => modals}/accept-issue-modal.tsx (100%) rename web/components/inbox/{ => modals}/decline-issue-modal.tsx (100%) rename web/components/inbox/{ => modals}/delete-issue-modal.tsx (100%) create mode 100644 web/components/inbox/modals/index.ts rename web/components/inbox/{ => modals}/select-duplicate.tsx (98%) delete mode 100644 web/components/issue-layouts/calendar/index.tsx delete mode 100644 web/components/issue-layouts/filters-preview/assignees.tsx delete mode 100644 web/components/issue-layouts/filters-preview/created-by.tsx delete mode 100644 web/components/issue-layouts/filters-preview/helpers/clear.tsx delete mode 100644 web/components/issue-layouts/filters-preview/helpers/content.tsx delete mode 100644 web/components/issue-layouts/filters-preview/helpers/header.tsx delete mode 100644 web/components/issue-layouts/filters-preview/index.tsx delete mode 100644 web/components/issue-layouts/filters-preview/labels.tsx delete mode 100644 web/components/issue-layouts/filters-preview/priority.tsx delete mode 100644 web/components/issue-layouts/filters-preview/start-date.tsx delete mode 100644 web/components/issue-layouts/filters-preview/state-group.tsx delete mode 100644 web/components/issue-layouts/filters-preview/state.tsx delete mode 100644 web/components/issue-layouts/filters-preview/target-date.tsx delete mode 100644 web/components/issue-layouts/gantt/index.tsx delete mode 100644 web/components/issue-layouts/index.ts delete mode 100644 web/components/issue-layouts/kanban/content.tsx delete mode 100644 web/components/issue-layouts/kanban/header.tsx delete mode 100644 web/components/issue-layouts/kanban/index.tsx delete mode 100644 web/components/issue-layouts/list/group-header.tsx delete mode 100644 web/components/issue-layouts/list/index.ts delete mode 100644 web/components/issue-layouts/list/item.tsx delete mode 100644 web/components/issue-layouts/list/list.tsx delete mode 100644 web/components/issue-layouts/list/root.tsx delete mode 100644 web/components/issue-layouts/properties/index.ts delete mode 100644 web/components/issue-layouts/properties/priority-select.tsx delete mode 100644 web/components/issue-layouts/root.tsx delete mode 100644 web/components/issue-layouts/spreadsheet/index.tsx rename web/components/issues/issue-layouts/calendar/{ => roots}/cycle-root.tsx (100%) create mode 100644 web/components/issues/issue-layouts/calendar/roots/index.ts rename web/components/issues/issue-layouts/calendar/{ => roots}/module-root.tsx (100%) rename web/components/issues/issue-layouts/calendar/{root.tsx => roots/project-root.tsx} (100%) rename web/components/issues/issue-layouts/calendar/{ => roots}/project-view-root.tsx (100%) rename web/components/issues/issue-layouts/filters/applied-filters/{ => roots}/cycle-root.tsx (100%) rename web/components/issues/issue-layouts/filters/applied-filters/{global-views-root.tsx => roots/global-view-root.tsx} (100%) create mode 100644 web/components/issues/issue-layouts/filters/applied-filters/roots/index.ts rename web/components/issues/issue-layouts/filters/applied-filters/{ => roots}/module-root.tsx (100%) rename web/components/issues/issue-layouts/filters/applied-filters/{root.tsx => roots/project-root.tsx} (97%) rename web/components/issues/issue-layouts/filters/applied-filters/{ => roots}/project-view-root.tsx (100%) rename web/components/issues/issue-layouts/{ => roots}/cycle-layout-root.tsx (97%) rename web/components/issues/issue-layouts/{global-view-all-layouts.tsx => roots/global-view-layout-root.tsx} (95%) create mode 100644 web/components/issues/issue-layouts/roots/index.ts rename web/components/issues/issue-layouts/{module-all-layouts.tsx => roots/module-layout-root.tsx} (94%) rename web/components/{core/views/all-views.tsx => issues/issue-layouts/roots/project-layout-root.tsx} (90%) rename web/components/issues/issue-layouts/{project-view-all-layouts.tsx => roots/project-view-layout-root.tsx} (95%) delete mode 100644 web/components/modules/gantt-chart/module-issues-layout.tsx delete mode 100644 web/components/search-listbox/index.tsx delete mode 100644 web/components/search-listbox/types.d.ts delete mode 100644 web/components/views/gantt-chart.tsx delete mode 100644 web/pages/calender/index.tsx diff --git a/web/components/core/views/board-view/all-boards.tsx b/web/components/core/views/board-view/all-boards.tsx deleted file mode 100644 index 4c42ae166..000000000 --- a/web/components/core/views/board-view/all-boards.tsx +++ /dev/null @@ -1,145 +0,0 @@ -import { useRouter } from "next/router"; - -//hook -import useMyIssues from "hooks/my-issues/use-my-issues"; -import useIssuesView from "hooks/use-issues-view"; -import useProfileIssues from "hooks/use-profile-issues"; -// components -import { SingleBoard } from "components/core/views/board-view/single-board"; -import { IssuePeekOverview } from "components/issues"; -// icons -import { StateGroupIcon } from "components/icons"; -// helpers -import { addSpaceIfCamelCase } from "helpers/string.helper"; -// types -import { ICurrentUserResponse, IIssue, IIssueViewProps, IState, UserAuth } from "types"; - -type Props = { - addIssueToGroup: (groupTitle: string) => void; - disableUserActions: boolean; - disableAddIssueOption?: boolean; - dragDisabled: boolean; - handleIssueAction: (issue: IIssue, action: "copy" | "delete" | "edit") => void; - handleDraftIssueAction?: (issue: IIssue, action: "edit" | "delete") => void; - handleTrashBox: (isDragging: boolean) => void; - openIssuesListModal?: (() => void) | null; - removeIssue: ((bridgeId: string, issueId: string) => void) | null; - myIssueProjectId?: string | null; - handleMyIssueOpen?: (issue: IIssue) => void; - states: IState[] | undefined; - user: ICurrentUserResponse | undefined; - userAuth: UserAuth; - viewProps: IIssueViewProps; -}; - -export const AllBoards: React.FC = ({ - addIssueToGroup, - disableUserActions, - disableAddIssueOption = false, - dragDisabled, - handleIssueAction, - handleDraftIssueAction, - handleTrashBox, - openIssuesListModal, - myIssueProjectId, - handleMyIssueOpen, - removeIssue, - states, - user, - userAuth, - viewProps, -}) => { - const router = useRouter(); - const { workspaceSlug, projectId, userId } = router.query; - - const isProfileIssue = - router.pathname.includes("assigned") || - router.pathname.includes("created") || - router.pathname.includes("subscribed"); - - const isMyIssue = router.pathname.includes("my-issues"); - - const { mutateIssues } = useIssuesView(); - const { mutateMyIssues } = useMyIssues(workspaceSlug?.toString()); - const { mutateProfileIssues } = useProfileIssues(workspaceSlug?.toString(), userId?.toString()); - - const { displayFilters, groupedIssues } = viewProps; - - return ( - <> - (isMyIssue ? mutateMyIssues() : isProfileIssue ? mutateProfileIssues() : mutateIssues())} - projectId={myIssueProjectId ? myIssueProjectId : projectId?.toString() ?? ""} - workspaceSlug={workspaceSlug?.toString() ?? ""} - readOnly={disableUserActions} - /> - {groupedIssues ? ( -
- {Object.keys(groupedIssues).map((singleGroup, index) => { - const currentState = - displayFilters?.group_by === "state" ? states?.find((s) => s.id === singleGroup) : null; - - if (!displayFilters?.show_empty_groups && groupedIssues[singleGroup].length === 0) return null; - - return ( - addIssueToGroup(singleGroup)} - currentState={currentState} - disableUserActions={disableUserActions} - disableAddIssueOption={disableAddIssueOption} - dragDisabled={dragDisabled} - groupTitle={singleGroup} - handleIssueAction={handleIssueAction} - handleDraftIssueAction={handleDraftIssueAction} - handleTrashBox={handleTrashBox} - openIssuesListModal={openIssuesListModal ?? null} - handleMyIssueOpen={handleMyIssueOpen} - removeIssue={removeIssue} - user={user} - userAuth={userAuth} - viewProps={viewProps} - /> - ); - })} - {!displayFilters?.show_empty_groups && ( -
-

Hidden groups

-
- {Object.keys(groupedIssues).map((singleGroup, index) => { - const currentState = - displayFilters?.group_by === "state" ? states?.find((s) => s.id === singleGroup) : null; - - if (groupedIssues[singleGroup].length === 0) - return ( -
-
- {currentState && ( - - )} -

- {displayFilters?.group_by === "state" - ? addSpaceIfCamelCase(currentState?.name ?? "") - : addSpaceIfCamelCase(singleGroup)} -

-
- 0 -
- ); - })} -
-
- )} -
- ) : null} - - ); -}; diff --git a/web/components/core/views/board-view/board-header.tsx b/web/components/core/views/board-view/board-header.tsx deleted file mode 100644 index 93e8f4db7..000000000 --- a/web/components/core/views/board-view/board-header.tsx +++ /dev/null @@ -1,214 +0,0 @@ -import React from "react"; - -import { useRouter } from "next/router"; - -import useSWR from "swr"; - -// services -import issuesService from "services/issue.service"; -import projectService from "services/project.service"; -// hooks -import useProjects from "hooks/use-projects"; -// component -import { Avatar, Icon } from "components/ui"; -// icons -import { PlusIcon } from "@heroicons/react/24/outline"; -import { PriorityIcon, StateGroupIcon } from "components/icons"; -// helpers -import { addSpaceIfCamelCase } from "helpers/string.helper"; -import { renderEmoji } from "helpers/emoji.helper"; -// types -import { IIssueViewProps, IState, TIssuePriorities, TStateGroups } from "types"; -// fetch-keys -import { PROJECT_ISSUE_LABELS, PROJECT_MEMBERS, WORKSPACE_LABELS } from "constants/fetch-keys"; -// constants -import { STATE_GROUP_COLORS } from "constants/state"; - -type Props = { - currentState?: IState | null; - groupTitle: string; - addIssueToGroup: () => void; - isCollapsed: boolean; - setIsCollapsed: React.Dispatch>; - disableUserActions: boolean; - disableAddIssue: boolean; - viewProps: IIssueViewProps; -}; - -export const BoardHeader: React.FC = ({ - currentState, - groupTitle, - addIssueToGroup, - isCollapsed, - setIsCollapsed, - disableUserActions, - disableAddIssue, - viewProps, -}) => { - const router = useRouter(); - const { workspaceSlug, projectId } = router.query; - - const { displayFilters, groupedIssues } = viewProps; - - const { data: issueLabels } = useSWR( - workspaceSlug && projectId && displayFilters?.group_by === "labels" - ? PROJECT_ISSUE_LABELS(projectId.toString()) - : null, - workspaceSlug && projectId && displayFilters?.group_by === "labels" - ? () => issuesService.getIssueLabels(workspaceSlug.toString(), projectId.toString()) - : null - ); - - const { data: workspaceLabels } = useSWR( - workspaceSlug && displayFilters?.group_by === "labels" ? WORKSPACE_LABELS(workspaceSlug.toString()) : null, - workspaceSlug && displayFilters?.group_by === "labels" - ? () => issuesService.getWorkspaceLabels(workspaceSlug.toString()) - : null - ); - - const { data: members } = useSWR( - workspaceSlug && - projectId && - (displayFilters?.group_by === "created_by" || displayFilters?.group_by === "assignees") - ? PROJECT_MEMBERS(projectId.toString()) - : null, - workspaceSlug && - projectId && - (displayFilters?.group_by === "created_by" || displayFilters?.group_by === "assignees") - ? () => projectService.projectMembers(workspaceSlug.toString(), projectId.toString()) - : null - ); - - const { projects } = useProjects(); - - const getGroupTitle = () => { - let title = addSpaceIfCamelCase(groupTitle); - - switch (displayFilters?.group_by) { - case "state": - title = addSpaceIfCamelCase(currentState?.name ?? ""); - break; - case "labels": - title = - [...(issueLabels ?? []), ...(workspaceLabels ?? [])]?.find((label) => label.id === groupTitle)?.name ?? - "None"; - break; - case "project": - title = projects?.find((p) => p.id === groupTitle)?.name ?? "None"; - break; - case "assignees": - case "created_by": - const member = members?.find((member) => member.member.id === groupTitle)?.member; - title = member ? member.display_name : "None"; - - break; - } - - return title; - }; - - const getGroupIcon = () => { - let icon; - - switch (displayFilters?.group_by) { - case "state": - icon = currentState && ( - - ); - break; - case "state_detail.group": - icon = ( - - ); - break; - case "priority": - icon = ; - break; - case "project": - const project = projects?.find((p) => p.id === groupTitle); - icon = - project && - (project.emoji !== null - ? renderEmoji(project.emoji) - : project.icon_prop !== null - ? renderEmoji(project.icon_prop) - : null); - break; - case "labels": - const labelColor = - [...(issueLabels ?? []), ...(workspaceLabels ?? [])]?.find((label) => label.id === groupTitle)?.color ?? - "#000000"; - icon = ; - break; - case "assignees": - case "created_by": - const member = members?.find((member) => member.member.id === groupTitle)?.member; - icon = member ? : <>; - - break; - } - - return icon; - }; - - return ( -
-
-
- {getGroupIcon()} -

- {getGroupTitle()} -

- - {groupedIssues?.[groupTitle].length ?? 0} - -
-
- -
- - {!disableAddIssue && !disableUserActions && displayFilters?.group_by !== "created_by" && ( - - )} -
-
- ); -}; diff --git a/web/components/core/views/board-view/index.ts b/web/components/core/views/board-view/index.ts deleted file mode 100644 index a5a6ee497..000000000 --- a/web/components/core/views/board-view/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export * from "./all-boards"; -export * from "./board-header"; -export * from "./single-board"; -export * from "./single-issue"; -export * from "./inline-create-issue-form"; diff --git a/web/components/core/views/board-view/inline-create-issue-form.tsx b/web/components/core/views/board-view/inline-create-issue-form.tsx deleted file mode 100644 index 1d6103d19..000000000 --- a/web/components/core/views/board-view/inline-create-issue-form.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import { useEffect } from "react"; - -// react hook form -import { useFormContext } from "react-hook-form"; - -// components -import { InlineCreateIssueFormWrapper } from "components/core"; - -// hooks -import useProjectDetails from "hooks/use-project-details"; - -// types -import { IIssue } from "types"; - -type Props = { - isOpen: boolean; - handleClose: () => void; - onSuccess?: (data: IIssue) => Promise | void; - prePopulatedData?: Partial; -}; - -const InlineInput = () => { - const { projectDetails } = useProjectDetails(); - - const { register, setFocus } = useFormContext(); - - useEffect(() => { - setFocus("name"); - }, [setFocus]); - - return ( -
-

- {projectDetails?.identifier ?? "..."} -

- -
- ); -}; - -export const BoardInlineCreateIssueForm: React.FC = (props) => ( - <> - - - - {props.isOpen && ( -

- Press {"'"}Enter{"'"} to add another issue -

- )} - -); diff --git a/web/components/core/views/board-view/single-board.tsx b/web/components/core/views/board-view/single-board.tsx deleted file mode 100644 index 6d583e772..000000000 --- a/web/components/core/views/board-view/single-board.tsx +++ /dev/null @@ -1,293 +0,0 @@ -import { useState } from "react"; - -import { useRouter } from "next/router"; - -// react-beautiful-dnd -import StrictModeDroppable from "components/dnd/StrictModeDroppable"; -import { Draggable } from "react-beautiful-dnd"; -// components -import { CreateUpdateDraftIssueModal } from "components/issues"; -import { BoardHeader, SingleBoardIssue, BoardInlineCreateIssueForm } from "components/core"; -// ui -import { CustomMenu } from "components/ui"; -// icons -import { PlusIcon } from "@heroicons/react/24/outline"; -// helpers -import { replaceUnderscoreIfSnakeCase } from "helpers/string.helper"; -// types -import { ICurrentUserResponse, IIssue, IIssueViewProps, IState, UserAuth } from "types"; - -type Props = { - addIssueToGroup: () => void; - currentState?: IState | null; - disableUserActions: boolean; - disableAddIssueOption?: boolean; - dragDisabled: boolean; - groupTitle: string; - handleIssueAction: (issue: IIssue, action: "copy" | "delete" | "edit") => void; - handleDraftIssueAction?: (issue: IIssue, action: "edit" | "delete") => void; - handleTrashBox: (isDragging: boolean) => void; - openIssuesListModal?: (() => void) | null; - handleMyIssueOpen?: (issue: IIssue) => void; - removeIssue: ((bridgeId: string, issueId: string) => void) | null; - user: ICurrentUserResponse | undefined; - userAuth: UserAuth; - viewProps: IIssueViewProps; -}; - -export const SingleBoard: React.FC = (props) => { - const { - addIssueToGroup, - currentState, - groupTitle, - disableUserActions, - disableAddIssueOption = false, - dragDisabled, - handleIssueAction, - handleDraftIssueAction, - handleTrashBox, - openIssuesListModal, - handleMyIssueOpen, - removeIssue, - user, - userAuth, - viewProps, - } = props; - - // collapse/expand - const [isCollapsed, setIsCollapsed] = useState(true); - - const [isInlineCreateIssueFormOpen, setIsInlineCreateIssueFormOpen] = useState(false); - const [isCreateDraftIssueModalOpen, setIsCreateDraftIssueModalOpen] = useState(false); - - const { displayFilters, groupedIssues } = viewProps; - - const router = useRouter(); - const { cycleId, moduleId } = router.query; - - const isMyIssuesPage = router.pathname.split("/")[3] === "my-issues"; - const isProfileIssuesPage = router.pathname.split("/")[2] === "profile"; - const isDraftIssuesPage = router.pathname.split("/")[4] === "draft-issues"; - - const type = cycleId ? "cycle" : moduleId ? "module" : "issue"; - - // Check if it has at least 4 tickets since it is enough to accommodate the Calendar height - const issuesLength = groupedIssues?.[groupTitle].length; - const hasMinimumNumberOfCards = issuesLength ? issuesLength >= 4 : false; - - const isNotAllowed = userAuth.isGuest || userAuth.isViewer || disableUserActions; - - const scrollToBottom = () => { - const boardListElement = document.getElementById(`board-list-${groupTitle}`); - - // timeout is needed because the animation - // takes time to complete & we can scroll only after that - const timeoutId = setTimeout(() => { - if (boardListElement) - boardListElement.scrollBy({ - top: boardListElement.scrollHeight, - left: 0, - behavior: "smooth", - }); - clearTimeout(timeoutId); - }, 10); - }; - - const onCreateClick = () => { - setIsInlineCreateIssueFormOpen(true); - scrollToBottom(); - }; - - const handleAddIssueToGroup = () => { - if (isDraftIssuesPage) setIsCreateDraftIssueModalOpen(true); - else if (isMyIssuesPage || isProfileIssuesPage) addIssueToGroup(); - else onCreateClick(); - }; - - return ( -
- setIsCreateDraftIssueModalOpen(false)} - prePopulateData={{ - ...(cycleId && { cycle: cycleId.toString() }), - ...(moduleId && { module: moduleId.toString() }), - [displayFilters?.group_by! === "labels" ? "labels_list" : displayFilters?.group_by!]: - displayFilters?.group_by === "labels" ? [groupTitle] : groupTitle, - }} - /> - - - {isCollapsed && ( - - {(provided, snapshot) => ( -
- {displayFilters?.order_by !== "sort_order" && ( - <> -
-
- This board is ordered by{" "} - {replaceUnderscoreIfSnakeCase( - displayFilters?.order_by - ? displayFilters?.order_by[0] === "-" - ? displayFilters?.order_by.slice(1) - : displayFilters?.order_by - : "created_at" - )} -
- - )} -
- {groupedIssues?.[groupTitle].map((issue, index) => ( - - {(provided, snapshot) => ( - handleIssueAction(issue, "edit")} - makeIssueCopy={() => handleIssueAction(issue, "copy")} - handleDeleteIssue={() => handleIssueAction(issue, "delete")} - handleDraftIssueEdit={ - handleDraftIssueAction - ? () => handleDraftIssueAction(issue, "edit") - : undefined - } - handleDraftIssueDelete={() => - handleDraftIssueAction - ? handleDraftIssueAction(issue, "delete") - : undefined - } - handleTrashBox={handleTrashBox} - handleMyIssueOpen={handleMyIssueOpen} - removeIssue={() => { - if (removeIssue && issue.bridge_id) - removeIssue(issue.bridge_id, issue.id); - }} - disableUserActions={disableUserActions} - user={user} - userAuth={userAuth} - viewProps={viewProps} - /> - )} - - ))} - - <>{provided.placeholder} - - - setIsInlineCreateIssueFormOpen(false)} - onSuccess={() => scrollToBottom()} - prePopulatedData={{ - ...(cycleId && { cycle: cycleId.toString() }), - ...(moduleId && { module: moduleId.toString() }), - [displayFilters?.group_by! === "labels" - ? "labels_list" - : displayFilters?.group_by!]: - displayFilters?.group_by === "labels" ? [groupTitle] : groupTitle, - }} - /> -
- {displayFilters?.group_by !== "created_by" && ( -
- {type === "issue" - ? !disableAddIssueOption && - !isDraftIssuesPage && ( - - ) - : !disableUserActions && - !isDraftIssuesPage && ( - - - Add Issue - - } - position="left" - noBorder - > - { - if (isDraftIssuesPage) setIsCreateDraftIssueModalOpen(true); - else if (isMyIssuesPage || isProfileIssuesPage) addIssueToGroup(); - else onCreateClick(); - }} - > - Create new - - {openIssuesListModal && ( - - Add an existing issue - - )} - - )} -
- )} -
- )} - - )} -
- ); -}; diff --git a/web/components/core/views/board-view/single-issue.tsx b/web/components/core/views/board-view/single-issue.tsx deleted file mode 100644 index 6d7528fa6..000000000 --- a/web/components/core/views/board-view/single-issue.tsx +++ /dev/null @@ -1,527 +0,0 @@ -import React, { useCallback, useEffect, useRef, useState } from "react"; - -import { useRouter } from "next/router"; - -import { mutate } from "swr"; - -// react-beautiful-dnd -import { DraggableProvided, DraggableStateSnapshot, DraggingStyle, NotDraggingStyle } from "react-beautiful-dnd"; -// services -import issuesService from "services/issue.service"; -import trackEventServices from "services/track_event.service"; -// hooks -import useToast from "hooks/use-toast"; -import useOutsideClickDetector from "hooks/use-outside-click-detector"; -// components -import { ViewDueDateSelect, ViewEstimateSelect, ViewStartDateSelect } from "components/issues"; -import { MembersSelect, LabelSelect, PrioritySelect } from "components/project"; -import { StateSelect } from "components/states"; -// ui -import { ContextMenu, CustomMenu } from "components/ui"; -import { Tooltip } from "@plane/ui"; -// icons -import { - ClipboardDocumentCheckIcon, - LinkIcon, - PencilIcon, - TrashIcon, - XMarkIcon, - ArrowTopRightOnSquareIcon, - PaperClipIcon, - EllipsisHorizontalIcon, -} from "@heroicons/react/24/outline"; -import { LayerDiagonalIcon } from "components/icons"; -// helpers -import { handleIssuesMutation } from "helpers/issue.helper"; -import { copyTextToClipboard } from "helpers/string.helper"; -// types -import { - ICurrentUserResponse, - IIssue, - IIssueViewProps, - IState, - ISubIssueResponse, - TIssuePriorities, - UserAuth, -} from "types"; -// fetch-keys -import { CYCLE_DETAILS, MODULE_DETAILS, SUB_ISSUES } from "constants/fetch-keys"; - -type Props = { - type?: string; - provided: DraggableProvided; - snapshot: DraggableStateSnapshot; - issue: IIssue; - projectId: string; - groupTitle?: string; - index: number; - editIssue: () => void; - makeIssueCopy: () => void; - handleMyIssueOpen?: (issue: IIssue) => void; - removeIssue?: (() => void) | null; - handleDeleteIssue: (issue: IIssue) => void; - handleDraftIssueEdit?: () => void; - handleDraftIssueDelete?: () => void; - handleTrashBox: (isDragging: boolean) => void; - disableUserActions: boolean; - user: ICurrentUserResponse | undefined; - userAuth: UserAuth; - viewProps: IIssueViewProps; -}; - -export const SingleBoardIssue: React.FC = ({ - type, - provided, - snapshot, - issue, - projectId, - index, - editIssue, - makeIssueCopy, - handleMyIssueOpen, - removeIssue, - groupTitle, - handleDeleteIssue, - handleDraftIssueEdit, - handleDraftIssueDelete, - handleTrashBox, - disableUserActions, - user, - userAuth, - viewProps, -}) => { - // context menu - const [contextMenu, setContextMenu] = useState(false); - const [contextMenuPosition, setContextMenuPosition] = useState(null); - - const [isMenuActive, setIsMenuActive] = useState(false); - const [isDropdownActive, setIsDropdownActive] = useState(false); - - const actionSectionRef = useRef(null); - - const { displayFilters, properties, mutateIssues } = viewProps; - - const router = useRouter(); - const { workspaceSlug, cycleId, moduleId } = router.query; - - const isDraftIssue = router.pathname.includes("draft-issues"); - - const { setToastAlert } = useToast(); - - const partialUpdateIssue = useCallback( - (formData: Partial, issue: IIssue) => { - if (!workspaceSlug || !issue) return; - - if (issue.parent) { - mutate( - SUB_ISSUES(issue.parent.toString()), - (prevData) => { - if (!prevData) return prevData; - - return { - ...prevData, - sub_issues: (prevData.sub_issues ?? []).map((i) => { - if (i.id === issue.id) { - return { - ...i, - ...formData, - }; - } - return i; - }), - }; - }, - false - ); - } else { - mutateIssues( - (prevData: any) => - handleIssuesMutation( - formData, - groupTitle ?? "", - displayFilters?.group_by ?? null, - index, - displayFilters?.order_by ?? "-created_at", - prevData - ), - false - ); - } - - issuesService.patchIssue(workspaceSlug as string, issue.project, issue.id, formData, user).then(() => { - mutateIssues(); - - if (cycleId) mutate(CYCLE_DETAILS(cycleId as string)); - if (moduleId) mutate(MODULE_DETAILS(moduleId as string)); - }); - }, - [displayFilters, workspaceSlug, cycleId, moduleId, groupTitle, index, mutateIssues, user] - ); - - const getStyle = (style: DraggingStyle | NotDraggingStyle | undefined, snapshot: DraggableStateSnapshot) => { - if (displayFilters?.order_by === "sort_order") return style; - if (!snapshot.isDragging) return {}; - if (!snapshot.isDropAnimating) return style; - - return { - ...style, - transitionDuration: `0.001s`, - }; - }; - - const handleCopyText = () => { - const originURL = typeof window !== "undefined" && window.location.origin ? window.location.origin : ""; - copyTextToClipboard(`${originURL}/${workspaceSlug}/projects/${projectId}/issues/${issue.id}`).then(() => { - setToastAlert({ - type: "success", - title: "Link Copied!", - message: "Issue link copied to clipboard.", - }); - setIsMenuActive(false); - }); - }; - - const handleStateChange = (data: string, states: IState[] | undefined) => { - const oldState = states?.find((s) => s.id === issue.state); - const newState = states?.find((s) => s.id === data); - - partialUpdateIssue( - { - state: data, - state_detail: newState, - }, - issue - ); - trackEventServices.trackIssuePartialPropertyUpdateEvent( - { - workspaceSlug, - workspaceId: issue.workspace, - projectId: issue.project_detail.id, - projectIdentifier: issue.project_detail.identifier, - projectName: issue.project_detail.name, - issueId: issue.id, - }, - "ISSUE_PROPERTY_UPDATE_STATE", - user - ); - if (oldState?.group !== "completed" && newState?.group !== "completed") { - trackEventServices.trackIssueMarkedAsDoneEvent( - { - workspaceSlug: issue.workspace_detail.slug, - workspaceId: issue.workspace_detail.id, - projectId: issue.project_detail.id, - projectIdentifier: issue.project_detail.identifier, - projectName: issue.project_detail.name, - issueId: issue.id, - }, - user - ); - } - }; - - const handleAssigneeChange = (data: any) => { - const newData = issue.assignees ?? []; - - if (newData.includes(data)) newData.splice(newData.indexOf(data), 1); - else newData.push(data); - - partialUpdateIssue({ assignees_list: data }, issue); - - trackEventServices.trackIssuePartialPropertyUpdateEvent( - { - workspaceSlug, - workspaceId: issue.workspace, - projectId: issue.project_detail.id, - projectIdentifier: issue.project_detail.identifier, - projectName: issue.project_detail.name, - issueId: issue.id, - }, - "ISSUE_PROPERTY_UPDATE_ASSIGNEE", - user - ); - }; - - const handleLabelChange = (data: any) => { - partialUpdateIssue({ labels_list: data }, issue); - }; - - const handlePriorityChange = (data: TIssuePriorities) => { - partialUpdateIssue({ priority: data }, issue); - trackEventServices.trackIssuePartialPropertyUpdateEvent( - { - workspaceSlug, - workspaceId: issue.workspace, - projectId: issue.project_detail.id, - projectIdentifier: issue.project_detail.identifier, - projectName: issue.project_detail.name, - issueId: issue.id, - }, - "ISSUE_PROPERTY_UPDATE_PRIORITY", - user - ); - }; - - useEffect(() => { - if (snapshot.isDragging) handleTrashBox(snapshot.isDragging); - }, [snapshot, handleTrashBox]); - - useOutsideClickDetector(actionSectionRef, () => setIsMenuActive(false)); - - const openPeekOverview = () => { - const { query } = router; - - if (handleMyIssueOpen) handleMyIssueOpen(issue); - - router.push({ - pathname: router.pathname, - query: { ...query, peekIssue: issue.id }, - }); - }; - - const isNotAllowed = userAuth.isGuest || userAuth.isViewer || disableUserActions; - - return ( - <> - - {!isNotAllowed && ( - <> - { - if (isDraftIssue && handleDraftIssueEdit) handleDraftIssueEdit(); - else editIssue(); - }} - > - Edit issue - - {!isDraftIssue && ( - - Make a copy... - - )} - { - if (isDraftIssue && handleDraftIssueDelete) handleDraftIssueDelete(); - else handleDeleteIssue(issue); - }} - > - Delete issue - - - )} - {!isDraftIssue && ( - - Copy issue link - - )} - {!isDraftIssue && ( - - Open issue in new tab - - )} - -
{ - e.preventDefault(); - setContextMenu(true); - setContextMenuPosition(e); - }} - > -
- {!isNotAllowed && ( - - )} - -
- {properties.key && ( -
- {issue.project_detail.identifier}-{issue.sequence_id} -
- )} - -
- -
- {properties.priority && ( - - )} - {properties.state && ( - - )} - {properties.start_date && issue.start_date && ( - setIsDropdownActive(true)} - handleOnClose={() => setIsDropdownActive(false)} - user={user} - isNotAllowed={isNotAllowed} - /> - )} - {properties.due_date && issue.target_date && ( - setIsDropdownActive(true)} - handleOnClose={() => setIsDropdownActive(false)} - user={user} - isNotAllowed={isNotAllowed} - /> - )} - {properties.labels && issue.labels.length > 0 && ( - - )} - {properties.assignee && ( - - )} - {properties.estimate && issue.estimate_point !== null && ( - - )} - {properties.sub_issue_count && issue.sub_issues_count > 0 && ( -
- -
- - {issue.sub_issues_count} -
-
-
- )} - {properties.link && issue.link_count > 0 && ( -
- -
- - {issue.link_count} -
-
-
- )} - {properties.attachment_count && issue.attachment_count > 0 && ( -
- -
- - {issue.attachment_count} -
-
-
- )} -
-
-
- - ); -}; diff --git a/web/components/core/views/calendar-view/calendar-header.tsx b/web/components/core/views/calendar-view/calendar-header.tsx deleted file mode 100644 index 931bd3b49..000000000 --- a/web/components/core/views/calendar-view/calendar-header.tsx +++ /dev/null @@ -1,133 +0,0 @@ -import React from "react"; - -// headless ui -import { Popover, Transition } from "@headlessui/react"; -// ui -import { CustomMenu } from "components/ui"; -import { ToggleSwitch } from "@plane/ui"; -// icons -import { ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon } from "@heroicons/react/24/outline"; -// helpers -import { formatDate, isSameMonth, isSameYear, updateDateWithMonth, updateDateWithYear } from "helpers/calendar.helper"; -// constants -import { MONTHS_LIST, YEARS_LIST } from "constants/calendar"; - -type Props = { - currentDate: Date; - setCurrentDate: React.Dispatch>; - showWeekEnds: boolean; - setShowWeekEnds: React.Dispatch>; -}; - -export const CalendarHeader: React.FC = ({ currentDate, setCurrentDate, showWeekEnds, setShowWeekEnds }) => ( -
-
- - {({ open }) => ( - <> - -
- {formatDate(currentDate, "Month")} {formatDate(currentDate, "yyyy")} -
-
- - - -
- {YEARS_LIST.map((year) => ( - - ))} -
-
- {MONTHS_LIST.map((month) => ( - - ))} -
-
-
- - )} -
- -
- - -
-
- -
- - - - Options -
- } - > -
-

Show weekends

- setShowWeekEnds(!showWeekEnds)} /> -
- -
-
-); - -export default CalendarHeader; diff --git a/web/components/core/views/calendar-view/calendar.tsx b/web/components/core/views/calendar-view/calendar.tsx deleted file mode 100644 index 6ded660bd..000000000 --- a/web/components/core/views/calendar-view/calendar.tsx +++ /dev/null @@ -1,203 +0,0 @@ -import React, { useEffect, useState } from "react"; -import { useRouter } from "next/router"; -import { mutate } from "swr"; -import { DragDropContext, DropResult } from "react-beautiful-dnd"; -// services -import issuesService from "services/issue.service"; -// components -import { SingleCalendarDate, CalendarHeader } from "components/core"; -import { IssuePeekOverview } from "components/issues"; -// ui -import { Spinner } from "@plane/ui"; -// helpers -import { renderDateFormat } from "helpers/date-time.helper"; -import { startOfWeek, lastDayOfWeek, eachDayOfInterval, weekDayInterval, formatDate } from "helpers/calendar.helper"; -// types -import { ICalendarRange, ICurrentUserResponse, IIssue, UserAuth } from "types"; -// fetch-keys -import { - CYCLE_ISSUES_WITH_PARAMS, - MODULE_ISSUES_WITH_PARAMS, - PROJECT_ISSUES_LIST_WITH_PARAMS, - VIEW_ISSUES, -} from "constants/fetch-keys"; - -type Props = { - handleIssueAction: (issue: IIssue, action: "copy" | "delete" | "edit") => void; - addIssueToDate: (date: string) => void; - disableUserActions: boolean; - user: ICurrentUserResponse | undefined; - userAuth: UserAuth; -}; - -export const CalendarView: React.FC = ({ - handleIssueAction, - addIssueToDate, - disableUserActions, - user, - userAuth, -}) => { - const [showWeekEnds, setShowWeekEnds] = useState(false); - - const { calendarIssues, mutateIssues, params, activeMonthDate, setActiveMonthDate } = useCalendarIssuesView(); - - const [calendarDates, setCalendarDates] = useState({ - startDate: startOfWeek(activeMonthDate), - endDate: lastDayOfWeek(activeMonthDate), - }); - - const router = useRouter(); - const { workspaceSlug, projectId, cycleId, moduleId, viewId } = router.query; - - const currentViewDays = showWeekEnds - ? eachDayOfInterval({ - start: calendarDates.startDate, - end: calendarDates.endDate, - }) - : weekDayInterval({ - start: calendarDates.startDate, - end: calendarDates.endDate, - }); - - const currentViewDaysData = currentViewDays.map((date: Date) => { - const filterIssue = - calendarIssues.length > 0 - ? calendarIssues.filter( - (issue) => issue.target_date && renderDateFormat(issue.target_date) === renderDateFormat(date) - ) - : []; - return { - date: renderDateFormat(date), - issues: filterIssue, - }; - }); - - const weeks = ((date: Date[]) => { - const weeks = []; - if (showWeekEnds) { - for (let day = 0; day <= 6; day++) { - weeks.push(date[day]); - } - } else { - for (let day = 0; day <= 4; day++) { - weeks.push(date[day]); - } - } - - return weeks; - })(currentViewDays); - - const onDragEnd = (result: DropResult) => { - const { source, destination, draggableId } = result; - - if (!destination || !workspaceSlug || !projectId) return; - - if (source.droppableId === destination.droppableId) return; - - const fetchKey = cycleId - ? CYCLE_ISSUES_WITH_PARAMS(cycleId.toString(), params) - : moduleId - ? MODULE_ISSUES_WITH_PARAMS(moduleId.toString(), params) - : viewId - ? VIEW_ISSUES(viewId.toString(), params) - : PROJECT_ISSUES_LIST_WITH_PARAMS(projectId.toString(), params); - - mutate( - fetchKey, - (prevData) => - (prevData ?? []).map((p) => { - if (p.id === draggableId) - return { - ...p, - target_date: destination.droppableId, - }; - - return p; - }), - false - ); - - issuesService - .patchIssue( - workspaceSlug as string, - projectId as string, - draggableId, - { - target_date: destination?.droppableId, - }, - user - ) - .then(() => mutate(fetchKey)); - }; - - useEffect(() => { - setCalendarDates({ - startDate: startOfWeek(activeMonthDate), - endDate: lastDayOfWeek(activeMonthDate), - }); - }, [activeMonthDate]); - - const isNotAllowed = userAuth.isGuest || userAuth.isViewer || disableUserActions; - - return ( - <> - mutateIssues()} - projectId={projectId?.toString() ?? ""} - workspaceSlug={workspaceSlug?.toString() ?? ""} - readOnly={disableUserActions} - /> - {calendarIssues ? ( -
- -
- - -
- {weeks.map((date, index) => ( -
- {formatDate(date, "eee").substring(0, 3)} -
- ))} -
- -
- {currentViewDaysData.map((date, index) => ( - - ))} -
-
-
-
- ) : ( -
- -
- )} - - ); -}; diff --git a/web/components/core/views/calendar-view/index.ts b/web/components/core/views/calendar-view/index.ts deleted file mode 100644 index 75d8a3a1e..000000000 --- a/web/components/core/views/calendar-view/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export * from "./calendar-header"; -export * from "./calendar"; -export * from "./single-date"; -export * from "./single-issue"; -export * from "./inline-create-issue-form"; diff --git a/web/components/core/views/calendar-view/inline-create-issue-form.tsx b/web/components/core/views/calendar-view/inline-create-issue-form.tsx deleted file mode 100644 index 51b6c518b..000000000 --- a/web/components/core/views/calendar-view/inline-create-issue-form.tsx +++ /dev/null @@ -1,102 +0,0 @@ -import { useEffect, useRef, useState } from "react"; - -// next -import { useRouter } from "next/router"; - -// react hook form -import { useFormContext } from "react-hook-form"; - -import { InlineCreateIssueFormWrapper } from "components/core"; - -// hooks -import useProjectDetails from "hooks/use-project-details"; - -// types -import { IIssue } from "types"; - -type Props = { - isOpen: boolean; - handleClose: () => void; - onSuccess?: (data: IIssue) => Promise | void; - prePopulatedData?: Partial; - dependencies: any[]; -}; - -const useCheckIfThereIsSpaceOnRight = (ref: React.RefObject, deps: any[]) => { - const [isThereSpaceOnRight, setIsThereSpaceOnRight] = useState(true); - - const router = useRouter(); - const { moduleId, cycleId, viewId } = router.query; - - const container = document.getElementById(`calendar-view-${cycleId ?? moduleId ?? viewId}`); - - useEffect(() => { - if (!ref.current) return; - - const { right } = ref.current.getBoundingClientRect(); - - const width = right; - - const innerWidth = container?.getBoundingClientRect().width ?? window.innerWidth; - - if (width > innerWidth) setIsThereSpaceOnRight(false); - else setIsThereSpaceOnRight(true); - }, [ref, deps, container]); - - return isThereSpaceOnRight; -}; - -const InlineInput = () => { - const { projectDetails } = useProjectDetails(); - - const { register, setFocus } = useFormContext(); - - useEffect(() => { - setFocus("name"); - }, [setFocus]); - - return ( - <> -

- {projectDetails?.identifier ?? "..."} -

- - - ); -}; - -export const CalendarInlineCreateIssueForm: React.FC = (props) => { - const { isOpen, dependencies } = props; - - const ref = useRef(null); - - const isSpaceOnRight = useCheckIfThereIsSpaceOnRight(ref, dependencies); - - return ( - <> -
- - - -
- {/* Added to make any other element as outside click. This will make input also to be outside. */} - {isOpen &&
} - - ); -}; diff --git a/web/components/core/views/calendar-view/single-date.tsx b/web/components/core/views/calendar-view/single-date.tsx deleted file mode 100644 index a67ca762b..000000000 --- a/web/components/core/views/calendar-view/single-date.tsx +++ /dev/null @@ -1,126 +0,0 @@ -import React, { useState } from "react"; - -// next -import { useRouter } from "next/router"; - -// react-beautiful-dnd -import { Draggable } from "react-beautiful-dnd"; -// component -import StrictModeDroppable from "components/dnd/StrictModeDroppable"; -import { SingleCalendarIssue } from "./single-issue"; -import { CalendarInlineCreateIssueForm } from "./inline-create-issue-form"; -// icons -import { PlusSmallIcon } from "@heroicons/react/24/outline"; -// helper -import { formatDate } from "helpers/calendar.helper"; -// types -import { ICurrentUserResponse, IIssue } from "types"; - -type Props = { - handleIssueAction: (issue: IIssue, action: "copy" | "delete" | "edit") => void; - index: number; - date: { - date: string; - issues: IIssue[]; - }; - addIssueToDate: (date: string) => void; - showWeekEnds: boolean; - user: ICurrentUserResponse | undefined; - isNotAllowed: boolean; -}; - -export const SingleCalendarDate: React.FC = (props) => { - const { handleIssueAction, date, index, showWeekEnds, user, isNotAllowed } = props; - - const router = useRouter(); - const { cycleId, moduleId } = router.query; - - const [showAllIssues, setShowAllIssues] = useState(false); - const [isCreateIssueFormOpen, setIsCreateIssueFormOpen] = useState(false); - - const [formPosition, setFormPosition] = useState({ x: 0, y: 0 }); - - const totalIssues = date.issues.length; - - return ( - - {(provided) => ( -
- <> - {formatDate(new Date(date.date), "d")} - {totalIssues > 0 && - date.issues.slice(0, showAllIssues ? totalIssues : 4).map((issue: IIssue, index) => ( - - {(provided, snapshot) => ( - handleIssueAction(issue, "edit")} - handleDeleteIssue={() => handleIssueAction(issue, "delete")} - user={user} - isNotAllowed={isNotAllowed} - /> - )} - - ))} - - setIsCreateIssueFormOpen(false)} - prePopulatedData={{ - target_date: date.date, - ...(cycleId && { cycle: cycleId.toString() }), - ...(moduleId && { module: moduleId.toString() }), - }} - /> - - {totalIssues > 4 && ( - - )} - -
- -
- - {provided.placeholder} - -
- )} -
- ); -}; diff --git a/web/components/core/views/calendar-view/single-issue.tsx b/web/components/core/views/calendar-view/single-issue.tsx deleted file mode 100644 index 5cdd3afe9..000000000 --- a/web/components/core/views/calendar-view/single-issue.tsx +++ /dev/null @@ -1,389 +0,0 @@ -import React, { useCallback } from "react"; - -import { useRouter } from "next/router"; - -import { mutate } from "swr"; - -// react-beautiful-dnd -import { DraggableProvided, DraggableStateSnapshot } from "react-beautiful-dnd"; -// services -import issuesService from "services/issue.service"; -import trackEventServices from "services/track_event.service"; -// hooks -import useIssuesProperties from "hooks/use-issue-properties"; -import useToast from "hooks/use-toast"; -// components -import { CustomMenu } from "components/ui"; -import { ViewDueDateSelect, ViewEstimateSelect, ViewStartDateSelect } from "components/issues"; -import { LabelSelect, MembersSelect, PrioritySelect } from "components/project"; -import { StateSelect } from "components/states"; -import { Tooltip } from "@plane/ui"; -// icons -import { LinkIcon, PaperClipIcon, PencilIcon, TrashIcon } from "@heroicons/react/24/outline"; -import { LayerDiagonalIcon } from "components/icons"; -// helper -import { copyTextToClipboard, truncateText } from "helpers/string.helper"; -// type -import { ICurrentUserResponse, IIssue, IState, ISubIssueResponse, TIssuePriorities } from "types"; -// fetch-keys -import { - CYCLE_ISSUES_WITH_PARAMS, - MODULE_ISSUES_WITH_PARAMS, - PROJECT_ISSUES_LIST_WITH_PARAMS, - SUB_ISSUES, - VIEW_ISSUES, -} from "constants/fetch-keys"; - -type Props = { - handleEditIssue: (issue: IIssue) => void; - handleDeleteIssue: (issue: IIssue) => void; - index: number; - provided: DraggableProvided; - snapshot: DraggableStateSnapshot; - issue: IIssue; - projectId: string; - user: ICurrentUserResponse | undefined; - isNotAllowed: boolean; -}; - -export const SingleCalendarIssue: React.FC = ({ - handleEditIssue, - handleDeleteIssue, - index, - provided, - snapshot, - issue, - projectId, - user, - isNotAllowed, -}) => { - const router = useRouter(); - const { workspaceSlug, cycleId, moduleId, viewId } = router.query; - - const { setToastAlert } = useToast(); - - const params = {}; - - const [properties] = useIssuesProperties(workspaceSlug as string, projectId as string); - - const partialUpdateIssue = useCallback( - (formData: Partial, issue: IIssue) => { - if (!workspaceSlug || !projectId) return; - - const fetchKey = cycleId - ? CYCLE_ISSUES_WITH_PARAMS(cycleId.toString(), params) - : moduleId - ? MODULE_ISSUES_WITH_PARAMS(moduleId.toString(), params) - : viewId - ? VIEW_ISSUES(viewId.toString(), params) - : PROJECT_ISSUES_LIST_WITH_PARAMS(projectId.toString(), params); - - if (issue.parent) { - mutate( - SUB_ISSUES(issue.parent.toString()), - (prevData) => { - if (!prevData) return prevData; - - return { - ...prevData, - sub_issues: (prevData.sub_issues ?? []).map((i) => { - if (i.id === issue.id) { - return { - ...i, - ...formData, - }; - } - return i; - }), - }; - }, - false - ); - } else { - mutate( - fetchKey, - (prevData) => - (prevData ?? []).map((p) => { - if (p.id === issue.id) { - return { - ...p, - ...formData, - assignees: formData?.assignees_list ?? p.assignees, - }; - } - - return p; - }), - false - ); - } - - issuesService - .patchIssue(workspaceSlug as string, projectId as string, issue.id as string, formData, user) - .then(() => { - mutate(fetchKey); - }) - .catch((error) => { - console.log(error); - }); - }, - [workspaceSlug, projectId, cycleId, moduleId, viewId, params, user] - ); - - const handleCopyText = () => { - const originURL = typeof window !== "undefined" && window.location.origin ? window.location.origin : ""; - copyTextToClipboard(`${originURL}/${workspaceSlug}/projects/${projectId}/issues/${issue.id}`).then(() => { - setToastAlert({ - type: "success", - title: "Link Copied!", - message: "Issue link copied to clipboard.", - }); - }); - }; - - const handleStateChange = (data: string, states: IState[] | undefined) => { - const oldState = states?.find((s) => s.id === issue.state); - const newState = states?.find((s) => s.id === data); - - partialUpdateIssue( - { - state: data, - state_detail: newState, - }, - issue - ); - trackEventServices.trackIssuePartialPropertyUpdateEvent( - { - workspaceSlug, - workspaceId: issue.workspace, - projectId: issue.project_detail.id, - projectIdentifier: issue.project_detail.identifier, - projectName: issue.project_detail.name, - issueId: issue.id, - }, - "ISSUE_PROPERTY_UPDATE_STATE", - user - ); - if (oldState?.group !== "completed" && newState?.group !== "completed") { - trackEventServices.trackIssueMarkedAsDoneEvent( - { - workspaceSlug: issue.workspace_detail.slug, - workspaceId: issue.workspace_detail.id, - projectId: issue.project_detail.id, - projectIdentifier: issue.project_detail.identifier, - projectName: issue.project_detail.name, - issueId: issue.id, - }, - user - ); - } - }; - - const handleAssigneeChange = (data: any) => { - const newData = issue.assignees ?? []; - - if (newData.includes(data)) newData.splice(newData.indexOf(data), 1); - else newData.push(data); - - partialUpdateIssue({ assignees_list: data }, issue); - - trackEventServices.trackIssuePartialPropertyUpdateEvent( - { - workspaceSlug, - workspaceId: issue.workspace, - projectId: issue.project_detail.id, - projectIdentifier: issue.project_detail.identifier, - projectName: issue.project_detail.name, - issueId: issue.id, - }, - "ISSUE_PROPERTY_UPDATE_ASSIGNEE", - user - ); - }; - - const handleLabelChange = (data: any) => { - partialUpdateIssue({ labels_list: data }, issue); - }; - - const handlePriorityChange = (data: TIssuePriorities) => { - partialUpdateIssue({ priority: data }, issue); - trackEventServices.trackIssuePartialPropertyUpdateEvent( - { - workspaceSlug, - workspaceId: issue.workspace, - projectId: issue.project_detail.id, - projectIdentifier: issue.project_detail.identifier, - projectName: issue.project_detail.name, - issueId: issue.id, - }, - "ISSUE_PROPERTY_UPDATE_PRIORITY", - user - ); - }; - - const displayProperties = properties ? Object.values(properties).some((value) => value === true) : false; - - const openPeekOverview = () => { - const { query } = router; - - router.push({ - pathname: router.pathname, - query: { ...query, peekIssue: issue.id }, - }); - }; - - return ( -
-
- {!isNotAllowed && ( -
- - handleEditIssue(issue)}> -
- - Edit issue -
-
- handleDeleteIssue(issue)}> -
- - Delete issue -
-
- -
- - Copy issue Link -
-
-
-
- )} - - - - {displayProperties && ( -
- {properties.priority && ( - - )} - {properties.state && ( - - )} - {properties.start_date && issue.start_date && ( - - )} - {properties.due_date && issue.target_date && ( - - )} - {properties.labels && issue.labels.length > 0 && ( - - )} - {properties.assignee && ( - - )} - {properties.estimate && issue.estimate_point !== null && ( - - )} - {properties.sub_issue_count && issue.sub_issues_count > 0 && ( -
- -
- - {issue.sub_issues_count} -
-
-
- )} - {properties.link && issue.link_count > 0 && ( -
- -
- - {issue.link_count} -
-
-
- )} - {properties.attachment_count && issue.attachment_count > 0 && ( -
- -
- - {issue.attachment_count} -
-
-
- )} -
- )} -
-
- ); -}; diff --git a/web/components/core/views/gantt-chart-view/index.tsx b/web/components/core/views/gantt-chart-view/index.tsx deleted file mode 100644 index 2cd10f95f..000000000 --- a/web/components/core/views/gantt-chart-view/index.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import { useRouter } from "next/router"; - -// components -import { CycleIssuesGanttChartView } from "components/cycles"; -import { IssueGanttChartView } from "components/issues"; -import { ModuleIssuesGanttChartView } from "components/modules"; -import { ViewIssuesGanttChartView } from "components/views"; - -type Props = { - disableUserActions: boolean; -}; - -export const GanttChartView: React.FC = ({ disableUserActions }) => { - const router = useRouter(); - const { cycleId, moduleId, viewId } = router.query; - - return ( - <> - {cycleId ? ( - - ) : moduleId ? ( - - ) : viewId ? ( - - ) : ( - - )} - - ); -}; diff --git a/web/components/core/views/gantt-chart-view/inline-create-issue-form.tsx b/web/components/core/views/gantt-chart-view/inline-create-issue-form.tsx deleted file mode 100644 index 785eb3c5a..000000000 --- a/web/components/core/views/gantt-chart-view/inline-create-issue-form.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import { useEffect } from "react"; - -// react hook form -import { useFormContext } from "react-hook-form"; - -// hooks -import useProjectDetails from "hooks/use-project-details"; - -// components -import { InlineCreateIssueFormWrapper } from "components/core"; - -// types -import { IIssue } from "types"; - -type Props = { - isOpen: boolean; - handleClose: () => void; - onSuccess?: (data: IIssue) => Promise | void; - prePopulatedData?: Partial; -}; - -const InlineInput = () => { - const { projectDetails } = useProjectDetails(); - - const { register, setFocus } = useFormContext(); - - useEffect(() => { - setFocus("name"); - }, [setFocus]); - - return ( - <> -
-

{projectDetails?.identifier ?? "..."}

- - - ); -}; - -export const GanttInlineCreateIssueForm: React.FC = (props) => ( - <> - - - - {props.isOpen && ( -

- Press {"'"}Enter{"'"} to add another issue -

- )} - -); diff --git a/web/components/core/views/index.ts b/web/components/core/views/index.ts index 13da90d8e..5a3edcd20 100644 --- a/web/components/core/views/index.ts +++ b/web/components/core/views/index.ts @@ -1,8 +1,3 @@ -export * from "./board-view"; -export * from "./calendar-view"; -export * from "./gantt-chart-view"; -export * from "./list-view"; export * from "./spreadsheet-view"; -export * from "./all-views"; export * from "./issues-view"; export * from "./inline-issue-create-wrapper"; diff --git a/web/components/core/views/list-view/all-lists.tsx b/web/components/core/views/list-view/all-lists.tsx deleted file mode 100644 index 58025b328..000000000 --- a/web/components/core/views/list-view/all-lists.tsx +++ /dev/null @@ -1,104 +0,0 @@ -import { useRouter } from "next/router"; - -// hooks -import useMyIssues from "hooks/my-issues/use-my-issues"; -import useIssuesView from "hooks/use-issues-view"; -import useProfileIssues from "hooks/use-profile-issues"; -// components -import { SingleList } from "components/core/views/list-view/single-list"; -import { IssuePeekOverview } from "components/issues"; -// types -import { ICurrentUserResponse, IIssue, IIssueViewProps, IState, UserAuth } from "types"; - -// types -type Props = { - states: IState[] | undefined; - addIssueToGroup: (groupTitle: string) => void; - handleIssueAction: (issue: IIssue, action: "copy" | "delete" | "edit") => void; - handleDraftIssueAction?: (issue: IIssue, action: "edit" | "delete") => void; - openIssuesListModal?: (() => void) | null; - myIssueProjectId?: string | null; - handleMyIssueOpen?: (issue: IIssue) => void; - removeIssue: ((bridgeId: string, issueId: string) => void) | null; - disableUserActions: boolean; - disableAddIssueOption?: boolean; - user: ICurrentUserResponse | undefined; - userAuth: UserAuth; - viewProps: IIssueViewProps; -}; - -export const AllLists: React.FC = ({ - addIssueToGroup, - handleIssueAction, - disableUserActions, - disableAddIssueOption = false, - openIssuesListModal, - handleMyIssueOpen, - myIssueProjectId, - removeIssue, - states, - handleDraftIssueAction, - user, - userAuth, - viewProps, -}) => { - const router = useRouter(); - const { workspaceSlug, projectId, userId } = router.query; - - const isProfileIssue = - router.pathname.includes("assigned") || - router.pathname.includes("created") || - router.pathname.includes("subscribed"); - - const isMyIssue = router.pathname.includes("my-issues"); - const { mutateIssues } = useIssuesView(); - const { mutateMyIssues } = useMyIssues(workspaceSlug?.toString()); - const { mutateProfileIssues } = useProfileIssues(workspaceSlug?.toString(), userId?.toString()); - - const { displayFilters, groupedIssues } = viewProps; - - return ( - <> - - isMyIssue ? mutateMyIssues() : isProfileIssue ? mutateProfileIssues() : mutateIssues() - } - projectId={myIssueProjectId ? myIssueProjectId : projectId?.toString() ?? ""} - workspaceSlug={workspaceSlug?.toString() ?? ""} - readOnly={disableUserActions} - /> - {groupedIssues && ( -
- {Object.keys(groupedIssues).map((singleGroup) => { - const currentState = - displayFilters?.group_by === "state" - ? states?.find((s) => s.id === singleGroup) - : null; - - if (!displayFilters?.show_empty_groups && groupedIssues[singleGroup].length === 0) - return null; - - return ( - addIssueToGroup(singleGroup)} - handleDraftIssueAction={handleDraftIssueAction} - handleIssueAction={handleIssueAction} - handleMyIssueOpen={handleMyIssueOpen} - openIssuesListModal={openIssuesListModal} - removeIssue={removeIssue} - disableUserActions={disableUserActions} - disableAddIssueOption={disableAddIssueOption} - user={user} - userAuth={userAuth} - viewProps={viewProps} - /> - ); - })} -
- )} - - ); -}; diff --git a/web/components/core/views/list-view/index.ts b/web/components/core/views/list-view/index.ts deleted file mode 100644 index 4d59be165..000000000 --- a/web/components/core/views/list-view/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from "./all-lists"; -export * from "./single-issue"; -export * from "./single-list"; -export * from "./inline-create-issue-form"; diff --git a/web/components/core/views/list-view/inline-create-issue-form.tsx b/web/components/core/views/list-view/inline-create-issue-form.tsx deleted file mode 100644 index b61420fc8..000000000 --- a/web/components/core/views/list-view/inline-create-issue-form.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import { useEffect } from "react"; -// react hook form -import { useFormContext } from "react-hook-form"; - -// hooks -import useProjectDetails from "hooks/use-project-details"; - -// components -import { InlineCreateIssueFormWrapper } from "../inline-issue-create-wrapper"; - -// types -import { IIssue } from "types"; - -type Props = { - isOpen: boolean; - handleClose: () => void; - onSuccess?: (data: IIssue) => Promise | void; - prePopulatedData?: Partial; -}; - -const InlineInput = () => { - const { projectDetails } = useProjectDetails(); - - const { register, setFocus } = useFormContext(); - - useEffect(() => { - setFocus("name"); - }, [setFocus]); - - return ( - <> -

- {projectDetails?.identifier ?? "..."} -

- - - ); -}; - -export const ListInlineCreateIssueForm: React.FC = (props) => ( - <> - - - - {props.isOpen && ( -

- Press {"'"}Enter{"'"} to add another issue -

- )} - -); diff --git a/web/components/core/views/list-view/single-issue.tsx b/web/components/core/views/list-view/single-issue.tsx deleted file mode 100644 index 6bf107443..000000000 --- a/web/components/core/views/list-view/single-issue.tsx +++ /dev/null @@ -1,482 +0,0 @@ -import React, { useCallback, useState } from "react"; - -import { useRouter } from "next/router"; - -import { mutate } from "swr"; - -// services -import issuesService from "services/issue.service"; -import trackEventServices from "services/track_event.service"; -// hooks -import useToast from "hooks/use-toast"; -// components -import { ViewDueDateSelect, ViewEstimateSelect, ViewStartDateSelect } from "components/issues"; -import { LabelSelect, MembersSelect, PrioritySelect } from "components/project"; -import { StateSelect } from "components/states"; -// ui -import { CustomMenu, ContextMenu } from "components/ui"; -import { Tooltip } from "@plane/ui"; -// icons -import { - ClipboardDocumentCheckIcon, - LinkIcon, - PencilIcon, - TrashIcon, - XMarkIcon, - ArrowTopRightOnSquareIcon, - PaperClipIcon, -} from "@heroicons/react/24/outline"; -import { LayerDiagonalIcon } from "components/icons"; -// helpers -import { copyTextToClipboard } from "helpers/string.helper"; -import { handleIssuesMutation } from "helpers/issue.helper"; -// types -import { - ICurrentUserResponse, - IIssue, - IIssueViewProps, - IState, - ISubIssueResponse, - IUserProfileProjectSegregation, - TIssuePriorities, - UserAuth, -} from "types"; -// fetch-keys -import { CYCLE_DETAILS, MODULE_DETAILS, SUB_ISSUES, USER_PROFILE_PROJECT_SEGREGATION } from "constants/fetch-keys"; - -type Props = { - type?: string; - issue: IIssue; - projectId: string; - groupTitle?: string; - editIssue: () => void; - index: number; - makeIssueCopy: () => void; - removeIssue?: (() => void) | null; - handleDeleteIssue: (issue: IIssue) => void; - handleDraftIssueSelect?: (issue: IIssue) => void; - handleDraftIssueDelete?: (issue: IIssue) => void; - handleMyIssueOpen?: (issue: IIssue) => void; - disableUserActions: boolean; - user: ICurrentUserResponse | undefined; - userAuth: UserAuth; - viewProps: IIssueViewProps; -}; - -export const SingleListIssue: React.FC = ({ - type, - issue, - projectId, - editIssue, - index, - makeIssueCopy, - removeIssue, - groupTitle, - handleDraftIssueDelete, - handleDeleteIssue, - handleMyIssueOpen, - disableUserActions, - user, - userAuth, - viewProps, - handleDraftIssueSelect, -}) => { - // context menu - const [contextMenu, setContextMenu] = useState(false); - const [contextMenuPosition, setContextMenuPosition] = useState(null); - - const router = useRouter(); - const { workspaceSlug, cycleId, moduleId, userId } = router.query; - const isArchivedIssues = router.pathname.includes("archived-issues"); - const isDraftIssues = router.pathname?.split("/")?.[4] === "draft-issues"; - - const { setToastAlert } = useToast(); - - const { displayFilters, properties, mutateIssues } = viewProps; - - const partialUpdateIssue = useCallback( - (formData: Partial, issue: IIssue) => { - if (!workspaceSlug || !issue) return; - - if (issue.parent) { - mutate( - SUB_ISSUES(issue.parent.toString()), - (prevData) => { - if (!prevData) return prevData; - - return { - ...prevData, - sub_issues: (prevData.sub_issues ?? []).map((i) => { - if (i.id === issue.id) { - return { - ...i, - ...formData, - }; - } - return i; - }), - }; - }, - false - ); - } else { - mutateIssues( - (prevData: any) => - handleIssuesMutation( - formData, - groupTitle ?? "", - displayFilters?.group_by ?? null, - index, - displayFilters?.order_by ?? "-created_at", - prevData - ), - false - ); - } - - issuesService.patchIssue(workspaceSlug as string, issue.project, issue.id, formData, user).then(() => { - mutateIssues(); - - if (userId) - mutate( - USER_PROFILE_PROJECT_SEGREGATION(workspaceSlug.toString(), userId.toString()) - ); - - if (cycleId) mutate(CYCLE_DETAILS(cycleId as string)); - if (moduleId) mutate(MODULE_DETAILS(moduleId as string)); - }); - }, - [displayFilters, workspaceSlug, cycleId, moduleId, userId, groupTitle, index, mutateIssues, user] - ); - - const handleCopyText = () => { - const originURL = typeof window !== "undefined" && window.location.origin ? window.location.origin : ""; - copyTextToClipboard(`${originURL}/${workspaceSlug}/projects/${projectId}/issues/${issue.id}`).then(() => { - setToastAlert({ - type: "success", - title: "Link Copied!", - message: "Issue link copied to clipboard.", - }); - }); - }; - - const handleStateChange = (data: string, states: IState[] | undefined) => { - const oldState = states?.find((s) => s.id === issue.state); - const newState = states?.find((s) => s.id === data); - - partialUpdateIssue( - { - state: data, - state_detail: newState, - }, - issue - ); - trackEventServices.trackIssuePartialPropertyUpdateEvent( - { - workspaceSlug, - workspaceId: issue.workspace, - projectId: issue.project_detail.id, - projectIdentifier: issue.project_detail.identifier, - projectName: issue.project_detail.name, - issueId: issue.id, - }, - "ISSUE_PROPERTY_UPDATE_STATE", - user - ); - if (oldState?.group !== "completed" && newState?.group !== "completed") { - trackEventServices.trackIssueMarkedAsDoneEvent( - { - workspaceSlug: issue.workspace_detail.slug, - workspaceId: issue.workspace_detail.id, - projectId: issue.project_detail.id, - projectIdentifier: issue.project_detail.identifier, - projectName: issue.project_detail.name, - issueId: issue.id, - }, - user - ); - } - }; - - const handleAssigneeChange = (data: any) => { - const newData = issue.assignees ?? []; - - if (newData.includes(data)) newData.splice(newData.indexOf(data), 1); - else newData.push(data); - - partialUpdateIssue({ assignees_list: data }, issue); - - trackEventServices.trackIssuePartialPropertyUpdateEvent( - { - workspaceSlug, - workspaceId: issue.workspace, - projectId: issue.project_detail.id, - projectIdentifier: issue.project_detail.identifier, - projectName: issue.project_detail.name, - issueId: issue.id, - }, - "ISSUE_PROPERTY_UPDATE_ASSIGNEE", - user - ); - }; - - const handleLabelChange = (data: any) => { - partialUpdateIssue({ labels_list: data }, issue); - }; - - const handlePriorityChange = (data: TIssuePriorities) => { - partialUpdateIssue({ priority: data }, issue); - trackEventServices.trackIssuePartialPropertyUpdateEvent( - { - workspaceSlug, - workspaceId: issue.workspace, - projectId: issue.project_detail.id, - projectIdentifier: issue.project_detail.identifier, - projectName: issue.project_detail.name, - issueId: issue.id, - }, - "ISSUE_PROPERTY_UPDATE_PRIORITY", - user - ); - }; - - const issuePath = isArchivedIssues - ? `/${workspaceSlug}/projects/${issue.project}/archived-issues/${issue.id}` - : isDraftIssues - ? `#` - : `/${workspaceSlug}/projects/${issue.project}/issues/${issue.id}`; - - const openPeekOverview = (issue: IIssue) => { - const { query } = router; - - if (handleMyIssueOpen) handleMyIssueOpen(issue); - router.push({ - pathname: router.pathname, - query: { ...query, peekIssue: issue.id }, - }); - }; - - const isNotAllowed = userAuth.isGuest || userAuth.isViewer || disableUserActions || isArchivedIssues; - - return ( - <> - - {!isNotAllowed && ( - <> - { - if (isDraftIssues && handleDraftIssueSelect) handleDraftIssueSelect(issue); - else editIssue(); - }} - > - Edit issue - - {!isDraftIssues && ( - - Make a copy... - - )} - { - if (isDraftIssues && handleDraftIssueDelete) handleDraftIssueDelete(issue); - else handleDeleteIssue(issue); - }} - > - Delete issue - - - )} - {!isDraftIssues && ( - <> - - Copy issue link - - - Open issue in new tab - - - )} - - -
{ - e.preventDefault(); - setContextMenu(true); - setContextMenuPosition(e); - }} - > -
-
- {properties.key && ( - - - {issue.project_detail?.identifier}-{issue.sequence_id} - - - )} - - - -
-
- -
- {properties.priority && ( - - )} - {properties.state && ( - - )} - {properties.start_date && issue.start_date && ( - - )} - {properties.due_date && issue.target_date && ( - - )} - {properties.labels && ( - - )} - {properties.assignee && ( - - )} - {properties.estimate && issue.estimate_point !== null && ( - - )} - {properties.sub_issue_count && issue.sub_issues_count > 0 && ( -
- -
- - {issue.sub_issues_count} -
-
-
- )} - {properties.link && issue.link_count > 0 && ( -
- -
- - {issue.link_count} -
-
-
- )} - {properties.attachment_count && issue.attachment_count > 0 && ( -
- -
- - {issue.attachment_count} -
-
-
- )} - {type && !isNotAllowed && ( - - { - if (isDraftIssues && handleDraftIssueSelect) handleDraftIssueSelect(issue); - else editIssue(); - }} - > -
- - Edit issue -
-
- {type !== "issue" && removeIssue && ( - -
- - Remove from {type} -
-
- )} - { - if (isDraftIssues && handleDraftIssueDelete) handleDraftIssueDelete(issue); - else handleDeleteIssue(issue); - }} - > -
- - Delete issue -
-
- {!isDraftIssues && ( - -
- - Copy issue link -
-
- )} -
- )} -
-
- - ); -}; diff --git a/web/components/core/views/list-view/single-list.tsx b/web/components/core/views/list-view/single-list.tsx deleted file mode 100644 index 83d52fd00..000000000 --- a/web/components/core/views/list-view/single-list.tsx +++ /dev/null @@ -1,349 +0,0 @@ -import { useState } from "react"; - -// next -import { useRouter } from "next/router"; - -import useSWR from "swr"; - -// headless ui -import { Disclosure, Transition } from "@headlessui/react"; -// services -import issuesService from "services/issue.service"; -import projectService from "services/project.service"; -// hooks -import useProjects from "hooks/use-projects"; -// components -import { CreateUpdateDraftIssueModal } from "components/issues"; -import { SingleListIssue, ListInlineCreateIssueForm } from "components/core"; -// ui -import { Avatar, CustomMenu } from "components/ui"; -// icons -import { PlusIcon } from "@heroicons/react/24/outline"; -import { PriorityIcon, StateGroupIcon } from "components/icons"; -// helpers -import { addSpaceIfCamelCase } from "helpers/string.helper"; -import { renderEmoji } from "helpers/emoji.helper"; -// types -import { - ICurrentUserResponse, - IIssue, - IIssueLabels, - IIssueViewProps, - IState, - TIssuePriorities, - TStateGroups, - UserAuth, -} from "types"; -// fetch-keys -import { PROJECT_ISSUE_LABELS, PROJECT_MEMBERS, WORKSPACE_LABELS } from "constants/fetch-keys"; -// constants -import { STATE_GROUP_COLORS } from "constants/state"; - -type Props = { - currentState?: IState | null; - groupTitle: string; - addIssueToGroup: () => void; - handleIssueAction: (issue: IIssue, action: "copy" | "delete" | "edit") => void; - handleDraftIssueAction?: (issue: IIssue, action: "edit" | "delete") => void; - openIssuesListModal?: (() => void) | null; - handleMyIssueOpen?: (issue: IIssue) => void; - removeIssue: ((bridgeId: string, issueId: string) => void) | null; - disableUserActions: boolean; - disableAddIssueOption?: boolean; - user: ICurrentUserResponse | undefined; - userAuth: UserAuth; - viewProps: IIssueViewProps; -}; - -export const SingleList: React.FC = (props) => { - const { - currentState, - groupTitle, - handleIssueAction, - openIssuesListModal, - handleDraftIssueAction, - handleMyIssueOpen, - addIssueToGroup, - removeIssue, - disableUserActions, - disableAddIssueOption = false, - user, - userAuth, - viewProps, - } = props; - - const router = useRouter(); - const { workspaceSlug, projectId, cycleId, moduleId } = router.query; - - const [isCreateIssueFormOpen, setIsCreateIssueFormOpen] = useState(false); - const [isDraftIssuesModalOpen, setIsDraftIssuesModalOpen] = useState(false); - - const isMyIssuesPage = router.pathname.split("/")[3] === "my-issues"; - const isProfileIssuesPage = router.pathname.split("/")[2] === "profile"; - const isDraftIssuesPage = router.pathname.split("/")[4] === "draft-issues"; - - const isArchivedIssues = router.pathname.includes("archived-issues"); - - const type = cycleId ? "cycle" : moduleId ? "module" : "issue"; - - const { displayFilters, groupedIssues } = viewProps; - - const { data: issueLabels } = useSWR( - workspaceSlug && projectId && displayFilters?.group_by === "labels" - ? PROJECT_ISSUE_LABELS(projectId.toString()) - : null, - workspaceSlug && projectId && displayFilters?.group_by === "labels" - ? () => issuesService.getIssueLabels(workspaceSlug.toString(), projectId.toString()) - : null - ); - - const { data: workspaceLabels } = useSWR( - workspaceSlug && displayFilters?.group_by === "labels" ? WORKSPACE_LABELS(workspaceSlug.toString()) : null, - workspaceSlug && displayFilters?.group_by === "labels" - ? () => issuesService.getWorkspaceLabels(workspaceSlug.toString()) - : null - ); - - const { data: members } = useSWR( - workspaceSlug && - projectId && - (displayFilters?.group_by === "created_by" || displayFilters?.group_by === "assignees") - ? PROJECT_MEMBERS(projectId as string) - : null, - workspaceSlug && - projectId && - (displayFilters?.group_by === "created_by" || displayFilters?.group_by === "assignees") - ? () => projectService.projectMembers(workspaceSlug as string, projectId as string) - : null - ); - - const { projects } = useProjects(); - - const getGroupTitle = () => { - let title = addSpaceIfCamelCase(groupTitle); - - switch (displayFilters?.group_by) { - case "state": - title = addSpaceIfCamelCase(currentState?.name ?? ""); - break; - case "labels": - title = - [...(issueLabels ?? []), ...(workspaceLabels ?? [])]?.find((label) => label.id === groupTitle)?.name ?? - "None"; - break; - case "project": - title = projects?.find((p) => p.id === groupTitle)?.name ?? "None"; - break; - case "assignees": - case "created_by": - const member = members?.find((member) => member.member.id === groupTitle)?.member; - title = member ? member.display_name : "None"; - break; - } - - return title; - }; - - const getGroupIcon = () => { - let icon; - - switch (displayFilters?.group_by) { - case "state": - icon = currentState && ( - - ); - break; - case "state_detail.group": - icon = ( - - ); - break; - case "priority": - icon = ; - break; - case "project": - const project = projects?.find((p) => p.id === groupTitle); - icon = - project && - (project.emoji !== null - ? renderEmoji(project.emoji) - : project.icon_prop !== null - ? renderEmoji(project.icon_prop) - : null); - break; - case "labels": - const labelColor = - [...(issueLabels ?? []), ...(workspaceLabels ?? [])]?.find((label) => label.id === groupTitle)?.color ?? - "#000000"; - icon = ; - break; - case "assignees": - case "created_by": - const member = members?.find((member) => member.member.id === groupTitle)?.member; - icon = member ? : <>; - - break; - } - - return icon; - }; - - if (!groupedIssues) return null; - - return ( - <> - setIsDraftIssuesModalOpen(false)} - prePopulateData={{ - ...(cycleId && { cycle: cycleId.toString() }), - ...(moduleId && { module: moduleId.toString() }), - [displayFilters?.group_by! === "labels" ? "labels_list" : displayFilters?.group_by!]: - displayFilters?.group_by === "labels" ? [groupTitle] : groupTitle, - }} - /> - - - {({ open }) => ( -
-
- -
- {displayFilters?.group_by !== null &&
{getGroupIcon()}
} - {displayFilters?.group_by !== null ? ( -

- {getGroupTitle()} -

- ) : ( -

All Issues

- )} - - {groupedIssues[groupTitle as keyof IIssue].length} - -
-
- {isArchivedIssues ? ( - "" - ) : type === "issue" ? ( - !disableAddIssueOption && ( - - ) - ) : disableUserActions ? ( - "" - ) : ( - - -
- } - position="right" - noBorder - > - setIsCreateIssueFormOpen(true)}>Create new - {openIssuesListModal && ( - Add an existing issue - )} - - )} -
- - - {groupedIssues[groupTitle] ? ( - groupedIssues[groupTitle].length > 0 ? ( - groupedIssues[groupTitle].map((issue, index) => ( - handleIssueAction(issue, "edit")} - makeIssueCopy={() => handleIssueAction(issue, "copy")} - handleDeleteIssue={() => handleIssueAction(issue, "delete")} - handleDraftIssueSelect={ - handleDraftIssueAction ? () => handleDraftIssueAction(issue, "edit") : undefined - } - handleDraftIssueDelete={ - handleDraftIssueAction ? () => handleDraftIssueAction(issue, "delete") : undefined - } - handleMyIssueOpen={handleMyIssueOpen} - removeIssue={() => { - if (removeIssue !== null && issue.bridge_id) removeIssue(issue.bridge_id, issue.id); - }} - disableUserActions={disableUserActions} - user={user} - userAuth={userAuth} - viewProps={viewProps} - /> - )) - ) : ( -

No issues.

- ) - ) : ( -
Loading...
- )} - - setIsCreateIssueFormOpen(false)} - prePopulatedData={{ - ...(cycleId && { cycle: cycleId.toString() }), - ...(moduleId && { module: moduleId.toString() }), - [displayFilters?.group_by! === "labels" ? "labels_list" : displayFilters?.group_by!]: - displayFilters?.group_by === "labels" ? [groupTitle] : groupTitle, - }} - /> - - {!disableAddIssueOption && !isCreateIssueFormOpen && !isDraftIssuesPage && ( -
- -
- )} -
-
-
- )} - - - ); -}; diff --git a/web/components/cycles/gantt-chart/cycle-issues-layout.tsx b/web/components/cycles/gantt-chart/cycle-issues-layout.tsx deleted file mode 100644 index e67bc516f..000000000 --- a/web/components/cycles/gantt-chart/cycle-issues-layout.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import { useRouter } from "next/router"; - -// hooks -import useIssuesView from "hooks/use-issues-view"; -import useUser from "hooks/use-user"; -import useGanttChartCycleIssues from "hooks/gantt-chart/cycle-issues-view"; -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"; - -type Props = { - disableUserActions: boolean; -}; - -export const CycleIssuesGanttChartView: React.FC = ({ disableUserActions }) => { - const router = useRouter(); - const { workspaceSlug, projectId, cycleId } = router.query; - - const { displayFilters } = useIssuesView(); - - const { user } = useUser(); - const { projectDetails } = useProjectDetails(); - - const { ganttIssues, mutateGanttIssues } = useGanttChartCycleIssues( - workspaceSlug as string, - projectId as string, - cycleId as string - ); - - const isAllowed = projectDetails?.member_role === 20 || projectDetails?.member_role === 15; - - return ( - <> - mutateGanttIssues()} - projectId={projectId?.toString() ?? ""} - workspaceSlug={workspaceSlug?.toString() ?? ""} - readOnly={disableUserActions} - /> -
- {}} - SidebarBlockRender={IssueGanttSidebarBlock} - BlockRender={IssueGanttBlock} - enableBlockLeftResize={isAllowed} - enableBlockRightResize={isAllowed} - enableBlockMove={isAllowed} - enableReorder={displayFilters.order_by === "sort_order" && isAllowed} - bottomSpacing - /> -
- - ); -}; diff --git a/web/components/cycles/gantt-chart/index.ts b/web/components/cycles/gantt-chart/index.ts index e4850b2e2..a0a16086b 100644 --- a/web/components/cycles/gantt-chart/index.ts +++ b/web/components/cycles/gantt-chart/index.ts @@ -1,3 +1,2 @@ export * from "./blocks"; -export * from "./cycle-issues-layout"; export * from "./cycles-list-layout"; diff --git a/web/components/gantt-chart/chart/index.tsx b/web/components/gantt-chart/chart/index.tsx index e21e803de..b3674566a 100644 --- a/web/components/gantt-chart/chart/index.tsx +++ b/web/components/gantt-chart/chart/index.tsx @@ -19,17 +19,17 @@ import { PlusIcon } from "lucide-react"; import { // generateHourChart, // generateDayChart, - generateWeekChart, - generateBiWeekChart, + // generateWeekChart, + // generateBiWeekChart, generateMonthChart, - generateQuarterChart, - generateYearChart, + // generateQuarterChart, + // generateYearChart, getNumberOfDaysBetweenTwoDatesInMonth, - getNumberOfDaysBetweenTwoDatesInQuarter, - getNumberOfDaysBetweenTwoDatesInYear, + // getNumberOfDaysBetweenTwoDatesInQuarter, + // getNumberOfDaysBetweenTwoDatesInYear, getMonthChartItemPositionWidthInMonth, } from "../views"; -import { GanttInlineCreateIssueForm } from "components/core/views/gantt-chart-view/inline-create-issue-form"; +// import { GanttInlineCreateIssueForm } from "components/core/views/gantt-chart-view/inline-create-issue-form"; // types import { ChartDataType, IBlockUpdateData, IGanttBlock, TGanttViews } from "../types"; // data @@ -74,8 +74,7 @@ export const ChartViewRoot: FC = ({ // blocks state management starts const [chartBlocks, setChartBlocks] = useState(null); - const { currentView, currentViewData, renderView, dispatch, allViews, updateScrollLeft } = - useChart(); + const { currentView, currentViewData, renderView, dispatch, allViews, updateScrollLeft } = useChart(); const router = useRouter(); const { cycleId, moduleId } = router.query; @@ -92,8 +91,7 @@ export const ChartViewRoot: FC = ({ : []; useEffect(() => { - if (currentViewData && blocks) - setChartBlocks(() => renderBlockStructure(currentViewData, blocks)); + if (currentViewData && blocks) setChartBlocks(() => renderBlockStructure(currentViewData, blocks)); }, [currentViewData, blocks]); // blocks state management ends @@ -115,8 +113,7 @@ export const ChartViewRoot: FC = ({ // if (view === "day") currentRender = generateDayChart(selectedCurrentViewData, side); // if (view === "week") currentRender = generateWeekChart(selectedCurrentViewData, side); // if (view === "bi_week") currentRender = generateBiWeekChart(selectedCurrentViewData, side); - if (selectedCurrentView === "month") - currentRender = generateMonthChart(selectedCurrentViewData, side); + if (selectedCurrentView === "month") currentRender = generateMonthChart(selectedCurrentViewData, side); // if (view === "quarter") currentRender = generateQuarterChart(selectedCurrentViewData, side); // if (selectedCurrentView === "year") // currentRender = generateYearChart(selectedCurrentViewData, side); @@ -155,10 +152,7 @@ export const ChartViewRoot: FC = ({ }); setItemsContainerWidth(currentRender.scrollWidth); setTimeout(() => { - handleScrollToCurrentSelectedDate( - currentRender.state, - currentRender.state.data.currentDate - ); + handleScrollToCurrentSelectedDate(currentRender.state, currentRender.state.data.currentDate); }, 50); } } @@ -202,8 +196,7 @@ export const ChartViewRoot: FC = ({ // if (currentView === "year") // daysDifference = getNumberOfDaysBetweenTwoDatesInYear(currentState.data.startDate, date); - scrollWidth = - daysDifference * currentState.data.width - (clientVisibleWidth / 2 - currentState.data.width); + scrollWidth = daysDifference * currentState.data.width - (clientVisibleWidth / 2 - currentState.data.width); scrollContainer.scrollLeft = scrollWidth; }; @@ -218,22 +211,17 @@ export const ChartViewRoot: FC = ({ updateScrollLeft(currentScrollPosition); - const approxRangeLeft: number = - scrollWidth >= clientVisibleWidth + 1000 ? 1000 : scrollWidth - clientVisibleWidth; + const approxRangeLeft: number = scrollWidth >= clientVisibleWidth + 1000 ? 1000 : scrollWidth - clientVisibleWidth; const approxRangeRight: number = scrollWidth - (approxRangeLeft + clientVisibleWidth); - if (currentScrollPosition >= approxRangeRight) - updateCurrentViewRenderPayload("right", currentView); - if (currentScrollPosition <= approxRangeLeft) - updateCurrentViewRenderPayload("left", currentView); + if (currentScrollPosition >= approxRangeRight) updateCurrentViewRenderPayload("right", currentView); + if (currentScrollPosition <= approxRangeLeft) updateCurrentViewRenderPayload("left", currentView); }; return (
= ({
handleChartView(_chatView?.key)} > @@ -305,10 +291,7 @@ export const ChartViewRoot: FC = ({ bottomSpacing ? "mb-8" : "" }`} > -
+
{title}
Duration
@@ -322,7 +305,7 @@ export const ChartViewRoot: FC = ({ /> {chartBlocks && !(isCyclePage || isModulePage) && (
- setIsCreateIssueFormOpen(false)} onSuccess={() => { @@ -344,7 +327,7 @@ export const ChartViewRoot: FC = ({ ...(cycleId && { cycle: cycleId.toString() }), ...(moduleId && { module: moduleId.toString() }), }} - /> + /> */} {!isCreateIssueFormOpen && ( - -
-
- -
- {displayProperties?.priority && ( - // - - )} - {displayProperties?.state && ( - - )} - {displayProperties?.start_date && issue.start_date && ( - - )} - {displayProperties?.due_date && issue.target_date && ( - - )} - {displayProperties?.labels && } - {displayProperties?.assignee && ( - - )} - {displayProperties?.estimate && issue.estimate_point !== null && ( - - )} - {displayProperties?.sub_issue_count && issue.sub_issues_count > 0 && ( -
- -
- - {issue.sub_issues_count} -
-
-
- )} - {displayProperties?.link && issue.link_count > 0 && ( -
- -
- - {issue.link_count} -
-
-
- )} - {displayProperties?.attachment_count && issue.attachment_count > 0 && ( -
- -
- - {issue.attachment_count} -
-
-
- )} - {/* {type && !isNotAllowed && ( - - -
- - Edit issue -
-
- {type !== "issue" && removeIssue && ( - -
- - Remove from {type} -
-
- )} - handleDeleteIssue(issue)}> -
- - Delete issue -
-
- -
- - Copy issue link -
-
-
- )} */} -
-
- -
- ); -}); diff --git a/web/components/issue-layouts/list/list.tsx b/web/components/issue-layouts/list/list.tsx deleted file mode 100644 index f06c6234d..000000000 --- a/web/components/issue-layouts/list/list.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import React, { FC } from "react"; -import { IIssue } from "types"; -import { IssueListItem } from "./item"; -import { observer } from "mobx-react-lite"; - -export interface IIssueListView { - issues: IIssue[] | null; - groupId: string; -} - -export const IssueListView: FC = observer((props) => { - const { issues = [], groupId } = props; - return
{issues && issues.map((issue) => )}
; -}); diff --git a/web/components/issue-layouts/list/root.tsx b/web/components/issue-layouts/list/root.tsx deleted file mode 100644 index 389c13fa1..000000000 --- a/web/components/issue-layouts/list/root.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import React from "react"; -import { Disclosure } from "@headlessui/react"; -import { observer } from "mobx-react-lite"; -// mobx store -import { useMobxStore } from "lib/mobx/store-provider"; -import { RootStore } from "store/root"; -// components -import { IssueListView } from "./list"; -import { IssueListGroupHeader } from "./group-header"; - -export const IssueListViewRoot = observer(() => { - const { issueView: issueViewStore, issueFilters: issueFilterStore }: RootStore = useMobxStore(); - console.log("issueViewStore", issueViewStore); - console.log("userFilters", issueFilterStore.userFilters); - console.log("issueFilterStore", issueFilterStore); - - return ( -
- {issueViewStore.loader || issueViewStore?.getIssues === null ? ( -
Loading...
- ) : ( - <> - {Object.keys(issueViewStore?.getIssues).map((groupId: any) => ( - - {({ open }) => ( - <> - - - - - - - - )} - - ))} - - )} -
- ); -}); diff --git a/web/components/issue-layouts/properties/index.ts b/web/components/issue-layouts/properties/index.ts deleted file mode 100644 index 3289b3237..000000000 --- a/web/components/issue-layouts/properties/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./priority-select"; diff --git a/web/components/issue-layouts/properties/priority-select.tsx b/web/components/issue-layouts/properties/priority-select.tsx deleted file mode 100644 index a914ed38a..000000000 --- a/web/components/issue-layouts/properties/priority-select.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import { FC, Fragment, useState } from "react"; -import { Listbox, Transition } from "@headlessui/react"; -import { CheckIcon, ChevronUpDownIcon } from "@heroicons/react/20/solid"; -import { useMobxStore } from "lib/mobx/store-provider"; -import { IIssue } from "types"; -import { observer } from "mobx-react-lite"; - -export interface IIssuePrioritySelect { - issue: IIssue; - groupId: string; -} - -export const IssuePrioritySelect: FC = observer((props) => { - const { issue, groupId } = props; - - const { issueView: issueViewStore, issueFilters: issueFilterStore } = useMobxStore(); - const priorityList = issueFilterStore.issueRenderFilters.priority; - - const selected = priorityList.find((p) => p.key === issue.priority); - - const changePriority = (selectedPriority: any) => { - issueViewStore.updateIssues(groupId, issue.id, { priority: selectedPriority.key }); - }; - - return ( - -
- - {selected?.title || "None"} - - - - {priorityList.map((priority) => ( - - `relative cursor-default select-none py-2 pl-10 pr-4 ${ - active ? "bg-amber-100 text-amber-900" : "text-gray-900" - }` - } - value={priority} - > - {({ selected }) => ( - <> - - {priority.title} - - {selected ? ( - - - ) : null} - - )} - - ))} - - -
-
- ); -}); diff --git a/web/components/issue-layouts/root.tsx b/web/components/issue-layouts/root.tsx deleted file mode 100644 index 90e1394d4..000000000 --- a/web/components/issue-layouts/root.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import React from "react"; -// components -import { LayoutSelection } from "../issues/issue-layouts/filters/header/layout-selection"; -import { IssueDropdown } from "../issues/issue-layouts/filters/header/helpers/dropdown"; -import { FilterSelection } from "../issues/issue-layouts/filters/header/filters/filters-selection"; -import { DisplayFiltersSelection } from "../issues/issue-layouts/filters/header/display-filters"; - -import { FilterPreview } from "./filters-preview"; - -import { IssueListViewRoot } from "./list/root"; -import { IssueKanBanViewRoot } from "./kanban"; -import { IssueCalendarViewRoot } from "./calendar"; -import { IssueSpreadsheetViewRoot } from "./spreadsheet"; -import { IssueGanttViewRoot } from "./gantt"; -// mobx -import { observer } from "mobx-react-lite"; -// mobx store -import { useMobxStore } from "lib/mobx/store-provider"; -import { RootStore } from "store/root"; - -export const IssuesRoot = observer(() => { - const { - workspace: workspaceStore, - project: projectStore, - issue: issueStore, - issueFilter: issueFilterStore, - }: RootStore = useMobxStore(); - - // console.log("---"); - // console.log("--- workspace store"); - // console.log("workspaces", workspaceStore?.workspaces); - // console.log("workspace id", workspaceStore?.workspaceId); - // console.log("current workspace", workspaceStore?.currentWorkspace); - // console.log("workspace by id", workspaceStore?.workspaceById("plane")); - // console.log("workspace labels", workspaceStore?.workspaceLabels); - // console.log("workspace label by id", workspaceStore?.workspaceLabelById("1fe1031b-8986-4e6a-86cc-0d2fe3ac272f")); - - // console.log("--- project store"); - // console.log("workspace projects", projectStore?.workspaceProjects); - // console.log("project id", projectStore?.projectId); - // console.log("project state by groups", projectStore?.projectStatesByGroups); - // console.log("project states", projectStore?.projectStates); - // console.log("project labels", projectStore?.projectLabels); - // console.log("project members", projectStore?.projectMembers); - // projectStore?.projectStates && - // console.log("project state by id", projectStore?.projectStateById(projectStore?.projectStates?.[0]?.id)); - // projectStore?.projectLabels && - // console.log("project label by id", projectStore?.projectLabelById(projectStore?.projectLabels?.[0]?.id)); - // projectStore?.projectMembers && - // console.log("project member by id", projectStore?.projectMemberById(projectStore?.projectMembers?.[0]?.id)); - - // console.log("--- issue filter store"); - // console.log("issues filters", issueFilterStore?.issueFilters); - - // console.log("--- issue store"); - // console.log("issues", issueStore?.issues); - // console.log("---"); - - return ( -
-
-
-
-
Filter Header
-
-
- {/* - - - - - - */} -
-
-
-
- -
-
- {issueFilterStore?.userDisplayFilters.layout === "list" && } - {issueFilterStore?.userDisplayFilters.layout === "kanban" && } - {issueFilterStore?.userDisplayFilters.layout === "calendar" && } - {issueFilterStore?.userDisplayFilters.layout === "spreadsheet" && } - {issueFilterStore?.userDisplayFilters.layout === "gantt_chart" && } -
-
- ); -}); diff --git a/web/components/issue-layouts/spreadsheet/index.tsx b/web/components/issue-layouts/spreadsheet/index.tsx deleted file mode 100644 index 02313458d..000000000 --- a/web/components/issue-layouts/spreadsheet/index.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import React from "react"; - -export const IssueSpreadsheetViewRoot = () => { - console.log(); - return
IssueSpreadsheetViewRoot
; -}; diff --git a/web/components/issues/issue-layouts/calendar/index.ts b/web/components/issues/issue-layouts/calendar/index.ts index ed7cebc45..be4383954 100644 --- a/web/components/issues/issue-layouts/calendar/index.ts +++ b/web/components/issues/issue-layouts/calendar/index.ts @@ -1,12 +1,9 @@ export * from "./dropdowns"; +export * from "./roots"; export * from "./calendar"; -export * from "./cycle-root"; export * from "./types.d"; export * from "./day-tile"; export * from "./header"; export * from "./issue-blocks"; -export * from "./module-root"; -export * from "./project-view-root"; -export * from "./root"; export * from "./week-days"; export * from "./week-header"; diff --git a/web/components/issues/issue-layouts/calendar/cycle-root.tsx b/web/components/issues/issue-layouts/calendar/roots/cycle-root.tsx similarity index 100% rename from web/components/issues/issue-layouts/calendar/cycle-root.tsx rename to web/components/issues/issue-layouts/calendar/roots/cycle-root.tsx diff --git a/web/components/issues/issue-layouts/calendar/roots/index.ts b/web/components/issues/issue-layouts/calendar/roots/index.ts new file mode 100644 index 000000000..19de04806 --- /dev/null +++ b/web/components/issues/issue-layouts/calendar/roots/index.ts @@ -0,0 +1,4 @@ +export * from "./cycle-root"; +export * from "./module-root"; +export * from "./project-view-root"; +export * from "./project-root"; diff --git a/web/components/issues/issue-layouts/calendar/module-root.tsx b/web/components/issues/issue-layouts/calendar/roots/module-root.tsx similarity index 100% rename from web/components/issues/issue-layouts/calendar/module-root.tsx rename to web/components/issues/issue-layouts/calendar/roots/module-root.tsx diff --git a/web/components/issues/issue-layouts/calendar/root.tsx b/web/components/issues/issue-layouts/calendar/roots/project-root.tsx similarity index 100% rename from web/components/issues/issue-layouts/calendar/root.tsx rename to web/components/issues/issue-layouts/calendar/roots/project-root.tsx diff --git a/web/components/issues/issue-layouts/calendar/project-view-root.tsx b/web/components/issues/issue-layouts/calendar/roots/project-view-root.tsx similarity index 100% rename from web/components/issues/issue-layouts/calendar/project-view-root.tsx rename to web/components/issues/issue-layouts/calendar/roots/project-view-root.tsx diff --git a/web/components/issues/issue-layouts/filters/applied-filters/index.ts b/web/components/issues/issue-layouts/filters/applied-filters/index.ts index d889fa25e..a9feecfdf 100644 --- a/web/components/issues/issue-layouts/filters/applied-filters/index.ts +++ b/web/components/issues/issue-layouts/filters/applied-filters/index.ts @@ -1,13 +1,9 @@ -export * from "./cycle-root"; +export * from "./roots"; export * from "./date"; export * from "./filters-list"; -export * from "./global-views-root"; export * from "./label"; export * from "./members"; -export * from "./module-root"; export * from "./priority"; -export * from "./project-view-root"; export * from "./project"; -export * from "./root"; export * from "./state"; export * from "./state-group"; diff --git a/web/components/issues/issue-layouts/filters/applied-filters/cycle-root.tsx b/web/components/issues/issue-layouts/filters/applied-filters/roots/cycle-root.tsx similarity index 100% rename from web/components/issues/issue-layouts/filters/applied-filters/cycle-root.tsx rename to web/components/issues/issue-layouts/filters/applied-filters/roots/cycle-root.tsx diff --git a/web/components/issues/issue-layouts/filters/applied-filters/global-views-root.tsx b/web/components/issues/issue-layouts/filters/applied-filters/roots/global-view-root.tsx similarity index 100% rename from web/components/issues/issue-layouts/filters/applied-filters/global-views-root.tsx rename to web/components/issues/issue-layouts/filters/applied-filters/roots/global-view-root.tsx diff --git a/web/components/issues/issue-layouts/filters/applied-filters/roots/index.ts b/web/components/issues/issue-layouts/filters/applied-filters/roots/index.ts new file mode 100644 index 000000000..c7280e470 --- /dev/null +++ b/web/components/issues/issue-layouts/filters/applied-filters/roots/index.ts @@ -0,0 +1,5 @@ +export * from "./cycle-root"; +export * from "./global-view-root"; +export * from "./module-root"; +export * from "./project-view-root"; +export * from "./project-root"; diff --git a/web/components/issues/issue-layouts/filters/applied-filters/module-root.tsx b/web/components/issues/issue-layouts/filters/applied-filters/roots/module-root.tsx similarity index 100% rename from web/components/issues/issue-layouts/filters/applied-filters/module-root.tsx rename to web/components/issues/issue-layouts/filters/applied-filters/roots/module-root.tsx diff --git a/web/components/issues/issue-layouts/filters/applied-filters/root.tsx b/web/components/issues/issue-layouts/filters/applied-filters/roots/project-root.tsx similarity index 97% rename from web/components/issues/issue-layouts/filters/applied-filters/root.tsx rename to web/components/issues/issue-layouts/filters/applied-filters/roots/project-root.tsx index ab6e41208..505649bce 100644 --- a/web/components/issues/issue-layouts/filters/applied-filters/root.tsx +++ b/web/components/issues/issue-layouts/filters/applied-filters/roots/project-root.tsx @@ -8,7 +8,7 @@ import { AppliedFiltersList } from "components/issues"; // types import { IIssueFilterOptions } from "types"; -export const AppliedFiltersRoot: React.FC = observer(() => { +export const ProjectAppliedFiltersRoot: React.FC = observer(() => { const router = useRouter(); const { workspaceSlug, projectId } = router.query; diff --git a/web/components/issues/issue-layouts/filters/applied-filters/project-view-root.tsx b/web/components/issues/issue-layouts/filters/applied-filters/roots/project-view-root.tsx similarity index 100% rename from web/components/issues/issue-layouts/filters/applied-filters/project-view-root.tsx rename to web/components/issues/issue-layouts/filters/applied-filters/roots/project-view-root.tsx diff --git a/web/components/issues/issue-layouts/filters/header/display-filters/display-filters-selection.tsx b/web/components/issues/issue-layouts/filters/header/display-filters/display-filters-selection.tsx index 3a18e7cc4..6a1dd8bc1 100644 --- a/web/components/issues/issue-layouts/filters/header/display-filters/display-filters-selection.tsx +++ b/web/components/issues/issue-layouts/filters/header/display-filters/display-filters-selection.tsx @@ -87,6 +87,7 @@ export const DisplayFiltersSelection: React.FC = observer((props) => { order_by: val, }) } + orderByOptions={layoutDisplayFiltersOptions?.display_filters.order_by ?? []} />
)} diff --git a/web/components/issues/issue-layouts/filters/header/display-filters/order-by.tsx b/web/components/issues/issue-layouts/filters/header/display-filters/order-by.tsx index 0387e9abb..18920c514 100644 --- a/web/components/issues/issue-layouts/filters/header/display-filters/order-by.tsx +++ b/web/components/issues/issue-layouts/filters/header/display-filters/order-by.tsx @@ -11,10 +11,11 @@ import { ISSUE_ORDER_BY_OPTIONS } from "constants/issue"; type Props = { selectedOrderBy: TIssueOrderByOptions | undefined; handleUpdate: (val: TIssueOrderByOptions) => void; + orderByOptions: TIssueOrderByOptions[]; }; export const FilterOrderBy: React.FC = observer((props) => { - const { selectedOrderBy, handleUpdate } = props; + const { selectedOrderBy, handleUpdate, orderByOptions } = props; const [previewEnabled, setPreviewEnabled] = useState(true); @@ -27,7 +28,7 @@ export const FilterOrderBy: React.FC = observer((props) => { /> {previewEnabled && (
- {ISSUE_ORDER_BY_OPTIONS.map((orderBy) => ( + {ISSUE_ORDER_BY_OPTIONS.filter((option) => orderByOptions.includes(option.key)).map((orderBy) => ( = (props) => { }); return ( - + {({ open }) => { if (open) { } diff --git a/web/components/issues/issue-layouts/index.ts b/web/components/issues/issue-layouts/index.ts index 7dfba5d76..e9c11aed8 100644 --- a/web/components/issues/issue-layouts/index.ts +++ b/web/components/issues/issue-layouts/index.ts @@ -8,14 +8,4 @@ export * from "./gantt"; export * from "./kanban"; export * from "./spreadsheet"; -// global view layout -export * from "./global-view-all-layouts"; - -// cycle root layout -export * from "./cycle-layout-root"; - -// module root layout -export * from "./module-all-layouts"; - -// project view layout -export * from "./project-view-all-layouts"; +export * from "./roots"; diff --git a/web/components/issues/issue-layouts/cycle-layout-root.tsx b/web/components/issues/issue-layouts/roots/cycle-layout-root.tsx similarity index 97% rename from web/components/issues/issue-layouts/cycle-layout-root.tsx rename to web/components/issues/issue-layouts/roots/cycle-layout-root.tsx index c7d602c4d..2be3abc56 100644 --- a/web/components/issues/issue-layouts/cycle-layout-root.tsx +++ b/web/components/issues/issue-layouts/roots/cycle-layout-root.tsx @@ -52,9 +52,9 @@ export const CycleLayoutRoot: React.FC = observer(() => { const activeLayout = issueFilterStore.userDisplayFilters.layout; return ( -
+
-
+
{activeLayout === "list" ? ( ) : activeLayout === "kanban" ? ( diff --git a/web/components/issues/issue-layouts/global-view-all-layouts.tsx b/web/components/issues/issue-layouts/roots/global-view-layout-root.tsx similarity index 95% rename from web/components/issues/issue-layouts/global-view-all-layouts.tsx rename to web/components/issues/issue-layouts/roots/global-view-layout-root.tsx index 59f0a030b..ff72eae3c 100644 --- a/web/components/issues/issue-layouts/global-view-all-layouts.tsx +++ b/web/components/issues/issue-layouts/roots/global-view-layout-root.tsx @@ -17,7 +17,7 @@ type Props = { type?: TStaticViewTypes; }; -export const GlobalViewsAllLayouts: React.FC = observer((props) => { +export const GlobalViewLayoutRoot: React.FC = observer((props) => { const { type } = props; const router = useRouter(); @@ -70,9 +70,9 @@ export const GlobalViewsAllLayouts: React.FC = observer((props) => { : undefined; return ( -
+
-
+
{ +export const ModuleLayoutRoot: React.FC = observer(() => { const router = useRouter(); const { workspaceSlug, projectId, moduleId } = router.query as { workspaceSlug: string; @@ -50,9 +50,9 @@ export const ModuleAllLayouts: React.FC = observer(() => { const activeLayout = issueFilterStore.userDisplayFilters.layout; return ( -
+
-
+
{activeLayout === "list" ? ( ) : activeLayout === "kanban" ? ( diff --git a/web/components/core/views/all-views.tsx b/web/components/issues/issue-layouts/roots/project-layout-root.tsx similarity index 90% rename from web/components/core/views/all-views.tsx rename to web/components/issues/issue-layouts/roots/project-layout-root.tsx index 04e501aae..576c6f9f2 100644 --- a/web/components/core/views/all-views.tsx +++ b/web/components/issues/issue-layouts/roots/project-layout-root.tsx @@ -7,15 +7,15 @@ import useSWR from "swr"; import { useMobxStore } from "lib/mobx/store-provider"; // components import { - AppliedFiltersRoot, ListLayout, CalendarLayout, GanttLayout, KanBanLayout, + ProjectAppliedFiltersRoot, SpreadsheetLayout, } from "components/issues"; -export const AllViews: React.FC = observer(() => { +export const ProjectLayoutRoot: React.FC = observer(() => { const router = useRouter(); const { workspaceSlug, projectId } = router.query as { workspaceSlug: string; @@ -46,9 +46,9 @@ export const AllViews: React.FC = observer(() => { const activeLayout = issueFilterStore.userDisplayFilters.layout; return ( -
- -
+
+ +
{activeLayout === "list" ? ( ) : activeLayout === "kanban" ? ( diff --git a/web/components/issues/issue-layouts/project-view-all-layouts.tsx b/web/components/issues/issue-layouts/roots/project-view-layout-root.tsx similarity index 95% rename from web/components/issues/issue-layouts/project-view-all-layouts.tsx rename to web/components/issues/issue-layouts/roots/project-view-layout-root.tsx index e524081ed..8ad7428a2 100644 --- a/web/components/issues/issue-layouts/project-view-all-layouts.tsx +++ b/web/components/issues/issue-layouts/roots/project-view-layout-root.tsx @@ -15,7 +15,7 @@ import { ProjectViewSpreadsheetLayout, } from "components/issues"; -export const ProjectViewAllLayouts: React.FC = observer(() => { +export const ProjectViewLayoutRoot: React.FC = observer(() => { const router = useRouter(); const { workspaceSlug, projectId, viewId } = router.query; @@ -52,9 +52,9 @@ export const ProjectViewAllLayouts: React.FC = observer(() => { const activeLayout = issueFilterStore.userDisplayFilters.layout; return ( -
+
-
+
{activeLayout === "list" ? ( ) : activeLayout === "kanban" ? ( diff --git a/web/components/modules/gantt-chart/index.ts b/web/components/modules/gantt-chart/index.ts index 301b9f840..72eb6bfc5 100644 --- a/web/components/modules/gantt-chart/index.ts +++ b/web/components/modules/gantt-chart/index.ts @@ -1,3 +1,2 @@ export * from "./blocks"; -export * from "./module-issues-layout"; export * from "./modules-list-layout"; diff --git a/web/components/modules/gantt-chart/module-issues-layout.tsx b/web/components/modules/gantt-chart/module-issues-layout.tsx deleted file mode 100644 index cfac41983..000000000 --- a/web/components/modules/gantt-chart/module-issues-layout.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import { useRouter } from "next/router"; - -// hooks -import useIssuesView from "hooks/use-issues-view"; -import useUser from "hooks/use-user"; -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"; - -type Props = { disableUserActions: boolean }; - -export const ModuleIssuesGanttChartView: React.FC = ({ disableUserActions }) => { - const router = useRouter(); - const { workspaceSlug, projectId, moduleId } = router.query; - - const { displayFilters } = useIssuesView(); - - const { user } = useUser(); - const { projectDetails } = useProjectDetails(); - - const isAllowed = projectDetails?.member_role === 20 || projectDetails?.member_role === 15; - - return ( - <> - -
- {}} - SidebarBlockRender={IssueGanttSidebarBlock} - BlockRender={IssueGanttBlock} - enableBlockLeftResize={isAllowed} - enableBlockRightResize={isAllowed} - enableBlockMove={isAllowed} - enableReorder={displayFilters.order_by === "sort_order" && isAllowed} - bottomSpacing - /> -
- - ); -}; diff --git a/web/components/search-listbox/index.tsx b/web/components/search-listbox/index.tsx deleted file mode 100644 index bd60deaab..000000000 --- a/web/components/search-listbox/index.tsx +++ /dev/null @@ -1,165 +0,0 @@ -import React, { useState } from "react"; - -import { useRouter } from "next/router"; - -import useSWR from "swr"; - -// headless ui -import { Transition, Combobox } from "@headlessui/react"; -// services -import workspaceService from "services/workspace.service"; -// types -import type { Props } from "./types"; -// fetch-keys -import { WORKSPACE_MEMBERS } from "constants/fetch-keys"; - -const SearchListbox: React.FC = ({ - title, - options, - onChange, - value, - multiple: canSelectMultiple, - icon, - optionsFontsize, - buttonClassName, - optionsClassName, - assignee = false, -}) => { - const [query, setQuery] = useState(""); - - const router = useRouter(); - const { workspaceSlug } = router.query; - - const filteredOptions = - query === "" - ? options - : options?.filter((option) => option.display.toLowerCase().includes(query.toLowerCase())); - - const props: any = { - value, - onChange, - }; - - if (canSelectMultiple) { - props.value = props.value ?? []; - props.onChange = (value: string[]) => { - onChange(value); - }; - props.multiple = true; - } - - const { data: people } = useSWR( - workspaceSlug ? WORKSPACE_MEMBERS(workspaceSlug as string) : null, - workspaceSlug ? () => workspaceService.workspaceMembers(workspaceSlug as string) : null - ); - - const userAvatar = (userId: string) => { - const user = people?.find((p) => p.member.id === userId); - - if (!user) return; - - if (user.member.avatar && user.member.avatar !== "") { - return ( -
- avatar -
- ); - } else - return ( -
- {user.member.display_name.charAt(0)} -
- ); - }; - - return ( - - {({ open }: any) => ( - <> - {title} - - {icon ?? null} - - {Array.isArray(value) - ? value - .map((v) => options?.find((option) => option.value === v)?.display) - .join(", ") || title - : options?.find((option) => option.value === value)?.display || title} - - - - - - setQuery(event.target.value)} - placeholder="Search" - displayValue={(assigned: any) => assigned?.name} - /> -
- {filteredOptions ? ( - filteredOptions.length > 0 ? ( - filteredOptions.map((option) => ( - - `${ - active ? "bg-indigo-50" : "" - } flex cursor-pointer select-none items-center gap-2 truncate p-2 text-custom-text-100` - } - value={option.value} - > - {assignee && userAvatar(option.value)} - {option.element ?? option.display} - - )) - ) : ( -

- No {title.toLowerCase()} found -

- ) - ) : ( -

Loading...

- )} -
-
-
- - )} -
- ); -}; - -export default SearchListbox; diff --git a/web/components/search-listbox/types.d.ts b/web/components/search-listbox/types.d.ts deleted file mode 100644 index c9ffa6af3..000000000 --- a/web/components/search-listbox/types.d.ts +++ /dev/null @@ -1,15 +0,0 @@ -type Value = any; - -export type Props = { - title: string; - multiple?: boolean; - options?: Array<{ display: string; element?: JSX.Element; value: Value }>; - onChange: (value: Value) => void; - value: Value; - icon?: JSX.Element; - buttonClassName?: string; - optionsClassName?: string; - width?: "xs" | "sm" | "md" | "lg" | "xl" | "2xl"; - optionsFontsize?: "sm" | "md" | "lg" | "xl" | "2xl"; - assignee?: boolean; -}; diff --git a/web/components/views/gantt-chart.tsx b/web/components/views/gantt-chart.tsx deleted file mode 100644 index e79bdeca6..000000000 --- a/web/components/views/gantt-chart.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { useRouter } from "next/router"; - -// hooks -import useGanttChartViewIssues from "hooks/gantt-chart/view-issues-view"; -import useUser from "hooks/use-user"; -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"; - -type Props = { disableUserActions: boolean }; - -export const ViewIssuesGanttChartView: React.FC = ({ disableUserActions }) => { - const router = useRouter(); - const { workspaceSlug, projectId, viewId } = router.query; - - const { user } = useUser(); - const { projectDetails } = useProjectDetails(); - - const { ganttIssues, mutateGanttIssues } = useGanttChartViewIssues( - workspaceSlug as string, - projectId as string, - viewId as string - ); - - const isAllowed = projectDetails?.member_role === 20 || projectDetails?.member_role === 15; - - return ( - <> - mutateGanttIssues()} - projectId={projectId?.toString() ?? ""} - workspaceSlug={workspaceSlug?.toString() ?? ""} - readOnly={disableUserActions} - /> -
- {}} - SidebarBlockRender={IssueGanttSidebarBlock} - BlockRender={IssueGanttBlock} - enableBlockLeftResize={isAllowed} - enableBlockRightResize={isAllowed} - enableBlockMove={isAllowed} - enableReorder={isAllowed} - /> -
- - ); -}; diff --git a/web/components/views/index.ts b/web/components/views/index.ts index 0b917e3c9..b4e2364a9 100644 --- a/web/components/views/index.ts +++ b/web/components/views/index.ts @@ -1,6 +1,5 @@ export * from "./delete-view-modal"; export * from "./form"; -export * from "./gantt-chart"; export * from "./modal"; export * from "./select-filters"; export * from "./view-list-item"; diff --git a/web/components/workspace/views/header.tsx b/web/components/workspace/views/header.tsx index 8cfd79f82..6c782e4c7 100644 --- a/web/components/workspace/views/header.tsx +++ b/web/components/workspace/views/header.tsx @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; import { useRouter } from "next/router"; import Link from "next/link"; import { observer } from "mobx-react-lite"; @@ -26,12 +26,20 @@ export const GlobalViewsHeader: React.FC = observer(() => { workspaceSlug ? () => globalViewsStore.fetchAllGlobalViews(workspaceSlug.toString()) : null ); - const isTabSelected = (tabKey: string) => router.pathname.includes(tabKey); + // bring the active view to the centre of the header + useEffect(() => { + if (!globalViewId) return; + const activeTabElement = document.querySelector(`#global-view-${globalViewId.toString()}`); + + if (activeTabElement) activeTabElement.scrollIntoView({ behavior: "smooth", inline: "center" }); + }, [globalViewId]); + + const isTabSelected = (tabKey: string) => router.pathname.includes(tabKey); return ( <> setCreateViewModal(false)} /> -
+
{DEFAULT_GLOBAL_VIEWS_LIST.map((tab) => ( { {globalViewsStore.globalViewsList?.map((view) => ( {