diff --git a/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/draft-issues/header.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/draft-issues/header.tsx deleted file mode 100644 index 1430fc0928b..00000000000 --- a/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/draft-issues/header.tsx +++ /dev/null @@ -1,178 +0,0 @@ -"use client"; - -import { FC, useCallback } from "react"; -import { observer } from "mobx-react"; -import { useParams } from "next/navigation"; -// plane constants -import { EIssueFilterType, ISSUE_DISPLAY_FILTERS_BY_PAGE } from "@plane/constants"; -// i18n -import { useTranslation } from "@plane/i18n"; -// types -import { - EIssuesStoreType, - IIssueDisplayFilterOptions, - IIssueDisplayProperties, - IIssueFilterOptions, - EIssueLayoutTypes, -} from "@plane/types"; -// ui -import { Breadcrumbs, LayersIcon, Tooltip } from "@plane/ui"; -// components -import { isIssueFilterActive } from "@plane/utils"; -import { BreadcrumbLink } from "@/components/common/breadcrumb-link"; -import { - DisplayFiltersSelection, - FiltersDropdown, - FilterSelection, - LayoutSelection, -} from "@/components/issues/issue-layouts/filters"; -// helpers -// hooks -import { useIssues } from "@/hooks/store/use-issues"; -import { useLabel } from "@/hooks/store/use-label"; -import { useMember } from "@/hooks/store/use-member"; -import { useProject } from "@/hooks/store/use-project"; -import { useProjectState } from "@/hooks/store/use-project-state"; -import { usePlatformOS } from "@/hooks/use-platform-os"; -// plane web -import { ProjectBreadcrumb } from "@/plane-web/components/breadcrumbs/project"; - -// FIXME: Deprecated. Remove it -export const ProjectDraftIssueHeader: FC = observer(() => { - // i18n - const { t } = useTranslation(); - // router - const { workspaceSlug, projectId } = useParams() as { workspaceSlug: string; projectId: string }; - // store hooks - const { - issuesFilter: { issueFilters, updateFilters }, - } = useIssues(EIssuesStoreType.DRAFT); - const { currentProjectDetails, loader } = useProject(); - const { projectStates } = useProjectState(); - const { projectLabels } = useLabel(); - const { - project: { projectMemberIds }, - } = useMember(); - const { isMobile } = usePlatformOS(); - const activeLayout = issueFilters?.displayFilters?.layout; - - const handleFiltersUpdate = useCallback( - (key: keyof IIssueFilterOptions, value: string | string[]) => { - if (!workspaceSlug || !projectId) return; - const newValues = issueFilters?.filters?.[key] ?? []; - - if (Array.isArray(value)) { - // this validation is majorly for the filter start_date, target_date custom - value.forEach((val) => { - if (!newValues.includes(val)) newValues.push(val); - else newValues.splice(newValues.indexOf(val), 1); - }); - } else { - if (issueFilters?.filters?.[key]?.includes(value)) newValues.splice(newValues.indexOf(value), 1); - else newValues.push(value); - } - - updateFilters(workspaceSlug, projectId, EIssueFilterType.FILTERS, { [key]: newValues }); - }, - [workspaceSlug, projectId, issueFilters, updateFilters] - ); - - const handleLayoutChange = useCallback( - (layout: EIssueLayoutTypes) => { - if (!workspaceSlug || !projectId) return; - updateFilters(workspaceSlug, projectId, EIssueFilterType.DISPLAY_FILTERS, { layout: layout }); - }, - [workspaceSlug, projectId, updateFilters] - ); - - const handleDisplayFilters = useCallback( - (updatedDisplayFilter: Partial) => { - if (!workspaceSlug || !projectId) return; - updateFilters(workspaceSlug, projectId, EIssueFilterType.DISPLAY_FILTERS, updatedDisplayFilter); - }, - [workspaceSlug, projectId, updateFilters] - ); - - const handleDisplayProperties = useCallback( - (property: Partial) => { - if (!workspaceSlug || !projectId) return; - updateFilters(workspaceSlug, projectId, EIssueFilterType.DISPLAY_PROPERTIES, property); - }, - [workspaceSlug, projectId, updateFilters] - ); - - const issueCount = undefined; - - return ( -
-
-
- - - - } - /> - } - /> - - {issueCount && issueCount > 0 ? ( - 1 ? "work items" : "work item"} in project's draft`} - position="bottom" - > - - {issueCount} - - - ) : null} -
- -
- handleLayoutChange(layout)} - selectedLayout={activeLayout} - /> - - - - - - -
-
-
- ); -}); diff --git a/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/draft-issues/layout.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/draft-issues/layout.tsx deleted file mode 100644 index ec6cdc1dd77..00000000000 --- a/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/draft-issues/layout.tsx +++ /dev/null @@ -1,15 +0,0 @@ -"use client"; - -// components -import { AppHeader } from "@/components/core/app-header"; -import { ContentWrapper } from "@/components/core/content-wrapper"; -import { ProjectDraftIssueHeader } from "./header"; - -export default function ProjectDraftIssuesLayou({ children }: { children: React.ReactNode }) { - return ( - <> - } /> - {children} - - ); -} diff --git a/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/draft-issues/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/draft-issues/page.tsx deleted file mode 100644 index ce91afb6167..00000000000 --- a/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/draft-issues/page.tsx +++ /dev/null @@ -1,43 +0,0 @@ -"use client"; - -import { observer } from "mobx-react"; -import { useParams } from "next/navigation"; -import { X, PenSquare } from "lucide-react"; -// components -import { PageHead } from "@/components/core/page-title"; -import { DraftIssueLayoutRoot } from "@/components/issues/issue-layouts/roots/draft-issue-layout-root"; -// hooks -import { useProject } from "@/hooks/store/use-project"; -import { useAppRouter } from "@/hooks/use-app-router"; - -const ProjectDraftIssuesPage = observer(() => { - const router = useAppRouter(); - const { workspaceSlug, projectId } = useParams(); - // store - const { getProjectById } = useProject(); - // derived values - const project = projectId ? getProjectById(projectId.toString()) : undefined; - const pageTitle = project?.name ? `${project?.name} - Draft work items` : undefined; - - return ( - <> - -
-
- -
- -
- - ); -}); - -export default ProjectDraftIssuesPage; diff --git a/apps/web/ce/components/command-palette/modals/issue-level.tsx b/apps/web/ce/components/command-palette/modals/issue-level.tsx index 843e39cfb74..b30d5ec30e4 100644 --- a/apps/web/ce/components/command-palette/modals/issue-level.tsx +++ b/apps/web/ce/components/command-palette/modals/issue-level.tsx @@ -1,6 +1,6 @@ import { FC } from "react"; import { observer } from "mobx-react"; -import { useParams, usePathname } from "next/navigation"; +import { useParams } from "next/navigation"; // plane imports import { EIssueServiceType, EIssuesStoreType, TIssue } from "@plane/types"; // components @@ -22,7 +22,6 @@ export type TIssueLevelModalsProps = { export const IssueLevelModals: FC = observer((props) => { const { projectId, issueId } = props; // router - const pathname = usePathname(); const { workspaceSlug, cycleId, moduleId } = useParams(); const router = useAppRouter(); // store hooks @@ -45,7 +44,6 @@ export const IssueLevelModals: FC = observer((props) => } = useCommandPalette(); // derived values const issueDetails = issueId ? getIssueById(issueId) : undefined; - const isDraftIssue = pathname?.includes("draft-issues") || false; const { fetchSubIssues: fetchSubWorkItems } = useIssueDetail(); const { fetchSubIssues: fetchEpicSubWorkItems } = useIssueDetail(EIssueServiceType.EPICS); @@ -81,7 +79,6 @@ export const IssueLevelModals: FC = observer((props) => isOpen={isCreateIssueModalOpen} onClose={() => toggleCreateIssueModal(false)} data={getCreateIssueModalData()} - isDraft={isDraftIssue} onSubmit={handleCreateIssueSubmit} allowedProjectIds={createWorkItemAllowedProjectIds} /> diff --git a/apps/web/core/components/issues/issue-layouts/empty-states/draft-issues.tsx b/apps/web/core/components/issues/issue-layouts/empty-states/draft-issues.tsx deleted file mode 100644 index bb10176ae9f..00000000000 --- a/apps/web/core/components/issues/issue-layouts/empty-states/draft-issues.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import { observer } from "mobx-react"; - -// FIXME: Project drafts is deprecated. Remove this component and all the related code. -export const ProjectDraftEmptyState: React.FC = observer(() => ( -
-)); diff --git a/apps/web/core/components/issues/issue-layouts/empty-states/index.tsx b/apps/web/core/components/issues/issue-layouts/empty-states/index.tsx index 1db3a3d8d11..ae23acb5747 100644 --- a/apps/web/core/components/issues/issue-layouts/empty-states/index.tsx +++ b/apps/web/core/components/issues/issue-layouts/empty-states/index.tsx @@ -5,7 +5,6 @@ import { TeamProjectWorkItemEmptyState } from "@/plane-web/components/issues/iss // components import { ProjectArchivedEmptyState } from "./archived-issues"; import { CycleEmptyState } from "./cycle"; -import { ProjectDraftEmptyState } from "./draft-issues"; import { GlobalViewEmptyState } from "./global-view"; import { ModuleEmptyState } from "./module"; import { ProfileViewEmptyState } from "./profile-view"; @@ -29,8 +28,6 @@ export const IssueLayoutEmptyState = (props: Props) => { return ; case EIssuesStoreType.MODULE: return ; - case EIssuesStoreType.DRAFT: - return ; case EIssuesStoreType.GLOBAL: return ; case EIssuesStoreType.PROFILE: diff --git a/apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/draft-issue.tsx b/apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/draft-issue.tsx deleted file mode 100644 index 3336327c376..00000000000 --- a/apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/draft-issue.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import { observer } from "mobx-react"; -import { useParams } from "next/navigation"; -// plane imports -import { EIssueFilterType } from "@plane/constants"; -import { EIssuesStoreType, IIssueFilterOptions } from "@plane/types"; -// hooks -import { useIssues } from "@/hooks/store/use-issues"; -import { useLabel } from "@/hooks/store/use-label"; -import { useProjectState } from "@/hooks/store/use-project-state"; -// local imports -import { AppliedFiltersList } from "../filters-list"; - -export const DraftIssueAppliedFiltersRoot: React.FC = observer(() => { - // router - const { workspaceSlug, projectId } = useParams() as { workspaceSlug: string; projectId: string }; - // store hooks - const { - issuesFilter: { issueFilters, updateFilters }, - } = useIssues(EIssuesStoreType.DRAFT); - const { projectLabels } = useLabel(); - const { projectStates } = useProjectState(); - // derived values - const userFilters = issueFilters?.filters; - // filters whose value not null or empty array - const appliedFilters: IIssueFilterOptions = {}; - Object.entries(userFilters ?? {}).forEach(([key, value]) => { - if (!value) return; - if (Array.isArray(value) && value.length === 0) return; - appliedFilters[key as keyof IIssueFilterOptions] = value; - }); - - const handleRemoveFilter = (key: keyof IIssueFilterOptions, value: string | null) => { - if (!workspaceSlug || !projectId) return; - - // remove all values of the key if value is null - if (!value) { - updateFilters(workspaceSlug.toString(), projectId.toString(), EIssueFilterType.FILTERS, { - [key]: null, - }); - return; - } - - // remove the passed value from the key - let newValues = issueFilters?.filters?.[key] ?? []; - newValues = newValues.filter((val) => val !== value); - - updateFilters(workspaceSlug.toString(), projectId.toString(), EIssueFilterType.FILTERS, { - [key]: newValues, - }); - }; - - const handleClearAllFilters = () => { - if (!workspaceSlug || !projectId) return; - - const newFilters: IIssueFilterOptions = {}; - Object.keys(userFilters ?? {}).forEach((key) => { - newFilters[key as keyof IIssueFilterOptions] = []; - }); - - updateFilters(workspaceSlug.toString(), projectId.toString(), EIssueFilterType.FILTERS, { ...newFilters }); - }; - - // return if no filters are applied - if (Object.keys(appliedFilters).length === 0) return null; - - return ( -
- -
- ); -}); diff --git a/apps/web/core/components/issues/issue-layouts/kanban/base-kanban-root.tsx b/apps/web/core/components/issues/issue-layouts/kanban/base-kanban-root.tsx index 11dfb2d92c3..f853f17df91 100644 --- a/apps/web/core/components/issues/issue-layouts/kanban/base-kanban-root.tsx +++ b/apps/web/core/components/issues/issue-layouts/kanban/base-kanban-root.tsx @@ -34,7 +34,6 @@ export type KanbanStoreType = | EIssuesStoreType.MODULE | EIssuesStoreType.CYCLE | EIssuesStoreType.PROJECT_VIEW - | EIssuesStoreType.DRAFT | EIssuesStoreType.PROFILE | EIssuesStoreType.TEAM | EIssuesStoreType.TEAM_VIEW diff --git a/apps/web/core/components/issues/issue-layouts/kanban/headers/group-by-card.tsx b/apps/web/core/components/issues/issue-layouts/kanban/headers/group-by-card.tsx index d9caaad1b4b..dc389a71583 100644 --- a/apps/web/core/components/issues/issue-layouts/kanban/headers/group-by-card.tsx +++ b/apps/web/core/components/issues/issue-layouts/kanban/headers/group-by-card.tsx @@ -2,7 +2,7 @@ import React, { FC } from "react"; import { observer } from "mobx-react"; -import { useParams, usePathname } from "next/navigation"; +import { useParams } from "next/navigation"; // lucide icons import { Minimize2, Maximize2, Circle, Plus } from "lucide-react"; import { WORK_ITEM_TRACKER_EVENTS } from "@plane/constants"; @@ -58,9 +58,6 @@ export const HeaderGroupByCard: FC = observer((props) => { const storeType = useIssueStoreType(); // router const { workspaceSlug, projectId, moduleId, cycleId } = useParams(); - const pathname = usePathname(); - - const isDraftIssue = pathname.includes("draft-issue"); const renderExistingIssueModal = moduleId || cycleId; const ExistingIssuesListModalPayload = moduleId ? { module: moduleId.toString() } : { cycle: true }; @@ -97,7 +94,6 @@ export const HeaderGroupByCard: FC = observer((props) => { onClose={() => setIsOpen(false)} data={issuePayload} storeType={storeType} - isDraft={isDraftIssue} /> )} diff --git a/apps/web/core/components/issues/issue-layouts/kanban/roots/draft-issue-root.tsx b/apps/web/core/components/issues/issue-layouts/kanban/roots/draft-issue-root.tsx deleted file mode 100644 index 568dd315fef..00000000000 --- a/apps/web/core/components/issues/issue-layouts/kanban/roots/draft-issue-root.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import { observer } from "mobx-react"; -// local imports -import { DraftIssueQuickActions } from "../../quick-action-dropdowns"; -import { BaseKanBanRoot } from "../base-kanban-root"; - -export const DraftKanBanLayout: React.FC = observer(() => ); diff --git a/apps/web/core/components/issues/issue-layouts/list/base-list-root.tsx b/apps/web/core/components/issues/issue-layouts/list/base-list-root.tsx index 99740ecfab5..aef85605366 100644 --- a/apps/web/core/components/issues/issue-layouts/list/base-list-root.tsx +++ b/apps/web/core/components/issues/issue-layouts/list/base-list-root.tsx @@ -30,7 +30,6 @@ type ListStoreType = | EIssuesStoreType.MODULE | EIssuesStoreType.CYCLE | EIssuesStoreType.PROJECT_VIEW - | EIssuesStoreType.DRAFT | EIssuesStoreType.PROFILE | EIssuesStoreType.ARCHIVED | EIssuesStoreType.WORKSPACE_DRAFT diff --git a/apps/web/core/components/issues/issue-layouts/list/headers/group-by-card.tsx b/apps/web/core/components/issues/issue-layouts/list/headers/group-by-card.tsx index 2e34570d368..a6bf2efe490 100644 --- a/apps/web/core/components/issues/issue-layouts/list/headers/group-by-card.tsx +++ b/apps/web/core/components/issues/issue-layouts/list/headers/group-by-card.tsx @@ -2,7 +2,7 @@ import { useState } from "react"; import { observer } from "mobx-react"; -import { useParams, usePathname } from "next/navigation"; +import { useParams } from "next/navigation"; import { CircleDashed, Plus } from "lucide-react"; // types import { WORK_ITEM_TRACKER_EVENTS } from "@plane/constants"; @@ -58,10 +58,8 @@ export const HeaderGroupByCard = observer((props: IHeaderGroupByCard) => { const [openExistingIssueListModal, setOpenExistingIssueListModal] = useState(false); // router const { workspaceSlug, projectId, moduleId, cycleId } = useParams(); - const pathname = usePathname(); const storeType = useIssueStoreType(); // derived values - const isDraftIssue = pathname.includes("draft-issue"); const renderExistingIssueModal = moduleId || cycleId; const existingIssuesListModalPayload = moduleId ? { module: moduleId.toString() } : { cycle: true }; const isGroupSelectionEmpty = selectionHelpers.isGroupSelected(groupID) === "empty"; @@ -167,7 +165,6 @@ export const HeaderGroupByCard = observer((props: IHeaderGroupByCard) => { onClose={() => setIsOpen(false)} data={issuePayload} storeType={storeType} - isDraft={isDraftIssue} /> )} diff --git a/apps/web/core/components/issues/issue-layouts/list/roots/draft-issue-root.tsx b/apps/web/core/components/issues/issue-layouts/list/roots/draft-issue-root.tsx deleted file mode 100644 index 4b3c8c5383b..00000000000 --- a/apps/web/core/components/issues/issue-layouts/list/roots/draft-issue-root.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { FC } from "react"; -import { observer } from "mobx-react"; -import { useParams } from "next/navigation"; -// local imports -import { DraftIssueQuickActions } from "../../quick-action-dropdowns"; -import { BaseListRoot } from "../base-list-root"; - -export const DraftIssueListLayout: FC = observer(() => { - const { workspaceSlug, projectId } = useParams(); - - if (!workspaceSlug || !projectId) return null; - - return ; -}); diff --git a/apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/all-issue.tsx b/apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/all-issue.tsx index f5ce7441d1a..4d8116f3a4f 100644 --- a/apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/all-issue.tsx +++ b/apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/all-issue.tsx @@ -118,7 +118,6 @@ export const AllIssueQuickActions: React.FC = observer((props if (issueToEdit && handleUpdate) await handleUpdate(data); }} storeType={EIssuesStoreType.GLOBAL} - isDraft={false} /> {issue.project_id && workspaceSlug && ( = observer((pro if (issueToEdit && handleUpdate) await handleUpdate(data); }} storeType={EIssuesStoreType.CYCLE} - isDraft={false} /> {issue.project_id && workspaceSlug && ( = observer((props) => { - const { - issue, - handleDelete, - handleUpdate, - customActionButton, - portalElement, - readOnly = false, - placements = "bottom-end", - parentRef, - } = props; - // router - const { workspaceSlug } = useParams(); - const pathname = usePathname(); - // states - const [createUpdateIssueModal, setCreateUpdateIssueModal] = useState(false); - const [issueToEdit, setIssueToEdit] = useState(undefined); - const [deleteIssueModal, setDeleteIssueModal] = useState(false); - // store hooks - const { allowPermissions } = useUserPermissions(); - // derived values - const activeLayout = "Draft Issues"; - // auth - const isEditingAllowed = - allowPermissions( - [EUserPermissions.ADMIN, EUserPermissions.MEMBER], - EUserPermissionsLevel.PROJECT, - workspaceSlug?.toString(), - issue.project_id ?? undefined - ) && !readOnly; - const isDeletingAllowed = isEditingAllowed; - - const isDraftIssue = pathname?.includes("draft-issues") || false; - - const duplicateIssuePayload = omit( - { - ...issue, - name: `${issue.name} (copy)`, - is_draft: isDraftIssue ? false : issue.is_draft, - sourceIssueId: issue.id, - }, - ["id"] - ); - - // Menu items and modals using helper - const menuItemProps: MenuItemFactoryProps = { - issue, - workspaceSlug: workspaceSlug?.toString(), - activeLayout, - isEditingAllowed, - isDeletingAllowed, - isDraftIssue, - setIssueToEdit, - setCreateUpdateIssueModal, - setDeleteIssueModal, - handleDelete, - handleUpdate, - storeType: EIssuesStoreType.DRAFT, - }; - - const MENU_ITEMS = useDraftIssueMenuItems(menuItemProps); - - const CONTEXT_MENU_ITEMS: TContextMenuItem[] = MENU_ITEMS.map((item) => ({ - ...item, - onClick: () => { - captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.QUICK_ACTIONS.DRAFT }); - item.action(); - }, - })); - - return ( - <> - {/* Modals */} - setDeleteIssueModal(false)} - onSubmit={handleDelete} - /> - { - setCreateUpdateIssueModal(false); - setIssueToEdit(undefined); - }} - data={issueToEdit ?? duplicateIssuePayload} - onSubmit={async (data) => { - if (issueToEdit && handleUpdate) await handleUpdate(data); - }} - storeType={EIssuesStoreType.DRAFT} - isDraft={isDraftIssue} - /> - - - - {MENU_ITEMS.map((item) => { - if (item.shouldRender === false) return null; - return ( - { - e.preventDefault(); - e.stopPropagation(); - captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.QUICK_ACTIONS.DRAFT }); - item.action(); - }} - className={cn( - "flex items-center gap-2", - { - "text-custom-text-400": item.disabled, - }, - item.className - )} - disabled={item.disabled} - > - {item.icon && } -
-
{item.title}
- {item.description && ( -

- {item.description} -

- )} -
-
- ); - })} -
- - ); -}); diff --git a/apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/helper.tsx b/apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/helper.tsx index 9d6862aaa20..80c4ae4f37b 100644 --- a/apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/helper.tsx +++ b/apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/helper.tsx @@ -54,7 +54,6 @@ export interface MenuItemFactoryProps { isRestoringAllowed?: boolean; isInArchivableGroup?: boolean; issueTypeDetail?: { is_active?: boolean }; - isDraftIssue?: boolean; // Action handlers setIssueToEdit: (issue: TIssue | undefined) => void; setCreateUpdateIssueModal: (open: boolean) => void; @@ -369,9 +368,3 @@ export const useArchivedIssueMenuItems = (props: MenuItemFactoryProps): TContext [factory] ); }; - -export const useDraftIssueMenuItems = (props: MenuItemFactoryProps): TContextMenuItem[] => { - const factory = useMenuItemFactory(props); - - return useMemo(() => [factory.createEditMenuItem(), factory.createDeleteMenuItem()], [factory]); -}; diff --git a/apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/index.ts b/apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/index.ts index 0862c68a933..19147a0ad61 100644 --- a/apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/index.ts +++ b/apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/index.ts @@ -1,7 +1,6 @@ export * from "./all-issue"; export * from "./archived-issue"; export * from "./cycle-issue"; -export * from "./draft-issue"; export * from "./module-issue"; export * from "./project-issue"; export * from "./helper"; diff --git a/apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/issue-detail.tsx b/apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/issue-detail.tsx index f2cd9a5c50f..1d83efc4e57 100644 --- a/apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/issue-detail.tsx +++ b/apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/issue-detail.tsx @@ -88,13 +88,10 @@ export const WorkItemDetailQuickActions: React.FC {issue.project_id && workspaceSlug && ( diff --git a/apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/module-issue.tsx b/apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/module-issue.tsx index 8b5db5b56c1..de20b469a35 100644 --- a/apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/module-issue.tsx +++ b/apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/module-issue.tsx @@ -134,7 +134,6 @@ export const ModuleIssueQuickActions: React.FC = observer((pr if (issueToEdit && handleUpdate) await handleUpdate(data); }} storeType={EIssuesStoreType.MODULE} - isDraft={false} /> {issue.project_id && workspaceSlug && ( = observer((p } = props; // router const { workspaceSlug } = useParams(); - const pathname = usePathname(); // states const [createUpdateIssueModal, setCreateUpdateIssueModal] = useState(false); const [issueToEdit, setIssueToEdit] = useState(undefined); @@ -71,13 +70,10 @@ export const ProjectIssueQuickActions: React.FC = observer((p const isInArchivableGroup = !!stateDetails && ARCHIVABLE_STATE_GROUPS.includes(stateDetails?.group); const isDeletingAllowed = isEditingAllowed; - const isDraftIssue = pathname?.includes("draft-issues") || false; - const duplicateIssuePayload = omit( { ...issue, name: `${issue.name} (copy)`, - is_draft: isDraftIssue ? false : issue.is_draft, sourceIssueId: issue.id, }, ["id"] @@ -93,7 +89,6 @@ export const ProjectIssueQuickActions: React.FC = observer((p isArchivingAllowed, isDeletingAllowed, isInArchivableGroup, - isDraftIssue, setIssueToEdit, setCreateUpdateIssueModal, setDeleteIssueModal, @@ -141,7 +136,6 @@ export const ProjectIssueQuickActions: React.FC = observer((p if (issueToEdit && handleUpdate) await handleUpdate(data); }} storeType={EIssuesStoreType.PROJECT} - isDraft={isDraftIssue} /> {issue.project_id && workspaceSlug && ( { - switch (props.activeLayout) { - case EIssueLayoutTypes.LIST: - return ; - case EIssueLayoutTypes.KANBAN: - return ; - default: - return null; - } -}; -export const DraftIssueLayoutRoot: React.FC = observer(() => { - // router - const { workspaceSlug, projectId } = useParams(); - // hooks - const { issuesFilter } = useIssues(EIssuesStoreType.DRAFT); - - const { isLoading } = useSWR( - workspaceSlug && projectId ? `DRAFT_ISSUES_${workspaceSlug.toString()}_${projectId.toString()}` : null, - async () => { - if (workspaceSlug && projectId) { - await issuesFilter?.fetchFilters(workspaceSlug.toString(), projectId.toString()); - } - }, - { revalidateIfStale: false, revalidateOnFocus: false } - ); - - const issueFilters = issuesFilter?.getIssueFilters(projectId?.toString()); - const activeLayout = issueFilters?.displayFilters?.layout || undefined; - - if (!workspaceSlug || !projectId) return <>; - - if (isLoading && !issueFilters) - return ( -
- -
- ); - - return ( - -
- -
- - {/* issue peek overview */} - -
-
-
- ); -}); diff --git a/apps/web/core/components/issues/issue-modal/base.tsx b/apps/web/core/components/issues/issue-modal/base.tsx index ed1351669fa..7a00bc17841 100644 --- a/apps/web/core/components/issues/issue-modal/base.tsx +++ b/apps/web/core/components/issues/issue-modal/base.tsx @@ -86,12 +86,7 @@ export const CreateUpdateIssueModalBase: React.FC = observer(( setDescription(data?.description_html || "

"); return; } - const response = await fetchIssue( - workspaceSlug.toString(), - projectId.toString(), - issueId, - isDraft ? "DRAFT" : "DEFAULT" - ); + const response = await fetchIssue(workspaceSlug.toString(), projectId.toString(), issueId); if (response) setDescription(response?.description_html || "

"); }; diff --git a/apps/web/core/components/issues/peek-overview/root.tsx b/apps/web/core/components/issues/peek-overview/root.tsx index a44bfa1c9d5..926b5430c17 100644 --- a/apps/web/core/components/issues/peek-overview/root.tsx +++ b/apps/web/core/components/issues/peek-overview/root.tsx @@ -64,7 +64,7 @@ export const IssuePeekOverview: FC = observer((props) => fetch: async (workspaceSlug: string, projectId: string, issueId: string) => { try { setError(false); - await fetchIssue(workspaceSlug, projectId, issueId, is_draft ? "DRAFT" : "DEFAULT"); + await fetchIssue(workspaceSlug, projectId, issueId); } catch (error) { setError(true); console.error("Error fetching the parent issue", error); diff --git a/apps/web/core/components/workspace/sidebar/quick-actions.tsx b/apps/web/core/components/workspace/sidebar/quick-actions.tsx index 4eee72815a0..4ed6b7bb228 100644 --- a/apps/web/core/components/workspace/sidebar/quick-actions.tsx +++ b/apps/web/core/components/workspace/sidebar/quick-actions.tsx @@ -70,6 +70,7 @@ export const SidebarQuickActions = observer(() => { onClose={() => setIsDraftIssueModalOpen(false)} data={workspaceDraftIssue ?? {}} onSubmit={() => removeWorkspaceDraftIssue()} + fetchIssueDetails={false} isDraft />
diff --git a/apps/web/core/hooks/store/use-issues.ts b/apps/web/core/hooks/store/use-issues.ts index 5ac116f9c2c..a732b6580d7 100644 --- a/apps/web/core/hooks/store/use-issues.ts +++ b/apps/web/core/hooks/store/use-issues.ts @@ -11,7 +11,6 @@ import type { ITeamViewIssues, ITeamViewIssuesFilter } from "@/plane-web/store/i import type { IWorkspaceIssues } from "@/plane-web/store/issue/workspace/issue.store"; import type { IArchivedIssues, IArchivedIssuesFilter } from "@/store/issue/archived"; import type { ICycleIssues, ICycleIssuesFilter } from "@/store/issue/cycle"; -import type { IDraftIssues, IDraftIssuesFilter } from "@/store/issue/draft"; import type { IModuleIssues, IModuleIssuesFilter } from "@/store/issue/module"; import type { IProfileIssues, IProfileIssuesFilter } from "@/store/issue/profile"; import type { IProjectIssues, IProjectIssuesFilter } from "@/store/issue/project"; @@ -65,10 +64,6 @@ export type TStoreIssues = { issues: IArchivedIssues; issuesFilter: IArchivedIssuesFilter; }; - [EIssuesStoreType.DRAFT]: defaultIssueStore & { - issues: IDraftIssues; - issuesFilter: IDraftIssuesFilter; - }; [EIssuesStoreType.DEFAULT]: defaultIssueStore & { issues: IProjectIssues; issuesFilter: IProjectIssuesFilter; @@ -142,11 +137,6 @@ export const useIssues = (storeType?: T): TStoreIssu issues: context.issue.archivedIssues, issuesFilter: context.issue.archivedIssuesFilter, }) as TStoreIssues[T]; - case EIssuesStoreType.DRAFT: - return merge(defaultStore, { - issues: context.issue.draftIssues, - issuesFilter: context.issue.draftIssuesFilter, - }) as TStoreIssues[T]; case EIssuesStoreType.EPIC: return merge(defaultStore, { issues: context.issue.projectEpics, diff --git a/apps/web/core/hooks/use-group-dragndrop.ts b/apps/web/core/hooks/use-group-dragndrop.ts index fedb079597a..4193e5c2375 100644 --- a/apps/web/core/hooks/use-group-dragndrop.ts +++ b/apps/web/core/hooks/use-group-dragndrop.ts @@ -14,7 +14,6 @@ type DNDStoreType = | EIssuesStoreType.MODULE | EIssuesStoreType.CYCLE | EIssuesStoreType.PROJECT_VIEW - | EIssuesStoreType.DRAFT | EIssuesStoreType.PROFILE | EIssuesStoreType.ARCHIVED | EIssuesStoreType.WORKSPACE_DRAFT diff --git a/apps/web/core/hooks/use-issues-actions.tsx b/apps/web/core/hooks/use-issues-actions.tsx index e8c97352525..cdfb5864f67 100644 --- a/apps/web/core/hooks/use-issues-actions.tsx +++ b/apps/web/core/hooks/use-issues-actions.tsx @@ -52,7 +52,6 @@ export const useIssuesActions = (storeType: EIssuesStoreType): IssueActions => { const projectViewIssueActions = useProjectViewIssueActions(); const globalIssueActions = useGlobalIssueActions(); const profileIssueActions = useProfileIssueActions(); - const draftIssueActions = useDraftIssueActions(); const archivedIssueActions = useArchivedIssueActions(); const workspaceDraftIssueActions = useWorkspaceDraftIssueActions(); const teamProjectWorkItemsActions = useTeamProjectWorkItemsActions(); @@ -68,8 +67,6 @@ export const useIssuesActions = (storeType: EIssuesStoreType): IssueActions => { return teamIssueActions; case EIssuesStoreType.ARCHIVED: return archivedIssueActions; - case EIssuesStoreType.DRAFT: - return draftIssueActions; case EIssuesStoreType.CYCLE: return cycleIssueActions; case EIssuesStoreType.MODULE: @@ -644,76 +641,6 @@ const useProjectViewIssueActions = () => { ); }; -const useDraftIssueActions = () => { - // router - const { workspaceSlug: routerWorkspaceSlug, projectId: routerProjectId } = useParams(); - const workspaceSlug = routerWorkspaceSlug?.toString(); - const projectId = routerProjectId?.toString(); - // store hooks - const { issues, issuesFilter } = useIssues(EIssuesStoreType.DRAFT); - - const fetchIssues = useCallback( - async (loadType: TLoader, options: IssuePaginationOptions) => { - if (!workspaceSlug || !projectId) return; - return issues.fetchIssues(workspaceSlug.toString(), projectId.toString(), loadType, options); - }, - [issues.fetchIssues, workspaceSlug, projectId] - ); - const fetchNextIssues = useCallback( - async (groupId?: string, subGroupId?: string) => { - if (!workspaceSlug || !projectId) return; - return issues.fetchNextIssues(workspaceSlug.toString(), projectId.toString(), groupId, subGroupId); - }, - [issues.fetchIssues, workspaceSlug, projectId] - ); - - const createIssue = useCallback( - async (projectId: string | undefined | null, data: Partial) => { - if (!workspaceSlug || !projectId) return; - return await issues.createIssue(workspaceSlug, projectId, data); - }, - [issues.createIssue, workspaceSlug] - ); - const updateIssue = useCallback( - async (projectId: string | undefined | null, issueId: string, data: Partial) => { - if (!workspaceSlug || !projectId) return; - return await issues.updateIssue(workspaceSlug, projectId, issueId, data); - }, - [issues.updateIssue, workspaceSlug] - ); - const removeIssue = useCallback( - async (projectId: string | undefined | null, issueId: string) => { - if (!workspaceSlug || !projectId) return; - return await issues.removeIssue(workspaceSlug, projectId, issueId); - }, - [issues.removeIssue, workspaceSlug] - ); - - const updateFilters = useCallback( - async ( - projectId: string, - filterType: EIssueFilterType, - filters: IIssueFilterOptions | IIssueDisplayFilterOptions | IIssueDisplayProperties | TIssueKanbanFilters - ) => { - if (!workspaceSlug) return; - return await issuesFilter.updateFilters(workspaceSlug, projectId, filterType, filters); - }, - [issuesFilter.updateFilters] - ); - - return useMemo( - () => ({ - fetchIssues, - fetchNextIssues, - createIssue, - updateIssue, - removeIssue, - updateFilters, - }), - [fetchIssues, createIssue, updateIssue, removeIssue, updateFilters] - ); -}; - const useArchivedIssueActions = () => { // router const { workspaceSlug: routerWorkspaceSlug, projectId: routerProjectId } = useParams(); diff --git a/apps/web/core/services/issue/index.ts b/apps/web/core/services/issue/index.ts index 77acc8625bd..08983c0e139 100644 --- a/apps/web/core/services/issue/index.ts +++ b/apps/web/core/services/issue/index.ts @@ -1,6 +1,5 @@ export * from "./issue_archive.service"; export * from "./issue.service"; -export * from "./issue_draft.service"; export * from "./issue_reaction.service"; export * from "./issue_label.service"; export * from "./issue_attachment.service"; diff --git a/apps/web/core/services/issue/issue_draft.service.ts b/apps/web/core/services/issue/issue_draft.service.ts deleted file mode 100644 index ebac8620511..00000000000 --- a/apps/web/core/services/issue/issue_draft.service.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { API_BASE_URL } from "@plane/constants"; -import { TIssue, TIssuesResponse } from "@plane/types"; -import { APIService } from "@/services/api.service"; -// helpers - -export class IssueDraftService extends APIService { - constructor() { - super(API_BASE_URL); - } - - async getDraftIssues(workspaceSlug: string, projectId: string, query?: any, config = {}): Promise { - return this.get( - `/api/workspaces/${workspaceSlug}/projects/${projectId}/issue-drafts/`, - { - params: { ...query }, - }, - config - ) - .then((response) => response?.data) - .catch((error) => { - throw error?.response?.data; - }); - } - - async createDraftIssue(workspaceSlug: string, projectId: string, data: any): Promise { - return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issue-drafts/`, data) - .then((response) => response?.data) - .catch((error) => { - throw error?.response; - }); - } - - async updateDraftIssue(workspaceSlug: string, projectId: string, issueId: string, data: any): Promise { - return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issue-drafts/${issueId}/`, data) - .then((response) => response?.data) - .catch((error) => { - throw error?.response; - }); - } - - async deleteDraftIssue(workspaceSlug: string, projectId: string, issueId: string): Promise { - return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issue-drafts/${issueId}/`) - .then((response) => response?.data) - .catch((error) => { - throw error?.response; - }); - } - - async getDraftIssueById(workspaceSlug: string, projectId: string, issueId: string, queries?: any): Promise { - return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issue-drafts/${issueId}/`, { - params: queries, - }) - .then((response) => response?.data) - .catch((error) => { - throw error?.response; - }); - } -} diff --git a/apps/web/core/store/issue/draft/filter.store.ts b/apps/web/core/store/issue/draft/filter.store.ts deleted file mode 100644 index bfde23bc05e..00000000000 --- a/apps/web/core/store/issue/draft/filter.store.ts +++ /dev/null @@ -1,279 +0,0 @@ -import isArray from "lodash/isArray"; -import isEmpty from "lodash/isEmpty"; -import pickBy from "lodash/pickBy"; -import set from "lodash/set"; -import { action, computed, makeObservable, observable, runInAction } from "mobx"; -// base class -import { computedFn } from "mobx-utils"; -import { EIssueFilterType } from "@plane/constants"; -import { - EIssuesStoreType, - IIssueFilterOptions, - IIssueDisplayFilterOptions, - IIssueDisplayProperties, - TIssueKanbanFilters, - IIssueFilters, - TIssueParams, - IssuePaginationOptions, -} from "@plane/types"; -import { handleIssueQueryParamsByLayout } from "@plane/utils"; -import { IssueFiltersService } from "@/services/issue_filter.service"; -import { IBaseIssueFilterStore, IssueFilterHelperStore } from "../helpers/issue-filter-helper.store"; -// helpers -// types -import { IIssueRootStore } from "../root.store"; -// constants -// services - -export interface IDraftIssuesFilter extends IBaseIssueFilterStore { - //helper actions - getFilterParams: ( - options: IssuePaginationOptions, - projectId: string, - cursor: string | undefined, - groupId: string | undefined, - subGroupId: string | undefined - ) => Partial>; - getIssueFilters(projectId: string): IIssueFilters | undefined; - // action - fetchFilters: (workspaceSlug: string, projectId: string) => Promise; - updateFilters: ( - workspaceSlug: string, - projectId: string, - filterType: EIssueFilterType, - filters: IIssueFilterOptions | IIssueDisplayFilterOptions | IIssueDisplayProperties | TIssueKanbanFilters - ) => Promise; -} - -export class DraftIssuesFilter extends IssueFilterHelperStore implements IDraftIssuesFilter { - // observables - filters: { [projectId: string]: IIssueFilters } = {}; - // root store - rootIssueStore: IIssueRootStore; - // services - issueFilterService; - - constructor(_rootStore: IIssueRootStore) { - super(); - makeObservable(this, { - // observables - filters: observable, - // computed - issueFilters: computed, - appliedFilters: computed, - // actions - fetchFilters: action, - updateFilters: action, - }); - // root store - this.rootIssueStore = _rootStore; - // services - this.issueFilterService = new IssueFiltersService(); - } - - get issueFilters() { - const projectId = this.rootIssueStore.projectId; - if (!projectId) return undefined; - - return this.getIssueFilters(projectId); - } - - get appliedFilters() { - const projectId = this.rootIssueStore.projectId; - if (!projectId) return undefined; - - return this.getAppliedFilters(projectId); - } - - getIssueFilters(projectId: string) { - const displayFilters = this.filters[projectId] || undefined; - if (!projectId || isEmpty(displayFilters)) return undefined; - - const _filters: IIssueFilters = this.computedIssueFilters(displayFilters); - - return _filters; - } - - getAppliedFilters(projectId: string) { - const userFilters = this.getIssueFilters(projectId); - if (!userFilters) return undefined; - - const filteredParams = handleIssueQueryParamsByLayout(userFilters?.displayFilters?.layout, "issues"); - if (!filteredParams) return undefined; - - const filteredRouteParams: Partial> = this.computedFilteredParams( - userFilters?.filters as IIssueFilterOptions, - userFilters?.displayFilters as IIssueDisplayFilterOptions, - filteredParams - ); - - return filteredRouteParams; - } - - getFilterParams = computedFn( - ( - options: IssuePaginationOptions, - projectId: string, - cursor: string | undefined, - groupId: string | undefined, - subGroupId: string | undefined - ) => { - const filterParams = this.getAppliedFilters(projectId); - - const paginationParams = this.getPaginationParams(filterParams, options, cursor, groupId, subGroupId); - return paginationParams; - } - ); - - fetchFilters = async (workspaceSlug: string, projectId: string) => { - const _filters = this.handleIssuesLocalFilters.get(EIssuesStoreType.DRAFT, workspaceSlug, projectId, undefined); - - const filters: IIssueFilterOptions = this.computedFilters(_filters?.filters); - const displayFilters: IIssueDisplayFilterOptions = this.computedDisplayFilters(_filters?.display_filters); - const displayProperties: IIssueDisplayProperties = this.computedDisplayProperties(_filters?.display_properties); - const kanbanFilters = { - group_by: [], - sub_group_by: [], - }; - kanbanFilters.group_by = _filters?.kanban_filters?.group_by || []; - kanbanFilters.sub_group_by = _filters?.kanban_filters?.sub_group_by || []; - - runInAction(() => { - set(this.filters, [projectId, "filters"], filters); - set(this.filters, [projectId, "displayFilters"], displayFilters); - set(this.filters, [projectId, "displayProperties"], displayProperties); - set(this.filters, [projectId, "kanbanFilters"], kanbanFilters); - }); - }; - - updateFilters = async ( - workspaceSlug: string, - projectId: string, - type: EIssueFilterType, - filters: IIssueFilterOptions | IIssueDisplayFilterOptions | IIssueDisplayProperties | TIssueKanbanFilters - ) => { - try { - if (isEmpty(this.filters) || isEmpty(this.filters[projectId]) || isEmpty(filters)) return; - - const _filters = { - filters: this.filters[projectId].filters as IIssueFilterOptions, - displayFilters: this.filters[projectId].displayFilters as IIssueDisplayFilterOptions, - displayProperties: this.filters[projectId].displayProperties as IIssueDisplayProperties, - kanbanFilters: this.filters[projectId].kanbanFilters as TIssueKanbanFilters, - }; - - switch (type) { - case EIssueFilterType.FILTERS: { - const updatedFilters = filters as IIssueFilterOptions; - _filters.filters = { ..._filters.filters, ...updatedFilters }; - - runInAction(() => { - Object.keys(updatedFilters).forEach((_key) => { - set(this.filters, [projectId, "filters", _key], updatedFilters[_key as keyof IIssueFilterOptions]); - }); - }); - const appliedFilters = _filters.filters || {}; - const filteredFilters = pickBy(appliedFilters, (value) => value && isArray(value) && value.length > 0); - this.rootIssueStore.draftIssues.fetchIssuesWithExistingPagination( - workspaceSlug, - projectId, - isEmpty(filteredFilters) ? "init-loader" : "mutation" - ); - this.handleIssuesLocalFilters.set(EIssuesStoreType.DRAFT, type, workspaceSlug, projectId, undefined, { - filters: _filters.filters, - }); - break; - } - case EIssueFilterType.DISPLAY_FILTERS: { - const updatedDisplayFilters = filters as IIssueDisplayFilterOptions; - _filters.displayFilters = { ..._filters.displayFilters, ...updatedDisplayFilters }; - - // set sub_group_by to null if group_by is set to null - if (_filters.displayFilters.group_by === null) { - _filters.displayFilters.sub_group_by = null; - updatedDisplayFilters.sub_group_by = null; - } - // set sub_group_by to null if layout is switched to kanban group_by and sub_group_by are same - if ( - _filters.displayFilters.layout === "kanban" && - _filters.displayFilters.group_by === _filters.displayFilters.sub_group_by - ) { - _filters.displayFilters.sub_group_by = null; - updatedDisplayFilters.sub_group_by = null; - } - // set group_by to state if layout is switched to kanban and group_by is null - if (_filters.displayFilters.layout === "kanban" && _filters.displayFilters.group_by === null) { - _filters.displayFilters.group_by = "state"; - updatedDisplayFilters.group_by = "state"; - } - - runInAction(() => { - Object.keys(updatedDisplayFilters).forEach((_key) => { - set( - this.filters, - [projectId, "displayFilters", _key], - updatedDisplayFilters[_key as keyof IIssueDisplayFilterOptions] - ); - }); - }); - - if (this.getShouldReFetchIssues(updatedDisplayFilters)) { - this.rootIssueStore.draftIssues.fetchIssuesWithExistingPagination(workspaceSlug, projectId, "mutation"); - } - - this.handleIssuesLocalFilters.set(EIssuesStoreType.DRAFT, type, workspaceSlug, projectId, undefined, { - display_filters: _filters.displayFilters, - }); - - break; - } - case EIssueFilterType.DISPLAY_PROPERTIES: { - const updatedDisplayProperties = filters as IIssueDisplayProperties; - _filters.displayProperties = { ..._filters.displayProperties, ...updatedDisplayProperties }; - - runInAction(() => { - Object.keys(updatedDisplayProperties).forEach((_key) => { - set( - this.filters, - [projectId, "displayProperties", _key], - updatedDisplayProperties[_key as keyof IIssueDisplayProperties] - ); - }); - }); - - this.handleIssuesLocalFilters.set(EIssuesStoreType.DRAFT, type, workspaceSlug, projectId, undefined, { - display_properties: _filters.displayProperties, - }); - break; - } - case EIssueFilterType.KANBAN_FILTERS: { - const updatedKanbanFilters = filters as TIssueKanbanFilters; - _filters.kanbanFilters = { ..._filters.kanbanFilters, ...updatedKanbanFilters }; - - const currentUserId = this.rootIssueStore.currentUserId; - if (currentUserId) - this.handleIssuesLocalFilters.set(EIssuesStoreType.DRAFT, type, workspaceSlug, projectId, undefined, { - kanban_filters: _filters.kanbanFilters, - }); - - runInAction(() => { - Object.keys(updatedKanbanFilters).forEach((_key) => { - set( - this.filters, - [projectId, "kanbanFilters", _key], - updatedKanbanFilters[_key as keyof TIssueKanbanFilters] - ); - }); - }); - - break; - } - default: - break; - } - } catch (error) { - this.fetchFilters(workspaceSlug, projectId); - throw error; - } - }; -} diff --git a/apps/web/core/store/issue/draft/index.ts b/apps/web/core/store/issue/draft/index.ts deleted file mode 100644 index 0fe6c946b0c..00000000000 --- a/apps/web/core/store/issue/draft/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./filter.store"; -export * from "./issue.store"; diff --git a/apps/web/core/store/issue/draft/issue.store.ts b/apps/web/core/store/issue/draft/issue.store.ts deleted file mode 100644 index c1ccc98a7b2..00000000000 --- a/apps/web/core/store/issue/draft/issue.store.ts +++ /dev/null @@ -1,186 +0,0 @@ -import { action, makeObservable, runInAction } from "mobx"; -// base class -// services -// types -import { - TIssue, - TLoader, - ViewFlags, - IssuePaginationOptions, - TIssuesResponse, - TBulkOperationsPayload, -} from "@plane/types"; -import { BaseIssuesStore, IBaseIssuesStore } from "../helpers/base-issues.store"; -import { IIssueRootStore } from "../root.store"; -import { IDraftIssuesFilter } from "./filter.store"; - -export interface IDraftIssues extends IBaseIssuesStore { - // observable - - viewFlags: ViewFlags; - // actions - fetchIssues: ( - workspaceSlug: string, - projectId: string, - loadType: TLoader, - option: IssuePaginationOptions - ) => Promise; - fetchIssuesWithExistingPagination: ( - workspaceSlug: string, - projectId: string, - loadType: TLoader - ) => Promise; - - fetchNextIssues: ( - workspaceSlug: string, - projectId: string, - groupId?: string, - subGroupId?: string - ) => Promise; - createIssue: (workspaceSlug: string, projectId: string, data: Partial) => Promise; - updateIssue: (workspaceSlug: string, projectId: string, issueId: string, data: Partial) => Promise; - removeBulkIssues: (workspaceSlug: string, projectId: string, issueIds: string[]) => Promise; - bulkUpdateProperties: (workspaceSlug: string, projectId: string, data: TBulkOperationsPayload) => Promise; - - archiveBulkIssues: undefined; - quickAddIssue: undefined; - archiveIssue: undefined; -} - -export class DraftIssues extends BaseIssuesStore implements IDraftIssues { - viewFlags = { - enableQuickAdd: false, - enableIssueCreation: true, - enableInlineEditing: true, - }; - // filter store - issueFilterStore: IDraftIssuesFilter; - - constructor(_rootStore: IIssueRootStore, issueFilterStore: IDraftIssuesFilter) { - super(_rootStore, issueFilterStore); - makeObservable(this, { - // action - fetchIssues: action, - fetchNextIssues: action, - fetchIssuesWithExistingPagination: action, - }); - // filter store - this.issueFilterStore = issueFilterStore; - } - - /** - * Fetches the project details - * @param workspaceSlug - * @param projectId - */ - fetchParentStats = async (workspaceSlug: string, projectId?: string) => { - projectId && this.rootIssueStore.rootStore.projectRoot.project.fetchProjectDetails(workspaceSlug, projectId); - }; - - /** */ - updateParentStats = () => {}; - - /** - * This method is called to fetch the first issues of pagination - * @param workspaceSlug - * @param projectId - * @param loadType - * @param options - * @returns - */ - fetchIssues = async ( - workspaceSlug: string, - projectId: string, - loadType: TLoader = "init-loader", - options: IssuePaginationOptions, - isExistingPaginationOptions: boolean = false - ) => { - try { - // set loader and clear store - runInAction(() => { - this.setLoader(loadType); - }); - this.clear(!isExistingPaginationOptions); - - // get params from pagination options - const params = this.issueFilterStore?.getFilterParams(options, projectId, undefined, undefined, undefined); - // call the fetch issues API with the params - const response = await this.issueDraftService.getDraftIssues(workspaceSlug, projectId, params, { - signal: this.controller.signal, - }); - - // after fetching issues, call the base method to process the response further - this.onfetchIssues(response, options, workspaceSlug, projectId, undefined, !isExistingPaginationOptions); - return response; - } catch (error) { - // set loader to undefined if errored out - this.setLoader(undefined); - throw error; - } - }; - - /** - * This method is called subsequent pages of pagination - * if groupId/subgroupId is provided, only that specific group's next page is fetched - * else all the groups' next page is fetched - * @param workspaceSlug - * @param projectId - * @param groupId - * @param subGroupId - * @returns - */ - fetchNextIssues = async (workspaceSlug: string, projectId: string, groupId?: string, subGroupId?: string) => { - const cursorObject = this.getPaginationData(groupId, subGroupId); - // if there are no pagination options and the next page results do not exist the return - if (!this.paginationOptions || (cursorObject && !cursorObject?.nextPageResults)) return; - try { - // set Loader - this.setLoader("pagination", groupId, subGroupId); - - // get params from stored pagination options - const params = this.issueFilterStore?.getFilterParams( - this.paginationOptions, - projectId, - this.getNextCursor(groupId, subGroupId), - groupId, - subGroupId - ); - // call the fetch issues API with the params for next page in issues - const response = await this.issueDraftService.getDraftIssues(workspaceSlug, projectId, params); - - // after the next page of issues are fetched, call the base method to process the response - this.onfetchNexIssues(response, groupId, subGroupId); - return response; - } catch (error) { - // set Loader as undefined if errored out - this.setLoader(undefined, groupId, subGroupId); - throw error; - } - }; - - /** - * This Method exists to fetch the first page of the issues with the existing stored pagination - * This is useful for refetching when filters, groupBy, orderBy etc changes - * @param workspaceSlug - * @param projectId - * @param loadType - * @returns - */ - fetchIssuesWithExistingPagination = async ( - workspaceSlug: string, - projectId: string, - loadType: TLoader = "mutation" - ) => { - if (!this.paginationOptions) return; - return await this.fetchIssues(workspaceSlug, projectId, loadType, this.paginationOptions, true); - }; - - // Using aliased names as they cannot be overridden in other stores - createIssue = this.createDraftIssue; - updateIssue = this.updateDraftIssue; - - // Setting them as undefined as they can not performed on draft issues - archiveBulkIssues = undefined; - quickAddIssue = undefined; - archiveIssue = undefined; -} diff --git a/apps/web/core/store/issue/helpers/base-issues.store.ts b/apps/web/core/store/issue/helpers/base-issues.store.ts index 43e92642f3e..c12bd9e9e50 100644 --- a/apps/web/core/store/issue/helpers/base-issues.store.ts +++ b/apps/web/core/store/issue/helpers/base-issues.store.ts @@ -41,7 +41,7 @@ import { updatePersistentLayer } from "@/local-db/utils/utils"; import { workItemSortWithOrderByExtended } from "@/plane-web/store/issue/helpers/base-issue.store"; // services import { CycleService } from "@/services/cycle.service"; -import { IssueArchiveService, IssueDraftService, IssueService } from "@/services/issue"; +import { IssueArchiveService, IssueService } from "@/services/issue"; import { ModuleService } from "@/services/module.service"; // import { IIssueRootStore } from "../root.store"; @@ -194,7 +194,6 @@ export abstract class BaseIssuesStore implements IBaseIssuesStore { // services issueService; issueArchiveService; - issueDraftService; moduleService; cycleService; // root store @@ -238,8 +237,6 @@ export abstract class BaseIssuesStore implements IBaseIssuesStore { createIssue: action, issueUpdate: action, - createDraftIssue: action, - updateDraftIssue: action, updateIssueDates: action, issueQuickAdd: action.bound, removeIssue: action.bound, @@ -264,7 +261,6 @@ export abstract class BaseIssuesStore implements IBaseIssuesStore { this.issueService = new IssueService(serviceType); this.issueArchiveService = new IssueArchiveService(); - this.issueDraftService = new IssueDraftService(); this.moduleService = new ModuleService(); this.cycleService = new CycleService(); @@ -613,54 +609,6 @@ export abstract class BaseIssuesStore implements IBaseIssuesStore { } } - /** - * Similar to Create Issue but for creating Draft issues - * @param workspaceSlug - * @param projectId - * @param data draft issue data - * @returns - */ - async createDraftIssue(workspaceSlug: string, projectId: string, data: Partial) { - // call API to create a Draft issue - const response = await this.issueDraftService.createDraftIssue(workspaceSlug, projectId, data); - // call Fetch parent stats - this.fetchParentStats(workspaceSlug, projectId); - // Add issue to store - this.addIssue(response); - return response; - } - - /** - * Similar to update issue but for draft issues. - * @param workspaceSlug - * @param projectId - * @param issueId - * @param data Partial Issue Data to be updated - */ - async updateDraftIssue(workspaceSlug: string, projectId: string, issueId: string, data: Partial) { - // Store Before state of the issue - const issueBeforeUpdate = clone(this.rootIssueStore.issues.getIssueById(issueId)); - try { - // Update the Respective Stores - this.rootIssueStore.issues.updateIssue(issueId, data); - this.updateIssueList({ ...issueBeforeUpdate, ...data } as TIssue, issueBeforeUpdate); - - // call API to update the issue - await this.issueDraftService.updateDraftIssue(workspaceSlug, projectId, issueId, data); - - // call Fetch parent stats - this.fetchParentStats(workspaceSlug, projectId); - - // If the issue is updated to not a draft issue anymore remove from the store list - if (!isNil(data.is_draft) && !data.is_draft) this.removeIssueFromList(issueId); - } catch (error) { - // If errored out update store again to revert the change - this.rootIssueStore.issues.updateIssue(issueId, issueBeforeUpdate ?? {}); - this.updateIssueList(issueBeforeUpdate, { ...issueBeforeUpdate, ...data } as TIssue); - throw error; - } - } - /** * This method is called to delete an issue * @param workspaceSlug diff --git a/apps/web/core/store/issue/issue-details/issue.store.ts b/apps/web/core/store/issue/issue-details/issue.store.ts index 21e879b307f..229fbf42e4a 100644 --- a/apps/web/core/store/issue/issue-details/issue.store.ts +++ b/apps/web/core/store/issue/issue-details/issue.store.ts @@ -5,18 +5,13 @@ import { EIssueServiceType, TIssue, TIssueServiceType } from "@plane/types"; // local import { persistence } from "@/local-db/storage.sqlite"; // services -import { IssueArchiveService, IssueDraftService, IssueService } from "@/services/issue"; +import { IssueArchiveService, WorkspaceDraftService, IssueService } from "@/services/issue"; // types import { IIssueDetail } from "./root.store"; export interface IIssueStoreActions { // actions - fetchIssue: ( - workspaceSlug: string, - projectId: string, - issueId: string, - issueStatus?: "DEFAULT" | "DRAFT" - ) => Promise; + fetchIssue: (workspaceSlug: string, projectId: string, issueId: string) => Promise; updateIssue: (workspaceSlug: string, projectId: string, issueId: string, data: Partial) => Promise; removeIssue: (workspaceSlug: string, projectId: string, issueId: string) => Promise; archiveIssue: (workspaceSlug: string, projectId: string, issueId: string) => Promise; @@ -52,7 +47,7 @@ export class IssueStore implements IIssueStore { issueService; epicService; issueArchiveService; - issueDraftService; + draftWorkItemService; constructor(rootStore: IIssueDetail, serviceType: TIssueServiceType) { makeObservable(this, { @@ -66,7 +61,7 @@ export class IssueStore implements IIssueStore { this.issueService = new IssueService(serviceType); this.epicService = new IssueService(EIssueServiceType.EPICS); this.issueArchiveService = new IssueArchiveService(serviceType); - this.issueDraftService = new IssueDraftService(); + this.draftWorkItemService = new WorkspaceDraftService(); } getIsFetchingIssueDetails = computedFn((issueId: string | undefined) => { @@ -93,7 +88,7 @@ export class IssueStore implements IIssueStore { }); // actions - fetchIssue = async (workspaceSlug: string, projectId: string, issueId: string, issueStatus = "DEFAULT") => { + fetchIssue = async (workspaceSlug: string, projectId: string, issueId: string) => { const query = { expand: "issue_reactions,issue_attachments,issue_link,parent", }; @@ -112,9 +107,7 @@ export class IssueStore implements IIssueStore { this.localDBIssueDescription = issueId; } - if (issueStatus === "DRAFT") - issue = await this.issueDraftService.getDraftIssueById(workspaceSlug, projectId, issueId, query); - else issue = await this.issueService.retrieve(workspaceSlug, projectId, issueId, query); + await this.issueService.retrieve(workspaceSlug, projectId, issueId, query); if (!issue) throw new Error("Work item not found"); diff --git a/apps/web/core/store/issue/issue-details/root.store.ts b/apps/web/core/store/issue/issue-details/root.store.ts index 1455dff91af..d8b9c80244d 100644 --- a/apps/web/core/store/issue/issue-details/root.store.ts +++ b/apps/web/core/store/issue/issue-details/root.store.ts @@ -272,12 +272,8 @@ export abstract class IssueDetail implements IIssueDetail { setIssueLinkData = (issueLinkData: TIssueLink | null) => (this.issueLinkData = issueLinkData); // issue - fetchIssue = async ( - workspaceSlug: string, - projectId: string, - issueId: string, - issueStatus: "DEFAULT" | "DRAFT" = "DEFAULT" - ) => this.issue.fetchIssue(workspaceSlug, projectId, issueId, issueStatus); + fetchIssue = async (workspaceSlug: string, projectId: string, issueId: string) => + this.issue.fetchIssue(workspaceSlug, projectId, issueId); fetchIssueWithIdentifier = async (workspaceSlug: string, projectIdentifier: string, sequenceId: string) => this.issue.fetchIssueWithIdentifier(workspaceSlug, projectIdentifier, sequenceId); updateIssue = async (workspaceSlug: string, projectId: string, issueId: string, data: Partial) => diff --git a/apps/web/core/store/issue/root.store.ts b/apps/web/core/store/issue/root.store.ts index 3dc835f0fad..d8cc94bfeb3 100644 --- a/apps/web/core/store/issue/root.store.ts +++ b/apps/web/core/store/issue/root.store.ts @@ -33,7 +33,6 @@ import { IWorkspaceMembership } from "@/store/member/workspace-member.store"; // issues data store import { IArchivedIssuesFilter, ArchivedIssuesFilter, IArchivedIssues, ArchivedIssues } from "./archived"; import { ICycleIssuesFilter, CycleIssuesFilter, ICycleIssues, CycleIssues } from "./cycle"; -import { IDraftIssuesFilter, DraftIssuesFilter, IDraftIssues, DraftIssues } from "./draft"; import { IIssueStore, IssueStore } from "./issue.store"; import { ICalendarStore, CalendarStore } from "./issue_calendar_view.store"; import { IIssueKanBanViewStore, IssueKanBanViewStore } from "./issue_kanban_view.store"; @@ -115,9 +114,6 @@ export interface IIssueRootStore { archivedIssuesFilter: IArchivedIssuesFilter; archivedIssues: IArchivedIssues; - draftIssuesFilter: IDraftIssuesFilter; - draftIssues: IDraftIssues; - issueKanBanView: IIssueKanBanViewStore; issueCalendarView: ICalendarStore; @@ -186,9 +182,6 @@ export class IssueRootStore implements IIssueRootStore { archivedIssuesFilter: IArchivedIssuesFilter; archivedIssues: IArchivedIssues; - draftIssuesFilter: IDraftIssuesFilter; - draftIssues: IDraftIssues; - issueKanBanView: IIssueKanBanViewStore; issueCalendarView: ICalendarStore; @@ -280,9 +273,6 @@ export class IssueRootStore implements IIssueRootStore { this.archivedIssuesFilter = new ArchivedIssuesFilter(this); this.archivedIssues = new ArchivedIssues(this, this.archivedIssuesFilter); - this.draftIssuesFilter = new DraftIssuesFilter(this); - this.draftIssues = new DraftIssues(this, this.draftIssuesFilter); - this.issueKanBanView = new IssueKanBanViewStore(this); this.issueCalendarView = new CalendarStore(); diff --git a/packages/types/src/issues/issue.ts b/packages/types/src/issues/issue.ts index f2adb48110a..85069632eb0 100644 --- a/packages/types/src/issues/issue.ts +++ b/packages/types/src/issues/issue.ts @@ -29,7 +29,6 @@ export enum EIssuesStoreType { TEAM_VIEW = "TEAM_VIEW", PROJECT_VIEW = "PROJECT_VIEW", ARCHIVED = "ARCHIVED", - DRAFT = "DRAFT", DEFAULT = "DEFAULT", WORKSPACE_DRAFT = "WORKSPACE_DRAFT", EPIC = "EPIC",