diff --git a/web/ce/store/issue/issue-details/activity.store.ts b/web/ce/store/issue/issue-details/activity.store.ts index 2ec70f3cc18..cf180eebf77 100644 --- a/web/ce/store/issue/issue-details/activity.store.ts +++ b/web/ce/store/issue/issue-details/activity.store.ts @@ -16,6 +16,7 @@ import { TIssueServiceType, } from "@plane/types"; // plane web constants +import { TSORT_ORDER } from "@/constants/common"; import { EActivityFilterType } from "@/plane-web/constants/issues"; // services import { IssueActivityService } from "@/services/issue"; @@ -36,20 +37,17 @@ export interface IIssueActivityStoreActions { export interface IIssueActivityStore extends IIssueActivityStoreActions { // observables - sortOrder: "asc" | "desc"; loader: TActivityLoader; activities: TIssueActivityIdMap; activityMap: TIssueActivityMap; // helper methods getActivitiesByIssueId: (issueId: string) => string[] | undefined; getActivityById: (activityId: string) => TIssueActivity | undefined; - getActivityCommentByIssueId: (issueId: string) => TIssueActivityComment[] | undefined; - toggleSortOrder: () => void; + getActivityCommentByIssueId: (issueId: string, sortOrder: TSORT_ORDER) => TIssueActivityComment[] | undefined; } export class IssueActivityStore implements IIssueActivityStore { // observables - sortOrder: "asc" | "desc" = "asc"; loader: TActivityLoader = "fetch"; activities: TIssueActivityIdMap = {}; activityMap: TIssueActivityMap = {}; @@ -64,13 +62,11 @@ export class IssueActivityStore implements IIssueActivityStore { ) { makeObservable(this, { // observables - sortOrder: observable.ref, loader: observable.ref, activities: observable, activityMap: observable, // actions fetchActivities: action, - toggleSortOrder: action, }); this.serviceType = serviceType; // services @@ -88,7 +84,7 @@ export class IssueActivityStore implements IIssueActivityStore { return this.activityMap[activityId] ?? undefined; }; - getActivityCommentByIssueId = computedFn((issueId: string) => { + getActivityCommentByIssueId = computedFn((issueId: string, sortOrder: TSORT_ORDER) => { if (!issueId) return undefined; let activityComments: TIssueActivityComment[] = []; @@ -119,15 +115,11 @@ 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), sortOrder); return activityComments; }); - toggleSortOrder = () => { - this.sortOrder = this.sortOrder === "asc" ? "desc" : "asc"; - }; - // actions public async fetchActivities( workspaceSlug: string, diff --git a/web/core/components/issues/issue-detail/issue-activity/activity-comment-root.tsx b/web/core/components/issues/issue-detail/issue-activity/activity-comment-root.tsx index 205942d8fa1..4ad46e92b72 100644 --- a/web/core/components/issues/issue-detail/issue-activity/activity-comment-root.tsx +++ b/web/core/components/issues/issue-detail/issue-activity/activity-comment-root.tsx @@ -1,5 +1,7 @@ import { FC } from "react"; import { observer } from "mobx-react"; +// constants +import { TSORT_ORDER } from "@/constants/common"; // hooks import { useIssueDetail } from "@/hooks/store"; // plane web components @@ -21,18 +23,27 @@ type TIssueActivityCommentRoot = { activityOperations: TActivityOperations; showAccessSpecifier?: boolean; disabled?: boolean; + sortOrder: TSORT_ORDER; }; export const IssueActivityCommentRoot: FC = observer((props) => { - const { workspaceSlug, issueId, selectedFilters, activityOperations, showAccessSpecifier, projectId, disabled } = - props; + const { + workspaceSlug, + issueId, + selectedFilters, + activityOperations, + showAccessSpecifier, + projectId, + disabled, + sortOrder, + } = props; // hooks const { activity: { getActivityCommentByIssueId }, comment: {}, } = useIssueDetail(); - const activityComments = getActivityCommentByIssueId(issueId); + const activityComments = getActivityCommentByIssueId(issueId, sortOrder); if (!activityComments || (activityComments && activityComments.length <= 0)) return <>; diff --git a/web/core/components/issues/issue-detail/issue-activity/activity-filter.tsx b/web/core/components/issues/issue-detail/issue-activity/activity-filter.tsx index 319058a017f..3733e7f72b2 100644 --- a/web/core/components/issues/issue-detail/issue-activity/activity-filter.tsx +++ b/web/core/components/issues/issue-detail/issue-activity/activity-filter.tsx @@ -26,6 +26,9 @@ export const ActivityFilter: FC = observer((props) => { className="relative" > Filters + {selectedFilters.length < filterOptions.length && ( + + )} } panelClassName="p-2 rounded-md border border-custom-border-200 bg-custom-background-100" diff --git a/web/core/components/issues/issue-detail/issue-activity/root.tsx b/web/core/components/issues/issue-detail/issue-activity/root.tsx index 38f6b01c600..102fc3c161d 100644 --- a/web/core/components/issues/issue-detail/issue-activity/root.tsx +++ b/web/core/components/issues/issue-detail/issue-activity/root.tsx @@ -1,7 +1,8 @@ "use client"; -import { FC, useMemo, useState } from "react"; +import { FC, useMemo } from "react"; import { observer } from "mobx-react"; +import { useLocalStorage } from "@plane/hooks"; // types import { TFileSignedURLResponse, TIssueComment } from "@plane/types"; import { EFileAssetType } from "@plane/types/src/enums"; @@ -10,6 +11,8 @@ import { TOAST_TYPE, setToast } from "@plane/ui"; // components import { IssueCommentCreate } from "@/components/issues"; import { ActivitySortRoot, IssueActivityCommentRoot } from "@/components/issues/issue-detail"; +// constants +import { TSORT_ORDER } from "@/constants/common"; // hooks import { useIssueDetail, useProject, useUser, useUserPermissions } from "@/hooks/store"; // plane web components @@ -38,12 +41,14 @@ export type TActivityOperations = { export const IssueActivity: FC = observer((props) => { const { workspaceSlug, projectId, issueId, disabled = false, isIntakeIssue = false } = props; - // state - const [selectedFilters, setSelectedFilters] = useState(defaultActivityFilters); // hooks + const { setValue: setFilterValue, storedValue: selectedFilters } = useLocalStorage( + "issue_activity_filters", + defaultActivityFilters + ); + const { setValue: setSortOrder, storedValue: sortOrder } = useLocalStorage("activity_sort_order", TSORT_ORDER.ASC); const { issue: { getIssueById }, - activity: { sortOrder, toggleSortOrder }, createComment, updateComment, removeComment, @@ -60,14 +65,20 @@ export const IssueActivity: FC = observer((props) => { const isWorklogButtonEnabled = !isIntakeIssue && !isGuest && (isAdmin || isAssigned); // toggle filter const toggleFilter = (filter: TActivityFilters) => { - setSelectedFilters((prevFilters) => { - if (prevFilters.includes(filter)) { - if (prevFilters.length === 1) return prevFilters; // Ensure at least one filter is applied - return prevFilters.filter((f) => f !== filter); - } else { - return [...prevFilters, filter]; - } - }); + if (!selectedFilters) return; + let _filters = []; + if (selectedFilters.includes(filter)) { + if (selectedFilters.length === 1) return selectedFilters; // Ensure at least one filter is applied + _filters = selectedFilters.filter((f) => f !== filter); + } else { + _filters = [...selectedFilters, filter]; + } + + setFilterValue(_filters); + }; + + const toggleSortOrder = () => { + setSortOrder(sortOrder === TSORT_ORDER.ASC ? TSORT_ORDER.DESC : TSORT_ORDER.ASC); }; const activityOperations: TActivityOperations = useMemo( @@ -163,9 +174,9 @@ export const IssueActivity: FC = observer((props) => { disabled={disabled} /> )} - + = observer((props) => { projectId={projectId} workspaceSlug={workspaceSlug} issueId={issueId} - selectedFilters={selectedFilters} + selectedFilters={selectedFilters || defaultActivityFilters} activityOperations={activityOperations} showAccessSpecifier={!!project.anchor} disabled={disabled} + sortOrder={sortOrder || TSORT_ORDER.ASC} /> {!disabled && ( void; className?: string; iconClassName?: string; diff --git a/web/core/constants/common.ts b/web/core/constants/common.ts index 99dce1b2112..8358d0e6430 100644 --- a/web/core/constants/common.ts +++ b/web/core/constants/common.ts @@ -28,3 +28,8 @@ export const PROGRESS_STATE_GROUPS_DETAILS = [ color: "#A3A3A3", }, ]; + +export enum TSORT_ORDER { + ASC = "asc", + DESC = "desc", +}