Skip to content

Commit

Permalink
feat(dashboard): added multiple nodeRun on single Task Node (#1113)
Browse files Browse the repository at this point in the history
* added fixes on conditional node on dashboard

* refactor(dashboard): added fixes on conditional node

* refactor(dashboard): added fixes on conditional node

* refactor(dashboard): added fixes on conditional node

* feat(dashboard): added multiple nodeRun on single Task Node

* bug(dashbaord): convert bool values to string in model for usertask

* bug(dashbaord): convert bool values to string in model for usertask

* feat(dashbaord): fix build error

* fix(dashbaord): add position field at accordion title

* feat(dashboard): added nodeRuns list on all available nodesType (#1092)
 * added nodeRuns list for TaskNode
 * added nodeRuns list for UserTaskNode
 * added nodeRuns for childThread
 * added nodeRuns for sleepNode
 * code cleaning
 * fix status pin sybmols

* feat(dashboard): fix build issue (#1092)
* added types to modal for noderuns

* fix(dashbord): change types for NodeType

* for nodeRuntype list , update the NodeType

* wip

* fix(dashboard) : minor ui fix
* remove zero which is showing when no input variable

* fix(dashboard): fix build error

---------

Co-authored-by: Hazim Arafa <[email protected]>
Co-authored-by: Mijail Rondon <[email protected]>
  • Loading branch information
3 people authored Nov 18, 2024
1 parent 788885e commit 649b5b4
Show file tree
Hide file tree
Showing 35 changed files with 4,415 additions and 3,101 deletions.
6,177 changes: 3,621 additions & 2,556 deletions dashboard/package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
},
"dependencies": {
"@headlessui/react": "^2.0.3",
"@radix-ui/react-accordion": "^1.2.1",
"@radix-ui/react-checkbox": "^1.1.1",
"@radix-ui/react-dialog": "^1.0.5",
"@radix-ui/react-label": "^2.1.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,15 @@ export const Layouter: FC<{ nodeRuns?: NodeRun[]; nodeRunNameToBeHighlighted?: s
const nodeRun = nodeRuns?.find(nodeRun => {
return nodeRun.nodeName === node.id
})
const nodeRunsList = nodeRuns?.filter(nodeRun => {
return nodeRun.nodeName === node.id
})
const fade = nodeRuns !== undefined && nodeRun === undefined
const nodeNeedsToBeHighlighted = node.id === nodeRunNameToBeHighlighted

return {
...node,
data: { ...node.data, nodeRun, fade, nodeNeedsToBeHighlighted },
data: { ...node.data, nodeRun, fade, nodeNeedsToBeHighlighted, nodeRunsList },
position: { x: nodeWithPosition.x - node.width! / 2, y: nodeWithPosition.y - node.height! / 2 },
layouted: true,
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { NodeRun, UserTaskNode } from 'littlehorse-client/proto'
import { NodeType } from '../../NodeTypes/extractNodes'
import {
ExternalEventDefDetail,
SleepDefDetail,
StartThreadDefDetail,
TaskDefDetail,
UserTaskDefDetail,
WaitForThreadDefDetail,
WorkflowEventDefDetail,
} from './'
import { FC } from 'react'

export type AccordionNode = { nodeRun: NodeRun; userTaskNode?: UserTaskNode }
type AccordionNodes = {
[key in NodeType]: FC<AccordionNode>
}

export const AccordionComponents: AccordionNodes = {
ENTRYPOINT: TaskDefDetail,
EXIT: TaskDefDetail,
EXTERNAL_EVENT: ExternalEventDefDetail,
NOP: TaskDefDetail,
SLEEP: SleepDefDetail,
START_MULTIPLE_THREADS: TaskDefDetail,
START_THREAD: StartThreadDefDetail,
TASK: TaskDefDetail,
THROW_EVENT: WorkflowEventDefDetail,
UNKNOWN_NODE_TYPE: TaskDefDetail,
USER_TASK: UserTaskDefDetail,
WAIT_FOR_THREADS: WaitForThreadDefDetail,
} as const

export type AccordionConentType = keyof typeof AccordionComponents
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React, { FC } from 'react'
import { AccordionComponents } from './AccordionContent'
import { NodeRun, UserTaskNode } from 'littlehorse-client/proto'
import * as AccordionRedux from '@radix-ui/react-accordion'
import { ChevronDownIcon } from 'lucide-react'
import { statusColors } from '../../../wfRun/[...ids]/components/Details'
import { getNodeType } from '../../NodeTypes/extractNodes'

export const AccordionItem: FC<{ node: NodeRun, userTaskNode?: UserTaskNode }> = ({ node, userTaskNode }) => {
const nodeType = getNodeType(node)
const Component = AccordionComponents[nodeType]
return (
<AccordionRedux.Item value={`item-${node.id?.position}`} className="overflow-hidden rounded-lg border">
<AccordionRedux.Header className="w-full">
<AccordionRedux.Trigger className="flex w-full items-center justify-between bg-gray-100 px-4 py-2 text-left hover:bg-gray-200 focus:outline-none">
<div className="mr-2 w-full font-medium">
<div className="flex w-full justify-between">
<div className="flex flex-col">
<div className="flex">
NodeRun Position: &nbsp;
<span className="bold text-blue-500">{node.id?.position}</span>
</div>
</div>
<div className="flex ">
<span className={`ml-2 rounded px-2 ${statusColors[node.status]}`}>{`${node.status}`}</span>
</div>
</div>
</div>
<ChevronDownIcon className="group-radix-state-open:rotate-180 h-5 w-5 transform transition-transform duration-300 ease-in-out" />
</AccordionRedux.Trigger>
</AccordionRedux.Header>
<AccordionRedux.Content className="bg-white px-4 py-2 text-gray-700">
<Component nodeRun={node} userTaskNode={userTaskNode} />
</AccordionRedux.Content>
</AccordionRedux.Item>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { getVariableValue, utcToLocalDateTime } from '@/app/utils'
import { cn } from '@/components/utils'
import { useQuery } from '@tanstack/react-query'
import { ClipboardIcon, RefreshCwIcon } from 'lucide-react'
import { getExternalEvent } from '../../NodeTypes/ExternalEvent/getExternalEvent'
import { AccordionNode } from './AccordionContent'
import { FC } from 'react'

export const ExternalEventDefDetail: FC<AccordionNode> = ({ nodeRun }) => {
const externalEventDefId = nodeRun.externalEvent?.externalEventId?.externalEventDefId
const guid = nodeRun.externalEvent?.externalEventId?.guid
const wfRunId = nodeRun.externalEvent?.externalEventId?.wfRunId?.id
const { data, isLoading } = useQuery({
queryKey: ['externalEvent', wfRunId, externalEventDefId],
queryFn: async () => {
if (!wfRunId) return
if (!externalEventDefId) return
if (!guid) return
const externalEventRun = await getExternalEvent({
wfRunId: {
id: wfRunId,
parentWfRunId: undefined,
},
externalEventDefId,
guid,
})
return externalEventRun
},
})

if (isLoading) {
return (
<div className="flex min-h-[60px] items-center justify-center text-center">
<RefreshCwIcon className="h-8 w-8 animate-spin text-blue-500" />
</div>
)
}

if (!data) return

return (
<>
<div className="mb-2 items-center gap-2">
<div className="mb-2 mt-1 flex ">
<span className="font-bold ">Task Guid :</span> <span>{guid}</span>
<span className="ml-2 mt-1">
<ClipboardIcon
className="h-4 w-4 cursor-pointer fill-transparent stroke-blue-500"
onClick={() => {
navigator.clipboard.writeText(guid ?? '')
}}
/>
</span>
</div>
<div className="mb-2 mt-1 ">
<span className="font-bold">Triggered: </span>
{data.createdAt && <span className="">{utcToLocalDateTime(data.createdAt)}</span>}
</div>
</div>

<div className={cn('flex w-full flex-col overflow-auto rounded p-1', 'bg-zinc-500 text-white')}>
<h3 className="font-bold">Content</h3>
<pre className="overflow-auto">{getVariableValue(data.content)}</pre>
</div>
</>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { FC } from 'react'
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'
import { Modal, NodeRuns } from '../../../context'
import { useModal } from '../../../hooks/useModal'
import { TaskLink } from '../../NodeTypes/Task/TaskDetails'
import { getNodeType } from '../../NodeTypes/extractNodes'
import * as Accordion from '@radix-ui/react-accordion'
import { AccordionItem } from './AccordionItem'

export const NodeRun: FC<Modal> = ({ data }) => {
const { nodeRunsList, taskNode, userTaskNode } = data as NodeRuns
const node = nodeRunsList[0]
const { showModal, setShowModal } = useModal()

return (
<Dialog open={showModal} onOpenChange={open => setShowModal(open)}>
<DialogContent className="flex max-w-5xl flex-col">
<DialogHeader>
<DialogTitle className="mr-8 flex items-center justify-between">
<h2 className="text-lg font-bold">NodeRuns</h2>
{taskNode && <TaskLink taskName={taskNode.taskDefId?.name} />}
</DialogTitle>
</DialogHeader>
<hr />
<div className="flex justify-between">
<div>
<strong>WfRun</strong>: {node.id?.wfRunId?.id}
</div>
<div>
<strong>Node Type</strong>: {getNodeType(node)}
</div>
</div>

<div className="h-full overflow-auto">
<Accordion.Root
className="bg-mauve6 wfull rounded-md shadow-[0_2px_10px] shadow-black/5"
type="single"
defaultValue="item-1"
collapsible
>
{nodeRunsList?.map(nodeRun => <AccordionItem key={`item-${node.id?.position}`} node={nodeRun} userTaskNode={userTaskNode} />)}
</Accordion.Root>
</div>
</DialogContent>
</Dialog>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { utcToLocalDateTime } from '@/app/utils'
import { cn } from '@/components/utils'
import { FC, Fragment } from 'react'
import { AccordionNode } from './AccordionContent'

export const SleepDefDetail: FC<AccordionNode> = ({ nodeRun }) => {
return (
<Fragment>
<div className="mb-2 items-center gap-2">
{nodeRun.arrivalTime && (
<div className="mb-2 mt-1 text-sm font-bold">
Arrival Time : <span className=" pb-2">{utcToLocalDateTime(nodeRun.arrivalTime)}</span>
</div>
)}
{nodeRun.endTime && (
<div className="mb-2 mt-1 text-sm font-bold">
End Time : <span className=" pb-2">{utcToLocalDateTime(nodeRun.endTime)}</span>
</div>
)}
</div>
<div className="mb-2 items-center gap-2">
<div className="mb-2 mt-1 text-sm font-bold">
Matured : <span className="border-2 border-blue-500 p-1">{nodeRun.sleep?.matured?.toString()}</span>
</div>
</div>

<div className={cn('flex w-full flex-col overflow-auto rounded p-1', 'bg-zinc-500 text-white')}>
<h3 className="font-bold">Maturation Time</h3>
{nodeRun.sleep?.maturationTime && (
<pre className="overflow-auto">{utcToLocalDateTime(nodeRun.sleep?.maturationTime)}</pre>
)}
</div>
</Fragment>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { utcToLocalDateTime } from '@/app/utils'
import { FC } from 'react'
import { AccordionNode } from './AccordionContent'

export const StartThreadDefDetail: FC<AccordionNode> = ({ nodeRun }) => {
return (
<div className="mb-2 items-center gap-2">
{nodeRun.arrivalTime && (
<div className="mb-2 mt-1 text-sm font-bold">
Arrival Time : <span className=" pb-2">{utcToLocalDateTime(nodeRun.arrivalTime)}</span>
</div>
)}
{nodeRun.endTime && (
<div className="mb-2 mt-1 text-sm font-bold">
End Time : <span className=" pb-2">{utcToLocalDateTime(nodeRun.endTime)}</span>
</div>
)}
</div>
)
}
Loading

0 comments on commit 649b5b4

Please sign in to comment.