Skip to content

Commit bf0bcf3

Browse files
committed
feat(logs): add sort to logs page
1 parent f0e988d commit bf0bcf3

File tree

1 file changed

+61
-9
lines changed
  • apps/sim/app/workspace/[workspaceId]/logs

1 file changed

+61
-9
lines changed

apps/sim/app/workspace/[workspaceId]/logs/logs.tsx

Lines changed: 61 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,10 @@ export default function Logs() {
288288
const activeLogRefetchRef = useRef<() => void>(() => {})
289289
const logsQueryRef = useRef({ isFetching: false, hasNextPage: false, fetchNextPage: () => {} })
290290
const [isNotificationSettingsOpen, setIsNotificationSettingsOpen] = useState(false)
291+
const [activeSort, setActiveSort] = useState<{
292+
column: string
293+
direction: 'asc' | 'desc'
294+
} | null>(null)
291295
const userPermissions = useUserPermissionsContext()
292296

293297
const [contextMenuOpen, setContextMenuOpen] = useState(false)
@@ -358,11 +362,43 @@ export default function Logs() {
358362
return logsQuery.data.pages.flatMap((page) => page.logs)
359363
}, [logsQuery.data?.pages])
360364

365+
const sortedLogs = useMemo(() => {
366+
if (!activeSort) return logs
367+
368+
const { column, direction } = activeSort
369+
return [...logs].sort((a, b) => {
370+
let cmp = 0
371+
switch (column) {
372+
case 'date':
373+
cmp = new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()
374+
break
375+
case 'duration': {
376+
const aDuration = parseDuration({ duration: a.duration ?? undefined }) ?? -1
377+
const bDuration = parseDuration({ duration: b.duration ?? undefined }) ?? -1
378+
cmp = aDuration - bDuration
379+
break
380+
}
381+
case 'cost': {
382+
const aCost = typeof a.cost?.total === 'number' ? a.cost.total : -1
383+
const bCost = typeof b.cost?.total === 'number' ? b.cost.total : -1
384+
cmp = aCost - bCost
385+
break
386+
}
387+
case 'status':
388+
cmp = (a.status ?? '').localeCompare(b.status ?? '')
389+
break
390+
default:
391+
break
392+
}
393+
return direction === 'asc' ? cmp : -cmp
394+
})
395+
}, [logs, activeSort])
396+
361397
const selectedLogIndex = useMemo(
362-
() => (selectedLogId ? logs.findIndex((l) => l.id === selectedLogId) : -1),
363-
[logs, selectedLogId]
398+
() => (selectedLogId ? sortedLogs.findIndex((l) => l.id === selectedLogId) : -1),
399+
[sortedLogs, selectedLogId]
364400
)
365-
const selectedLogFromList = selectedLogIndex >= 0 ? logs[selectedLogIndex] : null
401+
const selectedLogFromList = selectedLogIndex >= 0 ? sortedLogs[selectedLogIndex] : null
366402

367403
const selectedLog = useMemo(() => {
368404
if (!selectedLogFromList) return null
@@ -381,8 +417,8 @@ export default function Logs() {
381417
useFolders(workspaceId)
382418

383419
useEffect(() => {
384-
logsRef.current = logs
385-
}, [logs])
420+
logsRef.current = sortedLogs
421+
}, [sortedLogs])
386422
useEffect(() => {
387423
selectedLogIndexRef.current = selectedLogIndex
388424
}, [selectedLogIndex])
@@ -659,7 +695,7 @@ export default function Logs() {
659695

660696
const rows: ResourceRow[] = useMemo(
661697
() =>
662-
logs.map((log) => {
698+
sortedLogs.map((log) => {
663699
const formattedDate = formatDate(log.createdAt)
664700
const displayStatus = getDisplayStatus(log.status)
665701
const isMothershipJob = log.trigger === 'mothership'
@@ -710,7 +746,7 @@ export default function Logs() {
710746
},
711747
}
712748
}),
713-
[logs]
749+
[sortedLogs]
714750
)
715751

716752
const sidebarOverlay = useMemo(
@@ -721,7 +757,7 @@ export default function Logs() {
721757
onClose={handleCloseSidebar}
722758
onNavigateNext={handleNavigateNext}
723759
onNavigatePrev={handleNavigatePrev}
724-
hasNext={selectedLogIndex < logs.length - 1}
760+
hasNext={selectedLogIndex < sortedLogs.length - 1}
725761
hasPrev={selectedLogIndex > 0}
726762
/>
727763
),
@@ -732,7 +768,7 @@ export default function Logs() {
732768
handleNavigateNext,
733769
handleNavigatePrev,
734770
selectedLogIndex,
735-
logs.length,
771+
sortedLogs.length,
736772
]
737773
)
738774

@@ -978,6 +1014,21 @@ export default function Logs() {
9781014
[appliedFilters, textSearch, removeBadge, handleFiltersChange]
9791015
)
9801016

1017+
const sortConfig = useMemo<SortConfig>(
1018+
() => ({
1019+
options: [
1020+
{ id: 'date', label: 'Date' },
1021+
{ id: 'duration', label: 'Duration' },
1022+
{ id: 'cost', label: 'Cost' },
1023+
{ id: 'status', label: 'Status' },
1024+
],
1025+
active: activeSort,
1026+
onSort: (column, direction) => setActiveSort({ column, direction }),
1027+
onClear: () => setActiveSort(null),
1028+
}),
1029+
[activeSort]
1030+
)
1031+
9811032
const searchConfig = useMemo<SearchConfig>(
9821033
() => ({
9831034
value: currentInput,
@@ -1065,6 +1116,7 @@ export default function Logs() {
10651116
<ResourceHeader icon={Library} title='Logs' actions={headerActions} />
10661117
<ResourceOptionsBar
10671118
search={searchConfig}
1119+
sort={sortConfig}
10681120
filter={
10691121
<LogsFilterPanel searchQuery={searchQuery} onSearchQueryChange={setSearchQuery} />
10701122
}

0 commit comments

Comments
 (0)