diff --git a/plane-src/apps/web/ce/components/projects/external-contours/board-column.tsx b/plane-src/apps/web/ce/components/projects/external-contours/board-column.tsx index 6abce97..abf5331 100644 --- a/plane-src/apps/web/ce/components/projects/external-contours/board-column.tsx +++ b/plane-src/apps/web/ce/components/projects/external-contours/board-column.tsx @@ -6,20 +6,19 @@ import { observer } from "mobx-react"; import { useTranslation } from "@plane/i18n"; -import type { TExternalContourBoardDirection, TInboxIssueCurrentTab } from "@plane/types"; +import type { TExternalContourBoardDirection } from "@plane/types"; import { useProjectExternalContoursBoard } from "@/hooks/store/use-project-external-contours-board"; import { ExternalContoursBoardItem } from "./board-item"; import { ExternalContoursEmptyState } from "./empty-state"; type Props = { - currentTab: TInboxIssueCurrentTab; direction: TExternalContourBoardDirection; projectId: string; workspaceSlug: string; }; export const ExternalContoursBoardColumn = observer(function ExternalContoursBoardColumn(props: Props) { - const { currentTab, direction, projectId, workspaceSlug } = props; + const { direction, projectId, workspaceSlug } = props; const { t } = useTranslation(); const { getColumnRequestIds, getColumnTotalCount, getRequestById } = useProjectExternalContoursBoard(); const requestIds = getColumnRequestIds(direction); @@ -57,7 +56,6 @@ export const ExternalContoursBoardColumn = observer(function ExternalContoursBoa return ( 0) { - cachedRequests.forEach((request) => { - const option = getOption(request); - if (!option?.id || !selectedIds.includes(option.id) || optionMap.has(option.id)) return; - optionMap.set(option.id, option); - }); - } + cachedRequests.forEach(upsertOption); return sortFilterOptions(Array.from(optionMap.values())).map((option) => ({ data: option, @@ -526,19 +519,7 @@ const getAssigneeOptions = ( }; visibleRequests.forEach(upsertAssignees); - - if (selectedIds.length > 0) { - cachedRequests.forEach((request) => { - request.issue.assignee_details?.forEach((assignee) => { - if (!assignee?.id || !selectedIds.includes(assignee.id) || assigneeMap.has(assignee.id)) return; - assigneeMap.set(assignee.id, { - id: assignee.id, - label: assignee.display_name || "NODE.DC", - avatarUrl: assignee.avatar_url || "", - }); - }); - }); - } + cachedRequests.forEach(upsertAssignees); return sortFilterOptions(Array.from(assigneeMap.values())).map((option) => ({ data: option, value: option.id })); }; diff --git a/plane-src/apps/web/ce/components/projects/external-contours/board-item.tsx b/plane-src/apps/web/ce/components/projects/external-contours/board-item.tsx index 9292ce7..574a0b9 100644 --- a/plane-src/apps/web/ce/components/projects/external-contours/board-item.tsx +++ b/plane-src/apps/web/ce/components/projects/external-contours/board-item.tsx @@ -16,7 +16,6 @@ import type { IState, TExternalContourBoardDirection, TExternalContourRequest, - TInboxIssueCurrentTab, TIssue, } from "@plane/types"; import { Avatar } from "@plane/ui"; @@ -37,7 +36,6 @@ import { useUserPermissions } from "@/hooks/store/user"; import { IssueService } from "@/services/issue/issue.service"; type Props = { - currentTab: TInboxIssueCurrentTab; direction: TExternalContourBoardDirection; projectId: string; request: TExternalContourRequest; @@ -78,7 +76,7 @@ const resolveRequestStatus = (issue: TExternalContourRequest["issue"], fallbackS }; export const ExternalContoursBoardItem = observer(function ExternalContoursBoardItem(props: Props) { - const { currentTab, direction, projectId, request, workspaceSlug } = props; + const { direction, projectId, request, workspaceSlug } = props; const router = useAppRouter(); const searchParams = useSearchParams(); const { t } = useTranslation(); @@ -86,7 +84,6 @@ export const ExternalContoursBoardItem = observer(function ExternalContoursBoard const { getProjectRoleByWorkspaceSlugAndProjectId } = useUserPermissions(); const { getStateById, getProjectStateIds } = useProjectState(); const { - currentTab: boardCurrentTab, fetchBoard, upsertBoardItems, } = useProjectExternalContoursBoard(); @@ -116,7 +113,7 @@ export const ExternalContoursBoardItem = observer(function ExternalContoursBoard direction === "incoming" && !!targetProjectId && projectRole !== undefined && projectRole !== EUserPermissions.GUEST; const canEditSourceRequest = direction === "outgoing" && !!request.capabilities?.can_edit_request && !!targetProjectId; const canEditCard = canEditTargetIssue || canEditSourceRequest; - const requestLink = `/${workspaceSlug}/projects/${projectId}/external-contours?currentTab=${currentTab}&inboxIssueId=${request.id}`; + const requestLink = `/${workspaceSlug}/projects/${projectId}/external-contours?inboxIssueId=${request.id}`; const targetOptions = getTargetOptionsByProjectId(targetProjectId); const sourceStateMap = useMemo( () => buildSourceStateMap(targetOptions?.states, targetProjectId), @@ -145,7 +142,7 @@ export const ExternalContoursBoardItem = observer(function ExternalContoursBoard }; const syncBoardAfterMutation = async () => { - await fetchBoard(workspaceSlug, projectId, boardCurrentTab ?? currentTab); + await fetchBoard(workspaceSlug, projectId); }; const ensureSourceOptions = async () => { diff --git a/plane-src/apps/web/ce/components/projects/external-contours/board-root.tsx b/plane-src/apps/web/ce/components/projects/external-contours/board-root.tsx index 4e0f2aa..cd1f99c 100644 --- a/plane-src/apps/web/ce/components/projects/external-contours/board-root.tsx +++ b/plane-src/apps/web/ce/components/projects/external-contours/board-root.tsx @@ -6,11 +6,8 @@ import { observer } from "mobx-react"; import { useTranslation } from "@plane/i18n"; -import type { TInboxIssueCurrentTab } from "@plane/types"; -import { EInboxIssueCurrentTab } from "@plane/types"; import { cn } from "@plane/utils"; import { useProjectExternalContoursBoard } from "@/hooks/store/use-project-external-contours-board"; -import { useAppRouter } from "@/hooks/use-app-router"; import { ExternalContoursBoardFiltersRow } from "./board-filters-row"; import { ExternalContoursBoardColumn } from "./board-column"; @@ -19,51 +16,14 @@ type Props = { workspaceSlug: string; }; -const tabNavigationOptions: { key: TInboxIssueCurrentTab; i18nLabel: string }[] = [ - { key: EInboxIssueCurrentTab.OPEN, i18nLabel: "external_contours_page.tabs.open" }, - { key: EInboxIssueCurrentTab.CLOSED, i18nLabel: "external_contours_page.tabs.closed" }, -]; - export const ExternalContoursBoardRoot = observer(function ExternalContoursBoardRoot(props: Props) { const { projectId, workspaceSlug } = props; const { t } = useTranslation(); - const router = useAppRouter(); - const { currentTab, hasAnyItems, isFiltering, loader, tabCountMap, handleCurrentTab } = useProjectExternalContoursBoard(); + const { hasAnyItems, isFiltering, loader } = useProjectExternalContoursBoard(); return (
-
-
- {tabNavigationOptions.map((option) => { - const count = tabCountMap[option.key] ?? 0; - return ( - - ); - })} -
-
- -
+
@@ -84,13 +44,11 @@ export const ExternalContoursBoardRoot = observer(function ExternalContoursBoard )} > ("saved"); const [isDetailResolved, setIsDetailResolved] = useState(false); const { data: currentUser } = useUser(); - const { currentTab, fetchRequestById, getRequestById } = useProjectExternalContours(); + const { fetchRequestById, getRequestById } = useProjectExternalContours(); const contourRequest = getRequestById(inboxIssueId); const issue = contourRequest?.issue; const targetProjectId = issue?.project_id || projectId; @@ -46,10 +46,10 @@ export const ExternalContoursContentRoot = observer(function ExternalContoursCon useEffect(() => { if (isDetailResolved && !contourRequest && inboxIssueId) { - router.replace(`/${workspaceSlug}/projects/${projectId}/external-contours?currentTab=${currentTab}`); + router.replace(`/${workspaceSlug}/projects/${projectId}/external-contours`); } // eslint-disable-next-line react-hooks/exhaustive-deps - }, [contourRequest, currentTab, inboxIssueId, isDetailResolved, projectId, router, workspaceSlug]); + }, [contourRequest, inboxIssueId, isDetailResolved, projectId, router, workspaceSlug]); useSWR( workspaceSlug && projectId && inboxIssueId @@ -96,7 +96,7 @@ export const ExternalContoursContentRoot = observer(function ExternalContoursCon isSubmitting={isSubmitting} embedIssue={embedIssue} embedRemoveCurrentNotification={embedRemoveCurrentNotification} - onClose={() => router.replace(`/${workspaceSlug}/projects/${projectId}/external-contours?currentTab=${currentTab}`)} + onClose={() => router.replace(`/${workspaceSlug}/projects/${projectId}/external-contours`)} > void; peekMode: TExternalContourPeekMode; setPeekMode: (value: TExternalContourPeekMode) => void; - currentTab: TInboxIssueCurrentTab; embedIssue?: boolean; }; @@ -82,20 +80,18 @@ export const ExternalContoursIssueActionsHeader = observer(function ExternalCont removeRoutePeekId, peekMode, setPeekMode, - currentTab, embedIssue = false, } = props; const { t } = useTranslation(); const router = useAppRouter(); const [isDeclineModalOpen, setIsDeclineModalOpen] = useState(false); - const { decideRequest, filteredRequestIds, handleCurrentTab, loader } = useProjectExternalContours(); - const { currentTab: boardCurrentTab, columnIdsMap } = useProjectExternalContoursBoard(); + const { decideRequest, filteredRequestIds, loader } = useProjectExternalContours(); + const { columnIdsMap } = useProjectExternalContoursBoard(); const { getProjectById } = useProject(); const issue = contourRequest.issue; const currentRequestId = contourRequest.id; - const boardRequestIds = - boardCurrentTab === currentTab ? [...(columnIdsMap.outgoing ?? []), ...(columnIdsMap.incoming ?? [])] : []; + const boardRequestIds = [...(columnIdsMap.outgoing ?? []), ...(columnIdsMap.incoming ?? [])]; const relativeRequestIds = boardRequestIds.includes(currentRequestId) ? boardRequestIds : filteredRequestIds; const currentMode = PEEK_OPTIONS.find((mode) => mode.key === peekMode); const hasRelativeNavigation = !!currentRequestId && relativeRequestIds.includes(currentRequestId); @@ -115,9 +111,9 @@ export const ExternalContoursIssueActionsHeader = observer(function ExternalCont : (currentIssueIndex - 1 + relativeRequestIds.length) % relativeRequestIds.length; const nextIssueId = relativeRequestIds[nextIssueIndex]; if (!nextIssueId) return; - router.push(`/${workspaceSlug}/projects/${sourceProjectId}/external-contours?currentTab=${currentTab}&inboxIssueId=${nextIssueId}`); + router.push(`/${workspaceSlug}/projects/${sourceProjectId}/external-contours?inboxIssueId=${nextIssueId}`); }, - [currentRequestId, currentTab, hasRelativeNavigation, relativeRequestIds, router, sourceProjectId, workspaceSlug] + [currentRequestId, hasRelativeNavigation, relativeRequestIds, router, sourceProjectId, workspaceSlug] ); useEffect(() => { @@ -131,8 +127,7 @@ export const ExternalContoursIssueActionsHeader = observer(function ExternalCont }, [redirectToRelativeIssue]); const targetProjectIdentifier = issue.project_detail?.identifier || getProjectById(issue.project_id || "")?.identifier; - const requestTab = contourRequest.status === "closed" ? EInboxIssueCurrentTab.CLOSED : EInboxIssueCurrentTab.OPEN; - const requestLink = `/${workspaceSlug}/projects/${sourceProjectId}/external-contours?currentTab=${requestTab}&inboxIssueId=${contourRequest.id}`; + const requestLink = `/${workspaceSlug}/projects/${sourceProjectId}/external-contours?inboxIssueId=${contourRequest.id}`; const workItemLink = generateWorkItemLink({ workspaceSlug: workspaceSlug?.toString(), projectId: issue.project_id, @@ -183,10 +178,7 @@ export const ExternalContoursIssueActionsHeader = observer(function ExternalCont await decideRequest(workspaceSlug, sourceProjectId, contourRequest.id, action, comment); if (action === "decline") { setIsDeclineModalOpen(false); - await handleCurrentTab(workspaceSlug, sourceProjectId, EInboxIssueCurrentTab.OPEN); - router.push( - `/${workspaceSlug}/projects/${sourceProjectId}/external-contours?currentTab=${EInboxIssueCurrentTab.OPEN}&inboxIssueId=${contourRequest.id}` - ); + router.push(`/${workspaceSlug}/projects/${sourceProjectId}/external-contours?inboxIssueId=${contourRequest.id}`); } setToast({ type: TOAST_TYPE.SUCCESS, diff --git a/plane-src/apps/web/ce/components/projects/external-contours/peek-shell.tsx b/plane-src/apps/web/ce/components/projects/external-contours/peek-shell.tsx index 5303de5..6d363c1 100644 --- a/plane-src/apps/web/ce/components/projects/external-contours/peek-shell.tsx +++ b/plane-src/apps/web/ce/components/projects/external-contours/peek-shell.tsx @@ -9,7 +9,6 @@ import { useCallback, useEffect, useRef, useState, type MouseEvent as ReactMouse import { observer } from "mobx-react"; import { cn } from "@plane/utils"; import type { TExternalContourRequest, TNameDescriptionLoader } from "@plane/types"; -import { useProjectExternalContours } from "@/hooks/store/use-project-external-contours"; import useKeypress from "@/hooks/use-keypress"; import usePeekOverviewOutsideClickDetector from "@/hooks/use-peek-overview-outside-click"; import { ExternalContoursIssueActionsHeader, type TExternalContourPeekMode } from "./issue-header"; @@ -55,7 +54,6 @@ export const ExternalContoursPeekShell = observer(function ExternalContoursPeekS const issuePeekOverviewRef = useRef(null); const initialPeekWidthRef = useRef(0); const initialMouseXRef = useRef(0); - const { currentTab } = useProjectExternalContours(); const removeRoutePeekId = useCallback(() => { if (embedIssue) { @@ -190,7 +188,6 @@ export const ExternalContoursPeekShell = observer(function ExternalContoursPeekS removeRoutePeekId={removeRoutePeekId} peekMode={peekMode} setPeekMode={setPeekMode} - currentTab={currentTab} embedIssue={embedIssue} />
diff --git a/plane-src/apps/web/ce/components/projects/external-contours/root.tsx b/plane-src/apps/web/ce/components/projects/external-contours/root.tsx index fd91c9d..5833617 100644 --- a/plane-src/apps/web/ce/components/projects/external-contours/root.tsx +++ b/plane-src/apps/web/ce/components/projects/external-contours/root.tsx @@ -28,9 +28,7 @@ export const ExternalContoursRoot = observer(function ExternalContoursRoot(props const { error: boardError, currentProjectId: boardProjectId, - currentTab: boardCurrentTab, fetchBoard, - handleCurrentTab: handleBoardCurrentTab, loader: boardLoader, } = useProjectExternalContoursBoard(); @@ -61,20 +59,11 @@ export const ExternalContoursRoot = observer(function ExternalContoursRoot(props useEffect(() => { if (!workspaceSlug || !projectId) return; + if (boardProjectId === projectId && boardLoader === "init-loading") return; - const resolvedTab = navigationTab || EInboxIssueCurrentTab.OPEN; - const hasProjectChanged = boardProjectId && boardProjectId !== projectId; - - if (boardProjectId === projectId && boardCurrentTab === resolvedTab && boardLoader === "init-loading") return; - - if (hasProjectChanged || boardCurrentTab !== resolvedTab) { - void handleBoardCurrentTab(workspaceSlug, projectId, resolvedTab); - return; - } - - void fetchBoard(workspaceSlug.toString(), projectId.toString(), resolvedTab); + void fetchBoard(workspaceSlug.toString(), projectId.toString()); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [workspaceSlug, projectId, navigationTab]); + }, [workspaceSlug, projectId]); if (error && error?.status === "init-error" && !!inboxIssueId) { return ( diff --git a/plane-src/apps/web/core/store/external-contours/project-external-contours-board.store.ts b/plane-src/apps/web/core/store/external-contours/project-external-contours-board.store.ts index 83d017d..1814e18 100644 --- a/plane-src/apps/web/core/store/external-contours/project-external-contours-board.store.ts +++ b/plane-src/apps/web/core/store/external-contours/project-external-contours-board.store.ts @@ -59,7 +59,7 @@ export class ProjectExternalContoursBoardStore implements IProjectExternalContou currentProjectId = ""; currentTab: TInboxIssueCurrentTab = EInboxIssueCurrentTab.OPEN; error: { message: string; status: "init-error" } | undefined = undefined; - filters: Partial = { status: [EInboxIssueCurrentTab.OPEN] }; + filters: Partial = {}; items: Record = {}; loader: TLoader = "init-loading"; sorting: TExternalContourBoardSorting = DEFAULT_SORTING; @@ -145,10 +145,6 @@ export class ProjectExternalContoursBoardStore implements IProjectExternalContou handleCurrentTab = async (workspaceSlug: string, projectId: string, tab: TInboxIssueCurrentTab) => { this.currentTab = tab; - this.filters = sanitizeBoardFilters({ - ...this.filters, - status: [tab], - }); await this.fetchBoard(workspaceSlug, projectId, tab); }; @@ -160,30 +156,26 @@ export class ProjectExternalContoursBoardStore implements IProjectExternalContou this.filters = sanitizeBoardFilters({ ...this.filters, ...filters, - status: [this.currentTab], }); - await this.fetchBoard(workspaceSlug, projectId, this.currentTab); + await this.fetchBoard(workspaceSlug, projectId); }; updateSorting = async (workspaceSlug: string, projectId: string, sorting: TExternalContourBoardSorting) => { this.sorting = sorting; - await this.fetchBoard(workspaceSlug, projectId, this.currentTab); + await this.fetchBoard(workspaceSlug, projectId); }; clearFilters = async (workspaceSlug: string, projectId: string) => { - this.filters = { status: [this.currentTab] }; + this.filters = {}; this.sorting = DEFAULT_SORTING; - await this.fetchBoard(workspaceSlug, projectId, this.currentTab); + await this.fetchBoard(workspaceSlug, projectId); }; fetchBoard = async (workspaceSlug: string, projectId: string, tab = this.currentTab) => { const hasProjectChanged = !!this.currentProjectId && this.currentProjectId !== projectId; const isInitialLoad = this.hydratedProjectId !== projectId; - const nextFilters = sanitizeBoardFilters({ - ...(hasProjectChanged ? {} : this.filters), - status: [tab], - }); + const nextFilters = sanitizeBoardFilters(hasProjectChanged ? {} : this.filters); const nextSorting = hasProjectChanged ? DEFAULT_SORTING : this.sorting; const requestId = ++this.lastIssuedRequestId; @@ -213,16 +205,22 @@ export class ProjectExternalContoursBoardStore implements IProjectExternalContou this.filters = sanitizeBoardFilters(response.filters || nextFilters); this.sorting = response.sorting || nextSorting; this.hydratedProjectId = projectId; + let openCount = 0; + let closedCount = 0; response.columns.forEach((column) => { this.columnIdsMap[column.key] = column.results.map((request) => request.id); this.columnCountMap[column.key] = column.total_count; + column.results.forEach((request) => { + if (request.status === EInboxIssueCurrentTab.CLOSED) closedCount += 1; + else openCount += 1; + }); this.upsertBoardItems(column.results); }); this.tabCountMap = { - ...this.tabCountMap, - [tab]: response.columns.reduce((total, column) => total + column.total_count, 0), + [EInboxIssueCurrentTab.OPEN]: openCount, + [EInboxIssueCurrentTab.CLOSED]: closedCount, }; this.loader = undefined;