-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(dashboard): display scheduledWfRuns (#1202)
- Loading branch information
Showing
15 changed files
with
348 additions
and
53 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
19 changes: 0 additions & 19 deletions
19
dashboard/src/app/[tenantId]/(diagram)/wfSpec/[...props]/actions/ScheduleWfRun.ts
This file was deleted.
Oops, something went wrong.
24 changes: 17 additions & 7 deletions
24
dashboard/src/app/[tenantId]/(diagram)/wfSpec/[...props]/actions/getScheduleWfSpec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,30 @@ | ||
'use server' | ||
|
||
import { lhClient } from '@/app/lhClient' | ||
import { WithTenant } from '@/types' | ||
import { ScheduledWfRunIdList } from 'littlehorse-client/proto' | ||
import { ScheduledWfRun } from 'littlehorse-client/proto' | ||
|
||
type GetWfSpecProps = { | ||
name: string | ||
version: string | ||
} & WithTenant | ||
|
||
export const getScheduleWfSpec = async ({ name, version, tenantId }: GetWfSpecProps): Promise<ScheduledWfRunIdList> => { | ||
export const getScheduleWfSpec = async ({ name, version, tenantId }: GetWfSpecProps): Promise<ScheduledWfRun[]> => { | ||
const client = await lhClient({ tenantId }) | ||
|
||
const [majorVersion, revision] = version.split('.') | ||
return client.searchScheduledWfRun({ | ||
wfSpecName: name, | ||
majorVersion: parseInt(majorVersion) || 0, | ||
revision: parseInt(revision) | 0, | ||
}) | ||
|
||
return Promise.all( | ||
( | ||
await client.searchScheduledWfRun({ | ||
wfSpecName: name, | ||
majorVersion: parseInt(majorVersion) || 0, | ||
revision: parseInt(revision) || 0, | ||
}) | ||
).results.map(async scheduledWfRun => { | ||
return await client.getScheduledWfRun({ | ||
id: scheduledWfRun.id, | ||
}) | ||
}) | ||
) | ||
} |
124 changes: 124 additions & 0 deletions
124
dashboard/src/app/[tenantId]/(diagram)/wfSpec/[...props]/components/ScheduledWfRuns.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
'use client' | ||
|
||
import { ScheduledWfRunIdList, WfSpec } from 'littlehorse-client/proto' | ||
import { getScheduleWfSpec } from '../actions/getScheduleWfSpec' | ||
import { SelectionLink } from '@/app/[tenantId]/components/SelectionLink' | ||
import { ScheduledWfRun } from 'littlehorse-client/proto' | ||
import { FUTURE_TIME_RANGES, SEARCH_DEFAULT_LIMIT, TimeRange } from '@/app/constants' | ||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select' | ||
import { ClockIcon } from 'lucide-react' | ||
import { useEffect, useState, useMemo } from 'react' | ||
import { getCronTimeWindow } from '@/app/utils/getCronTimeWindow' | ||
import { parseExpression } from 'cron-parser' | ||
import { utcToLocalDateTime } from '@/app/utils' | ||
import { SearchVariableDialog } from './SearchVariableDialog' | ||
import { SearchFooter } from '@/app/[tenantId]/components/SearchFooter' | ||
import { useParams, useSearchParams } from 'next/navigation' | ||
import { RefreshCwIcon } from 'lucide-react' | ||
|
||
export const ScheduledWfRuns = (spec: WfSpec) => { | ||
const [currentWindow, setWindow] = useState<TimeRange>(-1) | ||
const [isLoading, setIsLoading] = useState(true) | ||
const [error, setError] = useState<Error | null>(null) | ||
const [scheduledWfRuns, setScheduledWfRuns] = useState<ScheduledWfRun[]>([]) | ||
const tenantId = useParams().tenantId as string | ||
|
||
useEffect(() => { | ||
let isMounted = true | ||
|
||
const fetchScheduledWfRuns = async () => { | ||
try { | ||
setIsLoading(true) | ||
setError(null) | ||
const runs = await getScheduleWfSpec({ | ||
name: spec.id!.name, | ||
version: spec.id!.majorVersion + '.' + spec.id!.revision, | ||
tenantId: tenantId, | ||
}) | ||
if (isMounted) { | ||
setScheduledWfRuns(runs) | ||
} | ||
} catch (err) { | ||
if (isMounted) { | ||
setError(err instanceof Error ? err : new Error('Failed to fetch scheduled runs')) | ||
} | ||
} finally { | ||
if (isMounted) { | ||
setIsLoading(false) | ||
} | ||
} | ||
} | ||
|
||
fetchScheduledWfRuns() | ||
|
||
return () => { | ||
isMounted = false | ||
} | ||
}, [spec.id, tenantId]) | ||
|
||
const filteredScheduledWfRuns = useMemo( | ||
() => | ||
scheduledWfRuns | ||
.filter(scheduledWfRun => { | ||
if (currentWindow === -1) return true | ||
const timeWindow = getCronTimeWindow(scheduledWfRun.cronExpression) | ||
return timeWindow && timeWindow <= currentWindow | ||
}) | ||
.sort((a, b) => { | ||
const timeA = parseExpression(a.cronExpression).next().toDate().getTime() | ||
const timeB = parseExpression(b.cronExpression).next().toDate().getTime() | ||
return timeA - timeB | ||
}), | ||
[currentWindow, scheduledWfRuns] | ||
) | ||
|
||
if (isLoading) { | ||
return ( | ||
<div className="flex min-h-[500px] items-center justify-center"> | ||
<RefreshCwIcon className="h-8 w-8 animate-spin text-blue-500" /> | ||
</div> | ||
) | ||
} | ||
|
||
if (error) { | ||
return ( | ||
<div className="flex min-h-[500px] flex-col items-center justify-center text-red-500"> | ||
<p>Error loading scheduled runs</p> | ||
<p className="text-sm">{error.message}</p> | ||
</div> | ||
) | ||
} | ||
|
||
return ( | ||
<div className="flex min-h-[500px] flex-col"> | ||
<div className="flex gap-4"> | ||
<Select value={currentWindow.toString()} onValueChange={value => setWindow(parseInt(value) as TimeRange)}> | ||
<SelectTrigger className="w-[150px] min-w-fit"> | ||
<div className="flex items-center gap-2"> | ||
<ClockIcon className="h-5 w-5 fill-none stroke-black" /> | ||
<SelectValue>{FUTURE_TIME_RANGES.find(time => time.value === currentWindow)?.label}</SelectValue> | ||
</div> | ||
</SelectTrigger> | ||
<SelectContent> | ||
{FUTURE_TIME_RANGES.map(time => ( | ||
<SelectItem key={time.value} value={time.value.toString()}> | ||
{time.label} | ||
</SelectItem> | ||
))} | ||
</SelectContent> | ||
</Select> | ||
</div> | ||
<div className="mt-4 flex flex-col"> | ||
{filteredScheduledWfRuns.map(scheduledWfRun => ( | ||
<SelectionLink aria-disabled key={scheduledWfRun.id?.id} href={undefined}> | ||
<p>{scheduledWfRun.id?.id}</p> | ||
<div className="flex items-center gap-2 rounded-md bg-gray-200 p-1 text-sm"> | ||
<ClockIcon className="h-5 w-5 fill-none stroke-black" /> | ||
<p>{utcToLocalDateTime(parseExpression(scheduledWfRun.cronExpression).next().toDate().toISOString())}</p> | ||
</div> | ||
</SelectionLink> | ||
))} | ||
</div> | ||
</div> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.