Skip to content

Commit

Permalink
pipeline-graph-v3
Browse files Browse the repository at this point in the history
  • Loading branch information
srdjan-harness committed Dec 10, 2024
1 parent ca7a1cc commit 38bb051
Show file tree
Hide file tree
Showing 85 changed files with 4,591 additions and 305 deletions.
2 changes: 1 addition & 1 deletion apps/gitness/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"@harnessio/code-service-client": "3.2.1-beta.1",
"@harnessio/forms": "workspace:*",
"@harnessio/ui": "workspace:*",
"@harnessio/unified-pipeline": "workspace:*",
"@harnessio/pipeline-graph": "workspace:*",
"@harnessio/views": "workspace:*",
"@harnessio/yaml-editor": "workspace:*",
"@hookform/resolvers": "^3.6.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export function CanvasButton(props: React.PropsWithChildren<{ onClick: () => void }>) {
const { children, onClick } = props

return (
<div
role="button"
tabIndex={0}
onClick={onClick}
className="flex size-8 items-center justify-center border bg-muted text-primary"
>
{children}
</div>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { useCanvasContext } from '@harnessio/pipeline-graph'

import { CanvasButton } from './canvas-button'

export function CanvasControls() {
const { increase, decrease, fit } = useCanvasContext()

return (
<div className="absolute bottom-3 left-3 flex flex-col gap-y-2">
<CanvasButton onClick={() => increase()}>+</CanvasButton>
<CanvasButton onClick={() => decrease()}>-</CanvasButton>
<CanvasButton onClick={() => fit()}>
<div className="size-3 border border-primary"></div>
</CanvasButton>
</div>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export enum ContentNodeTypes {
start = 'start',
end = 'end',
step = 'step',
approval = 'approval',
parallel = 'parallel',
serial = 'serial',
stage = 'stage',
form = 'form'
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { LeafNodeInternalType } from '@harnessio/pipeline-graph'

export interface EndNodeDataType {}

export function EndNode(_props: { node: LeafNodeInternalType<EndNodeDataType> }) {
return (
<div className="flex size-full items-center justify-center rounded-full border border-borders-6 bg-primary-foreground">
{/* TODO: replace with icon */}
<div className="size-2.5 bg-success"></div>
</div>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { ParallelNodeInternalType } from '@harnessio/pipeline-graph'

import { CommonNodeDataType } from '../types/nodes'

export interface ParallelGroupContentNodeDataType extends CommonNodeDataType {
icon?: React.ReactElement
}

export function ParallelGroupContentNode(props: {
node: ParallelNodeInternalType<ParallelGroupContentNodeDataType>
children: React.ReactElement
}) {
const { node, children } = props
const data = node.data as ParallelGroupContentNodeDataType

return (
<>
<div className="absolute inset-0 -z-10 rounded-xl border border-dashed border-borders-6"></div>
<div className="absolute inset-0 flex h-9 items-center">
<div title={data.name} className="m-3 h-9 cursor-default truncate pl-8 pt-2.5 text-primary-muted">
{data.name}
</div>
</div>
{children}
</>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { SerialNodeInternalType } from '@harnessio/pipeline-graph'

import { CommonNodeDataType } from '../types/nodes'

export interface SerialGroupContentNodeDataType extends CommonNodeDataType {
icon?: React.ReactElement
}

export function SerialGroupContentNode(props: {
node: SerialNodeInternalType<SerialGroupContentNodeDataType>
children: React.ReactElement
}) {
const { node, children } = props
const data = node.data as SerialGroupContentNodeDataType

return (
<>
<div className="absolute inset-0 -z-10 rounded-xl border border-dashed border-borders-6 bg-primary-foreground/30"></div>
<div className="absolute inset-0 flex h-9 items-center">
<div title={data.name} className="m-3 h-9 cursor-default truncate pl-8 pt-2.5 text-primary-muted">
{data.name}
</div>
</div>
{children}
</>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { Tooltip, TooltipContent, TooltipTrigger } from '@harnessio/canary'
import { SerialNodeInternalType } from '@harnessio/pipeline-graph'

import { CommonNodeDataType } from '../types/nodes'

export interface StageNodeContentType extends CommonNodeDataType {
icon?: React.ReactElement
}

export function SerialGroupNodeContent(props: {
node: SerialNodeInternalType<StageNodeContentType>
children: React.ReactElement
}) {
const { node, children } = props
const data = node.data as StageNodeContentType

return (
<>
<div className="absolute inset-0 -z-10 border border-borders-6" />
<div className="absolute inset-0 flex h-9 items-center bg-primary-foreground/50">
<Tooltip>
<TooltipTrigger asChild>
<div className="inset-0 m-3 h-9 cursor-default truncate pl-8 pt-2.5 text-primary-muted">{data.name}</div>
</TooltipTrigger>
<TooltipContent>{data.name}</TooltipContent>
</Tooltip>
</div>
{children}
</>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Icon } from '@harnessio/canary'
import { LeafNodeInternalType } from '@harnessio/pipeline-graph'

export interface StartNodeDataType {}

export function StartNode(_props: { node: LeafNodeInternalType<StartNodeDataType> }) {
return (
<div className="flex size-full items-center justify-center rounded-full border border-borders-6 bg-primary-foreground">
<Icon name="play" className="text-success" />
</div>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import cx from 'clsx'

import { LeafNodeInternalType } from '@harnessio/pipeline-graph'

import { CommonNodeDataType } from '../types/nodes'

export interface StepNodeDataType extends CommonNodeDataType {
icon?: React.ReactElement
state?: 'success' | 'loading'
selected?: boolean
}

export function StepNode(props: { node: LeafNodeInternalType<StepNodeDataType> }) {
const { node } = props
const data = node.data as StepNodeDataType

return (
<div
className={cx('-z-10 box-border size-full rounded-xl border bg-primary-foreground', {
'border-borders-3': data.selected,
'border-borders-6': !data.selected
})}
>
<div>{data?.icon}</div>
<div title={data.name} className="m-2 line-clamp-2 cursor-default text-primary">
{data.name}
</div>
</div>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface CommonNodeDataType {
yamlPath: string
name: string
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export const getIsRunStep = (step: Record<string, any>) => Object.hasOwn(step, 'run')

export const getIsRunTestStep = (step: Record<string, any>) => Object.hasOwn(step, 'run-test')

export const getIsBackgroundStep = (step: Record<string, any>) => Object.hasOwn(step, 'background')

export const getIsActionStep = (step: Record<string, any>) => Object.hasOwn(step, 'action')

export const getIsTemplateStep = (step: Record<string, any>) => Object.hasOwn(step, 'template')
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { IconProps } from '@harnessio/canary'

import {
getIsActionStep,
getIsBackgroundStep,
getIsRunStep,
getIsRunTestStep,
getIsTemplateStep
} from './common-step-utils'

export const getIconBasedOnStep = (step: any): IconProps['name'] => {
if (getIsRunStep(step)) return 'run'

if (getIsRunTestStep(step)) return 'run-test'

if (getIsBackgroundStep(step)) return 'cog-6'

if (getIsActionStep(step)) return 'github-actions'

if (getIsTemplateStep(step)) return 'harness-plugin'

/**
* Yet to add Bitrise plugins,
* Request backend to add a property to identify bitrise-plugin
*/

return 'harness'
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { get } from 'lodash-es'

import {
getIsActionStep,
getIsBackgroundStep,
getIsRunStep,
getIsRunTestStep,
getIsTemplateStep
} from './common-step-utils'

const getNameOrScriptText = (stepData: string | Record<'script', string>, defaultString: string): string => {
const isStepHasString = typeof stepData === 'string'

return isStepHasString ? stepData : get(stepData, 'script', defaultString)
}

export const getNameBasedOnStep = (step: any, stepIndex: number): string => {
if (step.name) return step.name

let displayName = `Step ${stepIndex}`
// Run
if (getIsRunStep(step)) {
displayName = getNameOrScriptText(step.run, 'Run')
}
// Run test
else if (getIsRunTestStep(step)) {
displayName = getNameOrScriptText(step?.['run-test'], 'Run Test')
}
// Background
else if (getIsBackgroundStep(step)) {
displayName = getNameOrScriptText(step?.background, 'Background')
}
// Action
else if (getIsActionStep(step)) {
displayName = get(step?.action, 'uses', 'GitHub Action')
}
// Template
else if (getIsTemplateStep(step)) {
displayName = get(step?.template, 'uses', 'Harness Template')
}

return displayName.split('\n')[0]
}
Loading

0 comments on commit 38bb051

Please sign in to comment.