From 1480ab26d728fed16705fd44f64af746efcb92f9 Mon Sep 17 00:00:00 2001 From: Anmol Singh Bhatia Date: Fri, 13 Dec 2024 17:12:27 +0530 Subject: [PATCH 1/3] chore: package code refactoring --- packages/constants/src/issue.ts | 5 +++++ packages/types/src/issues/issue.d.ts | 6 ++++++ packages/types/src/project/projects.d.ts | 1 + 3 files changed, 12 insertions(+) diff --git a/packages/constants/src/issue.ts b/packages/constants/src/issue.ts index 9f6a1a2e2e9..9aa65d13e38 100644 --- a/packages/constants/src/issue.ts +++ b/packages/constants/src/issue.ts @@ -39,3 +39,8 @@ export enum EServerGroupByToFilterOptions { "project_id" = "project", "created_by" = "created_by", } + +export enum EIssueServiceType { + ISSUES = "issues", + EPICS = "epics", +} diff --git a/packages/types/src/issues/issue.d.ts b/packages/types/src/issues/issue.d.ts index b9366cccba1..6fd160e77f7 100644 --- a/packages/types/src/issues/issue.d.ts +++ b/packages/types/src/issues/issue.d.ts @@ -1,3 +1,4 @@ +import { EIssueServiceType } from "@plane/constants"; import { TIssuePriorities } from "../issues"; import { TIssueAttachment } from "./issue_attachment"; import { TIssueLink } from "./issue_link"; @@ -39,6 +40,7 @@ export type TBaseIssue = { updated_by: string; is_draft: boolean; + is_epic?: boolean; }; export type IssueRelation = { @@ -121,3 +123,7 @@ export type TIssueDetailWidget = | "relations" | "links" | "attachments"; + +export type TIssueServiceType = + | EIssueServiceType.ISSUES + | EIssueServiceType.EPICS; diff --git a/packages/types/src/project/projects.d.ts b/packages/types/src/project/projects.d.ts index d48342cebb9..f878266b75d 100644 --- a/packages/types/src/project/projects.d.ts +++ b/packages/types/src/project/projects.d.ts @@ -136,6 +136,7 @@ export type TProjectIssuesSearchParams = { issue_id?: string; workspace_search: boolean; target_date?: string; + epic?: boolean; }; export interface ISearchIssueResponse { From d73dc1aa389a21eb64e3849293faa9440497e0b7 Mon Sep 17 00:00:00 2001 From: Anmol Singh Bhatia Date: Sat, 14 Dec 2024 18:38:10 +0530 Subject: [PATCH 2/3] chore: component restructuring and refactor --- web/ce/components/epics/epic-modal/index.ts | 1 + web/ce/components/epics/epic-modal/modal.tsx | 19 ++++ web/ce/components/epics/index.ts | 1 + .../dependency/dependency-paths.tsx | 10 +- .../components/issue-types/values/update.tsx | 3 + .../hooks/use-debounced-duplicate-issues.tsx | 1 + web/ce/store/issue/epic/filter.store.ts | 15 +++ web/ce/store/issue/epic/index.ts | 2 + web/ce/store/issue/epic/issue.store.ts | 14 +++ .../issue/issue-details/activity.store.ts | 40 +++++--- .../gantt-chart/chart/main-content.tsx | 7 +- .../components/gantt-chart/chart/root.tsx | 3 + web/core/components/gantt-chart/root.tsx | 3 + .../gantt-chart/sidebar/issues/block.tsx | 5 +- .../gantt-chart/sidebar/issues/sidebar.tsx | 3 + .../components/gantt-chart/sidebar/root.tsx | 3 + .../components/inbox/content/issue-root.tsx | 15 ++- .../inbox/modals/create-modal/create-root.tsx | 13 ++- .../attachment/attachment-item-list.tsx | 22 ++++- .../attachment/attachment-list-item.tsx | 7 +- .../attachment/delete-attachment-modal.tsx | 8 +- web/core/components/issues/filters.tsx | 30 +++--- .../attachments/content.tsx | 8 +- .../attachments/helper.tsx | 7 +- .../attachments/quick-action-button.tsx | 21 ++++- .../issue-detail-widgets/attachments/root.tsx | 9 +- .../attachments/title.tsx | 8 +- .../issue-detail-widgets/links/content.tsx | 16 +++- .../issue-detail-widgets/links/helper.tsx | 12 ++- .../links/quick-action-button.tsx | 7 +- .../issue-detail-widgets/links/root.tsx | 17 +++- .../issue-detail-widgets/links/title.tsx | 11 ++- .../relations/content.tsx | 9 +- .../issue-detail-widgets/relations/helper.tsx | 9 +- .../relations/quick-action-button.tsx | 7 +- .../issue-detail-widgets/relations/root.tsx | 17 +++- .../issue-detail-widgets/relations/title.tsx | 11 ++- .../sub-issues/content.tsx | 10 +- .../sub-issues/helper.tsx | 9 +- .../sub-issues/quick-action-button.tsx | 8 +- .../issue-detail-widgets/sub-issues/root.tsx | 17 +++- .../issue-detail-widgets/sub-issues/title.tsx | 37 ++++---- .../issues/issue-detail/label/root.tsx | 18 +++- .../links/create-update-link-modal.tsx | 8 +- .../issues/issue-detail/links/link-item.tsx | 7 +- .../issues/issue-detail/links/link-list.tsx | 15 ++- .../issues/issue-detail/main-content.tsx | 15 ++- .../issues/issue-detail/parent-select.tsx | 1 + .../components/issues/issue-detail/root.tsx | 3 +- .../calendar/base-calendar-root.tsx | 7 +- .../issue-layouts/calendar/calendar.tsx | 14 ++- .../issue-layouts/calendar/day-tile.tsx | 11 ++- .../calendar/dropdowns/months-dropdown.tsx | 8 +- .../calendar/dropdowns/options-dropdown.tsx | 8 +- .../issues/issue-layouts/calendar/header.tsx | 8 +- .../calendar/issue-block-root.tsx | 13 ++- .../issue-layouts/calendar/issue-block.tsx | 5 +- .../issue-layouts/calendar/issue-blocks.tsx | 3 + .../issue-layouts/calendar/week-days.tsx | 11 ++- .../issue-layouts/empty-states/index.tsx | 3 + .../empty-states/project-epic.tsx | 12 +++ .../applied-filters/roots/project-root.tsx | 25 ++--- .../issue-layouts/gantt/base-gantt-root.tsx | 11 ++- .../issues/issue-layouts/gantt/blocks.tsx | 11 ++- .../issue-layouts/kanban/base-kanban-root.tsx | 17 +++- .../issues/issue-layouts/kanban/block.tsx | 14 ++- .../issue-layouts/kanban/blocks-list.tsx | 3 + .../issues/issue-layouts/kanban/default.tsx | 4 + .../kanban/headers/group-by-card.tsx | 22 +++-- .../issue-layouts/kanban/kanban-group.tsx | 3 + .../issue-layouts/list/base-list-root.tsx | 14 ++- .../issues/issue-layouts/list/block-root.tsx | 7 +- .../issues/issue-layouts/list/block.tsx | 17 +++- .../issues/issue-layouts/list/blocks-list.tsx | 3 + .../issues/issue-layouts/list/default.tsx | 9 +- .../list/headers/group-by-card.tsx | 22 +++-- .../issues/issue-layouts/list/list-group.tsx | 4 + .../properties/all-properties.tsx | 79 ++++++++-------- .../spreadsheet/base-spreadsheet-root.tsx | 7 +- .../issue-layouts/spreadsheet/issue-row.tsx | 17 +++- .../spreadsheet/spreadsheet-table.tsx | 3 + .../spreadsheet/spreadsheet-view.tsx | 5 +- .../components/issues/issue-modal/base.tsx | 76 ++++++--------- .../components/default-properties.tsx | 1 + .../issues/issue-modal/context/index.ts | 2 +- ...ssue-modal.tsx => issue-modal-context.tsx} | 0 .../issues/issue-modal/draft-issue-layout.tsx | 71 ++------------ .../components/issues/issue-modal/form.tsx | 10 +- .../issues/parent-issues-list-modal.tsx | 3 + .../issues/peek-overview/issue-detail.tsx | 15 ++- .../components/issues/peek-overview/root.tsx | 15 ++- .../components/issues/peek-overview/view.tsx | 5 +- .../issues/relations/issue-list-item.tsx | 8 +- .../issues/relations/issue-list.tsx | 6 +- .../issues/relations/properties.tsx | 8 +- .../issues/sub-issues/issue-list-item.tsx | 3 +- .../issues/sub-issues/issues-list.tsx | 7 +- .../issues/sub-issues/properties.tsx | 2 + web/core/constants/empty-state.ts | 11 +++ web/core/constants/issue.ts | 89 +++++++++++++++++- web/core/hooks/store/use-issue-detail.ts | 9 +- web/core/hooks/store/use-issues.ts | 11 +++ web/core/hooks/use-group-dragndrop.ts | 3 +- web/core/hooks/use-issue-layout-store.ts | 5 +- .../use-issue-peek-overview-redirection.tsx | 10 +- web/core/hooks/use-issues-actions.tsx | 89 ++++++++++++++++++ web/core/services/issue/issue.service.ts | 82 ++++++++++------ .../services/issue/issue_activity.service.ts | 12 ++- .../services/issue/issue_archive.service.ts | 14 ++- .../issue/issue_attachment.service.ts | 17 ++-- .../services/issue/issue_comment.service.ts | 20 ++-- .../services/issue/issue_reaction.service.ts | 17 +++- web/core/services/issue_filter.service.ts | 20 ++++ web/core/services/project/project.service.ts | 14 ++- .../issue/issue-details/attachment.store.ts | 6 +- .../issue/issue-details/comment.store.ts | 8 +- .../store/issue/issue-details/issue.store.ts | 40 ++++++-- .../store/issue/issue-details/link.store.ts | 8 +- .../issue/issue-details/reaction.store.ts | 8 +- .../store/issue/issue-details/root.store.ts | 20 ++-- .../issue/issue-details/sub_issues.store.ts | 5 +- web/core/store/issue/issue.store.ts | 6 +- web/core/store/issue/root.store.ts | 23 ++++- web/core/store/project/project.store.ts | 27 ++++++ web/core/store/root.store.ts | 4 + web/core/store/router.store.ts | 10 ++ web/core/store/theme.store.ts | 14 +++ web/ee/components/epics/index.ts | 1 + web/public/empty-state/epics/epics-dark.webp | Bin 0 -> 48054 bytes web/public/empty-state/epics/epics-light.webp | Bin 0 -> 50384 bytes 130 files changed, 1290 insertions(+), 487 deletions(-) create mode 100644 web/ce/components/epics/epic-modal/index.ts create mode 100644 web/ce/components/epics/epic-modal/modal.tsx create mode 100644 web/ce/components/epics/index.ts create mode 100644 web/ce/store/issue/epic/filter.store.ts create mode 100644 web/ce/store/issue/epic/index.ts create mode 100644 web/ce/store/issue/epic/issue.store.ts create mode 100644 web/core/components/issues/issue-layouts/empty-states/project-epic.tsx rename web/core/components/issues/issue-modal/context/{issue-modal.tsx => issue-modal-context.tsx} (100%) create mode 100644 web/ee/components/epics/index.ts create mode 100644 web/public/empty-state/epics/epics-dark.webp create mode 100644 web/public/empty-state/epics/epics-light.webp diff --git a/web/ce/components/epics/epic-modal/index.ts b/web/ce/components/epics/epic-modal/index.ts new file mode 100644 index 00000000000..031608e25ff --- /dev/null +++ b/web/ce/components/epics/epic-modal/index.ts @@ -0,0 +1 @@ +export * from "./modal"; diff --git a/web/ce/components/epics/epic-modal/modal.tsx b/web/ce/components/epics/epic-modal/modal.tsx new file mode 100644 index 00000000000..9c76b7bdab8 --- /dev/null +++ b/web/ce/components/epics/epic-modal/modal.tsx @@ -0,0 +1,19 @@ +"use client"; +import React, { FC } from "react"; +import { TIssue } from "@plane/types"; + +export interface EpicModalProps { + data?: Partial; + isOpen: boolean; + onClose: () => void; + beforeFormSubmit?: () => Promise; + onSubmit?: (res: TIssue) => Promise; + fetchIssueDetails?: boolean; + primaryButtonText?: { + default: string; + loading: string; + }; + isProjectSelectionDisabled?: boolean; +} + +export const CreateUpdateEpicModal: FC = (props) => <>; diff --git a/web/ce/components/epics/index.ts b/web/ce/components/epics/index.ts new file mode 100644 index 00000000000..29da0cc8acc --- /dev/null +++ b/web/ce/components/epics/index.ts @@ -0,0 +1 @@ +export * from "./epic-modal"; diff --git a/web/ce/components/gantt-chart/dependency/dependency-paths.tsx b/web/ce/components/gantt-chart/dependency/dependency-paths.tsx index f049875f113..6feb208a8b7 100644 --- a/web/ce/components/gantt-chart/dependency/dependency-paths.tsx +++ b/web/ce/components/gantt-chart/dependency/dependency-paths.tsx @@ -1 +1,9 @@ -export const TimelineDependencyPaths = () => <>; +import { FC } from "react"; + +type Props = { + isEpic?: boolean; +}; +export const TimelineDependencyPaths: FC = (props) => { + const { isEpic = false } = props; + return <>; +}; diff --git a/web/ce/components/issue-types/values/update.tsx b/web/ce/components/issue-types/values/update.tsx index cff391d9ea9..2fd62904266 100644 --- a/web/ce/components/issue-types/values/update.tsx +++ b/web/ce/components/issue-types/values/update.tsx @@ -1,9 +1,12 @@ +import { TIssueServiceType } from "@plane/types"; + export type TIssueAdditionalPropertyValuesUpdateProps = { issueId: string; issueTypeId: string; projectId: string; workspaceSlug: string; isDisabled: boolean; + issueServiceType?: TIssueServiceType; }; export const IssueAdditionalPropertyValuesUpdate: React.FC = () => <>; diff --git a/web/ce/hooks/use-debounced-duplicate-issues.tsx b/web/ce/hooks/use-debounced-duplicate-issues.tsx index f0325bc1284..8028a619104 100644 --- a/web/ce/hooks/use-debounced-duplicate-issues.tsx +++ b/web/ce/hooks/use-debounced-duplicate-issues.tsx @@ -1,6 +1,7 @@ import { TDeDupeIssue } from "@plane/types"; export const useDebouncedDuplicateIssues = ( + workspaceSlug: string | undefined, workspaceId: string | undefined, projectId: string | undefined, formData: { name: string | undefined; description_html?: string | undefined; issueId?: string | undefined } diff --git a/web/ce/store/issue/epic/filter.store.ts b/web/ce/store/issue/epic/filter.store.ts new file mode 100644 index 00000000000..a4733c60a55 --- /dev/null +++ b/web/ce/store/issue/epic/filter.store.ts @@ -0,0 +1,15 @@ +import { IProjectIssuesFilter, ProjectIssuesFilter } from "@/store/issue/project"; +import { IIssueRootStore } from "@/store/issue/root.store"; + +// @ts-nocheck - This class will never be used, extending similar class to avoid type errors +export type IProjectEpicsFilter = IProjectIssuesFilter; + +// @ts-nocheck - This class will never be used, extending similar class to avoid type errors +export class ProjectEpicsFilter extends ProjectIssuesFilter implements IProjectEpicsFilter { + constructor(_rootStore: IIssueRootStore) { + super(_rootStore); + + // root store + this.rootIssueStore = _rootStore; + } +} diff --git a/web/ce/store/issue/epic/index.ts b/web/ce/store/issue/epic/index.ts new file mode 100644 index 00000000000..0fe6c946b0c --- /dev/null +++ b/web/ce/store/issue/epic/index.ts @@ -0,0 +1,2 @@ +export * from "./filter.store"; +export * from "./issue.store"; diff --git a/web/ce/store/issue/epic/issue.store.ts b/web/ce/store/issue/epic/issue.store.ts new file mode 100644 index 00000000000..90ccee84da0 --- /dev/null +++ b/web/ce/store/issue/epic/issue.store.ts @@ -0,0 +1,14 @@ +import { IProjectIssues, ProjectIssues } from "@/store/issue/project"; +import { IIssueRootStore } from "@/store/issue/root.store"; +import { IProjectEpicsFilter } from "./filter.store"; + +// @ts-nocheck - This class will never be used, extending similar class to avoid type errors + +export type IProjectEpics = IProjectIssues; + +// @ts-nocheck - This class will never be used, extending similar class to avoid type errors +export class ProjectEpics extends ProjectIssues implements IProjectEpics { + constructor(_rootStore: IIssueRootStore, issueFilterStore: IProjectEpicsFilter) { + super(_rootStore, issueFilterStore); + } +} diff --git a/web/ce/store/issue/issue-details/activity.store.ts b/web/ce/store/issue/issue-details/activity.store.ts index 6c0029c4f8c..de84fb87d9a 100644 --- a/web/ce/store/issue/issue-details/activity.store.ts +++ b/web/ce/store/issue/issue-details/activity.store.ts @@ -7,7 +7,14 @@ import uniq from "lodash/uniq"; import update from "lodash/update"; import { action, makeObservable, observable, runInAction } from "mobx"; import { computedFn } from "mobx-utils"; -import { TIssueActivityComment, TIssueActivity, TIssueActivityMap, TIssueActivityIdMap } from "@plane/types"; +import { EIssueServiceType } from "@plane/constants"; +import { + TIssueActivityComment, + TIssueActivity, + TIssueActivityMap, + TIssueActivityIdMap, + TIssueServiceType, +} from "@plane/types"; // plane web constants import { EActivityFilterType } from "@/plane-web/constants/issues"; // services @@ -29,7 +36,7 @@ export interface IIssueActivityStoreActions { export interface IIssueActivityStore extends IIssueActivityStoreActions { // observables - sortOrder: 'asc' | 'desc' + sortOrder: "asc" | "desc"; loader: TActivityLoader; activities: TIssueActivityIdMap; activityMap: TIssueActivityMap; @@ -37,20 +44,24 @@ export interface IIssueActivityStore extends IIssueActivityStoreActions { getActivitiesByIssueId: (issueId: string) => string[] | undefined; getActivityById: (activityId: string) => TIssueActivity | undefined; getActivityCommentByIssueId: (issueId: string) => TIssueActivityComment[] | undefined; - toggleSortOrder: ()=>void; + toggleSortOrder: () => void; } export class IssueActivityStore implements IIssueActivityStore { // observables - sortOrder: "asc" | "desc" = 'asc'; + sortOrder: "asc" | "desc" = "asc"; loader: TActivityLoader = "fetch"; activities: TIssueActivityIdMap = {}; activityMap: TIssueActivityMap = {}; // services + serviceType; issueActivityService; - constructor(protected store: CoreRootStore) { + constructor( + protected store: CoreRootStore, + serviceType: TIssueServiceType = EIssueServiceType.ISSUES + ) { makeObservable(this, { // observables sortOrder: observable.ref, @@ -59,10 +70,11 @@ export class IssueActivityStore implements IIssueActivityStore { activityMap: observable, // actions fetchActivities: action, - toggleSortOrder: action + toggleSortOrder: action, }); + this.serviceType = serviceType; // services - this.issueActivityService = new IssueActivityService(); + this.issueActivityService = new IssueActivityService(this.serviceType); } // helper methods @@ -81,8 +93,10 @@ export class IssueActivityStore implements IIssueActivityStore { let activityComments: TIssueActivityComment[] = []; + const currentStore = this.serviceType === EIssueServiceType.EPICS ? this.store.epic : this.store.issue; + const activities = this.getActivitiesByIssueId(issueId) || []; - const comments = this.store.issue.issueDetail.comment.getCommentsByIssueId(issueId) || []; + const comments = currentStore.issueDetail.comment.getCommentsByIssueId(issueId) || []; activities.forEach((activityId) => { const activity = this.getActivityById(activityId); @@ -95,7 +109,7 @@ export class IssueActivityStore implements IIssueActivityStore { }); comments.forEach((commentId) => { - const comment = this.store.issue.issueDetail.comment.getCommentById(commentId); + const comment = currentStore.issueDetail.comment.getCommentById(commentId); if (!comment) return; activityComments.push({ id: comment.id, @@ -104,14 +118,14 @@ export class IssueActivityStore implements IIssueActivityStore { }); }); - activityComments = orderBy(activityComments, (e)=>new Date(e.created_at || 0), this.sortOrder); + activityComments = orderBy(activityComments, (e) => new Date(e.created_at || 0), this.sortOrder); return activityComments; }); - toggleSortOrder = ()=>{ - this.sortOrder = this.sortOrder === 'asc' ? 'desc' : 'asc'; - } + toggleSortOrder = () => { + this.sortOrder = this.sortOrder === "asc" ? "desc" : "asc"; + }; // actions public async fetchActivities( diff --git a/web/core/components/gantt-chart/chart/main-content.tsx b/web/core/components/gantt-chart/chart/main-content.tsx index b9582d21cee..63e01c54ea0 100644 --- a/web/core/components/gantt-chart/chart/main-content.tsx +++ b/web/core/components/gantt-chart/chart/main-content.tsx @@ -56,6 +56,7 @@ type Props = { targetDate?: Date ) => ChartDataType | undefined; quickAdd?: React.JSX.Element | undefined; + isEpic?: boolean; }; export const GanttChartMainContent: React.FC = observer((props) => { @@ -79,6 +80,7 @@ export const GanttChartMainContent: React.FC = observer((props) => { updateCurrentViewRenderPayload, quickAdd, updateBlockDates, + isEpic = false, } = props; // refs const ganttContainerRef = useRef(null); @@ -159,7 +161,7 @@ export const GanttChartMainContent: React.FC = observer((props) => { entities={{ [GANTT_SELECT_GROUP]: blockIds ?? [], }} - disabled={!isBulkOperationsEnabled} + disabled={!isBulkOperationsEnabled || isEpic} > {(helpers) => ( <> @@ -187,6 +189,7 @@ export const GanttChartMainContent: React.FC = observer((props) => { title={title} quickAdd={quickAdd} selectionHelpers={helpers} + isEpic={isEpic} />
@@ -208,7 +211,7 @@ export const GanttChartMainContent: React.FC = observer((props) => { selectionHelpers={helpers} ganttContainerRef={ganttContainerRef} /> - + = observer((props) => { quickAdd, showToday, updateBlockDates, + isEpic = false, } = props; // states const [itemsContainerWidth, setItemsContainerWidth] = useState(0); @@ -204,6 +206,7 @@ export const ChartViewRoot: FC = observer((props) => { updateCurrentViewRenderPayload={updateCurrentViewRenderPayload} quickAdd={quickAdd} updateBlockDates={updateBlockDates} + isEpic={isEpic} />
); diff --git a/web/core/components/gantt-chart/root.tsx b/web/core/components/gantt-chart/root.tsx index 81f064e2fb4..3ed21d1440a 100644 --- a/web/core/components/gantt-chart/root.tsx +++ b/web/core/components/gantt-chart/root.tsx @@ -26,6 +26,7 @@ type GanttChartRootProps = { bottomSpacing?: boolean; showAllBlocks?: boolean; showToday?: boolean; + isEpic?: boolean; }; export const GanttChartRoot: FC = observer((props) => { @@ -50,6 +51,7 @@ export const GanttChartRoot: FC = observer((props) => { showToday = true, quickAdd, updateBlockDates, + isEpic = false, } = props; const { setBlockIds } = useTimeLineChartStore(); @@ -81,6 +83,7 @@ export const GanttChartRoot: FC = observer((props) => { quickAdd={quickAdd} showToday={showToday} updateBlockDates={updateBlockDates} + isEpic={isEpic} /> ); }); diff --git a/web/core/components/gantt-chart/sidebar/issues/block.tsx b/web/core/components/gantt-chart/sidebar/issues/block.tsx index bb286c28006..c0218aceb16 100644 --- a/web/core/components/gantt-chart/sidebar/issues/block.tsx +++ b/web/core/components/gantt-chart/sidebar/issues/block.tsx @@ -19,10 +19,11 @@ type Props = { enableSelection: boolean; isDragging: boolean; selectionHelpers?: TSelectionHelper; + isEpic?: boolean; }; export const IssuesSidebarBlock = observer((props: Props) => { - const { block, enableSelection, isDragging, selectionHelpers } = props; + const { block, enableSelection, isDragging, selectionHelpers, isEpic = false } = props; // store hooks const { updateActiveBlockId, isBlockActive, getNumberOfDaysFromPosition } = useTimeLineChartStore(); const { getIsIssuePeeked } = useIssueDetail(); @@ -73,7 +74,7 @@ export const IssuesSidebarBlock = observer((props: Props) => { )}
- +
{duration && (
diff --git a/web/core/components/gantt-chart/sidebar/issues/sidebar.tsx b/web/core/components/gantt-chart/sidebar/issues/sidebar.tsx index b2f6b879284..d2e5557ff84 100644 --- a/web/core/components/gantt-chart/sidebar/issues/sidebar.tsx +++ b/web/core/components/gantt-chart/sidebar/issues/sidebar.tsx @@ -29,6 +29,7 @@ type Props = { enableSelection: boolean; showAllBlocks?: boolean; selectionHelpers?: TSelectionHelper; + isEpic?: boolean; }; export const IssueGanttSidebar: React.FC = observer((props) => { @@ -42,6 +43,7 @@ export const IssueGanttSidebar: React.FC = observer((props) => { ganttContainerRef, showAllBlocks = false, selectionHelpers, + isEpic = false, } = props; const { getBlockById } = useTimeLineChart(ETimeLineTypeType.ISSUE); @@ -101,6 +103,7 @@ export const IssueGanttSidebar: React.FC = observer((props) => { enableSelection={enableSelection} isDragging={isDragging} selectionHelpers={selectionHelpers} + isEpic={isEpic} /> )} diff --git a/web/core/components/gantt-chart/sidebar/root.tsx b/web/core/components/gantt-chart/sidebar/root.tsx index 31c9137cc5a..7202efc55d9 100644 --- a/web/core/components/gantt-chart/sidebar/root.tsx +++ b/web/core/components/gantt-chart/sidebar/root.tsx @@ -23,6 +23,7 @@ type Props = { title: string; quickAdd?: React.JSX.Element | undefined; selectionHelpers: TSelectionHelper; + isEpic?: boolean; }; export const GanttChartSidebar: React.FC = observer((props) => { @@ -38,6 +39,7 @@ export const GanttChartSidebar: React.FC = observer((props) => { title, quickAdd, selectionHelpers, + isEpic = false, } = props; const isGroupSelectionEmpty = selectionHelpers.isGroupSelected(GANTT_SELECT_GROUP) === "empty"; @@ -90,6 +92,7 @@ export const GanttChartSidebar: React.FC = observer((props) => { ganttContainerRef, loadMoreBlocks, selectionHelpers, + isEpic, })} {quickAdd ? quickAdd : null} diff --git a/web/core/components/inbox/content/issue-root.tsx b/web/core/components/inbox/content/issue-root.tsx index b154bd2056a..258a1c50b00 100644 --- a/web/core/components/inbox/content/issue-root.tsx +++ b/web/core/components/inbox/content/issue-root.tsx @@ -65,11 +65,16 @@ export const InboxIssueMainContent: React.FC = observer((props) => { const projectDetails = issue?.project_id ? getProjectById(issue?.project_id) : undefined; // debounced duplicate issues swr - const { duplicateIssues } = useDebouncedDuplicateIssues(projectDetails?.workspace.toString(), projectId, { - name: issue?.name, - description_html: getTextContent(issue?.description_html), - issueId: issue?.id, - }); + const { duplicateIssues } = useDebouncedDuplicateIssues( + workspaceSlug, + projectDetails?.workspace.toString(), + projectId, + { + name: issue?.name, + description_html: getTextContent(issue?.description_html), + issueId: issue?.id, + } + ); if (!issue) return <>; diff --git a/web/core/components/inbox/modals/create-modal/create-root.tsx b/web/core/components/inbox/modals/create-modal/create-root.tsx index 4f7bbd4b45b..34c17e15b38 100644 --- a/web/core/components/inbox/modals/create-modal/create-root.tsx +++ b/web/core/components/inbox/modals/create-modal/create-root.tsx @@ -87,10 +87,15 @@ export const InboxIssueCreateRoot: FC = observer((props) const { getIndex } = getTabIndex(ETabIndices.INTAKE_ISSUE_FORM, isMobile); // debounced duplicate issues swr - const { duplicateIssues } = useDebouncedDuplicateIssues(projectDetails?.workspace.toString(), projectId, { - name: formData?.name, - description_html: formData?.description_html, - }); + const { duplicateIssues } = useDebouncedDuplicateIssues( + workspaceSlug, + projectDetails?.workspace.toString(), + projectId, + { + name: formData?.name, + description_html: formData?.description_html, + } + ); const handleEscKeyDown = (event: KeyboardEvent) => { if (descriptionEditorRef.current?.isEditorReadyToDiscard()) { diff --git a/web/core/components/issues/attachment/attachment-item-list.tsx b/web/core/components/issues/attachment/attachment-item-list.tsx index d377bd90a16..ca3c0ef9f11 100644 --- a/web/core/components/issues/attachment/attachment-item-list.tsx +++ b/web/core/components/issues/attachment/attachment-item-list.tsx @@ -2,6 +2,8 @@ import { FC, useCallback, useState } from "react"; import { observer } from "mobx-react"; import { FileRejection, useDropzone } from "react-dropzone"; import { UploadCloud } from "lucide-react"; +import { EIssueServiceType } from "@plane/constants"; +import { TIssueServiceType } from "@plane/types"; // hooks import { TOAST_TYPE, setToast } from "@plane/ui"; import { useIssueDetail } from "@/hooks/store"; @@ -21,10 +23,18 @@ type TIssueAttachmentItemList = { issueId: string; attachmentHelpers: TAttachmentHelpers; disabled?: boolean; + issueServiceType?: TIssueServiceType; }; export const IssueAttachmentItemList: FC = observer((props) => { - const { workspaceSlug, projectId, issueId, attachmentHelpers, disabled } = props; + const { + workspaceSlug, + projectId, + issueId, + attachmentHelpers, + disabled, + issueServiceType = EIssueServiceType.ISSUES, + } = props; // states const [isUploading, setIsUploading] = useState(false); // store hooks @@ -33,7 +43,7 @@ export const IssueAttachmentItemList: FC = observer((p attachmentDeleteModalId, toggleDeleteAttachmentModal, fetchActivities, - } = useIssueDetail(); + } = useIssueDetail(issueServiceType); const { operations: attachmentOperations, snapshot: attachmentSnapshot } = attachmentHelpers; const { create: createAttachment } = attachmentOperations; const { uploadStatus } = attachmentSnapshot; @@ -104,6 +114,7 @@ export const IssueAttachmentItemList: FC = observer((p onClose={() => toggleDeleteAttachmentModal(null)} attachmentOperations={attachmentOperations} attachmentId={attachmentDeleteModalId} + issueServiceType={issueServiceType} /> )}
= observer((p
)} {issueAttachments?.map((attachmentId) => ( - + ))}
diff --git a/web/core/components/issues/attachment/attachment-list-item.tsx b/web/core/components/issues/attachment/attachment-list-item.tsx index e3adc5f828b..dfdbde0741e 100644 --- a/web/core/components/issues/attachment/attachment-list-item.tsx +++ b/web/core/components/issues/attachment/attachment-list-item.tsx @@ -3,6 +3,8 @@ import { FC } from "react"; import { observer } from "mobx-react"; import { Trash } from "lucide-react"; +import { EIssueServiceType } from "@plane/constants"; +import { TIssueServiceType } from "@plane/types"; // ui import { CustomMenu, Tooltip } from "@plane/ui"; // components @@ -19,17 +21,18 @@ import { usePlatformOS } from "@/hooks/use-platform-os"; type TIssueAttachmentsListItem = { attachmentId: string; disabled?: boolean; + issueServiceType?: TIssueServiceType; }; export const IssueAttachmentsListItem: FC = observer((props) => { // props - const { attachmentId, disabled } = props; + const { attachmentId, disabled, issueServiceType = EIssueServiceType.ISSUES } = props; // store hooks const { getUserDetails } = useMember(); const { attachment: { getAttachmentById }, toggleDeleteAttachmentModal, - } = useIssueDetail(); + } = useIssueDetail(issueServiceType); // derived values const attachment = attachmentId ? getAttachmentById(attachmentId) : undefined; const fileName = getFileName(attachment?.attributes.name ?? ""); diff --git a/web/core/components/issues/attachment/delete-attachment-modal.tsx b/web/core/components/issues/attachment/delete-attachment-modal.tsx index 925ff21c0c9..32c9d961c7f 100644 --- a/web/core/components/issues/attachment/delete-attachment-modal.tsx +++ b/web/core/components/issues/attachment/delete-attachment-modal.tsx @@ -1,6 +1,9 @@ import { FC, useState } from "react"; import { observer } from "mobx-react"; +// constants +import { EIssueServiceType } from "@plane/constants"; // types +import { TIssueServiceType } from "@plane/types"; // ui import { AlertModalCore } from "@plane/ui"; // helper @@ -17,17 +20,18 @@ type Props = { onClose: () => void; attachmentId: string; attachmentOperations: TAttachmentOperationsRemoveModal; + issueServiceType?: TIssueServiceType; }; export const IssueAttachmentDeleteModal: FC = observer((props) => { - const { isOpen, onClose, attachmentId, attachmentOperations } = props; + const { isOpen, onClose, attachmentId, attachmentOperations, issueServiceType = EIssueServiceType.ISSUES } = props; // states const [loader, setLoader] = useState(false); // store hooks const { attachment: { getAttachmentById }, - } = useIssueDetail(); + } = useIssueDetail(issueServiceType); // derived values const attachment = attachmentId ? getAttachmentById(attachmentId) : undefined; diff --git a/web/core/components/issues/filters.tsx b/web/core/components/issues/filters.tsx index 4b80ba12f16..54b6f501572 100644 --- a/web/core/components/issues/filters.tsx +++ b/web/core/components/issues/filters.tsx @@ -4,24 +4,17 @@ import { useCallback, useState } from "react"; import { observer } from "mobx-react"; // types import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions } from "@plane/types"; -// ui import { Button } from "@plane/ui"; - +// components import { DisplayFiltersSelection, FiltersDropdown, FilterSelection, LayoutSelection } from "@/components/issues"; // constants -import { - EIssueFilterType, - EIssuesStoreType, - EIssueLayoutTypes, - ISSUE_DISPLAY_FILTERS_BY_LAYOUT, -} from "@/constants/issue"; +import { EIssueFilterType, EIssueLayoutTypes, EIssuesStoreType, ISSUE_STORE_TO_FILTERS_MAP } from "@/constants/issue"; // helpers import { isIssueFilterActive } from "@/helpers/filter.helper"; // hooks import { useLabel, useProjectState, useMember, useIssues } from "@/hooks/store"; // plane web types import { TProject } from "@/plane-web/types"; -// local components import { ProjectAnalyticsModal } from "../analytics"; type Props = { @@ -29,8 +22,16 @@ type Props = { projectId: string; workspaceSlug: string; canUserCreateIssue: boolean | undefined; + storeType?: EIssuesStoreType.PROJECT | EIssuesStoreType.EPIC; }; -const HeaderFilters = observer(({ currentProjectDetails, projectId, workspaceSlug, canUserCreateIssue }: Props) => { +const HeaderFilters = observer((props: Props) => { + const { + currentProjectDetails, + projectId, + workspaceSlug, + canUserCreateIssue, + storeType = EIssuesStoreType.PROJECT, + } = props; // states const [analyticsModal, setAnalyticsModal] = useState(false); // store hooks @@ -39,11 +40,12 @@ const HeaderFilters = observer(({ currentProjectDetails, projectId, workspaceSlu } = useMember(); const { issuesFilter: { issueFilters, updateFilters }, - } = useIssues(EIssuesStoreType.PROJECT); - + } = useIssues(storeType); const { projectStates } = useProjectState(); const { projectLabels } = useLabel(); + // derived values const activeLayout = issueFilters?.displayFilters?.layout; + const layoutDisplayFiltersOptions = ISSUE_STORE_TO_FILTERS_MAP[storeType]?.[activeLayout]; const handleFiltersUpdate = useCallback( (key: keyof IIssueFilterOptions, value: string | string[]) => { @@ -113,7 +115,7 @@ const HeaderFilters = observer(({ currentProjectDetails, projectId, workspaceSlu handleFiltersUpdate={handleFiltersUpdate} displayFilters={issueFilters?.displayFilters ?? {}} handleDisplayFiltersUpdate={handleDisplayFilters} - layoutDisplayFiltersOptions={activeLayout ? ISSUE_DISPLAY_FILTERS_BY_LAYOUT.issues[activeLayout] : undefined} + layoutDisplayFiltersOptions={layoutDisplayFiltersOptions} labels={projectLabels} memberIds={projectMemberIds ?? undefined} states={projectStates} @@ -123,7 +125,7 @@ const HeaderFilters = observer(({ currentProjectDetails, projectId, workspaceSlu = observer((props) => { - const { workspaceSlug, projectId, issueId, disabled } = props; + const { workspaceSlug, projectId, issueId, disabled, issueServiceType = EIssueServiceType.ISSUES } = props; // helper - const attachmentHelpers = useAttachmentOperations(workspaceSlug, projectId, issueId); + const attachmentHelpers = useAttachmentOperations(workspaceSlug, projectId, issueId, issueServiceType); return ( = observer((props) => issueId={issueId} disabled={disabled} attachmentHelpers={attachmentHelpers} + issueServiceType={issueServiceType} /> ); }); diff --git a/web/core/components/issues/issue-detail-widgets/attachments/helper.tsx b/web/core/components/issues/issue-detail-widgets/attachments/helper.tsx index 43b4812e6a0..28684ac9986 100644 --- a/web/core/components/issues/issue-detail-widgets/attachments/helper.tsx +++ b/web/core/components/issues/issue-detail-widgets/attachments/helper.tsx @@ -1,5 +1,7 @@ "use client"; import { useMemo } from "react"; +import { EIssueServiceType } from "@plane/constants"; +import { TIssueServiceType } from "@plane/types"; // plane ui import { TOAST_TYPE, setPromiseToast, setToast } from "@plane/ui"; // hooks @@ -24,11 +26,12 @@ export type TAttachmentHelpers = { export const useAttachmentOperations = ( workspaceSlug: string, projectId: string, - issueId: string + issueId: string, + issueServiceType: TIssueServiceType = EIssueServiceType.ISSUES ): TAttachmentHelpers => { const { attachment: { createAttachment, removeAttachment, getAttachmentsUploadStatusByIssueId }, - } = useIssueDetail(); + } = useIssueDetail(issueServiceType); const { captureIssueEvent } = useEventTracker(); const attachmentOperations: TAttachmentOperations = useMemo( diff --git a/web/core/components/issues/issue-detail-widgets/attachments/quick-action-button.tsx b/web/core/components/issues/issue-detail-widgets/attachments/quick-action-button.tsx index c2d88a9541c..fb0b5b2c6fd 100644 --- a/web/core/components/issues/issue-detail-widgets/attachments/quick-action-button.tsx +++ b/web/core/components/issues/issue-detail-widgets/attachments/quick-action-button.tsx @@ -4,6 +4,8 @@ import React, { FC, useCallback, useState } from "react"; import { observer } from "mobx-react"; import { FileRejection, useDropzone } from "react-dropzone"; import { Plus } from "lucide-react"; +import { EIssueServiceType } from "@plane/constants"; +import { TIssueServiceType } from "@plane/types"; // plane ui import { TOAST_TYPE, setToast } from "@plane/ui"; // hooks @@ -19,18 +21,31 @@ type Props = { issueId: string; customButton?: React.ReactNode; disabled?: boolean; + issueServiceType?: TIssueServiceType; }; export const IssueAttachmentActionButton: FC = observer((props) => { - const { workspaceSlug, projectId, issueId, customButton, disabled = false } = props; + const { + workspaceSlug, + projectId, + issueId, + customButton, + disabled = false, + issueServiceType = EIssueServiceType.ISSUES, + } = props; // state const [isLoading, setIsLoading] = useState(false); // store hooks - const { setLastWidgetAction, fetchActivities } = useIssueDetail(); + const { setLastWidgetAction, fetchActivities } = useIssueDetail(issueServiceType); // file size const { maxFileSize } = useFileSize(); // operations - const { operations: attachmentOperations } = useAttachmentOperations(workspaceSlug, projectId, issueId); + const { operations: attachmentOperations } = useAttachmentOperations( + workspaceSlug, + projectId, + issueId, + issueServiceType + ); // handlers const handleFetchPropertyActivities = useCallback(() => { fetchActivities(workspaceSlug, projectId, issueId); diff --git a/web/core/components/issues/issue-detail-widgets/attachments/root.tsx b/web/core/components/issues/issue-detail-widgets/attachments/root.tsx index 1f802759050..7b4788a1a6a 100644 --- a/web/core/components/issues/issue-detail-widgets/attachments/root.tsx +++ b/web/core/components/issues/issue-detail-widgets/attachments/root.tsx @@ -1,6 +1,8 @@ "use client"; import React, { FC } from "react"; import { observer } from "mobx-react"; +import { EIssueServiceType } from "@plane/constants"; +import { TIssueServiceType } from "@plane/types"; import { Collapsible } from "@plane/ui"; // components import { @@ -15,12 +17,13 @@ type Props = { projectId: string; issueId: string; disabled?: boolean; + issueServiceType?: TIssueServiceType; }; export const AttachmentsCollapsible: FC = observer((props) => { - const { workspaceSlug, projectId, issueId, disabled = false } = props; + const { workspaceSlug, projectId, issueId, disabled = false, issueServiceType = EIssueServiceType.ISSUES } = props; // store hooks - const { openWidgets, toggleOpenWidget } = useIssueDetail(); + const { openWidgets, toggleOpenWidget } = useIssueDetail(issueServiceType); // derived values const isCollapsibleOpen = openWidgets.includes("attachments"); @@ -36,6 +39,7 @@ export const AttachmentsCollapsible: FC = observer((props) => { projectId={projectId} issueId={issueId} disabled={disabled} + issueServiceType={issueServiceType} /> } buttonClassName="w-full" @@ -45,6 +49,7 @@ export const AttachmentsCollapsible: FC = observer((props) => { projectId={projectId} issueId={issueId} disabled={disabled} + issueServiceType={issueServiceType} /> ); diff --git a/web/core/components/issues/issue-detail-widgets/attachments/title.tsx b/web/core/components/issues/issue-detail-widgets/attachments/title.tsx index ce83f6826df..f2d0cd670c7 100644 --- a/web/core/components/issues/issue-detail-widgets/attachments/title.tsx +++ b/web/core/components/issues/issue-detail-widgets/attachments/title.tsx @@ -1,6 +1,8 @@ "use client"; import React, { FC, useMemo } from "react"; import { observer } from "mobx-react"; +import { EIssueServiceType } from "@plane/constants"; +import { TIssueServiceType } from "@plane/types"; import { CollapsibleButton } from "@plane/ui"; // components import { IssueAttachmentActionButton } from "@/components/issues/issue-detail-widgets"; @@ -13,14 +15,15 @@ type Props = { projectId: string; issueId: string; disabled: boolean; + issueServiceType?: TIssueServiceType; }; export const IssueAttachmentsCollapsibleTitle: FC = observer((props) => { - const { isOpen, workspaceSlug, projectId, issueId, disabled } = props; + const { isOpen, workspaceSlug, projectId, issueId, disabled, issueServiceType = EIssueServiceType.ISSUES } = props; // store hooks const { issue: { getIssueById }, - } = useIssueDetail(); + } = useIssueDetail(issueServiceType); // derived values const issue = getIssueById(issueId); @@ -48,6 +51,7 @@ export const IssueAttachmentsCollapsibleTitle: FC = observer((props) => { projectId={projectId} issueId={issueId} disabled={disabled} + issueServiceType={issueServiceType} /> ) } diff --git a/web/core/components/issues/issue-detail-widgets/links/content.tsx b/web/core/components/issues/issue-detail-widgets/links/content.tsx index 2d85270b022..fefc7938fdf 100644 --- a/web/core/components/issues/issue-detail-widgets/links/content.tsx +++ b/web/core/components/issues/issue-detail-widgets/links/content.tsx @@ -1,5 +1,7 @@ "use client"; import React, { FC } from "react"; +import { EIssueServiceType } from "@plane/constants"; +import { TIssueServiceType } from "@plane/types"; // components import { LinkList } from "../../issue-detail/links"; // helper @@ -10,13 +12,21 @@ type Props = { projectId: string; issueId: string; disabled: boolean; + issueServiceType?: TIssueServiceType; }; export const IssueLinksCollapsibleContent: FC = (props) => { - const { workspaceSlug, projectId, issueId, disabled } = props; + const { workspaceSlug, projectId, issueId, disabled, issueServiceType = EIssueServiceType.ISSUES } = props; // helper - const handleLinkOperations = useLinkOperations(workspaceSlug, projectId, issueId); + const handleLinkOperations = useLinkOperations(workspaceSlug, projectId, issueId, issueServiceType); - return ; + return ( + + ); }; diff --git a/web/core/components/issues/issue-detail-widgets/links/helper.tsx b/web/core/components/issues/issue-detail-widgets/links/helper.tsx index 4669528cd3a..ae915beb898 100644 --- a/web/core/components/issues/issue-detail-widgets/links/helper.tsx +++ b/web/core/components/issues/issue-detail-widgets/links/helper.tsx @@ -1,14 +1,20 @@ "use client"; import { useMemo } from "react"; -import { TIssueLink } from "@plane/types"; +import { EIssueServiceType } from "@plane/constants"; +import { TIssueLink, TIssueServiceType } from "@plane/types"; import { TOAST_TYPE, setToast } from "@plane/ui"; // hooks import { useIssueDetail } from "@/hooks/store"; // types import { TLinkOperations } from "../../issue-detail/links"; -export const useLinkOperations = (workspaceSlug: string, projectId: string, issueId: string): TLinkOperations => { - const { createLink, updateLink, removeLink } = useIssueDetail(); +export const useLinkOperations = ( + workspaceSlug: string, + projectId: string, + issueId: string, + issueServiceType: TIssueServiceType = EIssueServiceType.ISSUES +): TLinkOperations => { + const { createLink, updateLink, removeLink } = useIssueDetail(issueServiceType); const handleLinkOperations: TLinkOperations = useMemo( () => ({ diff --git a/web/core/components/issues/issue-detail-widgets/links/quick-action-button.tsx b/web/core/components/issues/issue-detail-widgets/links/quick-action-button.tsx index f9a59dd3a71..775e2f9d779 100644 --- a/web/core/components/issues/issue-detail-widgets/links/quick-action-button.tsx +++ b/web/core/components/issues/issue-detail-widgets/links/quick-action-button.tsx @@ -2,18 +2,21 @@ import React, { FC } from "react"; import { observer } from "mobx-react"; import { Plus } from "lucide-react"; +import { EIssueServiceType } from "@plane/constants"; +import { TIssueServiceType } from "@plane/types"; // hooks import { useIssueDetail } from "@/hooks/store"; type Props = { customButton?: React.ReactNode; disabled?: boolean; + issueServiceType?: TIssueServiceType; }; export const IssueLinksActionButton: FC = observer((props) => { - const { customButton, disabled = false } = props; + const { customButton, disabled = false, issueServiceType = EIssueServiceType.ISSUES } = props; // store hooks - const { toggleIssueLinkModal } = useIssueDetail(); + const { toggleIssueLinkModal } = useIssueDetail(issueServiceType); // handlers const handleOnClick = (e: React.MouseEvent) => { diff --git a/web/core/components/issues/issue-detail-widgets/links/root.tsx b/web/core/components/issues/issue-detail-widgets/links/root.tsx index 5b8c11b028d..655f23e0857 100644 --- a/web/core/components/issues/issue-detail-widgets/links/root.tsx +++ b/web/core/components/issues/issue-detail-widgets/links/root.tsx @@ -1,6 +1,8 @@ "use client"; import React, { FC } from "react"; import { observer } from "mobx-react"; +import { EIssueServiceType } from "@plane/constants"; +import { TIssueServiceType } from "@plane/types"; import { Collapsible } from "@plane/ui"; // components import { IssueLinksCollapsibleContent, IssueLinksCollapsibleTitle } from "@/components/issues/issue-detail-widgets"; @@ -12,12 +14,13 @@ type Props = { projectId: string; issueId: string; disabled?: boolean; + issueServiceType?: TIssueServiceType; }; export const LinksCollapsible: FC = observer((props) => { - const { workspaceSlug, projectId, issueId, disabled = false } = props; + const { workspaceSlug, projectId, issueId, disabled = false, issueServiceType = EIssueServiceType.ISSUES } = props; // store hooks - const { openWidgets, toggleOpenWidget } = useIssueDetail(); + const { openWidgets, toggleOpenWidget } = useIssueDetail(issueServiceType); // derived values const isCollapsibleOpen = openWidgets.includes("links"); @@ -26,7 +29,14 @@ export const LinksCollapsible: FC = observer((props) => { toggleOpenWidget("links")} - title={} + title={ + + } buttonClassName="w-full" > = observer((props) => { projectId={projectId} issueId={issueId} disabled={disabled} + issueServiceType={issueServiceType} /> ); diff --git a/web/core/components/issues/issue-detail-widgets/links/title.tsx b/web/core/components/issues/issue-detail-widgets/links/title.tsx index 1e01ee19887..19929df255d 100644 --- a/web/core/components/issues/issue-detail-widgets/links/title.tsx +++ b/web/core/components/issues/issue-detail-widgets/links/title.tsx @@ -1,6 +1,8 @@ "use client"; import React, { FC, useMemo } from "react"; import { observer } from "mobx-react"; +import { EIssueServiceType } from "@plane/constants"; +import { TIssueServiceType } from "@plane/types"; import { CollapsibleButton } from "@plane/ui"; // components import { IssueLinksActionButton } from "@/components/issues/issue-detail-widgets"; @@ -11,14 +13,15 @@ type Props = { isOpen: boolean; issueId: string; disabled: boolean; + issueServiceType?: TIssueServiceType; }; export const IssueLinksCollapsibleTitle: FC = observer((props) => { - const { isOpen, issueId, disabled } = props; + const { isOpen, issueId, disabled, issueServiceType = EIssueServiceType.ISSUES } = props; // store hooks const { issue: { getIssueById }, - } = useIssueDetail(); + } = useIssueDetail(issueServiceType); // derived values const issue = getIssueById(issueId); @@ -40,7 +43,9 @@ export const IssueLinksCollapsibleTitle: FC = observer((props) => { isOpen={isOpen} title="Links" indicatorElement={indicatorElement} - actionItemElement={!disabled && } + actionItemElement={ + !disabled && + } /> ); }); diff --git a/web/core/components/issues/issue-detail-widgets/relations/content.tsx b/web/core/components/issues/issue-detail-widgets/relations/content.tsx index 79be48e4f00..10b3b6585eb 100644 --- a/web/core/components/issues/issue-detail-widgets/relations/content.tsx +++ b/web/core/components/issues/issue-detail-widgets/relations/content.tsx @@ -1,7 +1,8 @@ "use client"; import { FC, useState } from "react"; import { observer } from "mobx-react"; -import { TIssue, TIssueRelationIdMap } from "@plane/types"; +import { EIssueServiceType } from "@plane/constants"; +import { TIssue, TIssueRelationIdMap, TIssueServiceType } from "@plane/types"; import { Collapsible } from "@plane/ui"; // components import { RelationIssueList } from "@/components/issues"; @@ -20,6 +21,7 @@ type Props = { projectId: string; issueId: string; disabled: boolean; + issueServiceType?: TIssueServiceType; }; type TIssueCrudState = { toggle: boolean; issueId: string | undefined; issue: TIssue | undefined }; @@ -33,7 +35,7 @@ export type TRelationObject = { }; export const RelationsCollapsibleContent: FC = observer((props) => { - const { workspaceSlug, projectId, issueId, disabled = false } = props; + const { workspaceSlug, projectId, issueId, disabled = false, issueServiceType = EIssueServiceType.ISSUES } = props; // state const [issueCrudState, setIssueCrudState] = useState<{ update: TIssueCrudState; @@ -56,7 +58,7 @@ export const RelationsCollapsibleContent: FC = observer((props) => { relation: { getRelationsByIssueId }, toggleDeleteIssueModal, toggleCreateIssueModal, - } = useIssueDetail(); + } = useIssueDetail(issueServiceType); // helper const issueOperations = useRelationOperations(); @@ -129,6 +131,7 @@ export const RelationsCollapsibleContent: FC = observer((props) => { disabled={disabled} issueOperations={issueOperations} handleIssueCrudState={handleIssueCrudState} + issueServiceType={issueServiceType} />
diff --git a/web/core/components/issues/issue-detail-widgets/relations/helper.tsx b/web/core/components/issues/issue-detail-widgets/relations/helper.tsx index ac8b0f66362..4267e9e1a91 100644 --- a/web/core/components/issues/issue-detail-widgets/relations/helper.tsx +++ b/web/core/components/issues/issue-detail-widgets/relations/helper.tsx @@ -1,7 +1,8 @@ "use client"; import { useMemo } from "react"; import { usePathname } from "next/navigation"; -import { TIssue } from "@plane/types"; +import { EIssueServiceType } from "@plane/constants"; +import { TIssue, TIssueServiceType } from "@plane/types"; import { TOAST_TYPE, setToast } from "@plane/ui"; // constants import { ISSUE_DELETED, ISSUE_UPDATED } from "@/constants/event-tracker"; @@ -16,8 +17,10 @@ export type TRelationIssueOperations = { remove: (workspaceSlug: string, projectId: string, issueId: string) => Promise; }; -export const useRelationOperations = (): TRelationIssueOperations => { - const { updateIssue, removeIssue } = useIssueDetail(); +export const useRelationOperations = ( + issueServiceType: TIssueServiceType = EIssueServiceType.ISSUES +): TRelationIssueOperations => { + const { updateIssue, removeIssue } = useIssueDetail(issueServiceType); const { captureIssueEvent } = useEventTracker(); const pathname = usePathname(); diff --git a/web/core/components/issues/issue-detail-widgets/relations/quick-action-button.tsx b/web/core/components/issues/issue-detail-widgets/relations/quick-action-button.tsx index dff072e7dca..b1ff260f6f5 100644 --- a/web/core/components/issues/issue-detail-widgets/relations/quick-action-button.tsx +++ b/web/core/components/issues/issue-detail-widgets/relations/quick-action-button.tsx @@ -2,6 +2,8 @@ import React, { FC } from "react"; import { observer } from "mobx-react"; import { Plus } from "lucide-react"; +import { EIssueServiceType } from "@plane/constants"; +import { TIssueServiceType } from "@plane/types"; import { CustomMenu } from "@plane/ui"; // hooks import { useIssueDetail } from "@/hooks/store"; @@ -13,12 +15,13 @@ type Props = { issueId: string; customButton?: React.ReactNode; disabled?: boolean; + issueServiceType?: TIssueServiceType; }; export const RelationActionButton: FC = observer((props) => { - const { customButton, issueId, disabled = false } = props; + const { customButton, issueId, disabled = false, issueServiceType = EIssueServiceType.ISSUES } = props; // store hooks - const { toggleRelationModal, setRelationKey } = useIssueDetail(); + const { toggleRelationModal, setRelationKey } = useIssueDetail(issueServiceType); const ISSUE_RELATION_OPTIONS = useTimeLineRelationOptions(); diff --git a/web/core/components/issues/issue-detail-widgets/relations/root.tsx b/web/core/components/issues/issue-detail-widgets/relations/root.tsx index d6a8edc3fc5..78c6ff39704 100644 --- a/web/core/components/issues/issue-detail-widgets/relations/root.tsx +++ b/web/core/components/issues/issue-detail-widgets/relations/root.tsx @@ -1,6 +1,8 @@ "use client"; import React, { FC } from "react"; import { observer } from "mobx-react"; +import { EIssueServiceType } from "@plane/constants"; +import { TIssueServiceType } from "@plane/types"; import { Collapsible } from "@plane/ui"; // components import { RelationsCollapsibleContent, RelationsCollapsibleTitle } from "@/components/issues/issue-detail-widgets"; @@ -12,12 +14,13 @@ type Props = { projectId: string; issueId: string; disabled?: boolean; + issueServiceType?: TIssueServiceType; }; export const RelationsCollapsible: FC = observer((props) => { - const { workspaceSlug, projectId, issueId, disabled = false } = props; + const { workspaceSlug, projectId, issueId, disabled = false, issueServiceType = EIssueServiceType.ISSUES } = props; // store hooks - const { openWidgets, toggleOpenWidget } = useIssueDetail(); + const { openWidgets, toggleOpenWidget } = useIssueDetail(issueServiceType); // derived values const isCollapsibleOpen = openWidgets.includes("relations"); @@ -26,7 +29,14 @@ export const RelationsCollapsible: FC = observer((props) => { toggleOpenWidget("relations")} - title={} + title={ + + } buttonClassName="w-full" > = observer((props) => { projectId={projectId} issueId={issueId} disabled={disabled} + issueServiceType={issueServiceType} /> ); diff --git a/web/core/components/issues/issue-detail-widgets/relations/title.tsx b/web/core/components/issues/issue-detail-widgets/relations/title.tsx index 2c3854beddd..3f91b712f77 100644 --- a/web/core/components/issues/issue-detail-widgets/relations/title.tsx +++ b/web/core/components/issues/issue-detail-widgets/relations/title.tsx @@ -1,6 +1,8 @@ "use client"; import React, { FC, useMemo } from "react"; import { observer } from "mobx-react"; +import { EIssueServiceType } from "@plane/constants"; +import { TIssueServiceType } from "@plane/types"; import { CollapsibleButton } from "@plane/ui"; // components import { RelationActionButton } from "@/components/issues/issue-detail-widgets"; @@ -13,14 +15,15 @@ type Props = { isOpen: boolean; issueId: string; disabled: boolean; + issueServiceType?: TIssueServiceType; }; export const RelationsCollapsibleTitle: FC = observer((props) => { - const { isOpen, issueId, disabled } = props; + const { isOpen, issueId, disabled, issueServiceType = EIssueServiceType.ISSUES } = props; // store hook const { relation: { getRelationCountByIssueId }, - } = useIssueDetail(); + } = useIssueDetail(issueServiceType); const ISSUE_RELATION_OPTIONS = useTimeLineRelationOptions(); // derived values @@ -41,7 +44,9 @@ export const RelationsCollapsibleTitle: FC = observer((props) => { isOpen={isOpen} title="Relations" indicatorElement={indicatorElement} - actionItemElement={!disabled && } + actionItemElement={ + !disabled && + } /> ); }); diff --git a/web/core/components/issues/issue-detail-widgets/sub-issues/content.tsx b/web/core/components/issues/issue-detail-widgets/sub-issues/content.tsx index 5432ee777e6..2bd9c90bfb5 100644 --- a/web/core/components/issues/issue-detail-widgets/sub-issues/content.tsx +++ b/web/core/components/issues/issue-detail-widgets/sub-issues/content.tsx @@ -1,7 +1,8 @@ "use client"; import React, { FC, useCallback, useEffect, useState } from "react"; import { observer } from "mobx-react"; -import { TIssue } from "@plane/types"; +import { EIssueServiceType } from "@plane/constants"; +import { TIssue, TIssueServiceType } from "@plane/types"; // components import { DeleteIssueModal } from "@/components/issues/delete-issue-modal"; import { CreateUpdateIssueModal } from "@/components/issues/issue-modal"; @@ -16,12 +17,13 @@ type Props = { projectId: string; parentIssueId: string; disabled: boolean; + issueServiceType?: TIssueServiceType; }; type TIssueCrudState = { toggle: boolean; parentIssueId: string | undefined; issue: TIssue | undefined }; export const SubIssuesCollapsibleContent: FC = observer((props) => { - const { workspaceSlug, projectId, parentIssueId, disabled } = props; + const { workspaceSlug, projectId, parentIssueId, disabled, issueServiceType = EIssueServiceType.ISSUES } = props; // state const [issueCrudState, setIssueCrudState] = useState<{ create: TIssueCrudState; @@ -58,7 +60,7 @@ export const SubIssuesCollapsibleContent: FC = observer((props) => { } = useIssueDetail(); // helpers - const subIssueOperations = useSubIssueOperations(); + const subIssueOperations = useSubIssueOperations(issueServiceType); const subIssueHelpers = subIssueHelpersByIssueId(`${parentIssueId}_root`); // handler @@ -95,7 +97,6 @@ export const SubIssuesCollapsibleContent: FC = observer((props) => { useEffect(() => { handleFetchSubIssues(); - return () => { handleFetchSubIssues(); }; @@ -123,6 +124,7 @@ export const SubIssuesCollapsibleContent: FC = observer((props) => { disabled={!disabled} handleIssueCrudState={handleIssueCrudState} subIssueOperations={subIssueOperations} + issueServiceType={issueServiceType} /> )} diff --git a/web/core/components/issues/issue-detail-widgets/sub-issues/helper.tsx b/web/core/components/issues/issue-detail-widgets/sub-issues/helper.tsx index 7df432d5d21..cc8abd82fd4 100644 --- a/web/core/components/issues/issue-detail-widgets/sub-issues/helper.tsx +++ b/web/core/components/issues/issue-detail-widgets/sub-issues/helper.tsx @@ -1,7 +1,8 @@ "use client"; import { useMemo } from "react"; import { usePathname } from "next/navigation"; -import { TIssue } from "@plane/types"; +import { EIssueServiceType } from "@plane/constants"; +import { TIssue, TIssueServiceType } from "@plane/types"; import { TOAST_TYPE, setToast } from "@plane/ui"; // helper import { copyTextToClipboard } from "@/helpers/string.helper"; @@ -16,15 +17,17 @@ export type TRelationIssueOperations = { remove: (workspaceSlug: string, projectId: string, issueId: string) => Promise; }; -export const useSubIssueOperations = (): TSubIssueOperations => { +export const useSubIssueOperations = ( + issueServiceType: TIssueServiceType = EIssueServiceType.ISSUES +): TSubIssueOperations => { const { subIssues: { setSubIssueHelpers }, fetchSubIssues, createSubIssues, updateSubIssue, - removeSubIssue, deleteSubIssue, } = useIssueDetail(); + const { removeSubIssue } = useIssueDetail(issueServiceType); const { captureIssueEvent } = useEventTracker(); const pathname = usePathname(); diff --git a/web/core/components/issues/issue-detail-widgets/sub-issues/quick-action-button.tsx b/web/core/components/issues/issue-detail-widgets/sub-issues/quick-action-button.tsx index bf1ece31008..73770bb130c 100644 --- a/web/core/components/issues/issue-detail-widgets/sub-issues/quick-action-button.tsx +++ b/web/core/components/issues/issue-detail-widgets/sub-issues/quick-action-button.tsx @@ -2,7 +2,8 @@ import React, { FC } from "react"; import { observer } from "mobx-react"; import { LayersIcon, Plus } from "lucide-react"; -import { TIssue } from "@plane/types"; +import { EIssueServiceType } from "@plane/constants"; +import { TIssue, TIssueServiceType } from "@plane/types"; import { CustomMenu } from "@plane/ui"; // hooks import { useEventTracker, useIssueDetail } from "@/hooks/store"; @@ -11,10 +12,11 @@ type Props = { issueId: string; customButton?: React.ReactNode; disabled?: boolean; + issueServiceType?: TIssueServiceType; }; export const SubIssuesActionButton: FC = observer((props) => { - const { issueId, customButton, disabled = false } = props; + const { issueId, customButton, disabled = false, issueServiceType = EIssueServiceType.ISSUES } = props; // store hooks const { issue: { getIssueById }, @@ -22,7 +24,7 @@ export const SubIssuesActionButton: FC = observer((props) => { toggleSubIssuesModal, setIssueCrudOperationState, issueCrudOperationState, - } = useIssueDetail(); + } = useIssueDetail(issueServiceType); const { setTrackElement } = useEventTracker(); // derived values diff --git a/web/core/components/issues/issue-detail-widgets/sub-issues/root.tsx b/web/core/components/issues/issue-detail-widgets/sub-issues/root.tsx index 99dbcacb510..5ead3bc5f4d 100644 --- a/web/core/components/issues/issue-detail-widgets/sub-issues/root.tsx +++ b/web/core/components/issues/issue-detail-widgets/sub-issues/root.tsx @@ -1,6 +1,8 @@ "use client"; import React, { FC } from "react"; import { observer } from "mobx-react"; +import { EIssueServiceType } from "@plane/constants"; +import { TIssueServiceType } from "@plane/types"; import { Collapsible } from "@plane/ui"; // components import { SubIssuesCollapsibleContent, SubIssuesCollapsibleTitle } from "@/components/issues/issue-detail-widgets"; @@ -12,13 +14,14 @@ type Props = { projectId: string; issueId: string; disabled?: boolean; + issueServiceType?: TIssueServiceType; }; export const SubIssuesCollapsible: FC = observer((props) => { - const { workspaceSlug, projectId, issueId, disabled = false } = props; + const { workspaceSlug, projectId, issueId, disabled = false, issueServiceType = EIssueServiceType.ISSUES } = props; // store hooks - const { openWidgets, toggleOpenWidget } = useIssueDetail(); + const { openWidgets, toggleOpenWidget } = useIssueDetail(issueServiceType); // derived state const isCollapsibleOpen = openWidgets.includes("sub-issues"); @@ -27,7 +30,14 @@ export const SubIssuesCollapsible: FC = observer((props) => { toggleOpenWidget("sub-issues")} - title={} + title={ + + } buttonClassName="w-full" > = observer((props) => { projectId={projectId} parentIssueId={issueId} disabled={disabled} + issueServiceType={issueServiceType} /> ); diff --git a/web/core/components/issues/issue-detail-widgets/sub-issues/title.tsx b/web/core/components/issues/issue-detail-widgets/sub-issues/title.tsx index b3d9bf1fc15..ad88c112ede 100644 --- a/web/core/components/issues/issue-detail-widgets/sub-issues/title.tsx +++ b/web/core/components/issues/issue-detail-widgets/sub-issues/title.tsx @@ -1,6 +1,8 @@ "use client"; -import React, { FC, useMemo } from "react"; +import React, { FC } from "react"; import { observer } from "mobx-react"; +import { EIssueServiceType } from "@plane/constants"; +import { TIssueServiceType } from "@plane/types"; import { CircularProgressIndicator, CollapsibleButton } from "@plane/ui"; // components import { SubIssuesActionButton } from "@/components/issues/issue-detail-widgets"; @@ -11,14 +13,15 @@ type Props = { isOpen: boolean; parentIssueId: string; disabled: boolean; + issueServiceType?: TIssueServiceType; }; export const SubIssuesCollapsibleTitle: FC = observer((props) => { - const { isOpen, parentIssueId, disabled } = props; + const { isOpen, parentIssueId, disabled, issueServiceType = EIssueServiceType.ISSUES } = props; // store hooks const { subIssues: { subIssuesByIssueId, stateDistributionByIssueId }, - } = useIssueDetail(); + } = useIssueDetail(issueServiceType); // derived data const subIssuesDistribution = stateDistributionByIssueId(parentIssueId); @@ -32,25 +35,23 @@ export const SubIssuesCollapsibleTitle: FC = observer((props) => { const totalCount = subIssues.length; const percentage = completedCount && totalCount ? (completedCount / totalCount) * 100 : 0; - // indicator element - const indicatorElement = useMemo( - () => ( -
- - - {completedCount}/{totalCount} Done - -
- ), - [completedCount, totalCount, percentage] - ); - return ( } + indicatorElement={ +
+ + + {completedCount}/{totalCount} Done + +
+ } + actionItemElement={ + !disabled && ( + + ) + } /> ); }); diff --git a/web/core/components/issues/issue-detail/label/root.tsx b/web/core/components/issues/issue-detail/label/root.tsx index daa5169b13b..f71e9ba3ce2 100644 --- a/web/core/components/issues/issue-detail/label/root.tsx +++ b/web/core/components/issues/issue-detail/label/root.tsx @@ -2,7 +2,8 @@ import { FC, useMemo } from "react"; import { observer } from "mobx-react"; -import { IIssueLabel, TIssue } from "@plane/types"; +import { EIssueServiceType } from "@plane/constants"; +import { IIssueLabel, TIssue, TIssueServiceType } from "@plane/types"; // components import { TOAST_TYPE, setToast } from "@plane/ui"; // hooks @@ -21,6 +22,7 @@ export type TIssueLabel = { disabled: boolean; isInboxIssue?: boolean; onLabelUpdate?: (labelIds: string[]) => void; + issueServiceType?: TIssueServiceType; }; export type TLabelOperations = { @@ -29,13 +31,21 @@ export type TLabelOperations = { }; export const IssueLabel: FC = observer((props) => { - const { workspaceSlug, projectId, issueId, disabled = false, isInboxIssue = false, onLabelUpdate } = props; + const { + workspaceSlug, + projectId, + issueId, + disabled = false, + isInboxIssue = false, + onLabelUpdate, + issueServiceType = EIssueServiceType.ISSUES, + } = props; // hooks - const { updateIssue } = useIssueDetail(); + const { updateIssue } = useIssueDetail(issueServiceType); const { createLabel } = useLabel(); const { issue: { getIssueById }, - } = useIssueDetail(); + } = useIssueDetail(issueServiceType); const { getIssueInboxByIssueId } = useProjectInbox(); const { allowPermissions } = useUserPermissions(); diff --git a/web/core/components/issues/issue-detail/links/create-update-link-modal.tsx b/web/core/components/issues/issue-detail/links/create-update-link-modal.tsx index 99e350c6132..2da5d0f7955 100644 --- a/web/core/components/issues/issue-detail/links/create-update-link-modal.tsx +++ b/web/core/components/issues/issue-detail/links/create-update-link-modal.tsx @@ -3,8 +3,9 @@ import { FC, useEffect } from "react"; import { observer } from "mobx-react"; import { Controller, useForm } from "react-hook-form"; +import { EIssueServiceType } from "@plane/constants"; // plane types -import type { TIssueLinkEditableFields } from "@plane/types"; +import type { TIssueLinkEditableFields, TIssueServiceType } from "@plane/types"; // plane ui import { Button, Input, ModalCore } from "@plane/ui"; // hooks @@ -22,6 +23,7 @@ export type TIssueLinkCreateEditModal = { isModalOpen: boolean; handleOnClose?: () => void; linkOperations: TLinkOperationsModal; + issueServiceType?: TIssueServiceType; }; const defaultValues: TIssueLinkCreateFormFieldOptions = { @@ -31,7 +33,7 @@ const defaultValues: TIssueLinkCreateFormFieldOptions = { export const IssueLinkCreateUpdateModal: FC = observer((props) => { // props - const { isModalOpen, handleOnClose, linkOperations } = props; + const { isModalOpen, handleOnClose, linkOperations, issueServiceType = EIssueServiceType.ISSUES } = props; // react hook form const { formState: { errors, isSubmitting }, @@ -42,7 +44,7 @@ export const IssueLinkCreateUpdateModal: FC = observe defaultValues, }); // store hooks - const { issueLinkData: preloadedData, setIssueLinkData } = useIssueDetail(); + const { issueLinkData: preloadedData, setIssueLinkData } = useIssueDetail(issueServiceType); const onClose = () => { setIssueLinkData(null); diff --git a/web/core/components/issues/issue-detail/links/link-item.tsx b/web/core/components/issues/issue-detail/links/link-item.tsx index c7629b5dce2..68e8acf4ded 100644 --- a/web/core/components/issues/issue-detail/links/link-item.tsx +++ b/web/core/components/issues/issue-detail/links/link-item.tsx @@ -3,6 +3,8 @@ import { FC } from "react"; import { observer } from "mobx-react"; import { Pencil, Trash2, LinkIcon, ExternalLink } from "lucide-react"; +import { EIssueServiceType } from "@plane/constants"; +import { TIssueServiceType } from "@plane/types"; // ui import { Tooltip, TOAST_TYPE, setToast, CustomMenu } from "@plane/ui"; // helpers @@ -17,17 +19,18 @@ type TIssueLinkItem = { linkId: string; linkOperations: TLinkOperationsModal; isNotAllowed: boolean; + issueServiceType?: TIssueServiceType; }; export const IssueLinkItem: FC = observer((props) => { // props - const { linkId, linkOperations, isNotAllowed } = props; + const { linkId, linkOperations, isNotAllowed, issueServiceType = EIssueServiceType.ISSUES } = props; // hooks const { toggleIssueLinkModal: toggleIssueLinkModalStore, setIssueLinkData, link: { getLinkById }, - } = useIssueDetail(); + } = useIssueDetail(issueServiceType); const { isMobile } = usePlatformOS(); const linkDetail = getLinkById(linkId); if (!linkDetail) return <>; diff --git a/web/core/components/issues/issue-detail/links/link-list.tsx b/web/core/components/issues/issue-detail/links/link-list.tsx index 7f20d53677c..7ca128b988e 100644 --- a/web/core/components/issues/issue-detail/links/link-list.tsx +++ b/web/core/components/issues/issue-detail/links/link-list.tsx @@ -1,5 +1,7 @@ import { FC } from "react"; import { observer } from "mobx-react"; +import { EIssueServiceType } from "@plane/constants"; +import { TIssueServiceType } from "@plane/types"; // computed import { useIssueDetail } from "@/hooks/store"; import { IssueLinkItem } from "./link-item"; @@ -12,15 +14,16 @@ type TLinkList = { issueId: string; linkOperations: TLinkOperationsModal; disabled?: boolean; + issueServiceType?: TIssueServiceType; }; export const LinkList: FC = observer((props) => { // props - const { issueId, linkOperations, disabled = false } = props; + const { issueId, linkOperations, disabled = false, issueServiceType = EIssueServiceType.ISSUES } = props; // hooks const { link: { getLinksByIssueId }, - } = useIssueDetail(); + } = useIssueDetail(issueServiceType); const issueLinks = getLinksByIssueId(issueId); @@ -29,7 +32,13 @@ export const LinkList: FC = observer((props) => { return (
{issueLinks.map((linkId) => ( - + ))}
); diff --git a/web/core/components/issues/issue-detail/main-content.tsx b/web/core/components/issues/issue-detail/main-content.tsx index 08d5c06630c..f484761641b 100644 --- a/web/core/components/issues/issue-detail/main-content.tsx +++ b/web/core/components/issues/issue-detail/main-content.tsx @@ -55,11 +55,16 @@ export const IssueMainContent: React.FC = observer((props) => { const issue = issueId ? getIssueById(issueId) : undefined; // debounced duplicate issues swr - const { duplicateIssues } = useDebouncedDuplicateIssues(projectDetails?.workspace.toString(), projectDetails?.id, { - name: issue?.name, - description_html: getTextContent(issue?.description_html), - issueId: issue?.id, - }); + const { duplicateIssues } = useDebouncedDuplicateIssues( + workspaceSlug, + projectDetails?.workspace.toString(), + projectDetails?.id, + { + name: issue?.name, + description_html: getTextContent(issue?.description_html), + issueId: issue?.id, + } + ); useEffect(() => { if (isSubmitting === "submitted") { diff --git a/web/core/components/issues/issue-detail/parent-select.tsx b/web/core/components/issues/issue-detail/parent-select.tsx index af9b40df1ec..d83bc635b47 100644 --- a/web/core/components/issues/issue-detail/parent-select.tsx +++ b/web/core/components/issues/issue-detail/parent-select.tsx @@ -88,6 +88,7 @@ export const IssueParentSelect: React.FC = observer((props) isOpen={isParentIssueModalOpen === issueId} handleClose={() => toggleParentIssueModal(null)} onChange={(issue: any) => handleParentIssue(issue?.id)} + searchEpic />