Skip to content

Commit

Permalink
feat(dashboard): taskRun Table
Browse files Browse the repository at this point in the history
* fix: unnecessary code

* fix: no avatar when not authenticated

* fix: valid way to detect auth disabled

* feat: init search for taskRun

* feat: table task def init

* feat: finish taskRun table

I will rewrite this with the new decided frontend design system. I just wanted to push what I already wrote

* fix: update table cols

* fix: filter `UNRECOGNIZED`

* fix: return all taskRuns by default

* chore: rename nodeRunName -> nodeName

* fix: mistyped emoji & extra css

* revert: "chore: rename nodeRunName -> nodeName"

This reverts commit bb4f4dc.
  • Loading branch information
HazimAr committed May 27, 2024
1 parent ce3be07 commit 3dd149e
Show file tree
Hide file tree
Showing 4 changed files with 180 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const Node: FC<NodeProps> = ({ data, selected }) => {
<>
<NodeDetails>
<div className="">
<div className="flex items-center items-center gap-1 text-nowrap">
<div className="flex items-center gap-1 text-nowrap">
<h3 className="font-bold">UserTask</h3>
<Link
className="flex items-center justify-center gap-1 text-blue-500 hover:underline"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
'use server'
import { lhClient } from '@/app/lhClient'
import { WithTenant } from '@/types'
import { NodeRun } from 'littlehorse-client/dist/proto/node_run'
import { TaskRunId } from 'littlehorse-client/dist/proto/object_id';
import { SearchTaskRunRequest, TaskRunIdList } from 'littlehorse-client/dist/proto/service'
import { TaskRun } from 'littlehorse-client/dist/proto/task_run'

export interface runDetails {
taskRun: TaskRun
nodeRun: NodeRun
}
export interface PaginatedTaskRunList extends TaskRunIdList {
resultsWithDetails: runDetails[]
bookmarkAsString: string | undefined
}

type WithBookmarkAsString = {
bookmarkAsString: string | undefined
}

export type TaskRunSearchProps = SearchTaskRunRequest & WithTenant & WithBookmarkAsString
export const searchTaskRun = async ({
tenantId,
bookmarkAsString,
...req
}: TaskRunSearchProps): Promise<PaginatedTaskRunList> => {
const client = await lhClient({ tenantId })
const requestWithBookmark = bookmarkAsString ? { ...req, bookmark: Buffer.from(bookmarkAsString, 'base64') } : req
const taskRunIdList: TaskRunIdList = await client.searchTaskRun(requestWithBookmark)
const hydrateWithTaskRunDetails = (): Promise<runDetails>[] => {
return taskRunIdList.results.map(async (taskRunId: TaskRunId) => {
const taskRun = await client.getTaskRun({
wfRunId: taskRunId.wfRunId,
taskGuid: taskRunId.taskGuid,
})
const nodeRun = await client.getNodeRun(taskRun.id!)

return {
taskRun,
nodeRun,
}
})
}

const taskRunWithDetails: runDetails[] = await Promise.all(hydrateWithTaskRunDetails())

return {
...taskRunIdList,
bookmarkAsString: taskRunIdList.bookmark?.toString('base64'),
resultsWithDetails: taskRunWithDetails,
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,142 @@
'use client'
import { Navigation } from '@/app/(authenticated)/components/Navigation'
import { concatWfRunIds, localDateTimeToUTCIsoString, utcToLocalDateTime } from '@/app/utils'
import { useWhoAmI } from '@/contexts/WhoAmIContext'
import { Field, Input, Label } from '@headlessui/react'
import { ArrowPathIcon } from '@heroicons/react/24/outline'
import { useInfiniteQuery } from '@tanstack/react-query'
import { TaskStatus } from 'littlehorse-client/dist/proto/common_enums'
import { TaskDef as TaskDefProto } from 'littlehorse-client/dist/proto/task_def'
import { FC } from 'react'
import Link from 'next/link'
import { FC, Fragment, useState } from 'react'
import { PaginatedTaskRunList, searchTaskRun } from '../actions/searchTaskRun'
import { Details } from './Details'
import { InputVars } from './InputVars'

type Props = {
spec: TaskDefProto
}
export const TaskDef: FC<Props> = ({ spec }) => {
const [selectedStatus, setSelectedStatus] = useState<TaskStatus | 'ALL'>('ALL')
const [createdAfter, setCreatedAfter] = useState('')
const [createdBefore, setCreatedBefore] = useState('')
const { tenantId } = useWhoAmI()

const { isPending, data, hasNextPage, fetchNextPage } = useInfiniteQuery({
queryKey: ['taskRun', selectedStatus, tenantId, 10, createdAfter, createdBefore],
initialPageParam: undefined,
getNextPageParam: (lastPage: PaginatedTaskRunList) => lastPage.bookmarkAsString,
queryFn: async ({ pageParam }) => {
return await searchTaskRun({
tenantId,
bookmarkAsString: pageParam,
limit: 10,
status: selectedStatus == 'ALL' ? undefined : selectedStatus,
taskDefName: spec.id?.name || '',
earliestStart: createdAfter ? localDateTimeToUTCIsoString(createdAfter) : undefined,
latestStart: createdBefore ? localDateTimeToUTCIsoString(createdBefore) : undefined,
})
},
})
return (
<>
<Navigation href="/?type=TaskDef" title="Go back to TaskDefs" />
<Details id={spec.id} />
<InputVars inputVars={spec.inputVars} />
<hr className="mt-6" />
<div className="mb-4 mt-6 flex items-center justify-between">
<h2 className="text-2xl font-bold">Related Task Run&apos;s:</h2>
<select
className="rounded border px-2 py-2"
onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
setSelectedStatus(e.target.value as TaskStatus)
}}
>
<option>ALL</option>
{Object.keys(TaskStatus)
.filter(status => status != TaskStatus.UNRECOGNIZED)
.map(status => (
<option key={status}>{status}</option>
))}
</select>
</div>
<div className="mb-5 flex max-w-fit items-start justify-between">
<Field className="flex items-center justify-between">
<Label className="block w-1/2 font-bold">Created after:</Label>
<Input
type="datetime-local"
value={createdAfter}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setCreatedAfter(e.target.value)}
className="focus:shadow-outline ml-3 w-full appearance-none rounded border px-3 py-2 leading-tight shadow focus:outline-none"
/>
</Field>

<Field className="ml-10 flex items-center justify-between">
<Label className="block w-1/2 font-bold">Created before:</Label>
<Input
type="datetime-local"
value={createdBefore}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setCreatedBefore(e.target.value)}
className="focus:shadow-outline ml-4 w-full appearance-none rounded border px-3 py-2 leading-tight shadow focus:outline-none"
/>
</Field>
</div>

{isPending ? (
<div className="flex min-h-[360px] items-center justify-center text-center">
<ArrowPathIcon className="h-8 w-8 animate-spin fill-blue-500 stroke-none" />
</div>
) : (
<div className="flex min-h-[360px] flex-col gap-4">
<table className="text-surface min-w-full text-center text-sm font-light">
<thead className="border-b border-neutral-200 bg-neutral-300 font-medium">
<tr>
<td scope="col" className="px-6 py-4">
WfRun Id
</td>
<th scope="col" className="px-6 py-4">
Task GUID
</th>
<th scope="col" className="px-6 py-4">
Creation Date
</th>
</tr>
</thead>
<tbody>
{data?.pages.map((page, i) => (
<Fragment key={i}>
{page.resultsWithDetails.length > 0 ? (
page.resultsWithDetails.map(({ taskRun }) => {
return (
<tr key={taskRun.id?.taskGuid} className="border-b border-neutral-200">
<td className="px-6 py-4">
<Link
className="py-2 text-blue-500 hover:underline"
target="_blank"
href={`/wfRun/${concatWfRunIds(taskRun.id?.wfRunId!)}?threadRunNumber=${taskRun.source?.taskNode?.nodeRunId?.threadRunNumber || taskRun.source?.userTaskTrigger?.nodeRunId?.threadRunNumber}&nodeName=${taskRun.source?.taskNode?.nodeRunId?.position}-${taskRun.source?.taskNode?.nodeRunId}-TASK`}
>
{concatWfRunIds(taskRun.id?.wfRunId!)}
</Link>
</td>
<td className="px-6 py-4">{taskRun.id?.taskGuid}</td>

<td className="px-6 py-4">
{taskRun.scheduledAt ? utcToLocalDateTime(taskRun.scheduledAt) : 'N/A'}
</td>
</tr>
)
})
) : (
<tr>
<td colSpan={5}>No data</td>
</tr>
)}
</Fragment>
))}
</tbody>
</table>
</div>
)}
</>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export const UserTaskDef: FC<Props> = ({ spec }) => {
<Fields fields={spec.fields} />
<hr className="mt-6" />
<div className="mb-4 mt-6 flex items-center justify-between">
<h2 className="text-2xl font-bold">Related User Task Run&apos;s:</h2>
<h2 className="text-2xl font-bold">Related User Task Runs:</h2>
<div className="flex">
{userTaskPossibleStatuses.map(status => (
<Button
Expand Down

0 comments on commit 3dd149e

Please sign in to comment.