Skip to content

Commit f4f5d68

Browse files
authored
refactor(21032): Add status of terminal transitions to the node (#362)
* refactor(21032): add types of state to the FSM schema * refactor(21032): add end state status to the transition payload * refactor(21032): add success/error handles * refactor(21032): fix the FSM model to add the disconnected (success) transitions * refactor(21032): change handle type based on success/failure of the terminal state * refactor(21032): add terminal status to the metadata of the options * refactor(21032): add end state type to the transition payload * test(21032): fix tests * fix(21032): fix
1 parent 5b0e001 commit f4f5d68

File tree

7 files changed

+81
-14
lines changed

7 files changed

+81
-14
lines changed

hivemq-edge/src/frontend/src/extensions/datahub/api/__generated__/schemas/BehaviorPolicyData.json

Lines changed: 24 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

hivemq-edge/src/frontend/src/extensions/datahub/components/forms/TransitionSelect.spec.cy.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ describe('TransitionSelect', () => {
3838
cy.get('label#transition-label + div').click()
3939

4040
cy.get('div#react-select-transition-listbox').find('[role="option"]').as('optionList')
41-
cy.get('@optionList').should('have.length', 7)
41+
cy.get('@optionList').should('have.length', 8)
4242
cy.get('#react-select-transition-option-0').should('contain.text', 'Mqtt.OnInboundConnect')
4343

4444
cy.checkAccessibility(undefined, {

hivemq-edge/src/frontend/src/extensions/datahub/components/forms/TransitionSelect.tsx

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,12 @@ import {
1111
createFilter,
1212
} from 'chakra-react-select'
1313

14-
import { FiniteStateMachine, FsmTransition } from '@datahub/types.ts'
14+
import { FiniteStateMachine, FsmState, FsmTransition } from '@datahub/types.ts'
1515
import { useTranslation } from 'react-i18next'
1616

1717
interface FsmTransitionWithId extends FsmTransition {
1818
id: string
19+
endStateType?: FsmState.Type
1920
}
2021

2122
const SingleValue = (props: SingleValueProps<FsmTransitionWithId>) => {
@@ -38,6 +39,8 @@ const Option = (props: OptionProps<FsmTransitionWithId>) => {
3839
if (__isNew__) {
3940
return <chakraComponents.Option {...props}>{props.children}</chakraComponents.Option>
4041
}
42+
const isTerminal =
43+
props.data.endStateType === FsmState.Type.FAILED || props.data.endStateType === FsmState.Type.SUCCESS
4144

4245
return (
4346
<chakraComponents.Option {...rest} isSelected={selectedTransition && selectedTransition.id === props.data.id}>
@@ -56,6 +59,7 @@ const Option = (props: OptionProps<FsmTransitionWithId>) => {
5659
</Text>
5760
<Text fontSize="sm" whiteSpace="nowrap">
5861
{t('workspace.transition.select.toState', { state: props.data.toState })}
62+
{isTerminal && ` [${props.data.endStateType}]`}
5963
</Text>
6064
</VStack>
6165
</HStack>
@@ -79,10 +83,16 @@ export const TransitionSelect = (props: WidgetProps) => {
7983
const metadata = props.options.metadata as FiniteStateMachine | null
8084
if (!metadata) return []
8185

82-
const opts = metadata.transitions.map<FsmTransitionWithId>((transition) => ({
83-
...transition,
84-
id: `${transition.event}-${transition.fromState}-${transition.toState}`,
85-
}))
86+
const states = metadata.states
87+
const opts = metadata.transitions.map<FsmTransitionWithId>((transition) => {
88+
const endState = states.find((state) => state.name === transition.toState)
89+
90+
return {
91+
...transition,
92+
id: `${transition.event}-${transition.fromState}-${transition.toState}-${endState?.type}`,
93+
endStateType: endState?.type,
94+
}
95+
})
8696
opts.push({
8797
id: 'Event.OnAny-Any.*-Any.*',
8898
event: 'Event.OnAny',

hivemq-edge/src/frontend/src/extensions/datahub/designer/transition/TransitionNode.tsx

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,22 @@
1-
import { FC } from 'react'
1+
import { FC, useMemo } from 'react'
22
import { HStack, Text, VStack } from '@chakra-ui/react'
33
import { useTranslation } from 'react-i18next'
44
import { NodeProps, Position } from 'reactflow'
55

6-
import { DataHubNodeType, TransitionData } from '@datahub/types.ts'
6+
import { DataHubNodeType, FsmState, TransitionData } from '@datahub/types.ts'
77
import { CustomHandle, NodeWrapper } from '@datahub/components/nodes'
88
import { NodeIcon, NodeParams } from '@datahub/components/helpers'
99

1010
export const TransitionNode: FC<NodeProps<TransitionData>> = (props) => {
1111
const { t } = useTranslation('datahub')
1212
const { data, id, type } = props
1313

14+
const className = useMemo(() => {
15+
if (data.type === FsmState.Type.SUCCESS) return TransitionData.Handle.ON_SUCCESS
16+
if (data.type === FsmState.Type.FAILED) return TransitionData.Handle.ON_ERROR
17+
return undefined
18+
}, [data.type])
19+
1420
return (
1521
<>
1622
<NodeWrapper route={`node/${DataHubNodeType.TRANSITION}/${id}`} {...props}>
@@ -23,7 +29,13 @@ export const TransitionNode: FC<NodeProps<TransitionData>> = (props) => {
2329
</HStack>
2430
</NodeWrapper>
2531
<CustomHandle type="target" position={Position.Left} id={TransitionData.Handle.BEHAVIOR_POLICY} />
26-
<CustomHandle type="source" id={TransitionData.Handle.OPERATION} position={Position.Right} isConnectable={1} />
32+
<CustomHandle
33+
type="source"
34+
id={TransitionData.Handle.OPERATION}
35+
position={Position.Right}
36+
isConnectable={1}
37+
className={className}
38+
/>
2739
</>
2840
)
2941
}

hivemq-edge/src/frontend/src/extensions/datahub/designer/transition/TransitionPanel.spec.cy.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ describe('TransitionPanel', () => {
5353
cy.get('label#root_event-label + div').click()
5454

5555
cy.get('div#react-select-root_event-listbox').find('[role="option"]').as('optionList')
56-
cy.get('@optionList').should('have.length', 7)
56+
cy.get('@optionList').should('have.length', 8)
5757
cy.get('@optionList').eq(0).should('contain.text', 'Mqtt.OnInboundConnect')
5858
})
5959

hivemq-edge/src/frontend/src/extensions/datahub/designer/transition/TransitionPanel.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
BehaviorPolicyData,
88
DataHubNodeType,
99
FiniteStateMachineSchema,
10+
FsmState,
1011
PanelProps,
1112
StateType,
1213
TransitionData,
@@ -53,12 +54,12 @@ export const TransitionPanel: FC<PanelProps> = ({ selectedNode, onFormSubmit })
5354
return null
5455
}
5556

56-
const { event, from, to } = adapterNode.data
57+
const { event, from, to, type } = adapterNode.data
5758
const tempData: TransitionData = {
5859
...adapterNode.data,
5960
model: parentPolicy ? parentPolicy.data.model : undefined,
6061
// @ts-ignore
61-
event: `${event || ''}-${from || ''}-${to || ''}`,
62+
event: `${event || ''}-${from || ''}-${to || ''}-${type || ''}`,
6263
}
6364
return tempData
6465
}, [nodes, parentPolicy, selectedNode])
@@ -90,12 +91,18 @@ export const TransitionPanel: FC<PanelProps> = ({ selectedNode, onFormSubmit })
9091
if (formData) {
9192
const { event: originalEvent } = formData
9293
if (originalEvent) {
93-
const [event, from, to] = originalEvent.split('-') as [TransitionType, StateType, StateType]
94+
const [event, from, to, type] = originalEvent.split('-') as [
95+
TransitionType,
96+
StateType,
97+
StateType,
98+
FsmState.Type | undefined
99+
]
94100
initData.formData = {
95101
...initData.formData,
96102
event,
97103
from,
98104
to,
105+
type: type,
99106
}
100107
}
101108
}

hivemq-edge/src/frontend/src/extensions/datahub/types.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,7 @@ export interface TransitionData extends DataHubNodeData {
286286
event?: TransitionType
287287
from?: StateType
288288
to?: StateType
289+
type?: FsmState.Type
289290
core?: BehaviorPolicyOnTransition
290291
}
291292

@@ -294,14 +295,27 @@ export namespace TransitionData {
294295
export enum Handle {
295296
BEHAVIOR_POLICY = 'target',
296297
OPERATION = 'source',
298+
ON_SUCCESS = 'onSuccess',
299+
ON_ERROR = 'onError',
297300
}
298301
}
299302

300303
export interface FsmState {
301304
name: string
302305
description: string
303-
type: string
306+
type: FsmState.Type
304307
}
308+
309+
// eslint-disable-next-line @typescript-eslint/no-namespace
310+
export namespace FsmState {
311+
export enum Type {
312+
INITIAL = 'INITIAL',
313+
INTERMEDIATE = 'INTERMEDIATE',
314+
SUCCESS = 'SUCCESS',
315+
FAILED = 'FAILED',
316+
}
317+
}
318+
305319
export interface FsmTransition {
306320
fromState: string
307321
toState: string

0 commit comments

Comments
 (0)