From a79dbdadb5072265512736c1c2fe139af3cc1323 Mon Sep 17 00:00:00 2001 From: guru_sainath Date: Wed, 6 Dec 2023 19:58:47 +0530 Subject: [PATCH] fix: issue layouts bugs and ui fixes (#3012) * fix: initial issue creation issue in the list layout * fix kanban drag n drop and updating properties * reduce z index of spreadsheet bottom row to not overlap with other elements * fix state update by using state id instead of state detail's id * fix add default use state for description * add create issue button for project views to be at par with production * save draft issues from modal * chore: added save view button in all layouts applied filters * use useEffect instead of swr for fetching issue details for peek overview * fix: resolved kanban dnd --------- Co-authored-by: rahulramesha --- .../headers/project-view-issues.tsx | 17 +- web/components/issues/draft-issue-modal.tsx | 12 +- .../applied-filters/roots/archived-issue.tsx | 8 +- .../applied-filters/roots/cycle-root.tsx | 7 +- .../applied-filters/roots/draft-issue.tsx | 8 +- .../applied-filters/roots/module-root.tsx | 6 +- .../applied-filters/roots/project-root.tsx | 12 +- .../roots/project-view-root.tsx | 20 +- web/components/issues/issue-layouts/index.ts | 3 + .../issues/issue-layouts/kanban/block.tsx | 176 +++++++++--------- .../issues/issue-layouts/list/blocks-list.tsx | 25 +-- .../issues/issue-layouts/save-filter-view.tsx | 33 ++++ .../spreadsheet/columns/state-column.tsx | 2 +- .../spreadsheet/spreadsheet-view.tsx | 2 +- .../issue-peek-overview/issue-detail.tsx | 8 +- .../issues/issue-peek-overview/root.tsx | 22 +-- 16 files changed, 213 insertions(+), 148 deletions(-) create mode 100644 web/components/issues/issue-layouts/save-filter-view.tsx diff --git a/web/components/headers/project-view-issues.tsx b/web/components/headers/project-view-issues.tsx index a3e0b2be4..b5f28b706 100644 --- a/web/components/headers/project-view-issues.tsx +++ b/web/components/headers/project-view-issues.tsx @@ -6,7 +6,7 @@ import { useMobxStore } from "lib/mobx/store-provider"; // components import { DisplayFiltersSelection, FiltersDropdown, FilterSelection, LayoutSelection } from "components/issues"; // ui -import { Breadcrumbs, CustomMenu, PhotoFilterIcon } from "@plane/ui"; +import { Breadcrumbs, Button, CustomMenu, PhotoFilterIcon } from "@plane/ui"; // helpers import { truncateText } from "helpers/string.helper"; import { renderEmoji } from "helpers/emoji.helper"; @@ -15,6 +15,8 @@ import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOption // constants import { ISSUE_DISPLAY_FILTERS_BY_LAYOUT } from "constants/issue"; import { EFilterType } from "store/issues/types"; +import { EProjectStore } from "store/command-palette.store"; +import { Plus } from "lucide-react"; export const ProjectViewIssuesHeader: React.FC = observer(() => { const router = useRouter(); @@ -25,7 +27,6 @@ export const ProjectViewIssuesHeader: React.FC = observer(() => { }; const { - issueFilter: issueFilterStore, projectViewFilters: projectViewFiltersStore, project: { currentProjectDetails }, projectLabel: { projectLabels }, @@ -33,6 +34,8 @@ export const ProjectViewIssuesHeader: React.FC = observer(() => { projectState: projectStateStore, projectViews: projectViewsStore, viewIssuesFilter: { issueFilters, updateFilters }, + commandPalette: commandPaletteStore, + trackEvent: { setTrackElement }, } = useMobxStore(); const storedFilters = viewId ? projectViewFiltersStore.storedFilters[viewId.toString()] : undefined; @@ -170,6 +173,16 @@ export const ProjectViewIssuesHeader: React.FC = observer(() => { handleDisplayPropertiesUpdate={handleDisplayProperties} /> + ); diff --git a/web/components/issues/draft-issue-modal.tsx b/web/components/issues/draft-issue-modal.tsx index 5d8711426..e7ee23481 100644 --- a/web/components/issues/draft-issue-modal.tsx +++ b/web/components/issues/draft-issue-modal.tsx @@ -43,7 +43,6 @@ interface IssuesModalProps { // services const issueService = new IssueService(); -const issueDraftService = new IssueDraftService(); const moduleService = new ModuleService(); export const CreateUpdateDraftIssueModal: React.FC = observer((props) => { @@ -65,7 +64,7 @@ export const CreateUpdateDraftIssueModal: React.FC = observer( const router = useRouter(); const { workspaceSlug, projectId, cycleId, moduleId } = router.query; - const { project: projectStore, user: userStore } = useMobxStore(); + const { project: projectStore, user: userStore, projectDraftIssues: draftIssueStore } = useMobxStore(); const user = userStore.currentUser; const projects = workspaceSlug ? projectStore.projects[workspaceSlug.toString()] : undefined; @@ -167,9 +166,10 @@ export const CreateUpdateDraftIssueModal: React.FC = observer( const createDraftIssue = async (payload: Partial) => { if (!workspaceSlug || !activeProject || !user) return; - await issueDraftService - .createDraftIssue(workspaceSlug as string, activeProject ?? "", payload) + await draftIssueStore + .createIssue(workspaceSlug as string, activeProject ?? "", payload) .then(async () => { + await draftIssueStore.fetchIssues(workspaceSlug as string, activeProject ?? "", "mutation"); setToastAlert({ type: "success", title: "Success!", @@ -192,8 +192,8 @@ export const CreateUpdateDraftIssueModal: React.FC = observer( const updateDraftIssue = async (payload: Partial) => { if (!user) return; - await issueDraftService - .updateDraftIssue(workspaceSlug as string, activeProject ?? "", data?.id ?? "", payload) + await draftIssueStore + .updateIssue(workspaceSlug as string, activeProject ?? "", data?.id ?? "", payload) .then((res) => { if (isUpdatingSingleIssue) { mutate(PROJECT_ISSUES_DETAILS, (prevData) => ({ ...prevData, ...res }), false); diff --git a/web/components/issues/issue-layouts/filters/applied-filters/roots/archived-issue.tsx b/web/components/issues/issue-layouts/filters/applied-filters/roots/archived-issue.tsx index c34ebc41f..73129c111 100644 --- a/web/components/issues/issue-layouts/filters/applied-filters/roots/archived-issue.tsx +++ b/web/components/issues/issue-layouts/filters/applied-filters/roots/archived-issue.tsx @@ -4,14 +4,14 @@ import { observer } from "mobx-react-lite"; // mobx store import { useMobxStore } from "lib/mobx/store-provider"; // components -import { AppliedFiltersList } from "components/issues"; +import { AppliedFiltersList, SaveFilterView } from "components/issues"; // types import { IIssueFilterOptions } from "types"; import { EFilterType } from "store/issues/types"; export const ArchivedIssueAppliedFiltersRoot: React.FC = observer(() => { const router = useRouter(); - const { workspaceSlug, projectId } = router.query; + const { workspaceSlug, projectId } = router.query as { workspaceSlug: string; projectId: string }; const { projectArchivedIssuesFilter: { issueFilters, updateFilters }, @@ -69,7 +69,7 @@ export const ArchivedIssueAppliedFiltersRoot: React.FC = observer(() => { if (Object.keys(appliedFilters).length === 0) return null; return ( -
+
{ members={projectMembers?.map((m) => m.member)} states={projectStateStore.states?.[projectId?.toString() ?? ""]} /> + +
); }); diff --git a/web/components/issues/issue-layouts/filters/applied-filters/roots/cycle-root.tsx b/web/components/issues/issue-layouts/filters/applied-filters/roots/cycle-root.tsx index f8604a456..c8de4c02a 100644 --- a/web/components/issues/issue-layouts/filters/applied-filters/roots/cycle-root.tsx +++ b/web/components/issues/issue-layouts/filters/applied-filters/roots/cycle-root.tsx @@ -1,9 +1,10 @@ import { useRouter } from "next/router"; import { observer } from "mobx-react-lite"; + // mobx store import { useMobxStore } from "lib/mobx/store-provider"; // components -import { AppliedFiltersList } from "components/issues"; +import { AppliedFiltersList, SaveFilterView } from "components/issues"; // types import { IIssueFilterOptions } from "types"; import { EFilterType } from "store/issues/types"; @@ -75,7 +76,7 @@ export const CycleAppliedFiltersRoot: React.FC = observer(() => { if (Object.keys(appliedFilters).length === 0) return null; return ( -
+
{ members={projectMembers?.map((m) => m.member)} states={projectStateStore.states?.[cycleId ?? ""]} /> + +
); }); diff --git a/web/components/issues/issue-layouts/filters/applied-filters/roots/draft-issue.tsx b/web/components/issues/issue-layouts/filters/applied-filters/roots/draft-issue.tsx index d69691426..917c5d17f 100644 --- a/web/components/issues/issue-layouts/filters/applied-filters/roots/draft-issue.tsx +++ b/web/components/issues/issue-layouts/filters/applied-filters/roots/draft-issue.tsx @@ -4,14 +4,14 @@ import { observer } from "mobx-react-lite"; // mobx store import { useMobxStore } from "lib/mobx/store-provider"; // components -import { AppliedFiltersList } from "components/issues"; +import { AppliedFiltersList, SaveFilterView } from "components/issues"; // types import { IIssueFilterOptions } from "types"; import { EFilterType } from "store/issues/types"; export const DraftIssueAppliedFiltersRoot: React.FC = observer(() => { const router = useRouter(); - const { workspaceSlug, projectId } = router.query; + const { workspaceSlug, projectId } = router.query as { workspaceSlug: string; projectId: string }; const { projectDraftIssuesFilter: { issueFilters, updateFilters }, @@ -64,7 +64,7 @@ export const DraftIssueAppliedFiltersRoot: React.FC = observer(() => { if (Object.keys(appliedFilters).length === 0) return null; return ( -
+
{ members={projectMembers?.map((m) => m.member)} states={projectStateStore.states?.[projectId?.toString() ?? ""]} /> + +
); }); diff --git a/web/components/issues/issue-layouts/filters/applied-filters/roots/module-root.tsx b/web/components/issues/issue-layouts/filters/applied-filters/roots/module-root.tsx index 0f85b837f..bbd554d41 100644 --- a/web/components/issues/issue-layouts/filters/applied-filters/roots/module-root.tsx +++ b/web/components/issues/issue-layouts/filters/applied-filters/roots/module-root.tsx @@ -4,7 +4,7 @@ import { observer } from "mobx-react-lite"; // mobx store import { useMobxStore } from "lib/mobx/store-provider"; // components -import { AppliedFiltersList } from "components/issues"; +import { AppliedFiltersList, SaveFilterView } from "components/issues"; // types import { IIssueFilterOptions } from "types"; import { EFilterType } from "store/issues/types"; @@ -76,7 +76,7 @@ export const ModuleAppliedFiltersRoot: React.FC = observer(() => { if (Object.keys(appliedFilters).length === 0) return null; return ( -
+
{ members={projectMembers?.map((m) => m.member)} states={projectStateStore.states?.[moduleId ?? ""]} /> + +
); }); diff --git a/web/components/issues/issue-layouts/filters/applied-filters/roots/project-root.tsx b/web/components/issues/issue-layouts/filters/applied-filters/roots/project-root.tsx index ac71259f2..90e49d54d 100644 --- a/web/components/issues/issue-layouts/filters/applied-filters/roots/project-root.tsx +++ b/web/components/issues/issue-layouts/filters/applied-filters/roots/project-root.tsx @@ -4,14 +4,18 @@ import { observer } from "mobx-react-lite"; // mobx store import { useMobxStore } from "lib/mobx/store-provider"; // components -import { AppliedFiltersList } from "components/issues"; +import { AppliedFiltersList, SaveFilterView } from "components/issues"; + // types import { IIssueFilterOptions } from "types"; import { EFilterType } from "store/issues/types"; export const ProjectAppliedFiltersRoot: React.FC = observer(() => { const router = useRouter(); - const { workspaceSlug, projectId } = router.query; + const { workspaceSlug, projectId } = router.query as { + workspaceSlug: string; + projectId: string; + }; const { projectLabel: { projectLabels }, @@ -60,7 +64,7 @@ export const ProjectAppliedFiltersRoot: React.FC = observer(() => { if (Object.keys(appliedFilters).length === 0) return null; return ( -
+
{ members={projectMembers?.map((m) => m.member)} states={projectStateStore.states?.[projectId?.toString() ?? ""]} /> + +
); }); diff --git a/web/components/issues/issue-layouts/filters/applied-filters/roots/project-view-root.tsx b/web/components/issues/issue-layouts/filters/applied-filters/roots/project-view-root.tsx index 873a1aea5..5e4a53b87 100644 --- a/web/components/issues/issue-layouts/filters/applied-filters/roots/project-view-root.tsx +++ b/web/components/issues/issue-layouts/filters/applied-filters/roots/project-view-root.tsx @@ -31,7 +31,6 @@ export const ProjectViewAppliedFiltersRoot: React.FC = observer(() => { } = useMobxStore(); const viewDetails = viewId ? projectViewsStore.viewDetails[viewId.toString()] : undefined; - const storedFilters = viewId ? projectViewFiltersStore.storedFilters[viewId.toString()] : undefined; const userFilters = issueFilters?.filters; // filters whose value not null or empty array @@ -89,7 +88,7 @@ export const ProjectViewAppliedFiltersRoot: React.FC = observer(() => { projectViewsStore.updateView(workspaceSlug.toString(), projectId.toString(), viewId.toString(), { query_data: { ...viewDetails.query_data, - ...(storedFilters ?? {}), + ...(appliedFilters ?? {}), }, }); }; @@ -104,13 +103,16 @@ export const ProjectViewAppliedFiltersRoot: React.FC = observer(() => { members={projectMembers?.map((m) => m.member)} states={projectStateStore.states?.[projectId?.toString() ?? ""]} /> - {storedFilters && viewDetails && areFiltersDifferent(storedFilters, viewDetails.query_data ?? {}) && ( -
- -
- )} + + {appliedFilters && + viewDetails?.query_data && + areFiltersDifferent(appliedFilters, viewDetails?.query_data ?? {}) && ( +
+ +
+ )}
); }); diff --git a/web/components/issues/issue-layouts/index.ts b/web/components/issues/issue-layouts/index.ts index 3a8a2baac..fc294b084 100644 --- a/web/components/issues/issue-layouts/index.ts +++ b/web/components/issues/issue-layouts/index.ts @@ -15,3 +15,6 @@ export * from "./spreadsheet"; // properties export * from "./properties"; + +// save view +export * from "./save-filter-view"; diff --git a/web/components/issues/issue-layouts/kanban/block.tsx b/web/components/issues/issue-layouts/kanban/block.tsx index f03101b12..e86235b36 100644 --- a/web/components/issues/issue-layouts/kanban/block.tsx +++ b/web/components/issues/issue-layouts/kanban/block.tsx @@ -1,16 +1,14 @@ -import { memo, useRef, useState } from "react"; +import { memo } from "react"; import { Draggable } from "@hello-pangea/dnd"; +import isEqual from "lodash/isEqual"; // components import { KanBanProperties } from "./properties"; // ui import { Tooltip } from "@plane/ui"; -// hooks -import useOutsideClickDetector from "hooks/use-outside-click-detector"; // types import { IIssueDisplayProperties, IIssue } from "types"; import { EIssueActions } from "../types"; import { useRouter } from "next/router"; -import { MoreHorizontal } from "lucide-react"; interface IssueBlockProps { sub_group_id: string; @@ -20,37 +18,28 @@ interface IssueBlockProps { isDragDisabled: boolean; showEmptyGroup: boolean; handleIssues: (sub_group_by: string | null, group_by: string | null, issue: IIssue, action: EIssueActions) => void; - quickActions: ( - sub_group_by: string | null, - group_by: string | null, - issue: IIssue, - customActionButton?: React.ReactElement - ) => React.ReactNode; + quickActions: (sub_group_by: string | null, group_by: string | null, issue: IIssue) => React.ReactNode; displayProperties: IIssueDisplayProperties | null; isReadOnly: boolean; } -export const KanBanIssueMemoBlock: React.FC = (props) => { - const { - sub_group_id, - columnId, - index, - issue, - isDragDisabled, - showEmptyGroup, - handleIssues, - quickActions, - displayProperties, - isReadOnly, - } = props; - // router +interface IssueDetailsBlockProps { + sub_group_id: string; + columnId: string; + issue: IIssue; + showEmptyGroup: boolean; + handleIssues: (sub_group_by: string | null, group_by: string | null, issue: IIssue, action: EIssueActions) => void; + quickActions: (sub_group_by: string | null, group_by: string | null, issue: IIssue) => React.ReactNode; + displayProperties: IIssueDisplayProperties | null; + isReadOnly: boolean; +} + +const KanbanIssueDetailsBlock: React.FC = (props) => { + const { sub_group_id, columnId, issue, showEmptyGroup, handleIssues, quickActions, displayProperties, isReadOnly } = + props; + const router = useRouter(); - // states - const [isMenuActive, setIsMenuActive] = useState(false); - - const menuActionRef = useRef(null); - const updateIssue = (sub_group_by: string | null, group_by: string | null, issueToUpdate: IIssue) => { if (issueToUpdate) handleIssues(sub_group_by, group_by, issueToUpdate, EIssueActions.UPDATE); }; @@ -64,24 +53,70 @@ export const KanBanIssueMemoBlock: React.FC = (props) => { }); }; + return ( + <> + {displayProperties && displayProperties?.key && ( +
+
+ {issue.project_detail.identifier}-{issue.sequence_id} +
+
+ {quickActions( + !sub_group_id && sub_group_id === "null" ? null : sub_group_id, + !columnId && columnId === "null" ? null : columnId, + issue + )} +
+
+ )} + +
+ {issue.name} +
+
+
+ +
+ + ); +}; + +const validateMemo = (prevProps: IssueDetailsBlockProps, nextProps: IssueDetailsBlockProps) => { + if (prevProps.issue !== nextProps.issue) return false; + if (!isEqual(prevProps.displayProperties, nextProps.displayProperties)) { + return false; + } + return true; +}; + +const KanbanIssueMemoBlock = memo(KanbanIssueDetailsBlock, validateMemo); + +export const KanbanIssueBlock: React.FC = (props) => { + const { + sub_group_id, + columnId, + index, + issue, + isDragDisabled, + showEmptyGroup, + handleIssues, + quickActions, + displayProperties, + isReadOnly, + } = props; + let draggableId = issue.id; if (columnId) draggableId = `${draggableId}__${columnId}`; if (sub_group_id) draggableId = `${draggableId}__${sub_group_id}`; - useOutsideClickDetector(menuActionRef, () => setIsMenuActive(false)); - - const customActionButton = ( -
setIsMenuActive(!isMenuActive)} - > - -
- ); - return ( <> @@ -100,44 +135,16 @@ export const KanBanIssueMemoBlock: React.FC = (props) => { isDragDisabled ? "" : "hover:cursor-grab" } ${snapshot.isDragging ? `border-custom-primary-100` : `border-transparent`}`} > - {displayProperties && displayProperties?.key && ( -
-
- {issue.project_detail.identifier}-{issue.sequence_id} -
- -
- )} - -
- {issue.name} -
-
-
- -
+
)} @@ -145,10 +152,3 @@ export const KanBanIssueMemoBlock: React.FC = (props) => { ); }; - -const validateMemo = (prevProps: IssueBlockProps, nextProps: IssueBlockProps) => { - if (prevProps.issue != nextProps.issue) return true; - return false; -}; - -export const KanbanIssueBlock = memo(KanBanIssueMemoBlock, validateMemo); diff --git a/web/components/issues/issue-layouts/list/blocks-list.tsx b/web/components/issues/issue-layouts/list/blocks-list.tsx index ad7fd7d8b..c0e5e6034 100644 --- a/web/components/issues/issue-layouts/list/blocks-list.tsx +++ b/web/components/issues/issue-layouts/list/blocks-list.tsx @@ -22,17 +22,20 @@ export const IssueBlocksList: FC = (props) => { return (
{issueIds && issueIds.length > 0 ? ( - issueIds.map((issueId: string) => ( - - )) + issueIds.map( + (issueId: string) => + issues[issueId] && ( + + ) + ) ) : (
No issues
)} diff --git a/web/components/issues/issue-layouts/save-filter-view.tsx b/web/components/issues/issue-layouts/save-filter-view.tsx new file mode 100644 index 000000000..42fac26ef --- /dev/null +++ b/web/components/issues/issue-layouts/save-filter-view.tsx @@ -0,0 +1,33 @@ +import { FC, useState } from "react"; +import { Plus } from "lucide-react"; +import { Button } from "@plane/ui"; +// components +import { CreateUpdateProjectViewModal } from "components/views"; + +interface ISaveFilterView { + workspaceSlug: string; + projectId: string; + filterParams: any; +} + +export const SaveFilterView: FC = (props) => { + const { workspaceSlug, projectId, filterParams } = props; + + const [viewModal, setViewModal] = useState(false); + + return ( +
+ setViewModal(false)} + /> + + +
+ ); +}; diff --git a/web/components/issues/issue-layouts/spreadsheet/columns/state-column.tsx b/web/components/issues/issue-layouts/spreadsheet/columns/state-column.tsx index 866a66405..b75336159 100644 --- a/web/components/issues/issue-layouts/spreadsheet/columns/state-column.tsx +++ b/web/components/issues/issue-layouts/spreadsheet/columns/state-column.tsx @@ -26,7 +26,7 @@ export const SpreadsheetStateColumn: React.FC = (props) => { <> onChange({ state: data.id, state_detail: data })} className="h-full w-full" diff --git a/web/components/issues/issue-layouts/spreadsheet/spreadsheet-view.tsx b/web/components/issues/issue-layouts/spreadsheet/spreadsheet-view.tsx index 63fd390a1..a6115f354 100644 --- a/web/components/issues/issue-layouts/spreadsheet/spreadsheet-view.tsx +++ b/web/components/issues/issue-layouts/spreadsheet/spreadsheet-view.tsx @@ -142,7 +142,7 @@ export const SpreadsheetView: React.FC = observer((props) => {
-
+
{enableQuickCreateIssue && ( )} diff --git a/web/components/issues/issue-peek-overview/issue-detail.tsx b/web/components/issues/issue-peek-overview/issue-detail.tsx index 2ceb6be77..b9c3152d4 100644 --- a/web/components/issues/issue-peek-overview/issue-detail.tsx +++ b/web/components/issues/issue-peek-overview/issue-detail.tsx @@ -78,8 +78,8 @@ export const PeekOverviewIssueDetails: FC = (props) = [issue, issueUpdate] ); - const [localTitleValue, setLocalTitleValue] = useState(""); - const [localIssueDescription, setLocalIssueDescription] = useState(""); + const [localTitleValue, setLocalTitleValue] = useState(issue.name); + const [localIssueDescription, setLocalIssueDescription] = useState(issue.description_html); useEffect(() => { if (issue.id) { @@ -88,10 +88,6 @@ export const PeekOverviewIssueDetails: FC = (props) = } }, [issue.id]); - useEffect(() => { - setLocalTitleValue(issue.name); - }, [issue.name]); - const debouncedFormSave = debounce(async () => { handleSubmit(handleDescriptionFormSubmit)().finally(() => setIsSubmitting("submitted")); }, 1500); diff --git a/web/components/issues/issue-peek-overview/root.tsx b/web/components/issues/issue-peek-overview/root.tsx index 09a5202b5..e9d0ecd3e 100644 --- a/web/components/issues/issue-peek-overview/root.tsx +++ b/web/components/issues/issue-peek-overview/root.tsx @@ -1,4 +1,4 @@ -import { FC, Fragment, ReactNode } from "react"; +import { FC, Fragment, ReactNode, useEffect } from "react"; import { useRouter } from "next/router"; import { observer } from "mobx-react-lite"; import useSWR from "swr"; @@ -40,17 +40,17 @@ export const IssuePeekOverview: FC = observer((props) => { const { setToastAlert } = useToast(); - useSWR( - workspaceSlug && projectId && issueId && peekIssueId && issueId === peekIssueId - ? `ISSUE_DETAILS_${workspaceSlug}_${projectId}_${peekIssueId}` - : null, - async () => { - if (workspaceSlug && projectId && issueId && issueId === peekIssueId) { - if (isArchived) await archivedIssueDetailStore.fetchPeekIssueDetails(workspaceSlug, projectId, peekIssueId); - else await issueDetailStore.fetchPeekIssueDetails(workspaceSlug, projectId, peekIssueId); - } + const fetchIssueDetail = async () => { + if (workspaceSlug && projectId && peekIssueId) { + if (isArchived) + await archivedIssueDetailStore.fetchPeekIssueDetails(workspaceSlug, projectId, peekIssueId as string); + else await issueDetailStore.fetchPeekIssueDetails(workspaceSlug, projectId, peekIssueId as string); } - ); + }; + + useEffect(() => { + fetchIssueDetail(); + }, [workspaceSlug, projectId, peekIssueId]); const handleCopyText = (e: React.MouseEvent) => { e.stopPropagation();