diff --git a/web/components/core/filters/index.ts b/web/components/core/filters/index.ts index 558db6841..035e1bb16 100644 --- a/web/components/core/filters/index.ts +++ b/web/components/core/filters/index.ts @@ -2,4 +2,3 @@ export * from "./date-filter-modal"; export * from "./date-filter-select"; export * from "./filters-list"; export * from "./workspace-filters-list"; -export * from "./issues-view-filter"; diff --git a/web/components/core/filters/issues-view-filter.tsx b/web/components/core/filters/issues-view-filter.tsx deleted file mode 100644 index d090f569b..000000000 --- a/web/components/core/filters/issues-view-filter.tsx +++ /dev/null @@ -1,361 +0,0 @@ -import React from "react"; - -import { useRouter } from "next/router"; - -// headless ui -import { Popover, Transition } from "@headlessui/react"; -// hooks -import useIssuesProperties from "hooks/use-issue-properties"; -import useIssuesView from "hooks/use-issues-view"; -import useEstimateOption from "hooks/use-estimate-option"; -// components -import { SelectFilters } from "components/views"; -// ui -import { CustomMenu } from "components/ui"; -import { ToggleSwitch, Tooltip } from "@plane/ui"; -// icons -import { CalendarDays, ChevronDown, GanttChart, Kanban, List, Sheet } from "lucide-react"; -// helpers -import { replaceUnderscoreIfSnakeCase } from "helpers/string.helper"; -import { checkIfArraysHaveSameElements } from "helpers/array.helper"; -// types -import { Properties, TIssueLayouts } from "types"; -// constants -import { ISSUE_GROUP_BY_OPTIONS, ISSUE_ORDER_BY_OPTIONS, ISSUE_FILTER_OPTIONS } from "constants/issue"; - -const issueViewOptions: { type: TIssueLayouts; Icon: any }[] = [ - { - type: "list", - Icon: List, - }, - { - type: "kanban", - Icon: Kanban, - }, - { - type: "calendar", - Icon: CalendarDays, - }, - { - type: "spreadsheet", - Icon: Sheet, - }, - { - type: "gantt_chart", - Icon: GanttChart, - }, -]; - -const issueViewForDraftIssues: { type: TIssueLayouts; Icon: any }[] = [ - { - type: "list", - Icon: List, - }, - { - type: "kanban", - Icon: Kanban, - }, -]; - -export const IssuesFilterView: React.FC = () => { - const router = useRouter(); - const { workspaceSlug, projectId, viewId } = router.query; - const isArchivedIssues = router.pathname.includes("archived-issues"); - const isDraftIssues = router.pathname?.split("/")?.[4] === "draft-issues"; - - const { displayFilters, setDisplayFilters, filters, setFilters, resetFilterToDefault, setNewFilterDefaultView } = - useIssuesView(); - - const [properties, setProperties] = useIssuesProperties(workspaceSlug as string, projectId as string); - - const { isEstimateActive } = useEstimateOption(); - - return ( -
- {!isArchivedIssues && !isDraftIssues && ( -
- {issueViewOptions.map((option) => ( - {replaceUnderscoreIfSnakeCase(option.type)} Layout} - position="bottom" - > - - - ))} -
- )} - {isDraftIssues && ( -
- {issueViewForDraftIssues.map((option) => ( - {replaceUnderscoreIfSnakeCase(option.type)} View} - position="bottom" - > - - - ))} -
- )} - { - const key = option.key as keyof typeof filters; - - if (key === "start_date" || key === "target_date") { - const valueExists = checkIfArraysHaveSameElements(filters[key] ?? [], option.value); - - setFilters({ - [key]: valueExists ? null : option.value, - }); - } else { - const valueExists = filters[key]?.includes(option.value); - - if (valueExists) - setFilters( - { - [option.key]: ((filters[key] ?? []) as any[])?.filter((val) => val !== option.value), - }, - !Boolean(viewId) - ); - else - setFilters( - { - [option.key]: [...((filters[key] ?? []) as any[]), option.value], - }, - !Boolean(viewId) - ); - } - }} - direction="left" - height="rg" - /> - - {({ open }) => ( - <> - - Display - - - - - -
-
- {displayFilters.layout !== "calendar" && - displayFilters.layout !== "spreadsheet" && - displayFilters.layout !== "gantt_chart" && ( -
-

Group by

-
- option.key === displayFilters.group_by) - ?.title ?? "Select" - } - className="!w-full" - buttonClassName="w-full" - > - {ISSUE_GROUP_BY_OPTIONS.map((option) => { - if (displayFilters.layout === "kanban" && option.key === null) return null; - if (option.key === "project") return null; - - if (isDraftIssues && option.key === "state_detail.group") return null; - - return ( - setDisplayFilters({ group_by: option.key })} - > - {option.title} - - ); - })} - -
-
- )} - {displayFilters.layout !== "calendar" && displayFilters.layout !== "spreadsheet" && ( -
-

Order by

-
- option.key === displayFilters.order_by)?.title ?? - "Select" - } - className="!w-full" - buttonClassName="w-full" - > - {ISSUE_ORDER_BY_OPTIONS.map((option) => - displayFilters.group_by === "priority" && option.key === "priority" ? null : ( - { - setDisplayFilters({ order_by: option.key }); - }} - > - {option.title} - - ) - )} - -
-
- )} - {!isArchivedIssues && ( -
-

Issue type

-
- option.key === displayFilters.type)?.title ?? - "Select" - } - className="!w-full" - buttonClassName="w-full" - > - {ISSUE_FILTER_OPTIONS.map((option) => ( - - setDisplayFilters({ - type: option.key, - }) - } - > - {option.title} - - ))} - -
-
- )} - - {displayFilters.layout !== "calendar" && displayFilters.layout !== "spreadsheet" && ( -
-

Show sub-issues

-
- setDisplayFilters({ sub_issue: !displayFilters.sub_issue })} - /> -
-
- )} - {displayFilters.layout !== "calendar" && - displayFilters.layout !== "spreadsheet" && - displayFilters.layout !== "gantt_chart" && ( -
-

Show empty groups

-
- - setDisplayFilters({ - show_empty_groups: !displayFilters.show_empty_groups, - }) - } - /> -
-
- )} - {displayFilters.layout !== "calendar" && - displayFilters.layout !== "spreadsheet" && - displayFilters.layout !== "gantt_chart" && ( -
- - -
- )} -
- - {displayFilters.layout !== "gantt_chart" && ( -
-

Display Properties

-
- {Object.keys(properties).map((key) => { - if (key === "estimate" && !isEstimateActive) return null; - - if ( - displayFilters.layout === "spreadsheet" && - (key === "attachment_count" || key === "link" || key === "sub_issue_count") - ) - return null; - - if (displayFilters.layout !== "spreadsheet" && (key === "created_on" || key === "updated_on")) - return null; - - return ( - - ); - })} -
-
- )} -
-
-
- - )} -
-
- ); -}; diff --git a/web/components/core/views/all-views.tsx b/web/components/core/views/all-views.tsx deleted file mode 100644 index 7711dc2a6..000000000 --- a/web/components/core/views/all-views.tsx +++ /dev/null @@ -1,220 +0,0 @@ -// import React, { useCallback, useState } from "react"; -// import { useRouter } from "next/router"; -// import useSWR from "swr"; -// import { DragDropContext, DropResult } from "react-beautiful-dnd"; -// // services -// import { ProjectStateService } from "services/project"; -// // hooks -// import useUser from "hooks/use-user"; -// import { useProjectMyMembership } from "contexts/project-member.context"; -// import useSpreadsheetIssuesView from "hooks/use-spreadsheet-issues-view"; -// // components -// import StrictModeDroppable from "components/dnd/StrictModeDroppable"; -// import { AllLists, AllBoards, CalendarView, SpreadsheetView, GanttChartView } from "components/core"; -// import { EmptyState } from "components/common"; -// // ui -// import { Spinner } from "components/ui"; -// // icons -// import { TrashIcon } from "@heroicons/react/24/outline"; -// // images -// import emptyIssue from "public/empty-state/issue.svg"; -// import emptyIssueArchive from "public/empty-state/issue-archive.svg"; -// // helpers -// import { getStatesList } from "helpers/state.helper"; -// // types -// import { IIssue, IIssueViewProps } from "types"; -// // fetch-keys -// import { STATES_LIST } from "constants/fetch-keys"; - -// type Props = { -// addIssueToDate: (date: string) => void; -// addIssueToGroup: (groupTitle: string) => void; -// disableUserActions: boolean; -// dragDisabled?: boolean; -// emptyState: { -// title: string; -// description?: string; -// primaryButton?: { -// icon: any; -// text: string; -// onClick: () => void; -// }; -// secondaryButton?: React.ReactNode; -// }; -// handleIssueAction: (issue: IIssue, action: "copy" | "delete" | "edit") => void; -// handleDraftIssueAction?: (issue: IIssue, action: "edit" | "delete") => void; -// handleOnDragEnd: (result: DropResult) => Promise; -// openIssuesListModal: (() => void) | null; -// removeIssue: ((bridgeId: string, issueId: string) => void) | null; -// disableAddIssueOption?: boolean; -// trashBox: boolean; -// setTrashBox: React.Dispatch>; -// viewProps: IIssueViewProps; -// }; - -// const projectStateService = new ProjectStateService(); - -// export const AllViews: React.FC = ({ -// addIssueToDate, -// addIssueToGroup, -// disableUserActions, -// dragDisabled = false, -// emptyState, -// handleIssueAction, -// handleDraftIssueAction, -// handleOnDragEnd, -// openIssuesListModal, -// removeIssue, -// disableAddIssueOption = false, -// trashBox, -// setTrashBox, -// viewProps, -// }) => { -// const router = useRouter(); -// const { workspaceSlug, projectId, cycleId, moduleId } = router.query; - -// const [myIssueProjectId, setMyIssueProjectId] = useState(null); - -// const { user } = useUser(); -// const { memberRole } = useProjectMyMembership(); - -// const { groupedIssues, isEmpty, displayFilters } = viewProps; - -// const { spreadsheetIssues, mutateIssues } = useSpreadsheetIssuesView(); - -// const { data: stateGroups } = useSWR( -// workspaceSlug && projectId ? STATES_LIST(projectId as string) : null, -// workspaceSlug ? () => projectStateService.getStates(workspaceSlug as string, projectId as string) : null -// ); -// const states = getStatesList(stateGroups); - -// const handleMyIssueOpen = (issue: IIssue) => { -// setMyIssueProjectId(issue.project); -// }; - -// const handleTrashBox = useCallback( -// (isDragging: boolean) => { -// if (isDragging && !trashBox) setTrashBox(true); -// }, -// [trashBox, setTrashBox] -// ); - -// return ( -// -// -// {(provided, snapshot) => ( -//
-// -// Drop here to delete the issue. -//
-// )} -//
-// {groupedIssues ? ( -// !isEmpty || -// displayFilters?.layout === "kanban" || -// displayFilters?.layout === "calendar" || -// displayFilters?.layout === "gantt_chart" ? ( -// <> -// {displayFilters?.layout === "list" ? ( -// -// ) : displayFilters?.layout === "kanban" ? ( -// -// ) : displayFilters?.layout === "calendar" ? ( -// -// ) : displayFilters?.layout === "spreadsheet" ? ( -// -// ) : ( -// displayFilters?.layout === "gantt_chart" && -// )} -// -// ) : router.pathname.includes("archived-issues") ? ( -// { -// router.push(`/${workspaceSlug}/projects/${projectId}/settings/automations`); -// }, -// }} -// /> -// ) : ( -// -// ) -// ) : ( -//
-// -//
-// )} -//
-// ); -// }; - -export const AllViews = () => <>; diff --git a/web/components/core/views/index.ts b/web/components/core/views/index.ts index 84e9b6e16..3323690a1 100644 --- a/web/components/core/views/index.ts +++ b/web/components/core/views/index.ts @@ -1,2 +1 @@ -export * from "./issues-view"; export * from "./inline-issue-create-wrapper"; diff --git a/web/components/core/views/issues-view.tsx b/web/components/core/views/issues-view.tsx deleted file mode 100644 index 9bb30fd3e..000000000 --- a/web/components/core/views/issues-view.tsx +++ /dev/null @@ -1,588 +0,0 @@ -// import { useCallback, useEffect, useState, FC } from "react"; -// import { useRouter } from "next/router"; -// import useSWR, { mutate } from "swr"; -// import { DropResult } from "react-beautiful-dnd"; -// // services -// import { IssueService, IssueLabelService } from "services/issue"; -// import { ProjectStateService } from "services/project"; -// import { ModuleService } from "services/module.service"; -// import { TrackEventService } from "services/track_event.service"; -// // hooks -// import useToast from "hooks/use-toast"; -// import useIssuesView from "hooks/use-issues-view"; -// import useUserAuth from "hooks/use-user-auth"; -// import useIssuesProperties from "hooks/use-issue-properties"; -// import useProjectMembers from "hooks/use-project-members"; -// // components -// import { FiltersList } from "components/core"; -// import { -// CreateUpdateIssueModal, -// DeleteIssueModal, -// DeleteDraftIssueModal, -// CreateUpdateDraftIssueModal, -// } from "components/issues"; -// import { CreateUpdateViewModal } from "components/views"; -// // ui -// import { Button } from "@plane/ui"; -// // icons -// import { PlusIcon } from "@heroicons/react/24/outline"; -// // helpers -// import { getStatesList } from "helpers/state.helper"; -// import { orderArrayBy } from "helpers/array.helper"; -// // types -// import { IIssue, IIssueFilterOptions, IState, TIssuePriorities } from "types"; -// // fetch-keys -// import { -// CYCLE_DETAILS, -// CYCLE_ISSUES_WITH_PARAMS, -// MODULE_DETAILS, -// MODULE_ISSUES_WITH_PARAMS, -// PROJECT_ISSUES_LIST_WITH_PARAMS, -// PROJECT_ISSUE_LABELS, -// STATES_LIST, -// } from "constants/fetch-keys"; - -// type Props = { -// openIssuesListModal?: () => void; -// disableUserActions?: boolean; -// }; - -// const issueService = new IssueService(); -// const issueLabelService = new IssueLabelService(); -// const projectStateService = new ProjectStateService(); -// const moduleService = new ModuleService(); -// const trackEventService = new TrackEventService(); - -// export const IssuesView: FC = () => { -// // const { openIssuesListModal, disableUserActions = false } = props; -// // create issue modal -// const [createIssueModal, setCreateIssueModal] = useState(false); -// const [createViewModal, setCreateViewModal] = useState(null); -// const [preloadedData, setPreloadedData] = useState< -// (Partial & { actionType: "createIssue" | "edit" | "delete" }) | undefined -// >(undefined); - -// // update issue modal -// const [editIssueModal, setEditIssueModal] = useState(false); -// const [issueToEdit, setIssueToEdit] = useState<(IIssue & { actionType: "edit" | "delete" }) | undefined>(undefined); - -// // delete issue modal -// const [deleteIssueModal, setDeleteIssueModal] = useState(false); -// const [issueToDelete, setIssueToDelete] = useState(null); - -// // trash box -// // const [trashBox, setTrashBox] = useState(false); - -// // selected draft issue -// const [selectedDraftIssue, setSelectedDraftIssue] = useState(null); -// const [selectedDraftForDelete, setSelectDraftForDelete] = useState(null); - -// const router = useRouter(); -// const { workspaceSlug, projectId, cycleId, moduleId, viewId } = router.query; - -// const isDraftIssues = router.pathname?.split("/")?.[4] === "draft-issues"; -// // const isArchivedIssues = router.pathname?.split("/")?.[4] === "archived-issues"; - -// const { user } = useUserAuth(); - -// const { setToastAlert } = useToast(); - -// const { groupedByIssues, mutateIssues, displayFilters, filters, isEmpty, setFilters, params, setDisplayFilters } = -// useIssuesView(); -// const [properties] = useIssuesProperties(workspaceSlug as string, projectId as string); - -// const { data: stateGroups } = useSWR( -// workspaceSlug && projectId ? STATES_LIST(projectId as string) : null, -// workspaceSlug ? () => projectStateService.getStates(workspaceSlug as string, projectId as string) : null -// ); -// const states = getStatesList(stateGroups); - -// const { data: labels } = useSWR( -// workspaceSlug && projectId ? PROJECT_ISSUE_LABELS(projectId.toString()) : null, -// workspaceSlug && projectId -// ? () => issueLabelService.getProjectIssueLabels(workspaceSlug.toString(), projectId.toString()) -// : null -// ); - -// const { members } = useProjectMembers(workspaceSlug?.toString(), projectId?.toString()); - -// useEffect(() => { -// if (!isDraftIssues) return; - -// if ( -// displayFilters.layout === "calendar" || -// displayFilters.layout === "gantt_chart" || -// displayFilters.layout === "spreadsheet" -// ) -// setDisplayFilters({ layout: "list" }); -// }, [isDraftIssues, displayFilters, setDisplayFilters]); - -// const handleDeleteIssue = useCallback( -// (issue: IIssue) => { -// setDeleteIssueModal(true); -// setIssueToDelete(issue); -// }, -// [setDeleteIssueModal, setIssueToDelete] -// ); - -// const handleDraftIssueClick = useCallback((issue: any) => setSelectedDraftIssue(issue), []); -// const handleDraftIssueDelete = useCallback((issue: any) => setSelectDraftForDelete(issue), []); - -// const handleOnDragEnd = useCallback( -// async (result: DropResult) => { -// setTrashBox(false); - -// if (!result.destination || !workspaceSlug || !projectId || !groupedByIssues) return; - -// const { source, destination } = result; - -// const draggedItem = groupedByIssues[source.droppableId][source.index]; - -// if (destination.droppableId === "trashBox") { -// handleDeleteIssue(draggedItem); -// } else { -// if (displayFilters.order_by === "sort_order") { -// let newSortOrder = draggedItem.sort_order; - -// const destinationGroupArray = groupedByIssues[destination.droppableId]; - -// if (destinationGroupArray.length !== 0) { -// // check if dropping in the same group -// if (source.droppableId === destination.droppableId) { -// // check if dropping at beginning -// if (destination.index === 0) newSortOrder = destinationGroupArray[0].sort_order - 10000; -// // check if dropping at last -// else if (destination.index === destinationGroupArray.length - 1) -// newSortOrder = destinationGroupArray[destinationGroupArray.length - 1].sort_order + 10000; -// else { -// if (destination.index > source.index) -// newSortOrder = -// (destinationGroupArray[source.index + 1].sort_order + -// destinationGroupArray[source.index + 2].sort_order) / -// 2; -// else if (destination.index < source.index) -// newSortOrder = -// (destinationGroupArray[source.index - 1].sort_order + -// destinationGroupArray[source.index - 2].sort_order) / -// 2; -// } -// } else { -// // check if dropping at beginning -// if (destination.index === 0) newSortOrder = destinationGroupArray[0].sort_order - 10000; -// // check if dropping at last -// else if (destination.index === destinationGroupArray.length) -// newSortOrder = destinationGroupArray[destinationGroupArray.length - 1].sort_order + 10000; -// else -// newSortOrder = -// (destinationGroupArray[destination.index - 1].sort_order + -// destinationGroupArray[destination.index].sort_order) / -// 2; -// } -// } - -// draggedItem.sort_order = newSortOrder; -// } - -// const destinationGroup = destination.droppableId; // destination group id - -// if (displayFilters.order_by === "sort_order" || source.droppableId !== destination.droppableId) { -// // different group/column; - -// // source.droppableId !== destination.droppableId -> even if order by is not sort_order, -// // if the issue is moved to a different group, then we will change the group of the -// // dragged item(or issue) - -// if (displayFilters.group_by === "priority") draggedItem.priority = destinationGroup as TIssuePriorities; -// else if (displayFilters.group_by === "state") { -// draggedItem.state = destinationGroup; -// draggedItem.state_detail = states?.find((s) => s.id === destinationGroup) as IState; -// } -// } - -// const sourceGroup = source.droppableId; // source group id - -// mutate<{ -// [key: string]: IIssue[]; -// }>( -// cycleId -// ? CYCLE_ISSUES_WITH_PARAMS(cycleId as string, params) -// : moduleId -// ? MODULE_ISSUES_WITH_PARAMS(moduleId as string, params) -// : PROJECT_ISSUES_LIST_WITH_PARAMS(projectId as string, params), -// (prevData) => { -// if (!prevData) return prevData; - -// const sourceGroupArray = [...groupedByIssues[sourceGroup]]; -// const destinationGroupArray = [...groupedByIssues[destinationGroup]]; - -// sourceGroupArray.splice(source.index, 1); -// destinationGroupArray.splice(destination.index, 0, draggedItem); - -// return { -// ...prevData, -// [sourceGroup]: orderArrayBy(sourceGroupArray, displayFilters.order_by ?? "-created_at"), -// [destinationGroup]: orderArrayBy(destinationGroupArray, displayFilters.order_by ?? "-created_at"), -// }; -// }, -// false -// ); - -// // patch request -// issueService -// .patchIssue( -// workspaceSlug as string, -// projectId as string, -// draggedItem.id, -// { -// priority: draggedItem.priority, -// state: draggedItem.state, -// sort_order: draggedItem.sort_order, -// }, -// user -// ) -// .then((response) => { -// const sourceStateBeforeDrag = states?.find((state) => state.name === source.droppableId); - -// if (sourceStateBeforeDrag?.group !== "completed" && response?.state_detail?.group === "completed") -// trackEventService.trackIssueMarkedAsDoneEvent( -// { -// workspaceSlug, -// workspaceId: draggedItem.workspace, -// projectName: draggedItem.project_detail.name, -// projectIdentifier: draggedItem.project_detail.identifier, -// projectId, -// issueId: draggedItem.id, -// }, -// user -// ); - -// if (cycleId) { -// mutate(CYCLE_ISSUES_WITH_PARAMS(cycleId as string, params)); -// mutate(CYCLE_DETAILS(cycleId as string)); -// } -// if (moduleId) { -// mutate(MODULE_ISSUES_WITH_PARAMS(moduleId as string, params)); -// mutate(MODULE_DETAILS(moduleId as string)); -// } -// mutate(PROJECT_ISSUES_LIST_WITH_PARAMS(projectId as string, params)); -// }); -// } -// }, -// [ -// displayFilters.group_by, -// displayFilters.order_by, -// workspaceSlug, -// cycleId, -// moduleId, -// groupedByIssues, -// projectId, -// handleDeleteIssue, -// params, -// states, -// user, -// ] -// ); - -// const addIssueToGroup = useCallback( -// (groupTitle: string) => { -// setCreateIssueModal(true); - -// let preloadedValue: string | string[] = groupTitle; - -// if (displayFilters.group_by === "labels") { -// if (groupTitle === "None") preloadedValue = []; -// else preloadedValue = [groupTitle]; -// } - -// if (displayFilters.group_by) -// setPreloadedData({ -// [displayFilters.group_by]: preloadedValue, -// actionType: "createIssue", -// }); -// else setPreloadedData({ actionType: "createIssue" }); -// }, -// [displayFilters.group_by, setCreateIssueModal, setPreloadedData] -// ); - -// const addIssueToDate = useCallback( -// (date: string) => { -// setCreateIssueModal(true); -// setPreloadedData({ -// target_date: date, -// actionType: "createIssue", -// }); -// }, -// [setCreateIssueModal, setPreloadedData] -// ); - -// const makeIssueCopy = useCallback( -// (issue: IIssue) => { -// setCreateIssueModal(true); - -// setPreloadedData({ ...issue, name: `${issue.name} (Copy)`, actionType: "createIssue" }); -// }, -// [setCreateIssueModal, setPreloadedData] -// ); - -// const handleEditIssue = useCallback( -// (issue: IIssue) => { -// setEditIssueModal(true); -// setIssueToEdit({ -// ...issue, -// actionType: "edit", -// cycle: issue.issue_cycle ? issue.issue_cycle.cycle : null, -// module: issue.issue_module ? issue.issue_module.module : null, -// }); -// }, -// [setEditIssueModal, setIssueToEdit] -// ); - -// const handleIssueAction = useCallback( -// (issue: IIssue, action: "copy" | "edit" | "delete") => { -// if (action === "copy") makeIssueCopy(issue); -// else if (action === "edit") handleEditIssue(issue); -// else if (action === "delete") handleDeleteIssue(issue); -// }, -// [makeIssueCopy, handleEditIssue, handleDeleteIssue] -// ); - -// const handleDraftIssueAction = useCallback( -// (issue: IIssue, action: "edit" | "delete") => { -// if (action === "edit") handleDraftIssueClick(issue); -// else if (action === "delete") handleDraftIssueDelete(issue); -// }, -// [handleDraftIssueClick, handleDraftIssueDelete] -// ); - -// const removeIssueFromCycle = useCallback( -// (bridgeId: string, issueId: string) => { -// if (!workspaceSlug || !projectId || !cycleId) return; - -// mutate( -// CYCLE_ISSUES_WITH_PARAMS(cycleId as string, params), -// (prevData: any) => { -// if (!prevData) return prevData; -// if (displayFilters.group_by) { -// const filteredData: any = {}; -// for (const key in prevData) { -// filteredData[key] = prevData[key].filter((item: any) => item.id !== issueId); -// } -// return filteredData; -// } else { -// const filteredData = prevData.filter((i: any) => i.id !== issueId); -// return filteredData; -// } -// }, -// false -// ); - -// issueService -// .removeIssueFromCycle(workspaceSlug as string, projectId as string, cycleId as string, bridgeId) -// .then(() => { -// setToastAlert({ -// title: "Success", -// message: "Issue removed successfully.", -// type: "success", -// }); -// }) -// .catch((e) => { -// console.log(e); -// }); -// }, -// [displayFilters.group_by, workspaceSlug, projectId, cycleId, params, setToastAlert] -// ); - -// const removeIssueFromModule = useCallback( -// (bridgeId: string, issueId: string) => { -// if (!workspaceSlug || !projectId || !moduleId) return; - -// mutate( -// MODULE_ISSUES_WITH_PARAMS(moduleId as string, params), -// (prevData: any) => { -// if (!prevData) return prevData; -// if (displayFilters.group_by) { -// const filteredData: any = {}; -// for (const key in prevData) { -// filteredData[key] = prevData[key].filter((item: any) => item.id !== issueId); -// } -// return filteredData; -// } else { -// const filteredData = prevData.filter((item: any) => item.id !== issueId); -// return filteredData; -// } -// }, -// false -// ); - -// moduleService -// .removeIssueFromModule(workspaceSlug as string, projectId as string, moduleId as string, bridgeId) -// .then(() => { -// setToastAlert({ -// title: "Success", -// message: "Issue removed successfully.", -// type: "success", -// }); -// }) -// .catch((e) => { -// console.log(e); -// }); -// }, -// [displayFilters.group_by, workspaceSlug, projectId, moduleId, params, setToastAlert] -// ); - -// const nullFilters = Object.keys(filters).filter((key) => filters[key as keyof IIssueFilterOptions] === null); - -// const areFiltersApplied = Object.keys(filters).length > 0 && nullFilters.length !== Object.keys(filters).length; - -// return ( -// <> -// setCreateViewModal(null)} -// preLoadedData={createViewModal} -// user={user} -// /> -// setCreateIssueModal(false)} -// prePopulateData={{ -// ...preloadedData, -// }} -// /> -// setSelectedDraftIssue(null)} -// data={ -// selectedDraftIssue -// ? { -// ...selectedDraftIssue, -// is_draft: true, -// } -// : null -// } -// fieldsToShow={["all"]} -// /> -// setEditIssueModal(false)} -// data={issueToEdit} -// /> -// setDeleteIssueModal(false)} -// isOpen={deleteIssueModal} -// data={issueToDelete} -// user={user} -// /> -// setSelectDraftForDelete(null)} -// /> - -// {areFiltersApplied && ( -// <> -//
-// setFilters(updatedFilter, !Boolean(viewId))} -// labels={labels} -// members={members?.map((m: any) => m.member)} -// states={states} -// clearAllFilters={() => -// setFilters({ -// assignees: null, -// created_by: null, -// labels: null, -// priority: null, -// state: null, -// state_group: null, -// start_date: null, -// target_date: null, -// }) -// } -// /> -// -//
-// {
} -// -// )} -// {/* , -// text: "New Issue", -// onClick: () => { -// const e = new KeyboardEvent("keydown", { -// key: "c", -// }); -// document.dispatchEvent(e); -// }, -// } -// : undefined, -// secondaryButton: -// cycleId || moduleId ? ( -// -// ) : null, -// }} -// handleOnDragEnd={handleOnDragEnd} -// handleIssueAction={handleIssueAction} -// handleDraftIssueAction={handleDraftIssueAction} -// openIssuesListModal={openIssuesListModal ?? null} -// removeIssue={cycleId ? removeIssueFromCycle : moduleId ? removeIssueFromModule : null} -// trashBox={trashBox} -// setTrashBox={setTrashBox} -// viewProps={{ -// groupedIssues: groupedByIssues, -// displayFilters, -// isEmpty, -// mutateIssues, -// params, -// properties, -// }} -// disableAddIssueOption={isArchivedIssues} -// /> */} -// -// ); -// }; - -export const IssuesView = () => <>; diff --git a/web/components/issues/issue-layouts/spreadsheet/columns/issue/issue-column.tsx b/web/components/issues/issue-layouts/spreadsheet/columns/issue/issue-column.tsx index 65547a805..41de853b1 100644 --- a/web/components/issues/issue-layouts/spreadsheet/columns/issue/issue-column.tsx +++ b/web/components/issues/issue-layouts/spreadsheet/columns/issue/issue-column.tsx @@ -7,14 +7,14 @@ import useToast from "hooks/use-toast"; // helpers import { copyTextToClipboard } from "helpers/string.helper"; // types -import { IIssue, Properties } from "types"; +import { IIssue, IIssueDisplayProperties } from "types"; type Props = { issue: IIssue; projectId: string; expanded: boolean; handleToggleExpand: (issueId: string) => void; - properties: Properties; + properties: IIssueDisplayProperties; handleEditIssue: (issue: IIssue) => void; handleDeleteIssue: (issue: IIssue) => void; disableUserActions: boolean; diff --git a/web/components/issues/issue-layouts/spreadsheet/columns/issue/spreadsheet-issue-column.tsx b/web/components/issues/issue-layouts/spreadsheet/columns/issue/spreadsheet-issue-column.tsx index 5500e77e6..f9ea0237b 100644 --- a/web/components/issues/issue-layouts/spreadsheet/columns/issue/spreadsheet-issue-column.tsx +++ b/web/components/issues/issue-layouts/spreadsheet/columns/issue/spreadsheet-issue-column.tsx @@ -5,14 +5,14 @@ import { IssueColumn } from "components/issues"; // hooks import useSubIssue from "hooks/use-sub-issue"; // types -import { IIssue, Properties } from "types"; +import { IIssue, IIssueDisplayProperties } from "types"; type Props = { issue: IIssue; projectId: string; expandedIssues: string[]; setExpandedIssues: React.Dispatch>; - properties: Properties; + properties: IIssueDisplayProperties; handleIssueAction: (issue: IIssue, action: "copy" | "delete" | "edit") => void; disableUserActions: boolean; nestingLevel?: number; diff --git a/web/components/issues/sub-issues/issue.tsx b/web/components/issues/sub-issues/issue.tsx index 99783df52..d0c7309c0 100644 --- a/web/components/issues/sub-issues/issue.tsx +++ b/web/components/issues/sub-issues/issue.tsx @@ -110,7 +110,6 @@ export const SubIssues: React.FC = ({
= observer( - ({ workspaceSlug, projectId, parentIssue, issue, user, editable }) => { - const [properties] = useIssuesProperties(workspaceSlug, projectId); +export const IssueProperty: React.FC = observer((props) => { + const { workspaceSlug, parentIssue, issue, user, editable } = props; - const { project: projectStore } = useMobxStore(); + const { project: projectStore, issueFilter: issueFilterStore } = useMobxStore(); - const handlePriorityChange = (data: any) => { - partialUpdateIssue({ priority: data }); - trackEventService.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 as IUser - ); - }; + const displayProperties = issueFilterStore.userDisplayProperties ?? {}; - const handleStateChange = (data: IState) => { - partialUpdateIssue({ - state: data.id, - state_detail: data, - }); - trackEventService.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 as IUser - ); - }; - - const handleAssigneeChange = (data: string[]) => { - partialUpdateIssue({ assignees_list: data, assignees: data }); - - trackEventService.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 as IUser - ); - }; - - const partialUpdateIssue = async (data: Partial) => { - mutate( - workspaceSlug && parentIssue ? SUB_ISSUES(parentIssue.id) : null, - (elements: any) => { - const _elements = { ...elements }; - const _issues = _elements.sub_issues.map((element: IIssue) => - element.id === issue.id ? { ...element, ...data } : element - ); - _elements["sub_issues"] = [..._issues]; - return _elements; - }, - false - ); - - const issueResponse = await issueService.patchIssue(workspaceSlug as string, issue.project, issue.id, data, user); - - mutate( - SUB_ISSUES(parentIssue.id), - (elements: any) => { - const _elements = elements.sub_issues.map((element: IIssue) => - element.id === issue.id ? issueResponse : element - ); - elements["sub_issues"] = _elements; - return elements; - }, - true - ); - }; - - return ( -
- {properties.priority && ( -
- -
- )} - - {properties.state && ( -
- handleStateChange(data)} - hideDropdownArrow - disabled={!editable} - /> -
- )} - - {properties.start_date && issue.start_date && ( -
- partialUpdateIssue({ start_date: val })} - disabled={!editable} - /> -
- )} - - {properties.due_date && issue.target_date && ( -
- {user && ( - partialUpdateIssue({ target_date: val })} - disabled={!editable} - /> - )} -
- )} - - {properties.assignee && ( -
- handleAssigneeChange(val)} - members={projectStore.members ? (projectStore.members[issue.project] ?? []).map((m) => m.member) : []} - hideDropdownArrow - disabled={!editable} - multiple - /> -
- )} -
+ const handlePriorityChange = (data: any) => { + partialUpdateIssue({ priority: data }); + trackEventService.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 as IUser ); - } -); + }; + + const handleStateChange = (data: IState) => { + partialUpdateIssue({ + state: data.id, + state_detail: data, + }); + trackEventService.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 as IUser + ); + }; + + const handleAssigneeChange = (data: string[]) => { + partialUpdateIssue({ assignees_list: data, assignees: data }); + + trackEventService.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 as IUser + ); + }; + + const partialUpdateIssue = async (data: Partial) => { + mutate( + workspaceSlug && parentIssue ? SUB_ISSUES(parentIssue.id) : null, + (elements: any) => { + const _elements = { ...elements }; + const _issues = _elements.sub_issues.map((element: IIssue) => + element.id === issue.id ? { ...element, ...data } : element + ); + _elements["sub_issues"] = [..._issues]; + return _elements; + }, + false + ); + + const issueResponse = await issueService.patchIssue(workspaceSlug as string, issue.project, issue.id, data, user); + + mutate( + SUB_ISSUES(parentIssue.id), + (elements: any) => { + const _elements = elements.sub_issues.map((element: IIssue) => + element.id === issue.id ? issueResponse : element + ); + elements["sub_issues"] = _elements; + return elements; + }, + true + ); + }; + + return ( +
+ {displayProperties.priority && ( +
+ +
+ )} + + {displayProperties.state && ( +
+ handleStateChange(data)} + hideDropdownArrow + disabled={!editable} + /> +
+ )} + + {displayProperties.start_date && issue.start_date && ( +
+ partialUpdateIssue({ start_date: val })} + disabled={!editable} + /> +
+ )} + + {displayProperties.due_date && issue.target_date && ( +
+ {user && ( + partialUpdateIssue({ target_date: val })} + disabled={!editable} + /> + )} +
+ )} + + {displayProperties.assignee && ( +
+ handleAssigneeChange(val)} + members={projectStore.members ? (projectStore.members[issue.project] ?? []).map((m) => m.member) : []} + hideDropdownArrow + disabled={!editable} + multiple + /> +
+ )} +
+ ); +}); diff --git a/web/hooks/use-issue-properties.tsx b/web/hooks/use-issue-properties.tsx deleted file mode 100644 index 6908b6669..000000000 --- a/web/hooks/use-issue-properties.tsx +++ /dev/null @@ -1,108 +0,0 @@ -import { useState, useEffect, useCallback } from "react"; -import useSWR from "swr"; -// services -import { IssueService } from "services/issue"; -// hooks -import useUser from "hooks/use-user"; -// types -import { IssuePriorities, Properties } from "types"; - -const issueService = new IssueService(); - -const initialValues: Properties = { - assignee: true, - start_date: true, - due_date: true, - key: true, - labels: true, - priority: true, - state: true, - sub_issue_count: true, - attachment_count: true, - link: true, - estimate: true, - created_on: true, - updated_on: true, -}; - -const useIssuesProperties = (workspaceSlug?: string, projectId?: string) => { - const [properties, setProperties] = useState(initialValues); - - const { user } = useUser(); - - const { data: issueProperties, mutate: mutateIssueProperties } = useSWR( - workspaceSlug && projectId ? `/api/workspaces/${workspaceSlug}/projects/${projectId}/issue-properties/` : null, - workspaceSlug && projectId ? () => issueService.getIssueProperties(workspaceSlug, projectId) : null - ); - - useEffect(() => { - if (!issueProperties || !workspaceSlug || !projectId || !user) return; - - setProperties({ ...initialValues, ...issueProperties.properties }); - - if (Object.keys(issueProperties).length === 0) - issueService.createIssueProperties(workspaceSlug, projectId, { - properties: { ...initialValues }, - user: user.id, - }); - else if (Object.keys(issueProperties?.properties).length === 0) - issueService.patchIssueProperties(workspaceSlug, projectId, issueProperties.id, { - properties: { ...initialValues }, - user: user.id, - }); - }, [issueProperties, workspaceSlug, projectId, user]); - - const updateIssueProperties = useCallback( - (key: keyof Properties) => { - if (!workspaceSlug || !user) return; - - setProperties((prev) => ({ ...prev, [key]: !prev[key] })); - - if (issueProperties && projectId) { - mutateIssueProperties( - (prev: any) => - ({ - ...prev, - properties: { ...prev?.properties, [key]: !prev?.properties?.[key] }, - } as IssuePriorities), - false - ); - if (Object.keys(issueProperties).length > 0) { - issueService.patchIssueProperties(workspaceSlug, projectId, issueProperties.id, { - properties: { - ...issueProperties.properties, - [key]: !issueProperties.properties[key], - }, - user: user.id, - }); - } else { - issueService.createIssueProperties(workspaceSlug, projectId, { - properties: { ...initialValues }, - user: user.id, - }); - } - } - }, - [workspaceSlug, projectId, issueProperties, user, mutateIssueProperties] - ); - - const newProperties: Properties = { - assignee: properties.assignee, - start_date: properties.start_date, - due_date: properties.due_date, - key: properties.key, - labels: properties.labels, - priority: properties.priority, - state: properties.state, - sub_issue_count: properties.sub_issue_count, - attachment_count: properties.attachment_count, - link: properties.link, - estimate: properties.estimate, - created_on: properties.created_on, - updated_on: properties.updated_on, - }; - - return [newProperties, updateIssueProperties] as const; -}; - -export default useIssuesProperties; diff --git a/web/pages/[workspaceSlug]/projects/[projectId]/archived-issues/index.tsx b/web/pages/[workspaceSlug]/projects/[projectId]/archived-issues/index.tsx index 91c842947..a9c774017 100644 --- a/web/pages/[workspaceSlug]/projects/[projectId]/archived-issues/index.tsx +++ b/web/pages/[workspaceSlug]/projects/[projectId]/archived-issues/index.tsx @@ -11,8 +11,6 @@ import { ProjectAuthorizationWrapper } from "layouts/auth-layout-legacy"; import { IssueViewContextProvider } from "contexts/issue-view.context"; // helper import { truncateText } from "helpers/string.helper"; -// components -import { IssuesFilterView, IssuesView } from "components/core"; // ui import { ArchiveIcon, BreadcrumbItem, Breadcrumbs } from "@plane/ui"; // icons @@ -51,11 +49,11 @@ const ProjectArchivedIssues: NextPage = () => { } - right={ -
- -
- } + // right={ + //
+ // + //
+ // } >
@@ -70,7 +68,7 @@ const ProjectArchivedIssues: NextPage = () => {
- + {/* */}
diff --git a/web/pages/[workspaceSlug]/projects/[projectId]/draft-issues/index.tsx b/web/pages/[workspaceSlug]/projects/[projectId]/draft-issues/index.tsx index 2645cf666..13c55e205 100644 --- a/web/pages/[workspaceSlug]/projects/[projectId]/draft-issues/index.tsx +++ b/web/pages/[workspaceSlug]/projects/[projectId]/draft-issues/index.tsx @@ -11,8 +11,6 @@ import { ProjectAuthorizationWrapper } from "layouts/auth-layout-legacy"; import { IssueViewContextProvider } from "contexts/issue-view.context"; // helper import { truncateText } from "helpers/string.helper"; -// components -import { IssuesFilterView, IssuesView } from "components/core"; // ui import { BreadcrumbItem, Breadcrumbs } from "@plane/ui"; // icons @@ -51,11 +49,11 @@ const ProjectDraftIssues: NextPage = () => { } - right={ -
- -
- } + // right={ + //
+ // + //
+ // } >
@@ -70,7 +68,6 @@ const ProjectDraftIssues: NextPage = () => {
-
diff --git a/web/services/issue/issue.service.ts b/web/services/issue/issue.service.ts index c0bb15980..135f811ec 100644 --- a/web/services/issue/issue.service.ts +++ b/web/services/issue/issue.service.ts @@ -2,7 +2,7 @@ import { APIService } from "services/api.service"; import { TrackEventService } from "services/track_event.service"; // type -import type { IUser, IIssue, IIssueActivity, ISubIssueResponse } from "types"; +import type { IUser, IIssue, IIssueActivity, ISubIssueResponse, IIssueDisplayProperties } from "types"; // helper import { API_BASE_URL } from "helpers/common.helper"; @@ -62,14 +62,6 @@ export class IssueService extends APIService { }); } - async getIssueProperties(workspaceSlug: string, projectId: string): Promise { - return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issue-properties/`) - .then((response) => response?.data) - .catch((error) => { - throw error?.response?.data; - }); - } - async addIssueToCycle( workspaceSlug: string, projectId: string, @@ -153,24 +145,20 @@ export class IssueService extends APIService { }); } - async createIssueProperties(workspaceSlug: string, projectId: string, data: any): Promise { - return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issue-properties/`, data) + async getIssueDisplayProperties(workspaceSlug: string, projectId: string): Promise { + return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issue-display-properties/`) .then((response) => response?.data) .catch((error) => { throw error?.response?.data; }); } - async patchIssueProperties( + async patchIssueDisplayProperties( workspaceSlug: string, projectId: string, - issuePropertyId: string, - data: any + data: IIssueDisplayProperties ): Promise { - return this.patch( - `/api/workspaces/${workspaceSlug}/projects/${projectId}/issue-properties/` + `${issuePropertyId}/`, - data - ) + return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issue-display-properties/`, data) .then((response) => response?.data) .catch((error) => { throw error?.response?.data; diff --git a/web/services/project/project.service.ts b/web/services/project/project.service.ts index 07dabbe17..e1309fafa 100644 --- a/web/services/project/project.service.ts +++ b/web/services/project/project.service.ts @@ -136,14 +136,6 @@ export class ProjectService extends APIService { }); } - async joinProjects(data: any): Promise { - return this.post("/api/users/me/invitations/projects/", data) - .then((response) => response?.data) - .catch((error) => { - throw error?.response?.data; - }); - } - async projectMembers(workspaceSlug: string, projectId: string): Promise { return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/project-members/`) .then((response) => response?.data) diff --git a/web/store/issue/issue_filters.store.ts b/web/store/issue/issue_filters.store.ts index 0a96db887..51544b68d 100644 --- a/web/store/issue/issue_filters.store.ts +++ b/web/store/issue/issue_filters.store.ts @@ -45,7 +45,7 @@ export class IssueFilterStore implements IIssueFilterStore { error: any | null = null; // observables - userDisplayProperties: any = {}; + userDisplayProperties: IIssueDisplayProperties = {}; userDisplayFilters: IIssueDisplayFilterOptions = {}; userFilters: IIssueFilterOptions = {}; defaultDisplayFilters: IIssueDisplayFilterOptions = {}; @@ -144,7 +144,7 @@ export class IssueFilterStore implements IIssueFilterStore { fetchUserProjectFilters = async (workspaceSlug: string, projectId: string) => { try { const memberResponse = await this.projectService.projectMemberMe(workspaceSlug, projectId); - const issueProperties = await this.issueService.getIssueProperties(workspaceSlug, projectId); + const issueProperties = await this.issueService.getIssueDisplayProperties(workspaceSlug, projectId); runInAction(() => { this.userFilters = memberResponse?.view_props?.filters; @@ -207,7 +207,7 @@ export class IssueFilterStore implements IIssueFilterStore { projectId: string, properties: Partial ) => { - const newProperties = { + const newProperties: IIssueDisplayProperties = { ...this.userDisplayProperties, ...properties, }; @@ -217,7 +217,7 @@ export class IssueFilterStore implements IIssueFilterStore { this.userDisplayProperties = newProperties; }); - // await this.issueService.patchIssueProperties(workspaceSlug, projectId, newProperties); + await this.issueService.patchIssueDisplayProperties(workspaceSlug, projectId, newProperties); } catch (error) { this.fetchUserProjectFilters(workspaceSlug, projectId); diff --git a/web/types/view-props.d.ts b/web/types/view-props.d.ts index 5a98b248c..a7e1ccda6 100644 --- a/web/types/view-props.d.ts +++ b/web/types/view-props.d.ts @@ -84,19 +84,19 @@ export interface IIssueDisplayFilterOptions { type?: TIssueTypeFilters; } export interface IIssueDisplayProperties { - assignee: boolean; - start_date: boolean; - due_date: boolean; - labels: boolean; - key: boolean; - priority: boolean; - state: boolean; - sub_issue_count: boolean; - link: boolean; - attachment_count: boolean; - estimate: boolean; - created_on: boolean; - updated_on: boolean; + assignee?: boolean; + start_date?: boolean; + due_date?: boolean; + labels?: boolean; + key?: boolean; + priority?: boolean; + state?: boolean; + sub_issue_count?: boolean; + link?: boolean; + attachment_count?: boolean; + estimate?: boolean; + created_on?: boolean; + updated_on?: boolean; } export interface IWorkspaceIssueFilterOptions { @@ -142,10 +142,10 @@ export interface IProjectViewProps { export interface IWorkspaceViewProps { filters: IIssueFilterOptions; display_filters: IIssueDisplayFilterOptions | undefined; - display_properties: Properties; + display_properties: IIssueDisplayProperties; } export interface IWorkspaceGlobalViewProps { filters: IWorkspaceIssueFilterOptions; display_filters: IWorkspaceIssueDisplayFilterOptions | undefined; - display_properties: Properties; + display_properties: IIssueDisplayProperties; }