Skip to content

Commit 1f38b36

Browse files
committed
Add issues days filter
1 parent 624b9d5 commit 1f38b36

File tree

15 files changed

+90
-37
lines changed

15 files changed

+90
-37
lines changed

src/components/Errors/GlobalErrorsList/DaysFilter/DaysFilter.stories.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,6 @@ type Story = StoryObj<typeof meta>;
1919
// More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args
2020
export const Default: Story = {
2121
args: {
22-
onChanged: fn()
22+
onChange: fn()
2323
}
2424
};

src/components/Errors/GlobalErrorsList/DaysFilter/index.tsx

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
import type { ChangeEvent } from "react";
22
import { useCallback, useEffect, useMemo, useState } from "react";
33
import { usePrevious } from "../../../../hooks/usePrevious";
4-
import { DAYS_FILTER_DEFAULT_VALUE } from "../../../../store/errors/errorsSlice";
54
import { isUndefined } from "../../../../typeGuards/isUndefined";
65
import { sendUserActionTrackingEvent } from "../../../../utils/actions/sendUserActionTrackingEvent";
6+
import { addPrefix } from "../../../../utils/addPrefix";
77
import { formatUnit } from "../../../../utils/formatUnit";
88
import { CalendarIcon } from "../../../common/icons/12px/CalendarIcon";
99
import { MinusIcon } from "../../../common/icons/MinusIcon";
1010
import { PlusIcon } from "../../../common/icons/PlusIcon";
1111
import { NewPopover } from "../../../common/NewPopover";
1212
import { NewIconButton } from "../../../common/v3/NewIconButton";
1313
import { MenuList } from "../../../Navigation/common/MenuList";
14-
import { trackingEvents } from "../../tracking";
1514
import * as s from "./styles";
15+
import { trackingEvents } from "./tracking";
1616
import type { DaysFilterProps } from "./types";
1717

1818
const MAX_VALUE = 14;
@@ -22,11 +22,16 @@ const DEFAULT_LIST_OPTIONS = [7, 14];
2222

2323
const getOptionLabel = (days: number) => `${days} ${formatUnit(days, "Day")}`;
2424

