Skip to content

Commit d39cd28

Browse files
authored
fix: allow execution back navigation with status (#875)
## Problem Status filter was not preserved when navigating back from a specific execution view. As a result, users are unable to see the same filtered view they had before clicking into an individual execution. ## Solution - Added support for preserving status filter when navigating between executions page and specific execution. - Refactor URL parameter validation for page and status ## Before & After Screenshots **BEFORE**: https://github.com/user-attachments/assets/8f4b85ca-7c6a-47ad-ae22-c6f7a2e57ced **AFTER**: https://github.com/user-attachments/assets/a035ea01-52bf-452d-842b-9ef745f33110 ## How to test - [x] Apply status filter on executions page - [x] Navigate to specific execution - [x] Use the back button and verify that the previous page and status filter are automatically applied - [x] Modify the `backToPage` and `backToStatus` to invalid parameters, verify that back navigation returns to the default first page with no status filter applied ## Deploy Notes Verify that behaviour works on Admin Dashboard
2 parents 7b3d0c2 + 762c9b0 commit d39cd28

File tree

3 files changed

+55
-9
lines changed

3 files changed

+55
-9
lines changed

packages/frontend/src/components/ExecutionHeader/index.tsx

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,59 @@ import { DateTime } from 'luxon'
99

1010
import * as URLS from '@/config/urls'
1111

12+
import { StatusType } from '../ExecutionStatusMenu'
13+
1214
type ExecutionHeaderProps = {
1315
execution: IExecution
1416
}
1517

18+
const isValidPage = (value: string | null): boolean => /^\d+$/.test(value || '')
19+
const isValidStatus = (value: string | null): boolean =>
20+
Object.values(StatusType).includes(value as StatusType) &&
21+
value !== StatusType.Empty
22+
23+
const buildBackUrl = (
24+
baseUrl: string,
25+
params: Record<string, string | null>,
26+
) => {
27+
const validParams = Object.entries(params)
28+
.filter(([key, value]) => {
29+
if (!value) {
30+
return false
31+
}
32+
33+
switch (key) {
34+
case 'page':
35+
return isValidPage(value)
36+
case 'status':
37+
return isValidStatus(value)
38+
default:
39+
return false
40+
}
41+
})
42+
.reduce((acc, [key, value]) => {
43+
acc.append(key, value || '')
44+
return acc
45+
}, new URLSearchParams())
46+
47+
return validParams.toString() ? `${baseUrl}?${validParams}` : baseUrl
48+
}
49+
1650
function ExecutionName(props: Pick<IExecution['flow'], 'name' | 'id'>) {
1751
const { id, name } = props
1852
const [searchParams] = useSearchParams()
1953
const navigate = useNavigate()
2054
const backToPage = searchParams.get('backToPage')
55+
const backToStatus = searchParams.get('backToStatus')
2156

2257
const handleBack = useCallback(() => {
23-
let backUrl = URLS.EXECUTIONS_FOR_FLOW(id)
24-
25-
if (backToPage && /^\d+$/.test(backToPage)) {
26-
backUrl += `?page=${backToPage}`
27-
}
58+
const baseUrl = URLS.EXECUTIONS_FOR_FLOW(id)
59+
const backUrl = buildBackUrl(baseUrl, {
60+
page: backToPage,
61+
status: backToStatus,
62+
})
2863
navigate(backUrl)
29-
}, [navigate, id, backToPage])
64+
}, [navigate, id, backToPage, backToStatus])
3065

3166
return (
3267
<Flex gap={2} alignItems="center">

packages/frontend/src/components/ExecutionRow/index.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,21 @@ import * as URLS from '@/config/urls'
2424
type ExecutionRowProps = {
2525
execution: IExecution
2626
page: number
27+
status: string
2728
}
2829

2930
export default function ExecutionRow(props: ExecutionRowProps): ReactElement {
30-
const { execution, page } = props
31+
const { execution, page, status } = props
3132
const { flow, executionSteps } = execution
3233

3334
const createdAt = DateTime.fromMillis(parseInt(execution.createdAt, 10))
3435
const relativeCreatedAt = createdAt.toRelative()
3536

3637
return (
3738
<Link
38-
to={`${URLS.EXECUTION(execution.id)}?backToPage=${page}`}
39+
to={`${URLS.EXECUTION(
40+
execution.id,
41+
)}?backToPage=${page}&backToStatus=${status}`}
3942
data-test="execution-row"
4043
>
4144
<Card

packages/frontend/src/pages/ExecutionsForFlow/index.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ interface ExecutionsListProps {
2424
isSearching: boolean
2525
isLoading: boolean
2626
page: number
27+
status: string
2728
}
2829

2930
const getLimitAndOffset = (page: number) => ({
@@ -40,6 +41,7 @@ function ExecutionsList({
4041
isLoading,
4142
isSearching,
4243
page,
44+
status,
4345
}: ExecutionsListProps) {
4446
const hasExecutions = executions.length > 0
4547

@@ -69,7 +71,12 @@ function ExecutionsList({
6971
return (
7072
<>
7173
{executions.map((execution) => (
72-
<ExecutionRow key={execution.id} execution={execution} page={page} />
74+
<ExecutionRow
75+
key={execution.id}
76+
execution={execution}
77+
page={page}
78+
status={status}
79+
/>
7380
))}
7481
</>
7582
)
@@ -152,6 +159,7 @@ export default function ExecutionsForFlowPage() {
152159
isLoading={isLoading}
153160
isSearching={isSearching}
154161
page={page}
162+
status={status}
155163
/>
156164
{hasPagination && (
157165
<Flex justifyContent="center" mt={6}>

0 commit comments

Comments
 (0)