You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
87 lines
2.7 KiB
JavaScript
87 lines
2.7 KiB
JavaScript
import _ from 'lodash'
|
|
import { useEffect, useState } from 'preact/hooks'
|
|
|
|
import { durationToString } from './lib/utils'
|
|
|
|
/**
|
|
* @param {import('@/jobs.ts').QueuedJob} props
|
|
*/
|
|
export const QueuedJob = ({ uuid, status, name, submitter, submittedAt }) => (
|
|
<div class={'job ' + status} title={uuid} onClick={() => (location.href = `/jobs/${uuid}`)}>
|
|
<div class="name">{name}</div>
|
|
<div class="footer">
|
|
<div class="submitted-at">{new Date(submittedAt).toLocaleString()}</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
|
|
/**
|
|
* @param {import('@/jobs.ts').CompletedJob} props
|
|
*/
|
|
export const CompletedJob = ({ uuid, name, submittedAt, startedAt, completedAt }) => {
|
|
return (
|
|
<div class="job completed" title={uuid} onClick={() => (location.href = `/jobs/${uuid}`)}>
|
|
<div class="name">{name}</div>
|
|
<div class="footer">
|
|
<div class="submitted-at">{new Date(submittedAt).toLocaleString()}</div>
|
|
<div class="delta">{durationToString(startedAt, completedAt)}</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export const JobsPage = ({}) => {
|
|
const [jobStore, setJobStore] = useState({})
|
|
|
|
useEffect(async () => {
|
|
// const { searchParams } = new URL(location.href)
|
|
|
|
// const limit = searchParams.has('limit') ? parseInt(searchParams.get('limit')) : 10
|
|
// const offset = (searchParams.has('page') ? parseInt(searchParams.get('page')) : 1) - 1
|
|
|
|
const res = await fetch(location.href + '?format=json')
|
|
const jobs = await res.json()
|
|
|
|
// const result = {}
|
|
|
|
// for (const item of jobs) {
|
|
// result[item.uuid] = item
|
|
// }
|
|
|
|
const result = _.keyBy(jobs, 'uuid')
|
|
console.log(result)
|
|
setJobStore(result)
|
|
|
|
// Setup SSE
|
|
const es = new EventSource(location.href + '?format=sse')
|
|
es.addEventListener('message', ({ data }) => {
|
|
const event = JSON.parse(data)
|
|
setJobStore(s => ({
|
|
...s,
|
|
[event.job.uuid]: event.job,
|
|
}))
|
|
})
|
|
}, [])
|
|
|
|
return (
|
|
<>
|
|
<h2>Queued Jobs</h2>
|
|
<div class="list">
|
|
{Object.values(jobStore)
|
|
.filter(job => job.status !== 'completed')
|
|
.map(job => (
|
|
<QueuedJob {...job} />
|
|
))}
|
|
</div>
|
|
<h2>Completed Jobs</h2>
|
|
<div class="list">
|
|
{Object.values(jobStore)
|
|
.filter(job => job.status === 'completed')
|
|
.map(job => (
|
|
<CompletedJob {...job} />
|
|
))}
|
|
</div>
|
|
</>
|
|
)
|
|
}
|