25-
export const DaysFilter = ({ onChanged }: DaysFilterProps) => {
25+
export const DaysFilter = ({
26+
onChange,
27+
defaultValue,
28+
trackingPrefix = ""
29+
}: DaysFilterProps) => {
30+
const prefixedTrackingEvents = addPrefix(trackingPrefix, trackingEvents, " ");
2631
const [isDateMenuOpen, setIsDateMenuOpen] = useState(false);
2732
const [selectedDays, setSelectedDays] = useState<number>();
2833
const [currentValue, setCurrentValue] = useState<number | undefined>(
29-
DAYS_FILTER_DEFAULT_VALUE
34+
defaultValue
3035
);
3136
const previousSelectedDays = usePrevious(selectedDays);
3237
const handleSelectionChange = useCallback((days: number) => {
@@ -48,13 +53,13 @@ export const DaysFilter = ({ onChanged }: DaysFilterProps) => {
4853

4954
useEffect(() => {
5055
if (previousSelectedDays !== selectedDays) {
51-
onChanged(selectedDays ?? DAYS_FILTER_DEFAULT_VALUE);
56+
onChange(selectedDays ?? defaultValue);
5257
}
53-
}, [selectedDays, previousSelectedDays, onChanged]);
58+
}, [selectedDays, previousSelectedDays, onChange, defaultValue]);
5459

5560
const handleMenuButtonClick = () => {
5661
sendUserActionTrackingEvent(
57-
trackingEvents.GLOBAL_ERRORS_VIEW_DATES_FILTERS_CHANGE
62+
prefixedTrackingEvents.DAYS_FILTER_BUTTON_CLICKED
5863
);
5964
setIsDateMenuOpen(!isDateMenuOpen);
6065
setCurrentValue(selectedDays);
@@ -71,7 +76,7 @@ export const DaysFilter = ({ onChanged }: DaysFilterProps) => {
7176
: intValue;
7277

7378
sendUserActionTrackingEvent(
74-
trackingEvents.GLOBAL_ERRORS_DAYS_FILTER_DECREMENT_CLICKED
79+
prefixedTrackingEvents.DAYS_FILTER_INPUT_VALUE_CHANGE
7580
);
7681
setCurrentValue(days);
7782
};
@@ -81,7 +86,7 @@ export const DaysFilter = ({ onChanged }: DaysFilterProps) => {
8186
return;
8287
}
8388
sendUserActionTrackingEvent(
84-
trackingEvents.GLOBAL_ERRORS_DAYS_FILTER_DECREMENT_CLICKED
89+
prefixedTrackingEvents.DAYS_FILTER_DECREMENT_CLICKED
8590
);
8691
setCurrentValue(currentValue ? currentValue - 1 : 0);
8792
};
@@ -92,18 +97,16 @@ export const DaysFilter = ({ onChanged }: DaysFilterProps) => {
9297
}
9398

9499
sendUserActionTrackingEvent(
95-
trackingEvents.GLOBAL_ERRORS_DAYS_FILTER_INCREMENT_CLICKED
100+
prefixedTrackingEvents.DAYS_FILTER_INCREMENT_CLICKED
96101
);
97102
setCurrentValue(currentValue ? currentValue + 1 : 1);
98103
};
99104

100105
const handleApplyClick = () => {
101-
sendUserActionTrackingEvent(
102-
trackingEvents.GLOBAL_ERRORS_DAYS_FILTER_APPLY_BTN_CLICKED
103-
);
106+
sendUserActionTrackingEvent(trackingEvents.DAYS_FILTER_APPLY_BTN_CLICKED);
104107

105108
if (!currentValue) {
106-
setCurrentValue(DAYS_FILTER_DEFAULT_VALUE);
109+
setCurrentValue(defaultValue);
107110
} else {
108111
setSelectedDays(currentValue);
109112
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export const trackingEvents = {
2+
DAYS_FILTER_INPUT_VALUE_CHANGE: "days filter input value change",
3+
DAYS_FILTER_INCREMENT_CLICKED: "days filter increment change",
4+
DAYS_FILTER_DECREMENT_CLICKED: "days filter decrement change",
5+
DAYS_FILTER_APPLY_BTN_CLICKED: "days filter apply button clicked",
6+
DAYS_FILTER_BUTTON_CLICKED: "days filter button clicked"
7+
};

src/components/Errors/GlobalErrorsList/DaysFilter/types.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ export interface DaysButtonProps extends ButtonProps {
2929
}
3030

3131
export interface DaysFilterProps {
32-
onChanged: (days?: number) => void;
32+
onChange: (days?: number) => void;
33+
defaultValue: number;
34+
trackingPrefix?: string;
3335
}
3436

3537
export interface CounterInputProps {

src/components/Errors/GlobalErrorsList/index.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { useMount } from "../../../hooks/useMount";
77
import { usePrevious } from "../../../hooks/usePrevious";
88
import { useConfigSelector } from "../../../store/config/useConfigSelector";
99
import {
10+
DAYS_FILTER_DEFAULT_VALUE,
1011
GlobalErrorsSortingCriterion,
1112
PAGE_SIZE,
1213
ViewMode
@@ -388,7 +389,11 @@ export const GlobalErrorsList = () => {
388389
{areGlobalErrorsFiltersEnabled && <GlobalErrorsFilters />}
389390
<SearchInput value={search} onChange={handleSearchInputChange} />
390391
{isGlobalErrorsLastDaysFilterEnabled && (
391-
<DaysFilter onChanged={handleDayFilterChange} />
392+
<DaysFilter
393+
onChange={handleDayFilterChange}
394+
defaultValue={DAYS_FILTER_DEFAULT_VALUE}
395+
trackingPrefix={"global errors"}
396+
/>
392397
)}
393398
<NewPopover
394399
isOpen={isSortingMenuOpen}

src/components/Errors/tracking.ts

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,7 @@ export const trackingEvents = addPrefix(
1515
WORKSPACE_ONLY_TOGGLE_SWITCHED: "workspace only toggle switched",
1616
GLOBAL_ERRORS_VIEW_SEARCH_CHANGED: "global errors view search changed",
1717
GLOBAL_ERRORS_VIEW_SORTING_CHANGE: "global errors view sorting change",
18-
GLOBAL_ERRORS_VIEW_DATES_FILTERS_CHANGE:
19-
"global errors view date filters change",
2018
GLOBAL_ERRORS_VIEW_PAGE_CHANGE: "global errors view page change",
21-
GLOBAL_ERRORS_DAYS_FILTER_INPUT_VALUE_CHANGE:
22-
"global errors days filter input value change",
23-
GLOBAL_ERRORS_DAYS_FILTER_INCREMENT_CLICKED:
24-
"global errors days filter increment change",
25-
GLOBAL_ERRORS_DAYS_FILTER_DECREMENT_CLICKED:
26-
"global errors days filter decrement change",
27-
GLOBAL_ERRORS_DAYS_FILTER_APPLY_BTN_CLICKED:
28-
"global errors days filter apply button clicked",
2919
GLOBAL_ERRORS_VIEW_RESET_FILTERS_BUTTON_CLICKED:
3020
"global errors view reset filters button clicked",
3121
GLOBAL_ERRORS_VIEW_FILTERS_BUTTON_CLICKED:

src/components/Insights/InsightsCatalog/FilterPanel/IssuesFilter/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,5 @@ export interface IssuesFilterQuery {
1818
services?: string[];
1919
criticalityFilter?: IssueCriticality[];
2020
criticalityFilterInGlobalScope?: IssueCriticality[];
21+
lastDays?: number;
2122
}

src/components/Insights/InsightsCatalog/index.tsx

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
type IssueCriticality
1313
} from "../../../redux/services/types";
1414
import { useConfigSelector } from "../../../store/config/useConfigSelector";
15+
import { DAYS_FILTER_DEFAULT_VALUE } from "../../../store/insights/insightsSlice";
1516
import { useInsightsSelector } from "../../../store/insights/useInsightsSelector";
1617
import { useStore } from "../../../store/useStore";
1718
import { isNumber } from "../../../typeGuards/isNumber";
@@ -33,6 +34,7 @@ import type {
3334
import { NewButton } from "../../common/v3/NewButton";
3435
import { NewIconButton } from "../../common/v3/NewIconButton";
3536
import { Tooltip } from "../../common/v3/Tooltip";
37+
import { DaysFilter } from "../../Errors/GlobalErrorsList/DaysFilter";
3638
import { PAGE_SIZE } from "../hooks/useInsightsData";
3739
import { useInsightsStats } from "../hooks/useInsightsStats";
3840
import { trackingEvents } from "../tracking";
@@ -98,7 +100,8 @@ export const InsightsCatalog = ({
98100
setInsightsViewMode: setMode,
99101
setInsightsPage: setPage,
100102
setInsightsSorting: setSorting,
101-
setInsightsSearch: setSearch
103+
setInsightsSearch: setSearch,
104+
setInsightsLastDays: setLastDays
102105
} = useStore.getState();
103106

104107
const {
@@ -151,6 +154,10 @@ export const InsightsCatalog = ({
151154
backendInfo,
152155
FeatureFlag.IsIssuesCriticalityLevelsFilterEnabled
153156
);
157+
const isIssuesLastDaysFilterEnabled = getFeatureFlagValue(
158+
backendInfo,
159+
FeatureFlag.IsIssuesLastDaysFilterEnabled
160+
);
154161

155162
const appliedFilterCount =
156163
(isIssuesView
@@ -263,6 +270,10 @@ export const InsightsCatalog = ({
263270
setSorting(value);
264271
};
265272

273+
const handleDaysFilterChange = (days: number | undefined) => {
274+
setLastDays(days);
275+
};
276+
266277
useEffect(() => {
267278
setSearch("");
268279
}, [scopeSpanCodeObjectId, setSearch]);
@@ -321,6 +332,13 @@ export const InsightsCatalog = ({
321332
onChange={handleSearchInputChange}
322333
value={searchInputValue}
323334
/>
335+
{isIssuesView && isIssuesLastDaysFilterEnabled && (
336+
<DaysFilter
337+
onChange={handleDaysFilterChange}
338+
defaultValue={DAYS_FILTER_DEFAULT_VALUE}
339+
trackingPrefix={"issues"}
340+
/>
341+
)}
324342
{sortingOptions.length > 0 && (
325343
<SortingSelector
326344
onChange={handleSortingChange}

src/components/Insights/hooks/useInsightsData.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ export const useInsightsData = ({
4040
filteredCriticalityLevels: filteredCriticalityLevelsInSpanScope,
4141
filteredCriticalityLevelsInGlobalScope,
4242
isDataLoading: isLoading,
43-
insightViewType
43+
insightViewType,
44+
lastDays
4445
} = useInsightsSelector();
4546
const { setInsightsData: setData, setIsInsightsDataLoading: setIsLoading } =
4647
useStore.getState();
@@ -82,6 +83,11 @@ export const useInsightsData = ({
8283
FeatureFlag.IsIssuesCriticalityLevelsFilterEnabled
8384
);
8485

86+
const isIssuesLastDaysFilterEnabled = getFeatureFlagValue(
87+
backendInfo,
88+
FeatureFlag.IsIssuesLastDaysFilterEnabled
89+
);
90+
8591
const areSpanEnvironmentsEnabled = getFeatureFlagValue(
8692
backendInfo,
8793
FeatureFlag.AreSpanEnvironmentsEnabled
@@ -155,7 +161,8 @@ export const useInsightsData = ({
155161
...(isCriticalityLevelsFilterEnabled
156162
? { criticalityFilter: filteredCriticalityLevels }
157163
: {}),
158-
environment: environmentId
164+
environment: environmentId,
165+
lastDays: isIssuesLastDaysFilterEnabled ? lastDays : undefined
159166
},
160167
{
161168
skip: !isAppReadyToGetData || !isIssuesQueryActive,

src/components/Insights/index.tsx

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ export const Insights = ({ insightViewType }: InsightsProps) => {
5959
setInsightsFilteredCriticalityLevelsInGlobalScope:
6060
setFilteredCriticalityLevelsInGlobalScope,
6161
setInsightsFilters: setFilters,
62+
setInsightsLastDays: setLastDays,
6263
resetInsights: reset
6364
} = useStore.getState();
6465
const {
@@ -67,7 +68,8 @@ export const Insights = ({ insightViewType }: InsightsProps) => {
6768
filteredInsightTypesInGlobalScope,
6869
filteredCriticalityLevels: filteredCriticalityLevelsInSpanScope,
6970
filteredCriticalityLevelsInGlobalScope,
70-
filters
71+
filters,
72+
lastDays
7173
} = useInsightsSelector();
7274
const scopeSpanCodeObjectId = scope?.span?.spanCodeObjectId;
7375
const filteredInsightTypes = scopeSpanCodeObjectId
@@ -81,6 +83,7 @@ export const Insights = ({ insightViewType }: InsightsProps) => {
8183
filteredCriticalityLevels
8284
);
8385
const previousFilters = usePrevious(filters);
86+
const previousLastDays = usePrevious(lastDays);
8487
const previousBackendInfo = usePrevious(backendInfo);
8588

8689
useEffect(() => {
@@ -123,6 +126,7 @@ export const Insights = ({ insightViewType }: InsightsProps) => {
123126
insightsInitialState.filteredCriticalityLevelsInGlobalScope
124127
);
125128
setFilters(persistedFilters?.filters ?? []);
129+
setLastDays(persistedFilters?.lastDays ?? insightsInitialState.lastDays);
126130
setAreFiltersRehydrated(true);
127131
}
128132
}, [
@@ -131,15 +135,17 @@ export const Insights = ({ insightViewType }: InsightsProps) => {
131135
setFilters,
132136
setFilteredInsightTypes,
133137
setFilteredInsightTypesInGlobalScope,
134-
setFilteredCriticalityLevelsInGlobalScope
138+
setFilteredCriticalityLevelsInGlobalScope,
139+
setLastDays
135140
]);
136141

137142
// Persist filters on its change
138143
useEffect(() => {
139144
if (
140145
(previousFilteredInsightTypes !== filteredInsightTypes ||
141146
previousFilters !== filters ||
142-
previousFilteredCriticalityLevels !== filteredCriticalityLevels) &&
147+
previousFilteredCriticalityLevels !== filteredCriticalityLevels ||
148+
previousLastDays !== lastDays) &&
143149
areFiltersRehydrated
144150
) {
145151
setPersistedFilters({
@@ -169,7 +175,9 @@ export const Insights = ({ insightViewType }: InsightsProps) => {
169175
setPersistedFilters,
170176
areFiltersRehydrated,
171177
persistedFilters,
172-
scopeSpanCodeObjectId
178+
scopeSpanCodeObjectId,
179+
lastDays,
180+
previousLastDays
173181
]);
174182

175183
// Reset insight type, criticality and unread filters (for span and global scopes) on backend instance change

0 commit comments

Comments
 (0)