Skip to content

Commit 3491c31

Browse files
authored
Merge pull request #159 from SdgSoft/main
Added Switch Node to the Flow group, implement Object Property Hide Editor and restict type dropdown with list of type options
2 parents 239eaa8 + 0f4f51d commit 3491c31

33 files changed

Lines changed: 439 additions & 73 deletions

File tree

apps/chaingraph-frontend/src/components/flow/nodes/ChaingraphNode/ChaingraphNode.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import {
3131
removeFieldObjectPort,
3232
requestUpdatePortUI,
3333
requestUpdatePortValue,
34+
updateItemConfigArrayPort,
3435
} from '@/store/ports'
3536
import { NodeResizeControl, ResizeControlVariant } from '@xyflow/react'
3637
import { useUnit } from 'effector-react'
@@ -75,6 +76,7 @@ function ChaingraphNodeComponent({
7576
removeBreakpoint,
7677
requestUpdatePortValue,
7778
requestUpdatePortUI,
79+
updateItemConfigArrayPort,
7880
appendElementArrayPort,
7981
removeElementArrayPort,
8082
addFieldObjectPort,
@@ -190,6 +192,11 @@ function ChaingraphNodeComponent({
190192
portId: params.portId,
191193
key: params.key,
192194
}),
195+
updateItemConfigArrayPort: params => dispatch.updateItemConfigArrayPort({
196+
nodeId: params.nodeId,
197+
portId: params.portId,
198+
itemConfig: params.itemConfig,
199+
}),
193200
appendElementArrayPort: params => dispatch.appendElementArrayPort({
194201
nodeId: params.nodeId,
195202
portId: params.portId,

apps/chaingraph-frontend/src/components/flow/nodes/ChaingraphNode/SchemaEditor/ArrayItemSchemaEditor.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,11 @@ export function ArrayItemSchemaEditor({
105105
</TabsList>
106106
</div>
107107

108-
<TabsContent value="visual" className="flex-1 flex flex-col">
109-
<ArrayItemEditorContent onSave={onSave} />
110-
</TabsContent>
108+
{tab === 'visual' && (
109+
<TabsContent value="visual" className="flex-1 flex flex-col">
110+
<ArrayItemEditorContent onSave={onSave} />
111+
</TabsContent>
112+
)}
111113

112114
<TabsContent value="json" className="flex-1 p-6">
113115
<JsonEditor onSave={onSave} />
@@ -238,11 +240,11 @@ function ArrayItemEditorContent({ onSave }: { onSave: (config: IPortConfig) => v
238240

239241
return (
240242
<>
241-
<ScrollArea className="flex-1">
243+
<ScrollArea type="scroll" className="flex-1">
242244
<div className="p-6">
243245
<div className="mb-4">
244246
<h3 className="text-lg font-medium">
245-
Array Item Type:
247+
Array Item Type:&nbsp;
246248
<span className="text-primary">{itemConfig.type}</span>
247249
</h3>
248250
<p className="text-sm text-muted-foreground mb-4">

apps/chaingraph-frontend/src/components/flow/nodes/ChaingraphNode/ports/ArrayPort/AddElementPopover.tsx

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* As of the Change Date specified in that file, in accordance with the Business Source License, use of this software will be governed by the Apache License, version 2.0.
77
*/
88

9-
import type { ArrayPort, IPortConfig, PortType } from '@badaitech/chaingraph-types'
9+
import type { ArrayPortConfig, IPort, IPortConfig, PortType } from '@badaitech/chaingraph-types'
1010
import { Button } from '@/components/ui/button'
1111
import {
1212
DropdownMenu,
@@ -26,9 +26,9 @@ interface Data {
2626
}
2727

2828
interface Props {
29-
port: ArrayPort
29+
port: IPort<ArrayPortConfig>
3030
onClose: () => void
31-
onSubmit: (data: Data) => void
31+
onSubmit: (newItemConfig: IPortConfig) => void
3232
}
3333

3434
const typeConfigMap: Record<PortType, IPortConfig> = {
@@ -111,18 +111,19 @@ const typeConfigMap: Record<PortType, IPortConfig> = {
111111
export function AddElementPopover(props: Props) {
112112
const { onClose, onSubmit, port } = props
113113

114+
const itemType = port.getConfig().itemConfig.type
115+
const dropDownValues = (itemType !== 'any' ? [itemType] : (port.getConfig().ui?.allowedTypes || PORT_TYPES)).filter(portType => portType !== 'any') // && portType !== 'secret')))
116+
114117
const [type, setType] = useState<PortType | undefined>(
115-
port.getConfig().itemConfig?.type || 'any',
118+
dropDownValues.at(0) || itemType,
116119
)
117120
const [isDropdownOpen, setIsDropdownOpen] = useState(false)
118121

119122
const handleSubmit = () => {
120123
if (!type)
121124
return
122125

123-
onSubmit({
124-
config: typeConfigMap[type],
125-
})
126+
onSubmit(typeConfigMap[type])
126127
}
127128

128129
return (
@@ -157,8 +158,7 @@ export function AddElementPopover(props: Props) {
157158
</DropdownMenuTrigger>
158159

159160
<DropdownMenuContent align="start">
160-
{PORT_TYPES
161-
.filter(portType => portType !== 'any')// && portType !== 'secret')
161+
{dropDownValues
162162
.map(portType => (
163163
<DropdownMenuItem
164164
key={portType}

apps/chaingraph-frontend/src/components/flow/nodes/ChaingraphNode/ports/ArrayPort/ArrayPort.tsx

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import type {
1111
} from '@/components/flow/nodes/ChaingraphNode/ports/context/PortContext'
1212
import type {
1313
ArrayPortConfig,
14-
ArrayPort as ArrayPortType,
1514
INode,
1615
IPort,
1716
IPortConfig,
@@ -82,6 +81,7 @@ export function ArrayPort({ node, port, context }: ArrayPortProps) {
8281
const [isSchemaEditorOpen, setIsSchemaEditorOpen] = useState(false)
8382
const {
8483
updatePortUI,
84+
updateItemConfigArrayPort,
8585
appendElementArrayPort,
8686
removeElementArrayPort,
8787
updatePortValue,
@@ -95,6 +95,15 @@ export function ArrayPort({ node, port, context }: ArrayPortProps) {
9595
const ui = config.ui
9696
const executionID = useExecutionID()
9797

98+
// Memoize child ports to prevent recalculation
99+
const childPorts = useMemo(() => {
100+
return Array.from(node.ports.values())
101+
.filter(p => p.getConfig().parentId === config.id)
102+
}, [node.ports, config.id])
103+
104+
// Use firstport config as itemconfig otherwise, arrayports itemConfig
105+
const newItemConfig = useMemo(() => childPorts.length > 0 ? childPorts[0].getConfig() : config.itemConfig, [childPorts, config.itemConfig])
106+
98107
// Memoize edges
99108
const connectedEdges = useMemo(() => {
100109
return getEdgesForPort(port.id)
@@ -108,21 +117,38 @@ export function ArrayPort({ node, port, context }: ArrayPortProps) {
108117

109118
// Memoize callback functions
110119
const handleAddElement = useCallback(() => {
111-
setIsAddPropOpen(true)
112-
}, [])
120+
// if type is not any you want immediately add element instead of choose type
121+
if (newItemConfig.type === 'any') {
122+
setIsAddPropOpen(true)
123+
} else {
124+
// if type is not any you want immediately add element instead of choose type
125+
appendElementArrayPort({
126+
nodeId: node.id,
127+
portId: port.id,
128+
value: newItemConfig.defaultValue,
129+
})
130+
}
131+
}, [newItemConfig, appendElementArrayPort, node.id, port.id])
113132

114133
const handleClosePopover = useCallback(() => {
115134
setIsAddPropOpen(false)
116135
}, [])
117136

118-
const handleSubmitPopover = useCallback(() => {
137+
const handleSubmitPopover = useCallback((newItemConfig: IPortConfig) => {
138+
// Update array ports itemConfig
139+
updateItemConfigArrayPort({
140+
nodeId: node.id,
141+
portId: port.id,
142+
itemConfig: newItemConfig,
143+
})
144+
// Add new array element with the choosen type
119145
appendElementArrayPort({
120146
nodeId: node.id,
121147
portId: port.id,
122-
value: config.itemConfig.defaultValue,
148+
value: newItemConfig.defaultValue,
123149
})
124150
setIsAddPropOpen(false)
125-
}, [node.id, port.id, config.itemConfig.defaultValue, appendElementArrayPort])
151+
}, [node.id, port.id, appendElementArrayPort, updateItemConfigArrayPort])
126152

127153
const handleToggleCollapsible = useCallback(() => {
128154
updatePortUI({
@@ -184,13 +210,7 @@ export function ArrayPort({ node, port, context }: ArrayPortProps) {
184210
setIsSchemaEditorOpen(false)
185211
}, [node.id, port, config.ui, updatePortUI, updatePortValue])
186212

187-
// Memoize child ports to prevent recalculation
188-
const childPorts = useMemo(() => {
189-
return Array.from(node.ports.values())
190-
.filter(p => p.getConfig().parentId === config.id)
191-
}, [node.ports, config.id])
192-
193-
if (ui?.hide)
213+
if (ui?.hidden)
194214
return null
195215

196216
return (
@@ -296,7 +316,7 @@ export function ArrayPort({ node, port, context }: ArrayPortProps) {
296316
</PopoverTrigger>
297317
{isAddPropOpen && (
298318
<AddElementPopover
299-
port={port as ArrayPortType}
319+
port={port}
300320
onClose={handleClosePopover}
301321
onSubmit={handleSubmitPopover}
302322
/>

apps/chaingraph-frontend/src/components/flow/nodes/ChaingraphNode/ports/ArrayPort/ObjectSchemaEditor.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,15 @@ export function ObjectSchemaEditor({ initialSchema, onChange }: ObjectSchemaEdit
146146
setVirtualNode(virtualNode.clone())
147147
},
148148

149+
updateItemConfigArrayPort: (params) => {
150+
const port = virtualNode.getPort(params.portId)
151+
if (!port) {
152+
return
153+
}
154+
155+
virtualNode.updateArrayItemConfig(port)
156+
setVirtualNode(virtualNode.clone())
157+
},
149158
appendElementArrayPort: (params) => {
150159
const port = virtualNode.getPort(params.portId)
151160
if (!port) {

apps/chaingraph-frontend/src/components/flow/nodes/ChaingraphNode/ports/ArrayPort/PortHeader.tsx

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -64,17 +64,16 @@ export function PortHeader({
6464
{title}
6565
</PortTitle>
6666
</button>
67-
</div>
68-
69-
{rightElement && (
70-
<div className={cn(
71-
'flex',
72-
isOutput ? 'justify-end' : 'justify-start',
67+
{rightElement && (
68+
<div className={cn(
69+
'flex',
70+
isOutput ? 'justify-end' : 'justify-start',
71+
)}
72+
>
73+
{rightElement}
74+
</div>
7375
)}
74-
>
75-
{rightElement}
76-
</div>
77-
)}
76+
</div>
7877
</div>
7978
)
8079
}

apps/chaingraph-frontend/src/components/flow/nodes/ChaingraphNode/ports/ObjectPort/ObjectPort.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ export function ObjectPort({ node, port, context }: ObjectPortProps) {
223223
onClose={handleClosePopover}
224224
onSubmit={handleSubmitPopover}
225225
nextOrder={childPorts.length + 1}
226+
port={port}
226227
/>
227228
)}
228229
</Popover>

apps/chaingraph-frontend/src/components/flow/nodes/ChaingraphNode/ports/ObjectPort/components/AddPropPopover.tsx

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* As of the Change Date specified in that file, in accordance with the Business Source License, use of this software will be governed by the Apache License, version 2.0.
77
*/
88

9-
import type { IPortConfig, PortType } from '@badaitech/chaingraph-types'
9+
import type { IPort, IPortConfig, ObjectPortConfig, PortType } from '@badaitech/chaingraph-types'
1010
import { Button } from '@/components/ui/button'
1111
import {
1212
DropdownMenu,
@@ -29,6 +29,7 @@ interface Props {
2929
onClose: () => void
3030
onSubmit: (data: Data) => void
3131
nextOrder?: number
32+
port: IPort<ObjectPortConfig>
3233
}
3334

3435
const typeConfigMap: Record<PortType, IPortConfig> = {
@@ -88,6 +89,7 @@ const typeConfigMap: Record<PortType, IPortConfig> = {
8889
defaultValue: [],
8990
ui: {
9091
hideEditor: false,
92+
allowedTypes: ['string', 'number', 'boolean'],
9193
},
9294
isMutable: true,
9395
},
@@ -109,10 +111,16 @@ const typeConfigMap: Record<PortType, IPortConfig> = {
109111
}
110112

111113
export function AddPropPopover(props: Props) {
112-
const { onClose, onSubmit } = props
113-
114+
const { onClose, onSubmit, port } = props
114115
const [key, setKey] = useState('')
115-
const [type, setType] = useState<PortType | undefined>('string')
116+
117+
// use all porttypes if allowedTypes undefined and filter stream ans any out
118+
const dropDownValues = (port.getConfig().ui?.allowedTypes || PORT_TYPES).filter(t => t !== 'stream' && t !== 'any')
119+
120+
const [type, setType] = useState<PortType | undefined>(
121+
// use as initial value first enumvalue if type is any
122+
dropDownValues.at(0),
123+
)
116124
const [isDropdownOpen, setIsDropdownOpen] = useState(false)
117125

118126
const handleSubmit = () => {
@@ -163,8 +171,7 @@ export function AddPropPopover(props: Props) {
163171
</DropdownMenuTrigger>
164172

165173
<DropdownMenuContent>
166-
{PORT_TYPES
167-
.filter(t => t !== 'stream' && t !== 'any')
174+
{dropDownValues
168175
.map(portType => (
169176
<DropdownMenuItem
170177
key={portType}

apps/chaingraph-frontend/src/components/flow/nodes/ChaingraphNode/ports/ObjectPort/components/PortField.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,15 @@ export function PortField({
3939
parentPort.getConfig()?.ui?.keyDeletable
4040
|| parentPort.getConfig()?.ui?.keyDeletable === undefined, [parentPort])
4141

42+
const portConfig = port.getConfig()
43+
port.setConfig({
44+
...portConfig,
45+
ui: {
46+
...portConfig.ui || {},
47+
hideEditor: parentPort.getConfig()?.ui?.hidePropertyEditor || false,
48+
},
49+
})
50+
4251
return (
4352
<div className="py-1 w-full relative">
4453
<div className={cn(

apps/chaingraph-frontend/src/components/flow/nodes/ChaingraphNode/ports/context/PortContext.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ export interface RemoveFieldObjectPortParams {
3737
key: string
3838
}
3939

40+
export interface UpdateItemConfigArrayPortParams {
41+
nodeId: string
42+
portId: string
43+
itemConfig: IPortConfig
44+
}
45+
4046
export interface AddElementArrayPortParams {
4147
nodeId: string
4248
portId: string
@@ -57,6 +63,7 @@ export interface PortContextValue {
5763
addFieldObjectPort: (params: AddFieldObjectPortParams) => void
5864
removeFieldObjectPort: (params: RemoveFieldObjectPortParams) => void
5965
// Array port callbacks
66+
updateItemConfigArrayPort: (params: UpdateItemConfigArrayPortParams) => void
6067
appendElementArrayPort: (params: AddElementArrayPortParams) => void
6168
removeElementArrayPort: (params: RemoveElementArrayPortParams) => void
6269
// Edge utilities
@@ -69,6 +76,7 @@ const defaultContext: PortContextValue = {
6976
updatePortUI: () => { },
7077
addFieldObjectPort: () => { },
7178
removeFieldObjectPort: () => { },
79+
updateItemConfigArrayPort: () => { },
7280
appendElementArrayPort: () => { },
7381
removeElementArrayPort: () => { },
7482
getEdgesForPort: () => [],

0 commit comments

Comments
 (0)