Skip to content

Commit 45b1a9e

Browse files
chore: added issue activity filters to local storage
chore: added sort order to local storage
1 parent e4f9d02 commit 45b1a9e

File tree

6 files changed

+55
-31
lines changed

6 files changed

+55
-31
lines changed

web/ce/store/issue/issue-details/activity.store.ts

+4-12
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
TIssueServiceType,
1717
} from "@plane/types";
1818
// plane web constants
19+
import { TSORT_ORDER } from "@/constants/common";
1920
import { EActivityFilterType } from "@/plane-web/constants/issues";
2021
// services
2122
import { IssueActivityService } from "@/services/issue";
@@ -36,20 +37,17 @@ export interface IIssueActivityStoreActions {
3637

3738
export interface IIssueActivityStore extends IIssueActivityStoreActions {
3839
// observables
39-
sortOrder: "asc" | "desc";
4040
loader: TActivityLoader;
4141
activities: TIssueActivityIdMap;
4242
activityMap: TIssueActivityMap;
4343
// helper methods
4444
getActivitiesByIssueId: (issueId: string) => string[] | undefined;
4545
getActivityById: (activityId: string) => TIssueActivity | undefined;
46-
getActivityCommentByIssueId: (issueId: string) => TIssueActivityComment[] | undefined;
47-
toggleSortOrder: () => void;
46+
getActivityCommentByIssueId: (issueId: string, sortOrder: TSORT_ORDER) => TIssueActivityComment[] | undefined;
4847
}
4948

5049
export class IssueActivityStore implements IIssueActivityStore {
5150
// observables
52-
sortOrder: "asc" | "desc" = "asc";
5351
loader: TActivityLoader = "fetch";
5452
activities: TIssueActivityIdMap = {};
5553
activityMap: TIssueActivityMap = {};
@@ -64,13 +62,11 @@ export class IssueActivityStore implements IIssueActivityStore {
6462
) {
6563
makeObservable(this, {
6664
// observables
67-
sortOrder: observable.ref,
6865
loader: observable.ref,
6966
activities: observable,
7067
activityMap: observable,
7168
// actions
7269
fetchActivities: action,
73-
toggleSortOrder: action,
7470
});
7571
this.serviceType = serviceType;
7672
// services
@@ -88,7 +84,7 @@ export class IssueActivityStore implements IIssueActivityStore {
8884
return this.activityMap[activityId] ?? undefined;
8985
};
9086

91-
getActivityCommentByIssueId = computedFn((issueId: string) => {
87+
getActivityCommentByIssueId = computedFn((issueId: string, sortOrder: TSORT_ORDER) => {
9288
if (!issueId) return undefined;
9389

9490
let activityComments: TIssueActivityComment[] = [];
@@ -119,15 +115,11 @@ export class IssueActivityStore implements IIssueActivityStore {
119115
});
120116
});
121117

122-
activityComments = orderBy(activityComments, (e) => new Date(e.created_at || 0), this.sortOrder);
118+
activityComments = orderBy(activityComments, (e) => new Date(e.created_at || 0), sortOrder);
123119

124120
return activityComments;
125121
});
126122

127-
toggleSortOrder = () => {
128-
this.sortOrder = this.sortOrder === "asc" ? "desc" : "asc";
129-
};
130-
131123
// actions
132124
public async fetchActivities(
133125
workspaceSlug: string,

web/core/components/issues/issue-detail/issue-activity/activity-comment-root.tsx

+14-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { FC } from "react";
22
import { observer } from "mobx-react";
3+
// constants
4+
import { TSORT_ORDER } from "@/constants/common";
35
// hooks
46
import { useIssueDetail } from "@/hooks/store";
57
// plane web components
@@ -21,18 +23,27 @@ type TIssueActivityCommentRoot = {
2123
activityOperations: TActivityOperations;
2224
showAccessSpecifier?: boolean;
2325
disabled?: boolean;
26+
sortOrder: TSORT_ORDER;
2427
};
2528

2629
export const IssueActivityCommentRoot: FC<TIssueActivityCommentRoot> = observer((props) => {
27-
const { workspaceSlug, issueId, selectedFilters, activityOperations, showAccessSpecifier, projectId, disabled } =
28-
props;
30+
const {
31+
workspaceSlug,
32+
issueId,
33+
selectedFilters,
34+
activityOperations,
35+
showAccessSpecifier,
36+
projectId,
37+
disabled,
38+
sortOrder,
39+
} = props;
2940
// hooks
3041
const {
3142
activity: { getActivityCommentByIssueId },
3243
comment: {},
3344
} = useIssueDetail();
3445

35-
const activityComments = getActivityCommentByIssueId(issueId);
46+
const activityComments = getActivityCommentByIssueId(issueId, sortOrder);
3647

3748
if (!activityComments || (activityComments && activityComments.length <= 0)) return <></>;
3849

web/core/components/issues/issue-detail/issue-activity/activity-filter.tsx

+3
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ export const ActivityFilter: FC<TActivityFilter> = observer((props) => {
2626
className="relative"
2727
>
2828
<span className="text-custom-text-200">Filters</span>
29+
{selectedFilters.length < filterOptions.length && (
30+
<span className="absolute h-2 w-2 -right-0.5 -top-0.5 bg-custom-primary-100 rounded-full" />
31+
)}
2932
</Button>
3033
}
3134
panelClassName="p-2 rounded-md border border-custom-border-200 bg-custom-background-100"

web/core/components/issues/issue-detail/issue-activity/root.tsx

+27-15
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
"use client";
22

3-
import { FC, useMemo, useState } from "react";
3+
import { FC, useMemo } from "react";
44
import { observer } from "mobx-react";
5+
import { useLocalStorage } from "@plane/hooks";
56
// types
67
import { TFileSignedURLResponse, TIssueComment } from "@plane/types";
78
import { EFileAssetType } from "@plane/types/src/enums";
@@ -10,6 +11,8 @@ import { TOAST_TYPE, setToast } from "@plane/ui";
1011
// components
1112
import { IssueCommentCreate } from "@/components/issues";
1213
import { ActivitySortRoot, IssueActivityCommentRoot } from "@/components/issues/issue-detail";
14+
// constants
15+
import { TSORT_ORDER } from "@/constants/common";
1316
// hooks
1417
import { useIssueDetail, useProject, useUser, useUserPermissions } from "@/hooks/store";
1518
// plane web components
@@ -38,12 +41,14 @@ export type TActivityOperations = {
3841

3942
export const IssueActivity: FC<TIssueActivity> = observer((props) => {
4043
const { workspaceSlug, projectId, issueId, disabled = false, isIntakeIssue = false } = props;
41-
// state
42-
const [selectedFilters, setSelectedFilters] = useState<TActivityFilters[]>(defaultActivityFilters);
4344
// hooks
45+
const { setValue: setFilterValue, storedValue: selectedFilters } = useLocalStorage(
46+
"issue_activity_filters",
47+
defaultActivityFilters
48+
);
49+
const { setValue: setSortOrder, storedValue: sortOrder } = useLocalStorage("activity_sort_order", TSORT_ORDER.ASC);
4450
const {
4551
issue: { getIssueById },
46-
activity: { sortOrder, toggleSortOrder },
4752
createComment,
4853
updateComment,
4954
removeComment,
@@ -60,14 +65,20 @@ export const IssueActivity: FC<TIssueActivity> = observer((props) => {
6065
const isWorklogButtonEnabled = !isIntakeIssue && !isGuest && (isAdmin || isAssigned);
6166
// toggle filter
6267
const toggleFilter = (filter: TActivityFilters) => {
63-
setSelectedFilters((prevFilters) => {
64-
if (prevFilters.includes(filter)) {
65-
if (prevFilters.length === 1) return prevFilters; // Ensure at least one filter is applied
66-
return prevFilters.filter((f) => f !== filter);
67-
} else {
68-
return [...prevFilters, filter];
69-
}
70-
});
68+
if (!selectedFilters) return;
69+
let _filters = [];
70+
if (selectedFilters.includes(filter)) {
71+
if (selectedFilters.length === 1) return selectedFilters; // Ensure at least one filter is applied
72+
_filters = selectedFilters.filter((f) => f !== filter);
73+
} else {
74+
_filters = [...selectedFilters, filter];
75+
}
76+
77+
setFilterValue(_filters);
78+
};
79+
80+
const toggleSortOrder = () => {
81+
setSortOrder(sortOrder === TSORT_ORDER.ASC ? TSORT_ORDER.DESC : TSORT_ORDER.ASC);
7182
};
7283

7384
const activityOperations: TActivityOperations = useMemo(
@@ -163,9 +174,9 @@ export const IssueActivity: FC<TIssueActivity> = observer((props) => {
163174
disabled={disabled}
164175
/>
165176
)}
166-
<ActivitySortRoot sortOrder={sortOrder} toggleSort={toggleSortOrder} />
177+
<ActivitySortRoot sortOrder={sortOrder || TSORT_ORDER.ASC} toggleSort={toggleSortOrder} />
167178
<ActivityFilterRoot
168-
selectedFilters={selectedFilters}
179+
selectedFilters={selectedFilters || defaultActivityFilters}
169180
toggleFilter={toggleFilter}
170181
isIntakeIssue={isIntakeIssue}
171182
projectId={projectId}
@@ -181,10 +192,11 @@ export const IssueActivity: FC<TIssueActivity> = observer((props) => {
181192
projectId={projectId}
182193
workspaceSlug={workspaceSlug}
183194
issueId={issueId}
184-
selectedFilters={selectedFilters}
195+
selectedFilters={selectedFilters || defaultActivityFilters}
185196
activityOperations={activityOperations}
186197
showAccessSpecifier={!!project.anchor}
187198
disabled={disabled}
199+
sortOrder={sortOrder || TSORT_ORDER.ASC}
188200
/>
189201
{!disabled && (
190202
<IssueCommentCreate

web/core/components/issues/issue-detail/issue-activity/sort-root.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33
import { FC, memo } from "react";
44
import { ArrowUpWideNarrow, ArrowDownWideNarrow } from "lucide-react";
55
import { getButtonStyling } from "@plane/ui";
6+
import { TSORT_ORDER } from "@/constants/common";
67
// helpers
78
import { cn } from "@/helpers/common.helper";
89

910
export type TActivitySortRoot = {
10-
sortOrder: "asc" | "desc";
11+
sortOrder: TSORT_ORDER;
1112
toggleSort: () => void;
1213
className?: string;
1314
iconClassName?: string;

web/core/constants/common.ts

+5
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,8 @@ export const PROGRESS_STATE_GROUPS_DETAILS = [
2828
color: "#A3A3A3",
2929
},
3030
];
31+
32+
export enum TSORT_ORDER {
33+
ASC = "asc",
34+
DESC = "desc",
35+
}

0 commit comments

Comments
 (0)