chore: add sort order in URL params

This commit is contained in:
Abhishek Kumar 2026-02-06 09:01:06 +05:30
parent e8005042e2
commit 9824d88d53
7 changed files with 148 additions and 59 deletions

View file

@ -92,9 +92,14 @@ export default function RunsPage() {
return decodeFiltersFromURL(searchParams, superadminFilterAttributes);
});
// Sort state
const [sortBy, setSortBy] = useState<string | null>(null);
const [sortOrder, setSortOrder] = useState<'asc' | 'desc'>('desc');
// Sort state (initialized from URL)
const [sortBy, setSortBy] = useState<string | null>(() => {
return searchParams.get('sort_by') || null;
});
const [sortOrder, setSortOrder] = useState<'asc' | 'desc'>(() => {
const order = searchParams.get('sort_order');
return order === 'asc' ? 'asc' : 'desc';
});
// Dialog state for comment editing
const [isCommentDialogOpen, setIsCommentDialogOpen] = useState(false);
@ -167,7 +172,7 @@ export default function RunsPage() {
}
}, [limit, accessToken]);
const updatePageInUrl = useCallback((page: number, filters?: ActiveFilter[]) => {
const updatePageInUrl = useCallback((page: number, filters?: ActiveFilter[], sortByParam?: string | null, sortOrderParam?: 'asc' | 'desc') => {
const params = new URLSearchParams();
params.set('page', page.toString());
@ -180,6 +185,12 @@ export default function RunsPage() {
}
}
// Add sort to URL if present
if (sortByParam) {
params.set('sort_by', sortByParam);
params.set('sort_order', sortOrderParam || 'desc');
}
router.push(`/superadmin/runs?${params.toString()}`);
}, [router]);
@ -208,7 +219,7 @@ export default function RunsPage() {
const handlePageChange = (page: number) => {
setCurrentPage(page);
updatePageInUrl(page, appliedFilters);
updatePageInUrl(page, appliedFilters, sortBy, sortOrder);
fetchRuns(page, appliedFilters, false, sortBy, sortOrder);
};
@ -216,7 +227,7 @@ export default function RunsPage() {
setIsExecutingFilters(true);
setCurrentPage(1); // Reset to first page when applying filters
setAppliedFilters(activeFilters); // Update applied filters
updatePageInUrl(1, activeFilters);
updatePageInUrl(1, activeFilters, sortBy, sortOrder);
await fetchRuns(1, activeFilters, false, sortBy, sortOrder);
setIsExecutingFilters(false);
}, [activeFilters, fetchRuns, updatePageInUrl, sortBy, sortOrder]);
@ -229,7 +240,7 @@ export default function RunsPage() {
setIsExecutingFilters(true);
setCurrentPage(1);
setAppliedFilters([]); // Clear applied filters
updatePageInUrl(1, []); // Clear filters from URL
updatePageInUrl(1, [], sortBy, sortOrder); // Clear filters from URL
await fetchRuns(1, [], false, sortBy, sortOrder); // Fetch all runs without filters
setIsExecutingFilters(false);
}, [fetchRuns, updatePageInUrl, sortBy, sortOrder]);
@ -238,15 +249,16 @@ export default function RunsPage() {
// Reset to first page when sort changes
setCurrentPage(1);
const newSortBy = field;
let newSortOrder: 'asc' | 'desc' = 'desc';
if (sortBy === field) {
// Toggle order if same field
setSortOrder(prev => prev === 'asc' ? 'desc' : 'asc');
} else {
// New field, default to desc
setSortBy(field);
setSortOrder('desc');
newSortOrder = sortOrder === 'asc' ? 'desc' : 'asc';
}
}, [sortBy]);
setSortBy(newSortBy);
setSortOrder(newSortOrder);
updatePageInUrl(1, appliedFilters, newSortBy, newSortOrder);
}, [sortBy, sortOrder, updatePageInUrl, appliedFilters]);
// Save comment function declared outside JSX (requirement #2)
const saveAdminComment = useCallback(async () => {
@ -345,6 +357,7 @@ export default function RunsPage() {
isExecuting={isExecutingFilters}
autoRefresh={autoRefresh}
onAutoRefreshChange={setAutoRefresh}
hasAppliedFilters={appliedFilters.length > 0}
/>
<Card>

View file

@ -30,9 +30,14 @@ export function WorkflowExecutions({ workflowId, searchParams }: WorkflowExecuti
const [isExecutingFilters, setIsExecutingFilters] = useState(false);
const [configuredAttributes, setConfiguredAttributes] = useState<FilterAttribute[]>(availableAttributes);
// Sort state
const [sortBy, setSortBy] = useState<string | null>(null);
const [sortOrder, setSortOrder] = useState<'asc' | 'desc'>('desc');
// Sort state (initialized from URL)
const [sortBy, setSortBy] = useState<string | null>(() => {
return searchParams.get('sort_by') || null;
});
const [sortOrder, setSortOrder] = useState<'asc' | 'desc'>(() => {
const order = searchParams.get('sort_order');
return order === 'asc' ? 'asc' : 'desc';
});
const { accessToken } = useUserConfig();
@ -41,6 +46,11 @@ export function WorkflowExecutions({ workflowId, searchParams }: WorkflowExecuti
return decodeFiltersFromURL(searchParams, availableAttributes);
});
// Applied filters are the ones actually used for fetching (only updated on Apply click)
const [appliedFilters, setAppliedFilters] = useState<ActiveFilter[]>(() => {
return decodeFiltersFromURL(searchParams, availableAttributes);
});
// Load disposition codes from workflow configuration
const loadDispositionCodes = useCallback(async () => {
if (!accessToken) return;
@ -130,7 +140,7 @@ export function WorkflowExecutions({ workflowId, searchParams }: WorkflowExecuti
}
}, [workflowId, accessToken]);
const updatePageInUrl = useCallback((page: number, filters?: ActiveFilter[]) => {
const updatePageInUrl = useCallback((page: number, filters?: ActiveFilter[], sortByParam?: string | null, sortOrderParam?: 'asc' | 'desc') => {
const params = new URLSearchParams();
params.set('page', page.toString());
@ -143,17 +153,24 @@ export function WorkflowExecutions({ workflowId, searchParams }: WorkflowExecuti
}
}
// Add sort to URL if present
if (sortByParam) {
params.set('sort_by', sortByParam);
params.set('sort_order', sortOrderParam || 'desc');
}
router.push(`/workflow/${workflowId}/runs?${params.toString()}`, { scroll: false });
}, [router, workflowId]);
useEffect(() => {
fetchWorkflowRuns(currentPage, activeFilters, sortBy, sortOrder);
}, [currentPage, activeFilters, fetchWorkflowRuns, sortBy, sortOrder]);
fetchWorkflowRuns(currentPage, appliedFilters, sortBy, sortOrder);
}, [currentPage, appliedFilters, fetchWorkflowRuns, sortBy, sortOrder]);
const handleApplyFilters = useCallback(async () => {
setIsExecutingFilters(true);
setCurrentPage(1); // Reset to first page when applying filters
updatePageInUrl(1, activeFilters);
setAppliedFilters(activeFilters);
updatePageInUrl(1, activeFilters, sortBy, sortOrder);
await fetchWorkflowRuns(1, activeFilters, sortBy, sortOrder);
setIsExecutingFilters(false);
}, [activeFilters, fetchWorkflowRuns, updatePageInUrl, sortBy, sortOrder]);
@ -165,29 +182,36 @@ export function WorkflowExecutions({ workflowId, searchParams }: WorkflowExecuti
const handleClearFilters = useCallback(async () => {
setIsExecutingFilters(true);
setCurrentPage(1);
updatePageInUrl(1, []); // Clear filters from URL
setActiveFilters([]);
setAppliedFilters([]);
updatePageInUrl(1, [], sortBy, sortOrder); // Clear filters from URL
await fetchWorkflowRuns(1, [], sortBy, sortOrder); // Fetch all workflows without filters
setIsExecutingFilters(false);
}, [fetchWorkflowRuns, updatePageInUrl, sortBy, sortOrder]);
const handlePageChange = useCallback((page: number) => {
setCurrentPage(page);
updatePageInUrl(page, activeFilters);
}, [updatePageInUrl, activeFilters]);
updatePageInUrl(page, appliedFilters, sortBy, sortOrder);
}, [updatePageInUrl, appliedFilters, sortBy, sortOrder]);
const handleSort = useCallback((field: string) => {
// Reset to first page when sort changes
setCurrentPage(1);
const newSortBy = field;
let newSortOrder: 'asc' | 'desc' = 'desc';
if (sortBy === field) {
// Toggle order if same field
setSortOrder(prev => prev === 'asc' ? 'desc' : 'asc');
} else {
// New field, default to desc
setSortBy(field);
setSortOrder('desc');
newSortOrder = sortOrder === 'asc' ? 'desc' : 'asc';
}
}, [sortBy]);
setSortBy(newSortBy);
setSortOrder(newSortOrder);
updatePageInUrl(1, appliedFilters, newSortBy, newSortOrder);
}, [sortBy, sortOrder, updatePageInUrl, appliedFilters]);
const handleReload = useCallback(() => {
fetchWorkflowRuns(currentPage, appliedFilters, sortBy, sortOrder);
}, [fetchWorkflowRuns, currentPage, appliedFilters, sortBy, sortOrder]);
return (
<div className="container mx-auto py-8">
@ -205,11 +229,13 @@ export function WorkflowExecutions({ workflowId, searchParams }: WorkflowExecuti
onApplyFilters={handleApplyFilters}
onClearFilters={handleClearFilters}
isExecutingFilters={isExecutingFilters}
hasAppliedFilters={appliedFilters.length > 0}
sortBy={sortBy}
sortOrder={sortOrder}
onSort={handleSort}
workflowId={workflowId}
accessToken={accessToken}
onReload={handleReload}
/>
</div>
);