Skip to content

Commit 53f9e7d

Browse files
authored
chore: trace funnels bugfixes/improvements (#8114)
* fix: refetch funnel steps overview on clicking refresh * chore: temporarily hide latency pointer from funnel steps * chore: remove the existing filters of a step on clicking replace button * fix(useLocalStorage): stabilize initialValue handling to prevent unnecessary re-renders * chore: remove p99_latency references from funnel metrics * fix(useFunnelMetrics): ensure latency type defaults to P99 when undefined
1 parent ad46e22 commit 53f9e7d

File tree

17 files changed

+492
-233
lines changed

17 files changed

+492
-233
lines changed

frontend/src/api/traceFunnels/index.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,8 +196,6 @@ export interface FunnelOverviewResponse {
196196
avg_rate: number;
197197
conversion_rate: number | null;
198198
errors: number;
199-
// TODO(shaheer): remove p99_latency once we have support for latency
200-
p99_latency: number;
201199
latency: number;
202200
};
203201
}>;

frontend/src/container/TraceWaterfall/AddSpanToFunnelModal/AddSpanToFunnelModal.styles.scss

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,51 @@
1616

1717
&-body {
1818
padding: 14px 16px !important;
19+
padding-bottom: 0 !important;
20+
border-bottom-left-radius: 0;
21+
border-bottom-right-radius: 0;
1922
}
20-
}
21-
&--details {
22-
.ant-modal-content {
23-
height: 710px;
23+
24+
&-footer {
25+
margin-top: 0;
26+
background: var(--bg-ink-400);
27+
border-top: 1px solid var(--bg-slate-500);
28+
padding: 16px !important;
29+
.add-span-to-funnel-modal {
30+
&__save-button {
31+
display: flex;
32+
align-items: center;
33+
justify-content: center;
34+
gap: 4px;
35+
color: var(--bg-vanilla-100);
36+
font-size: 12px;
37+
font-weight: 500;
38+
line-height: 24px;
39+
width: 135px;
40+
41+
.ant-btn-icon {
42+
display: flex;
43+
}
44+
&:disabled {
45+
color: var(--bg-vanilla-400);
46+
.ant-btn-icon {
47+
svg {
48+
stroke: var(--bg-vanilla-400);
49+
}
50+
}
51+
}
52+
}
53+
&__discard-button {
54+
background: var(--bg-slate-500);
55+
}
56+
}
57+
.ant-btn {
58+
border-radius: 2px;
59+
padding: 4px 8px;
60+
margin: 0 !important;
61+
border: none;
62+
box-shadow: none;
63+
}
2464
}
2565
}
2666
}

frontend/src/container/TraceWaterfall/AddSpanToFunnelModal/AddSpanToFunnelModal.tsx

Lines changed: 102 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,18 @@ import {
99
useFunnelDetails,
1010
useFunnelsList,
1111
} from 'hooks/TracesFunnels/useFunnels';
12-
import { ArrowLeft, Plus, Search } from 'lucide-react';
12+
import { isEqual } from 'lodash-es';
13+
import { ArrowLeft, Check, Plus, Search } from 'lucide-react';
1314
import FunnelConfiguration from 'pages/TracesFunnelDetails/components/FunnelConfiguration/FunnelConfiguration';
1415
import { TracesFunnelsContentRenderer } from 'pages/TracesFunnels';
1516
import CreateFunnel from 'pages/TracesFunnels/components/CreateFunnel/CreateFunnel';
1617
import { FunnelListItem } from 'pages/TracesFunnels/components/FunnelsList/FunnelsList';
17-
import { FunnelProvider } from 'pages/TracesFunnels/FunnelContext';
18+
import {
19+
FunnelProvider,
20+
useFunnelContext,
21+
} from 'pages/TracesFunnels/FunnelContext';
1822
import { filterFunnelsByQuery } from 'pages/TracesFunnels/utils';
19-
import { ChangeEvent, useMemo, useState } from 'react';
23+
import { ChangeEvent, useEffect, useMemo, useState } from 'react';
2024
import { Span } from 'types/api/trace/getTraceV2';
2125
import { FunnelData } from 'types/api/traceFunnels';
2226

