From f420006172821d1ee3edbaf8d052efdaa2a1815a Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal Date: Thu, 12 Oct 2023 18:27:02 +0530 Subject: [PATCH 1/4] refactor: folder structure --- .../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 ------------------ web/components/core/views/index.ts | 2 - web/components/headers/global-issues.tsx | 2 +- .../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 .../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/workspace/views/header.tsx | 17 +- 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 - 41 files changed, 76 insertions(+), 1052 deletions(-) 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 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/pages/calender/index.tsx 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 931bd3b49a8..00000000000 --- 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 6ded660bd61..00000000000 --- 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 75d8a3a1eff..00000000000 --- 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 51b6c518b42..00000000000 --- 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 a67ca762b11..00000000000 --- 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 5cdd3afe959..00000000000 --- 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/index.ts b/web/components/core/views/index.ts index 13da90d8e68..a956ceda86f 100644 --- a/web/components/core/views/index.ts +++ b/web/components/core/views/index.ts @@ -1,8 +1,6 @@ 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/headers/global-issues.tsx b/web/components/headers/global-issues.tsx index 5e136209e2f..95ba2a182ec 100644 --- a/web/components/headers/global-issues.tsx +++ b/web/components/headers/global-issues.tsx @@ -98,7 +98,7 @@ export const GlobalIssuesHeader: React.FC = observer((props) => { return ( <> setCreateViewModal(false)} /> -
+
{activeLayout === "spreadsheet" && } Workspace {activeLayout === "spreadsheet" ? "Issues" : "Views"} diff --git a/web/components/issues/issue-layouts/calendar/index.ts b/web/components/issues/issue-layouts/calendar/index.ts index ed7cebc452d..be438395470 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 00000000000..19de048067f --- /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 d889fa25ee9..a9feecfdf02 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 00000000000..c7280e4700b --- /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 ab6e41208cc..505649bce30 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/helpers/dropdown.tsx b/web/components/issues/issue-layouts/filters/header/helpers/dropdown.tsx index f1d56ac1dad..105a0732412 100644 --- a/web/components/issues/issue-layouts/filters/header/helpers/dropdown.tsx +++ b/web/components/issues/issue-layouts/filters/header/helpers/dropdown.tsx @@ -23,7 +23,7 @@ export const FiltersDropdown: React.FC = (props) => { }); return ( - + {({ open }) => { if (open) { } diff --git a/web/components/issues/issue-layouts/index.ts b/web/components/issues/issue-layouts/index.ts index 7dfba5d7617..e9c11aed85e 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 c7d602c4d07..2be3abc563d 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 59f0a030b7b..ff72eae3ccd 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 04e501aae1e..576c6f9f2b4 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 e524081ede7..8ad7428a296 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/workspace/views/header.tsx b/web/components/workspace/views/header.tsx index 8cfd79f8254..6c782e4c782 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) => ( {
)} 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 0387e9abb59..18920c514d9 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) => ( Date: Fri, 13 Oct 2023 00:18:08 +0530 Subject: [PATCH 3/4] refactor: remove old layout components --- .../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 ------------------ .../core/views/gantt-chart-view/index.tsx | 30 - .../inline-create-issue-form.tsx | 62 --- web/components/core/views/index.ts | 3 - .../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 ------------ .../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 - 41 files changed, 3711 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/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/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 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 4c42ae166b3..00000000000 --- 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 93e8f4db7e5..00000000000 --- 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 a5a6ee497f1..00000000000 --- 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 1d6103d19df..00000000000 --- 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 6d583e772b3..00000000000 --- 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 6d7528fa6eb..00000000000 --- 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/gantt-chart-view/index.tsx b/web/components/core/views/gantt-chart-view/index.tsx deleted file mode 100644 index 2cd10f95f3f..00000000000 --- 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 785eb3c5a14..00000000000 --- 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 a956ceda86f..5a3edcd200f 100644 --- a/web/components/core/views/index.ts +++ b/web/components/core/views/index.ts @@ -1,6 +1,3 @@ -export * from "./board-view"; -export * from "./gantt-chart-view"; -export * from "./list-view"; export * from "./spreadsheet-view"; 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 58025b32807..00000000000 --- 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 4d59be1654d..00000000000 --- 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 b61420fc82a..00000000000 --- 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 6bf107443f3..00000000000 --- 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 83d52fd00b7..00000000000 --- 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/issue-layouts/calendar/index.tsx b/web/components/issue-layouts/calendar/index.tsx deleted file mode 100644 index c3c4147f9b0..00000000000 --- a/web/components/issue-layouts/calendar/index.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import React from "react"; - -export const IssueCalendarViewRoot = () => { - console.log(); - return
IssueCalendarViewRoot
; -}; diff --git a/web/components/issue-layouts/filters-preview/assignees.tsx b/web/components/issue-layouts/filters-preview/assignees.tsx deleted file mode 100644 index be91064a965..00000000000 --- a/web/components/issue-layouts/filters-preview/assignees.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import React from "react"; -// components -import { FilterPreviewHeader } from "./helpers/header"; -import { FilterPreviewContent } from "./helpers/content"; -import { FilterPreviewClear } from "./helpers/clear"; -// mobx react lite -import { observer } from "mobx-react-lite"; -// mobx store -import { useMobxStore } from "lib/mobx/store-provider"; -import { RootStore } from "store/root"; - -export const MemberIcons = ({ display_name, avatar }: { display_name: string; avatar: string | null }) => ( -
- {avatar ? ( - {display_name - ) : ( -
- {(display_name ?? "U")[0]} -
- )} -
-); - -export const FilterAssignees = observer(() => { - const store: RootStore = useMobxStore(); - const { issueFilters: issueFilterStore } = store; - - const handleFilter = (key: string, value: string) => { - let _value = - issueFilterStore?.userFilters?.filters?.[key] != null && - issueFilterStore?.userFilters?.filters?.[key].filter((p: string) => p != value); - _value = _value && _value.length > 0 ? _value : null; - issueFilterStore.handleUserFilter("filters", key, _value); - }; - - const clearFilter = () => { - issueFilterStore.handleUserFilter("filters", "assignees", null); - }; - - return ( - <> - {issueFilterStore?.userFilters?.filters?.assignees != null && ( -
-
- -
-
- {issueFilterStore?.projectMembers && - issueFilterStore?.projectMembers.length > 0 && - issueFilterStore?.projectMembers.map( - (_member) => - issueFilterStore?.userFilters?.filters?.assignees != null && - issueFilterStore?.userFilters?.filters?.assignees.includes(_member?.member?.id) && ( - } - title={`${_member?.member?.display_name}`} - onClick={() => handleFilter("assignees", _member?.member?.id)} - className="border border-custom-border-100 bg-custom-background-100" - /> - ) - )} -
- -
-
-
- )} - - ); -}); diff --git a/web/components/issue-layouts/filters-preview/created-by.tsx b/web/components/issue-layouts/filters-preview/created-by.tsx deleted file mode 100644 index c32b7fcb61b..00000000000 --- a/web/components/issue-layouts/filters-preview/created-by.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import React from "react"; -// components -import { MemberIcons } from "./assignees"; -import { FilterPreviewHeader } from "./helpers/header"; -import { FilterPreviewContent } from "./helpers/content"; -import { FilterPreviewClear } from "./helpers/clear"; -// mobx react lite -import { observer } from "mobx-react-lite"; -// mobx store -import { useMobxStore } from "lib/mobx/store-provider"; -import { RootStore } from "store/root"; - -export const FilterCreatedBy = observer(() => { - const store: RootStore = useMobxStore(); - const { issueFilters: issueFilterStore } = store; - - const handleFilter = (key: string, value: string) => { - let _value = - issueFilterStore?.userFilters?.filters?.[key] != null && - issueFilterStore?.userFilters?.filters?.[key].filter((p: string) => p != value); - _value = _value && _value.length > 0 ? _value : null; - issueFilterStore.handleUserFilter("filters", key, _value); - }; - - const clearFilter = () => { - issueFilterStore.handleUserFilter("filters", "created_by", null); - }; - - return ( - <> - {issueFilterStore?.userFilters?.filters?.created_by != null && ( -
-
- -
- -
- {issueFilterStore?.projectMembers && - issueFilterStore?.projectMembers.length > 0 && - issueFilterStore?.projectMembers.map( - (_member) => - issueFilterStore?.userFilters?.filters?.created_by != null && - issueFilterStore?.userFilters?.filters?.created_by.includes(_member?.member?.id) && ( - } - onClick={() => handleFilter("created_by", _member?.member?.id)} - className="border border-custom-border-100 bg-custom-background-100" - /> - ) - )} -
- -
-
-
- )} - - ); -}); diff --git a/web/components/issue-layouts/filters-preview/helpers/clear.tsx b/web/components/issue-layouts/filters-preview/helpers/clear.tsx deleted file mode 100644 index d2cc57a3781..00000000000 --- a/web/components/issue-layouts/filters-preview/helpers/clear.tsx +++ /dev/null @@ -1,17 +0,0 @@ -// lucide icons -import { X } from "lucide-react"; - -interface IFilterPreviewClear { - onClick?: () => void; -} - -export const FilterPreviewClear = ({ onClick }: IFilterPreviewClear) => ( -
{ - if (onClick) onClick(); - }} - > - -
-); diff --git a/web/components/issue-layouts/filters-preview/helpers/content.tsx b/web/components/issue-layouts/filters-preview/helpers/content.tsx deleted file mode 100644 index 4838c931995..00000000000 --- a/web/components/issue-layouts/filters-preview/helpers/content.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { FilterPreviewClear } from "./clear"; - -interface IFilterPreviewContent { - icon?: React.ReactNode; - title?: string; - onClick?: () => void; - className?: string; - style?: any; -} - -export const FilterPreviewContent = ({ icon, title, onClick, className, style }: IFilterPreviewContent) => ( -
-
{icon}
-
{title}
-
- { - if (onClick) onClick(); - }} - /> -
-
-); diff --git a/web/components/issue-layouts/filters-preview/helpers/header.tsx b/web/components/issue-layouts/filters-preview/helpers/header.tsx deleted file mode 100644 index 5fc9c9caae7..00000000000 --- a/web/components/issue-layouts/filters-preview/helpers/header.tsx +++ /dev/null @@ -1,12 +0,0 @@ -interface IFilterPreviewHeader { - title: string; -} - -export const FilterPreviewHeader = ({ title }: IFilterPreviewHeader) => { - console.log(); - return ( -
-
{title}
-
- ); -}; diff --git a/web/components/issue-layouts/filters-preview/index.tsx b/web/components/issue-layouts/filters-preview/index.tsx deleted file mode 100644 index 758dbc71cb7..00000000000 --- a/web/components/issue-layouts/filters-preview/index.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import React from "react"; -// components -import { FilterPriority } from "./priority"; -import { FilterState } from "./state"; -import { FilterStateGroup } from "./state-group"; -import { FilterAssignees } from "./assignees"; -import { FilterCreatedBy } from "./created-by"; -import { FilterLabels } from "./labels"; -import { FilterStartDate } from "./start-date"; -import { FilterTargetDate } from "./target-date"; -// mobx react lite -import { observer } from "mobx-react-lite"; -// mobx store -import { useMobxStore } from "lib/mobx/store-provider"; -import { RootStore } from "store/root"; -// default data -// import { issueFilterVisibilityData } from "store/helpers/issue-data"; - -export const FilterPreview = observer(() => { - const store: RootStore = useMobxStore(); - const { issueFilter: issueFilterStore } = store; - - const handleFilterSectionVisibility = (section_key: string) => { - // issueFilterStore?.issueView && - // issueFilterStore?.issueLayout && - // issueFilterVisibilityData[issueFilterStore?.issueView === "my_issues" ? "my_issues" : "issues"]?.filters?.[ - // issueFilterStore?.issueLayout - // ]?.includes(section_key); - }; - - const validateFiltersAvailability = - issueFilterStore?.userFilters?.filters != null && - Object.keys(issueFilterStore?.userFilters?.filters).length > 0 && - Object.keys(issueFilterStore?.userFilters?.filters) - .map((key) => issueFilterStore?.userFilters?.filters?.[key]?.length) - .filter((v) => v != undefined || v != null).length > 0; - - return ( - <> - {validateFiltersAvailability && ( -
- {/* priority */} - {handleFilterSectionVisibility("priority") && } - - {/* state group */} - {handleFilterSectionVisibility("state_group") && } - - {/* state */} - {handleFilterSectionVisibility("state") && } - - {/* assignees */} - {handleFilterSectionVisibility("assignees") && } - - {/* created_by */} - {handleFilterSectionVisibility("created_by") && } - - {/* labels */} - {handleFilterSectionVisibility("labels") && } - - {/* start_date */} - {handleFilterSectionVisibility("start_date") && } - - {/* due_date */} - {handleFilterSectionVisibility("due_date") && } -
- )} - - ); -}); diff --git a/web/components/issue-layouts/filters-preview/labels.tsx b/web/components/issue-layouts/filters-preview/labels.tsx deleted file mode 100644 index 2542b2ac82d..00000000000 --- a/web/components/issue-layouts/filters-preview/labels.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import React from "react"; -// components -import { FilterPreviewHeader } from "./helpers/header"; -import { FilterPreviewContent } from "./helpers/content"; -import { FilterPreviewClear } from "./helpers/clear"; -// mobx react lite -import { observer } from "mobx-react-lite"; -// mobx store -import { useMobxStore } from "lib/mobx/store-provider"; -import { RootStore } from "store/root"; - -const LabelIcons = ({ color }: { color: string }) => ( -
-
-
-); - -export const FilterLabels = observer(() => { - const store: RootStore = useMobxStore(); - const { issueFilters: issueFilterStore } = store; - - const stateStyles = (color: any) => ({ color: color, backgroundColor: `${color}20` }); - - const handleFilter = (key: string, value: string) => { - let _value = - issueFilterStore?.userFilters?.filters?.[key] != null && - issueFilterStore?.userFilters?.filters?.[key].filter((p: string) => p != value); - _value = _value && _value.length > 0 ? _value : null; - issueFilterStore.handleUserFilter("filters", key, _value); - }; - - const clearFilter = () => { - issueFilterStore.handleUserFilter("filters", "labels", null); - }; - - const handleLabels = - issueFilterStore.issueView && issueFilterStore.issueView === "my_issues" - ? issueFilterStore?.workspaceLabels - : issueFilterStore?.projectLabels; - - return ( - <> - {issueFilterStore?.userFilters?.filters?.labels != null && ( -
-
- -
- -
- {handleLabels && - handleLabels.length > 0 && - handleLabels.map( - (_label) => - issueFilterStore?.userFilters?.filters?.labels != null && - issueFilterStore?.userFilters?.filters?.labels.includes(_label?.id) && ( - handleFilter("labels", _label?.id)} - icon={} - title={_label.name} - style={stateStyles(_label.color)} - /> - ) - )} -
- -
-
-
- )} - - ); -}); diff --git a/web/components/issue-layouts/filters-preview/priority.tsx b/web/components/issue-layouts/filters-preview/priority.tsx deleted file mode 100644 index 44780d81f03..00000000000 --- a/web/components/issue-layouts/filters-preview/priority.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import React from "react"; -// lucide icons -import { AlertCircle, SignalHigh, SignalMedium, SignalLow, Ban } from "lucide-react"; -// components -import { FilterPreviewHeader } from "./helpers/header"; -import { FilterPreviewContent } from "./helpers/content"; -import { FilterPreviewClear } from "./helpers/clear"; -// mobx react lite -import { observer } from "mobx-react-lite"; -// mobx store -import { useMobxStore } from "lib/mobx/store-provider"; -import { RootStore } from "store/root"; - -const PriorityIcons = ({ priority }: { priority: string }) => { - if (priority === "urgent") return ; - if (priority === "high") return ; - if (priority === "medium") return ; - if (priority === "low") return ; - return ; -}; - -const classNamesStyling = (priority: string) => { - if (priority == "urgent") return "bg-red-500/20 text-red-500"; - if (priority == "high") return "bg-orange-500/20 text-orange-500 !-pt-[30px]"; - if (priority == "medium") return "bg-orange-500/20 text-orange-500 -pt-2"; - if (priority == "low") return "bg-green-500/20 text-green-500 -pt-2"; - return "bg-gray-500/10 text-gray-500"; -}; - -export const FilterPriority = observer(() => { - const store: RootStore = useMobxStore(); - const { issueFilters: issueFilterStore } = store; - - const handleFilter = (key: string, value: string) => { - let _value = - issueFilterStore?.userFilters?.filters?.[key] != null && - issueFilterStore?.userFilters?.filters?.[key].filter((p: string) => p != value); - _value = _value && _value.length > 0 ? _value : null; - issueFilterStore.handleUserFilter("filters", key, _value); - }; - - const clearFilter = () => { - issueFilterStore.handleUserFilter("filters", "priority", null); - }; - - return ( - <> - {issueFilterStore?.userFilters?.filters?.priority != null && ( -
-
- -
-
- {issueFilterStore?.issueRenderFilters?.priority && - issueFilterStore?.issueRenderFilters?.priority.length > 0 && - issueFilterStore?.issueRenderFilters?.priority.map( - (_priority) => - issueFilterStore?.userFilters?.filters?.priority != null && - issueFilterStore?.userFilters?.filters?.priority.includes(_priority?.key) && ( - } - title={_priority.title} - className={classNamesStyling(_priority?.key)} - onClick={() => handleFilter("priority", _priority?.key)} - /> - ) - )} -
- -
-
-
- )} - - ); -}); diff --git a/web/components/issue-layouts/filters-preview/start-date.tsx b/web/components/issue-layouts/filters-preview/start-date.tsx deleted file mode 100644 index 7967917621d..00000000000 --- a/web/components/issue-layouts/filters-preview/start-date.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import React from "react"; -// components -import { FilterPreviewHeader } from "./helpers/header"; -import { FilterPreviewContent } from "./helpers/content"; -import { FilterPreviewClear } from "./helpers/clear"; -// mobx react lite -import { observer } from "mobx-react-lite"; -// mobx store -import { useMobxStore } from "lib/mobx/store-provider"; -import { RootStore } from "store/root"; - -export const FilterStartDate = observer(() => { - const store: RootStore = useMobxStore(); - const { issueFilters: issueFilterStore } = store; - - const handleFilter = (key: string, value: string) => { - let _value = - issueFilterStore?.userFilters?.filters?.[key] != null && - issueFilterStore?.userFilters?.filters?.[key].filter((p: string) => p != value); - _value = _value && _value.length > 0 ? _value : null; - - issueFilterStore.handleUserFilter("filters", key, _value); - }; - - const clearFilter = () => { - issueFilterStore.handleUserFilter("filters", "start_date", null); - }; - - return ( - <> - {issueFilterStore?.userFilters?.filters?.start_date != null && ( -
-
- -
- -
- {issueFilterStore?.issueRenderFilters?.start_date && - issueFilterStore?.issueRenderFilters?.start_date.length > 0 && - issueFilterStore?.issueRenderFilters?.start_date.map((_startDate) => ( - handleFilter("start_date", _startDate?.key)} - /> - ))} -
-
- -
-
- )} - - ); -}); diff --git a/web/components/issue-layouts/filters-preview/state-group.tsx b/web/components/issue-layouts/filters-preview/state-group.tsx deleted file mode 100644 index cffaf6de8c7..00000000000 --- a/web/components/issue-layouts/filters-preview/state-group.tsx +++ /dev/null @@ -1,129 +0,0 @@ -import React from "react"; -import { - StateGroupBacklogIcon, - StateGroupCancelledIcon, - StateGroupCompletedIcon, - StateGroupStartedIcon, - StateGroupUnstartedIcon, -} from "components/icons"; -// components -import { FilterPreviewHeader } from "./helpers/header"; -import { FilterPreviewContent } from "./helpers/content"; -import { FilterPreviewClear } from "./helpers/clear"; -// mobx react lite -import { observer } from "mobx-react-lite"; -// mobx store -import { useMobxStore } from "lib/mobx/store-provider"; -import { RootStore } from "store/root"; -// constants -import { STATE_GROUP_COLORS } from "constants/state"; - -export const StateGroupIcons = ({ stateGroup, color = null }: { stateGroup: string; color?: string | null }) => { - if (stateGroup === "cancelled") - return ( - - ); - if (stateGroup === "completed") - return ( - - ); - if (stateGroup === "started") - return ( - - ); - if (stateGroup === "unstarted") - return ( - - ); - if (stateGroup === "backlog") - return ( -
- -
- ); - return <>; -}; - -export const stateStyles = (stateGroup: string, color: any) => { - if (stateGroup === "cancelled") { - return { - color: color ? color : STATE_GROUP_COLORS[stateGroup], - backgroundColor: `${color ? color : STATE_GROUP_COLORS[stateGroup]}20`, - }; - } - if (stateGroup === "completed") { - return { - color: color ? color : STATE_GROUP_COLORS[stateGroup], - backgroundColor: `${color ? color : STATE_GROUP_COLORS[stateGroup]}20`, - }; - } - if (stateGroup === "started") { - return { - color: color ? color : STATE_GROUP_COLORS[stateGroup], - backgroundColor: `${color ? color : STATE_GROUP_COLORS[stateGroup]}20`, - }; - } - if (stateGroup === "unstarted") { - return { - color: color ? color : STATE_GROUP_COLORS[stateGroup], - backgroundColor: `${color ? color : STATE_GROUP_COLORS[stateGroup]}20`, - }; - } - if (stateGroup === "backlog") { - return { - color: color ? color : STATE_GROUP_COLORS[stateGroup], - backgroundColor: `${color ? color : STATE_GROUP_COLORS[stateGroup]}20`, - }; - } -}; - -export const FilterStateGroup = observer(() => { - const store: RootStore = useMobxStore(); - const { issueFilters: issueFilterStore } = store; - - const handleFilter = (key: string, value: string) => { - let _value = - issueFilterStore?.userFilters?.filters?.[key] != null && - issueFilterStore?.userFilters?.filters?.[key].filter((p: string) => p != value); - _value = _value && _value.length > 0 ? _value : null; - issueFilterStore.handleUserFilter("filters", key, _value); - }; - - const clearFilter = () => { - issueFilterStore.handleUserFilter("filters", "state_group", null); - }; - - return ( - <> - {issueFilterStore?.userFilters?.filters?.state_group != null && ( -
-
- -
-
- {issueFilterStore?.issueRenderFilters?.state_group && - issueFilterStore?.issueRenderFilters?.state_group.length > 0 && - issueFilterStore?.issueRenderFilters?.state_group.map( - (_stateGroup) => - issueFilterStore?.userFilters?.filters?.state_group != null && - issueFilterStore?.userFilters?.filters?.state_group.includes(_stateGroup?.key) && ( - } - title={_stateGroup.title} - style={stateStyles(_stateGroup?.key, null)} - onClick={() => handleFilter("state_group", _stateGroup?.key)} - /> - ) - )} -
- -
-
-
- )} - - ); -}); diff --git a/web/components/issue-layouts/filters-preview/state.tsx b/web/components/issue-layouts/filters-preview/state.tsx deleted file mode 100644 index dd0652e78cb..00000000000 --- a/web/components/issue-layouts/filters-preview/state.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import React from "react"; -// components -import { StateGroupIcons, stateStyles } from "./state-group"; -import { FilterPreviewHeader } from "./helpers/header"; -import { FilterPreviewContent } from "./helpers/content"; -import { FilterPreviewClear } from "./helpers/clear"; -// mobx react lite -import { observer } from "mobx-react-lite"; -// mobx store -import { useMobxStore } from "lib/mobx/store-provider"; -import { RootStore } from "store/root"; -// store default data -import { stateGroups } from "store/helpers/issue-data"; - -export const FilterState = observer(() => { - const store: RootStore = useMobxStore(); - const { issueFilters: issueFilterStore } = store; - - const handleFilter = (key: string, value: string) => { - let _value = - issueFilterStore?.userFilters?.filters?.[key] != null && - issueFilterStore?.userFilters?.filters?.[key].filter((p: string) => p != value); - _value = _value && _value.length > 0 ? _value : null; - issueFilterStore.handleUserFilter("filters", key, _value); - }; - - const clearFilter = () => { - issueFilterStore.handleUserFilter("filters", "state", null); - }; - - return ( - <> - {issueFilterStore?.userFilters?.filters?.state != null && ( -
-
- -
-
- {stateGroups.map( - (_stateGroup) => - issueFilterStore?.projectStates && - issueFilterStore?.projectStates[_stateGroup?.key] && - issueFilterStore?.projectStates[_stateGroup?.key].length > 0 && - issueFilterStore?.projectStates[_stateGroup?.key].map( - (_state: any) => - issueFilterStore?.userFilters?.filters?.state != null && - issueFilterStore?.userFilters?.filters?.state.includes(_state?.id) && ( - } - title={_state?.name} - style={stateStyles(_state?.group, _state?.color)} - onClick={() => handleFilter("state", _state?.id)} - /> - ) - ) - )} -
- -
-
-
- )} - - ); -}); diff --git a/web/components/issue-layouts/filters-preview/target-date.tsx b/web/components/issue-layouts/filters-preview/target-date.tsx deleted file mode 100644 index 866f550b5e4..00000000000 --- a/web/components/issue-layouts/filters-preview/target-date.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import React from "react"; -// components -import { FilterPreviewHeader } from "./helpers/header"; -import { FilterPreviewContent } from "./helpers/content"; -import { FilterPreviewClear } from "./helpers/clear"; -// mobx react lite -import { observer } from "mobx-react-lite"; -// mobx store -import { useMobxStore } from "lib/mobx/store-provider"; -import { RootStore } from "store/root"; - -export const FilterTargetDate = observer(() => { - const store: RootStore = useMobxStore(); - const { issueFilters: issueFilterStore } = store; - - const handleFilter = (key: string, value: string) => { - let _value = - issueFilterStore?.userFilters?.filters?.[key] != null && - issueFilterStore?.userFilters?.filters?.[key].filter((p: string) => p != value); - _value = _value && _value.length > 0 ? _value : null; - - issueFilterStore.handleUserFilter("filters", key, _value); - }; - - const clearFilter = () => { - issueFilterStore.handleUserFilter("filters", "target_date", null); - }; - - return ( - <> - {issueFilterStore?.userFilters?.filters?.target_date != null && ( -
-
- -
- -
- {issueFilterStore?.issueRenderFilters?.due_date && - issueFilterStore?.issueRenderFilters?.due_date.length > 0 && - issueFilterStore?.issueRenderFilters?.due_date.map((_targetDate) => ( - handleFilter("target_date", _targetDate?.key)} - /> - ))} -
-
- -
-
- )} - - ); -}); diff --git a/web/components/issue-layouts/gantt/index.tsx b/web/components/issue-layouts/gantt/index.tsx deleted file mode 100644 index b00e20632f6..00000000000 --- a/web/components/issue-layouts/gantt/index.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import React from "react"; - -export const IssueGanttViewRoot = () => { - console.log(); - return
IssueGanttViewRoot
; -}; diff --git a/web/components/issue-layouts/index.ts b/web/components/issue-layouts/index.ts deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/web/components/issue-layouts/kanban/content.tsx b/web/components/issue-layouts/kanban/content.tsx deleted file mode 100644 index ad83c29602e..00000000000 --- a/web/components/issue-layouts/kanban/content.tsx +++ /dev/null @@ -1,45 +0,0 @@ -// react beautiful dnd -import { Draggable } from "react-beautiful-dnd"; - -interface IssueContentProps { - columnId: string; - issues: any; -} - -export const IssueContent = ({ columnId, issues }: IssueContentProps) => { - console.log(); - - return ( - <> - {issues && issues.length > 0 ? ( - <> - {issues.map((issue: any, index: any) => ( - - {(provided: any, snapshot: any) => ( -
-
-
ONE-{issue.sequence_id}
-
{issue.name}
-
Footer
-
-
- )} -
- ))} - - ) : ( -
No issues are available.
- )} - - ); -}; diff --git a/web/components/issue-layouts/kanban/header.tsx b/web/components/issue-layouts/kanban/header.tsx deleted file mode 100644 index c9a308a276b..00000000000 --- a/web/components/issue-layouts/kanban/header.tsx +++ /dev/null @@ -1,18 +0,0 @@ -// lucide icons -import { Plus } from "lucide-react"; - -export const IssueHeader = () => ( -
- {/* default layout */} -
I
-
Kanban Issue Heading
-
0
- -
- M -
-
- -
-
-); diff --git a/web/components/issue-layouts/kanban/index.tsx b/web/components/issue-layouts/kanban/index.tsx deleted file mode 100644 index 33b72c4b43a..00000000000 --- a/web/components/issue-layouts/kanban/index.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import React from "react"; -// react beautiful dnd -import { DragDropContext, Droppable } from "react-beautiful-dnd"; -// components -import { IssueHeader } from "./header"; -import { IssueContent } from "./content"; -// mobx -import { observer } from "mobx-react-lite"; -// mobx store -import { useMobxStore } from "lib/mobx/store-provider"; -import { RootStore } from "store/root"; - -export const IssueKanBanViewRoot = observer(() => { - const { issueView: issueViewStore, issueKanBanView: issueKanBanViewStore }: RootStore = useMobxStore(); - - const onDragEnd = (result: any) => { - if (!result) return; - - if ( - result.destination && - result.source && - result.destination.droppableId === result.source.droppableId && - result.destination.index === result.source.index - ) - return; - - issueKanBanViewStore?.handleDragDrop(result.source, result.destination); - }; - - return ( -
- {issueViewStore.loader || issueViewStore?.getIssues === null ? ( -
Loading...
- ) : ( - <> - {issueViewStore?.getIssues && Object.keys(issueViewStore?.getIssues).length > 0 ? ( - -
- {Object.keys(issueViewStore?.getIssues).map((_issueStateKey: any) => ( -
-
- -
- - - {(provided: any, snapshot: any) => ( -
- {issueViewStore?.getIssues && ( - - )} - {provided.placeholder} -
- )} -
-
- ))} -
-
- ) : ( -
No Issues are available
- )} - - )} -
- ); -}); diff --git a/web/components/issue-layouts/list/group-header.tsx b/web/components/issue-layouts/list/group-header.tsx deleted file mode 100644 index ca9ecb1f2a0..00000000000 --- a/web/components/issue-layouts/list/group-header.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import { FC } from "react"; -// lib -import { useMobxStore } from "lib/mobx/store-provider"; -import { RootStore } from "store/root"; - -export interface IIssueListGroupHeader { - groupId: string; - groupBy: string; -} - -export const IssueListGroupHeader: FC = (props) => { - const { groupId, groupBy } = props; - - const { issueFilters: issueFilterStore }: RootStore = useMobxStore(); - - return ( -
- {groupBy === "state" && <>{issueFilterStore.getProjectStateById(groupId)?.name}} - {groupBy === "state_detail.group" && <>{groupId}} - {groupBy === "priority" && <>{groupId}} - {groupBy === "project" && <>{issueFilterStore.workspaceProjects?.find((p) => (p.id = groupId))}} - {groupBy === "labels" && <>{issueFilterStore.projectLabels?.find((p) => p.id === groupId)?.name || " None"}} - {groupBy === "assignees" && ( - <>{issueFilterStore.projectMembers?.find((p) => p?.member?.id === groupId)?.member?.display_name || " None"} - )} - {groupBy === "created_by" && ( - <>{issueFilterStore.projectMembers?.find((p) => p?.member?.id === groupId)?.member?.display_name || " None"} - )} -
- ); -}; diff --git a/web/components/issue-layouts/list/index.ts b/web/components/issue-layouts/list/index.ts deleted file mode 100644 index a4e3561c619..00000000000 --- a/web/components/issue-layouts/list/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from "./root"; -export * from "./list"; -export * from "./item"; -export * from "./group-header"; diff --git a/web/components/issue-layouts/list/item.tsx b/web/components/issue-layouts/list/item.tsx deleted file mode 100644 index 30d4e730f2e..00000000000 --- a/web/components/issue-layouts/list/item.tsx +++ /dev/null @@ -1,246 +0,0 @@ -import React, { FC, useState } from "react"; -import { observer } from "mobx-react-lite"; -// lib -import { useMobxStore } from "lib/mobx/store-provider"; -import { IIssue } from "types"; -import useUserAuth from "hooks/use-user-auth"; -// icons -import { - ClipboardDocumentCheckIcon, - LinkIcon, - PencilIcon, - TrashIcon, - XMarkIcon, - ArrowTopRightOnSquareIcon, - PaperClipIcon, -} from "@heroicons/react/24/outline"; -// components -import { CustomMenu, ContextMenu } from "components/ui"; -import { Tooltip } from "@plane/ui"; -import { LayerDiagonalIcon } from "components/icons"; -import { - ViewAssigneeSelect, - ViewDueDateSelect, - ViewEstimateSelect, - ViewIssueLabel, - ViewPrioritySelect, - ViewStartDateSelect, - ViewStateSelect, -} from "components/issues"; -import { IssuePrioritySelect } from "../properties"; - -export interface IIssueListItem { - issue: IIssue; - groupId: string; -} - -export const IssueListItem: FC = observer((props) => { - const { issue, groupId } = props; - // store - const { user: userStore, issueFilters: issueFilterStore, issueDetail: issueDetailStore } = useMobxStore(); - const displayProperties = issueFilterStore.userFilters?.display_properties; - const workspaceId = issueFilterStore.workspaceId; - const projectId = issueFilterStore.projectId; - const issueId = issue.id; - const user = userStore.currentUser; - console.log("userStore", userStore); - // context menu - const [contextMenu, setContextMenu] = useState(false); - const [contextMenuPosition, setContextMenuPosition] = useState(null); - - const isNotAllowed = false; - // const isNotAllowed = - // userAuth?.isGuest || userAuth?.isViewer || disableUserActions || isArchivedIssues; - - const partialUpdateIssue = (data: any) => { - // console.log("data", data); - if (workspaceId && projectId && issueId) issueDetailStore.updateIssueAsync(workspaceId, projectId, issueId, data); - }; - - return ( -
- <> - - {/* {!isNotAllowed && ( - <> - - Edit issue - - - Make a copy... - - handleDeleteIssue(issue)}> - Delete issue - - - )} - - Copy issue link - - - - Open issue in new tab - - */} - -
{ - e.preventDefault(); - setContextMenu(true); - setContextMenuPosition(e); - }} - > -
-
- {/* {properties.key && ( - - - {issue.project_detail?.identifier}-{issue.sequence_id} - - - )} */} - - - -
-
- -
- {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 f06c6234da4..00000000000 --- 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 389c13fa16f..00000000000 --- 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 3289b323781..00000000000 --- 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 a914ed38ac4..00000000000 --- 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 90e1394d442..00000000000 --- 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 02313458dab..00000000000 --- 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
; -}; From f46b990064f23500feb06f7ccc5e94f2214652f7 Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal Date: Fri, 13 Oct 2023 00:32:28 +0530 Subject: [PATCH 4/4] refactor: inbox folder structure --- .../gantt-chart/cycle-issues-layout.tsx | 61 ------- web/components/cycles/gantt-chart/index.ts | 1 - web/components/gantt-chart/chart/index.tsx | 57 +++--- ...-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 +- 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 - 19 files changed, 30 insertions(+), 401 deletions(-) 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/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 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 e67bc516f01..00000000000 --- 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 e4850b2e259..a0a16086b2a 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 e21e803de1f..b3674566a2c 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 && (