@@ -28,21 +32,54 @@ enum ModalView {
2832
function FunnelDetailsView({
2933
funnel,
3034
span,
35+
triggerAutoSave,
36+
showNotifications,
37+
onChangesDetected,
38+
triggerDiscard,
3139
}: {
3240
funnel: FunnelData;
3341
span: Span;
42+
triggerAutoSave: boolean;
43+
showNotifications: boolean;
44+
onChangesDetected: (hasChanges: boolean) => void;
45+
triggerDiscard: boolean;
3446
}): JSX.Element {
47+
const { handleRestoreSteps, steps } = useFunnelContext();
48+
49+
// Track changes between current steps and original steps
50+
useEffect(() => {
51+
const hasChanges = !isEqual(steps, funnel.steps);
52+
if (onChangesDetected) {
53+
onChangesDetected(hasChanges);
54+
}
55+
}, [steps, funnel.steps, onChangesDetected]);
56+
57+
// Handle discard when triggered from parent
58+
useEffect(() => {
59+
if (triggerDiscard && funnel.steps) {
60+
handleRestoreSteps(funnel.steps);
61+
}
62+
}, [triggerDiscard, funnel.steps, handleRestoreSteps]);
63+
3564
return (
3665
<div className="add-span-to-funnel-modal__details">
3766
<FunnelListItem
3867
funnel={funnel}
3968
shouldRedirectToTracesListOnDeleteSuccess={false}
4069
isSpanDetailsPage
4170
/>
42-
<FunnelConfiguration funnel={funnel} isTraceDetailsPage span={span} />
71+
<FunnelConfiguration
72+
funnel={funnel}
73+
isTraceDetailsPage
74+
span={span}
75+
disableAutoSave
76+
triggerAutoSave={triggerAutoSave}
77+
showNotifications={showNotifications}
78+
/>
4379
</div>
4480
);
4581
}
82+
4683
interface AddSpanToFunnelModalProps {
4784
isOpen: boolean;
4885
onClose: () => void;
@@ -60,6 +97,9 @@ function AddSpanToFunnelModal({
6097
undefined,
6198
);
6299
const [isCreateModalOpen, setIsCreateModalOpen] = useState<boolean>(false);
100+
const [triggerSave, setTriggerSave] = useState<boolean>(false);
101+
const [isUnsavedChanges, setIsUnsavedChanges] = useState<boolean>(false);
102+
const [triggerDiscard, setTriggerDiscard] = useState<boolean>(false);
63103

64104
const handleSearch = (e: ChangeEvent<HTMLInputElement>): void => {
65105
setSearchQuery(e.target.value);
@@ -92,12 +132,26 @@ function AddSpanToFunnelModal({
92132
const handleBack = (): void => {
93133
setActiveView(ModalView.LIST);
94134
setSelectedFunnelId(undefined);
135+
setIsUnsavedChanges(false);
136+
setTriggerSave(false);
95137
};
96138

97139
const handleCreateNewClick = (): void => {
98140
setIsCreateModalOpen(true);
99141
};
100142

143+
const handleSaveFunnel = (): void => {
144+
setTriggerSave(true);
145+
// Reset trigger after a brief moment to allow the save to be processed
146+
setTimeout(() => setTriggerSave(false), 100);
147+
};
148+
149+
const handleDiscard = (): void => {
150+
setTriggerDiscard(true);
151+
// Reset trigger after a brief moment
152+
setTimeout(() => setTriggerDiscard(false), 100);
153+
};
154+
101155
const renderListView = (): JSX.Element => (
102156
<div className="add-span-to-funnel-modal">
103157
{!!filteredData?.length && (
@@ -156,7 +210,14 @@ function AddSpanToFunnelModal({
156210
<div className="traces-funnel-details__steps-config">
157211
{selectedFunnelId && funnelDetails?.payload && (
158212
<FunnelProvider funnelId={selectedFunnelId}>
159-
<FunnelDetailsView funnel={funnelDetails.payload} span={span} />
213+
<FunnelDetailsView
214+
funnel={funnelDetails.payload}
215+
span={span}
216+
triggerAutoSave={triggerSave}
217+
showNotifications
218+
onChangesDetected={setIsUnsavedChanges}
219+
triggerDiscard={triggerDiscard}
220+
/>
160221
</FunnelProvider>
161222
)}
162223
</div>
@@ -175,18 +236,43 @@ function AddSpanToFunnelModal({
175236
'add-span-to-funnel-modal-container--details':
176237
activeView === ModalView.DETAILS,
177238
})}
178-
okText="Save Funnel"
179239
footer={
180-
activeView === ModalView.LIST && !!filteredData?.length ? (
181-
<Button
182-
type="default"
183-
className="add-span-to-funnel-modal__create-button"
184-
onClick={handleCreateNewClick}
185-
icon={<Plus size={14} />}
186-
>
187-
Create new funnel
188-
</Button>
189-
) : null
240+
activeView === ModalView.DETAILS
241+
? [
242+
<Button key="close" onClick={onClose}>
243+
Close
244+
</Button>,
245+
<Button
246+
type="default"
247+
key="discard"
248+
onClick={handleDiscard}
249+
className="add-span-to-funnel-modal__discard-button"
250+
disabled={!isUnsavedChanges}
251+
>
252+
Discard
253+
</Button>,
254+
<Button
255+
key="save"
256+
type="primary"
257+
className="add-span-to-funnel-modal__save-button"
258+
onClick={handleSaveFunnel}
259+
disabled={!isUnsavedChanges}
260+
icon={<Check size={14} color="var(--bg-vanilla-100)" />}
261+
>
262+
Save Funnel
263+
</Button>,
264+
]
265+
: [
266+
<Button
267+
key="create"
268+
type="default"
269+
className="add-span-to-funnel-modal__create-button"
270+
onClick={handleCreateNewClick}
271+
icon={<Plus size={14} />}
272+
>
273+
Create new funnel
274+
</Button>,
275+
]
190276
}
191277
>
192278
{activeView === ModalView.LIST

0 commit comments

Comments
 (0)