Skip to content

Commit 3a2b0cc

Browse files
authored
Merge pull request #219 from code0-tech/feat/#200
Rework JSON input, adding generic and sub flow input
2 parents 27cbc72 + 01e171b commit 3a2b0cc

13 files changed

Lines changed: 211 additions & 119 deletions

.env.local

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ NEXT_PUBLIC_EDITION=ce
44
SAGITTARIUS_GRAPHQL_URL=http://localhost:3010/graphql
55

66
NEXT_PUBLIC_SCULPTOR_VERSION=0.0.0
7-
NEXT_PUBLIC_PICTOR_VERSION=0.7.0
7+
NEXT_PUBLIC_PICTOR_VERSION=0.7.2
88
NEXT_PUBLIC_ALLOWED_REDIRECT_DOMAINS=*.code0.tech,*.codezero.build
99

1010
NEXT_PUBLIC_OTEL_SERVICE_NAME=#"sculptor-client"

package-lock.json

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

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"dependencies": {
1717
"@apollo/client": "^4.0.9",
1818
"@code0-tech/pictor": "^0.7.2",
19-
"@code0-tech/triangulum": "^0.14.3",
19+
"@code0-tech/triangulum": "^0.14.6",
2020
"@codemirror/lang-javascript": "^6.2.5",
2121
"@codemirror/lint": "^6.9.5",
2222
"@opentelemetry/api": "^1.9.1",

src/packages/ce/src/datatype/components/inputs/DataTypeInputComponent.tsx

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,13 @@ import {DataTypeBooleanInputComponent} from "@edition/datatype/components/inputs
66
import {DataTypeSelectInputComponent} from "@edition/datatype/components/inputs/select/DataTypeSelectInputComponent";
77
import {InputWrapperProps} from "@code0-tech/pictor/dist/components/form/InputWrapper";
88
import {DataTypeNumberInputComponent} from "@edition/datatype/components/inputs/number/DataTypeNumberInputComponent";
9+
import {DataTypeJSONInputComponent} from "@edition/datatype/components/inputs/json/DataTypeJSONInputComponent";
10+
import {DataTypeGenericInputComponent} from "@edition/datatype/components/inputs/generic/DataTypeGenericInputComponent";
11+
import {
12+
DataTypeSubFlowInputComponent
13+
} from "@edition/datatype/components/inputs/sub-flow/DataTypeSubFlowInputComponent";
914

10-
export interface DataTypeInputComponentProps extends Omit<InputWrapperProps<NodeParameterValue | NodeFunction>, "wrapperComponent" | "onChange"> {
15+
export interface DataTypeInputComponentProps extends Omit<InputWrapperProps<NodeParameterValue | NodeFunction>, "onChange"> {
1116
schema: NodeSchema
1217
clearable?: boolean
1318
onChange?: (value: ReferenceValue | LiteralValue | NodeFunction | undefined) => void
@@ -20,8 +25,9 @@ export const DataTypeInputComponent: React.FC<DataTypeInputComponentProps> = (pr
2025
const {schema, ...rest} = props
2126

2227
const suggestions = schema?.schema?.suggestions as (NodeFunction | ReferenceValue | LiteralValue)[]
28+
const inputName = schema?.schema?.input === "generic" ? schema.functionSchema.input : schema?.schema?.input
2329

24-
switch (schema?.schema?.input) {
30+
switch (inputName) {
2531
case "boolean":
2632
return <DataTypeBooleanInputComponent
2733
schema={schema}
@@ -38,6 +44,22 @@ export const DataTypeInputComponent: React.FC<DataTypeInputComponentProps> = (pr
3844
schema={schema}
3945
suggestions={suggestions}
4046
{...rest}/>
47+
case "list":
48+
case "data":
49+
return <DataTypeJSONInputComponent
50+
schema={schema}
51+
suggestions={suggestions}
52+
{...rest}/>
53+
case "generic":
54+
return <DataTypeGenericInputComponent
55+
schema={schema}
56+
suggestions={suggestions}
57+
{...rest}/>
58+
case "sub-flow":
59+
return <DataTypeSubFlowInputComponent
60+
schema={schema}
61+
suggestions={suggestions}
62+
{...rest}/>
4163
default:
4264
return <DataTypeTextInputComponent
4365
suggestions={suggestions}

src/packages/ce/src/datatype/components/inputs/DataTypeInputControlsComponent.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,10 @@ export const DataTypeInputControlsComponent: React.FC<DataTypeInputControlsCompo
7272
</MenuContent>
7373
</MenuPortal>
7474
</Menu>
75-
<Button paddingSize={"xxs"} onClick={() => {
75+
<Button paddingSize={"xxs"} onClick={(event) => {
7676
onSelect?.(undefined)
77+
event.stopPropagation()
78+
event.preventDefault()
7779
}}>
7880
<IconX size={13}/>
7981
</Button>

src/packages/ce/src/datatype/components/inputs/DataTypeInputValueComponent.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ export interface DataTypeInputValueComponentProps extends Omit<DataTypeInputComp
1212

1313
export const DataTypeInputValueComponent: React.FC<DataTypeInputValueComponentProps> = (props) => {
1414

15-
const {children, inside = false, initialValue, suggestions, onChange, formValidation} = props
15+
const {children, inside = false, initialValue, suggestions, onChange, formValidation, ...rest} = props
1616

1717
return inside || initialValue?.__typename === "NodeFunction" || initialValue?.__typename === "NodeFunctionIdWrapper" || initialValue?.__typename === "ReferenceValue" ?
1818
<InputWrapper formValidation={{...formValidation, setValue: undefined}} right={
1919
<DataTypeInputControlsComponent suggestions={suggestions} onSelect={onChange}/>
20-
} rightType={"action"}>
20+
} rightType={"action"} {...rest}>
2121
<div style={{alignSelf: "center", flex: "1 1 auto"}}>
2222
{
2323
initialValue?.__typename === "NodeFunction" || initialValue?.__typename === "NodeFunctionIdWrapper" ? (
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import {DataTypeInputComponentProps} from "@edition/datatype/components/inputs/DataTypeInputComponent";
2+
import React from "react";
3+
import {ButtonGroup} from "@code0-tech/pictor/dist/components/button-group/ButtonGroup";
4+
import {Button, InputDescription, InputLabel} from "@code0-tech/pictor";
5+
import {useDebouncedCallback} from "use-debounce";
6+
import {LiteralValue, NodeFunction, ReferenceValue} from "@code0-tech/sagittarius-graphql-types";
7+
8+
export type DataTypeGenericInputComponentProps = DataTypeInputComponentProps
9+
10+
export const DataTypeGenericInputComponent: React.FC<DataTypeGenericInputComponentProps> = (props) => {
11+
12+
const {title, description, onChange, formValidation} = props
13+
14+
const onChangeDebounced = useDebouncedCallback((value: LiteralValue | NodeFunction | ReferenceValue | undefined) => {
15+
formValidation?.setValue?.(value)
16+
onChange?.(value)
17+
}, 200)
18+
19+
return <>
20+
<InputLabel>{title}</InputLabel>
21+
<InputDescription>{description}</InputDescription>
22+
<ButtonGroup color={"secondary"}>
23+
<Button color={"tertiary"} onClick={() => onChangeDebounced({__typename: "LiteralValue", value: 0})}>
24+
Number Value
25+
</Button>
26+
<Button color={"tertiary"} onClick={() => onChangeDebounced({__typename: "LiteralValue", value: false})}>
27+
Boolean Value
28+
</Button>
29+
<Button color={"tertiary"} onClick={() => onChangeDebounced({__typename: "LiteralValue", value: ""})}>
30+
Text Value
31+
</Button>
32+
<Button color={"tertiary"} onClick={() => onChangeDebounced({__typename: "LiteralValue", value: []})}>
33+
List Value
34+
</Button>
35+
<Button color={"tertiary"} onClick={() => onChangeDebounced({__typename: "LiteralValue", value: {}})}>
36+
Data Value
37+
</Button>
38+
</ButtonGroup>
39+
</>
40+
41+
}
Lines changed: 55 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,15 @@
11
import React from "react"
2-
import {IconAlignLeft, IconEdit, IconX} from "@tabler/icons-react"
32
import "../type/DataTypeTypeInputComponent.style.scss"
43
import {DataTypeJSONInputTreeComponent} from "./DataTypeJSONInputTreeComponent";
54
import {DataTypeInputComponentProps} from "../DataTypeInputComponent";
6-
import {LiteralValue, NodeFunction, NodeParameterValue} from "@code0-tech/sagittarius-graphql-types";
7-
import {NodeBadgeComponent} from "../../badges/NodeBadgeComponent";
8-
import {ReferenceBadgeComponent} from "../../badges/ReferenceBadgeComponent";
9-
import {
10-
Button,
11-
Card,
12-
Flex,
13-
InputDescription,
14-
InputLabel,
15-
InputMessage,
16-
Text,
17-
useService,
18-
useStore
19-
} from "@code0-tech/pictor";
20-
import {ButtonGroup} from "@code0-tech/pictor/dist/components/button-group/ButtonGroup";
21-
import {FunctionSuggestionMenuComponent} from "@edition/function/components/suggestion/FunctionSuggestionMenuComponent";
5+
import {LiteralValue, NodeFunction, ReferenceValue} from "@code0-tech/sagittarius-graphql-types";
6+
import {InputDescription, InputLabel, Spacing} from "@code0-tech/pictor";
227
import {
238
DataTypeJSONInputEditDialogComponent
249
} from "@edition/datatype/components/inputs/json/DataTypeJSONInputEditDialogComponent";
25-
import {FlowService} from "@edition/flow/services/Flow.service";
26-
import {useValue} from "@edition/datatype/hooks/DataType.value.hook";
10+
import {DataTypeInputValueComponent} from "@edition/datatype/components/inputs/DataTypeInputValueComponent";
11+
import {useDebouncedCallback} from "use-debounce";
12+
import {DataInput} from "@code0-tech/triangulum/dist/util/schema.util";
2713

2814
export interface EditableJSONEntry {
2915
key: string
@@ -33,21 +19,27 @@ export interface EditableJSONEntry {
3319

3420
export type DataTypeJSONInputComponentProps = DataTypeInputComponentProps
3521

22+
//TODO render fallback value if undefined based on schema
3623
export const DataTypeJSONInputComponent: React.FC<DataTypeJSONInputComponentProps> = (props) => {
3724

25+
const {schema, title, description, suggestions, formValidation, initialValue, onChange} = props
3826

39-
const {schema, title, description, formValidation, onChange} = props
40-
41-
const flowService = useService(FlowService)
42-
const flowStore = useStore(FlowService)
43-
44-
const suggestions = []
4527
const [editDialogOpen, setEditDialogOpen] = React.useState(false)
46-
const [editEntry, setEditEntry] = React.useState<EditableJSONEntry | null>(null)
28+
const [editEntry, setEditEntry] = React.useState<EditableJSONEntry | undefined>(undefined)
4729
const [collapsedState, setCollapsedStateRaw] = React.useState<Record<string, boolean>>({})
4830

31+
const onChangeDebounced = useDebouncedCallback((value: LiteralValue | NodeFunction | ReferenceValue | undefined) => {
32+
formValidation?.setValue?.(value)
33+
onChange?.(value)
34+
}, 200)
4935

50-
const [value, setValue] = React.useState<NodeParameterValue | NodeFunction | null>(null)
36+
const value = React.useMemo(
37+
() => initialValue ?? (schema.functionSchema.input === "list" ? {
38+
__typename: "LiteralValue",
39+
value: []
40+
} as LiteralValue : generateDefaultDataValue(schema.functionSchema as DataInput)),
41+
[initialValue, schema]
42+
)
5143

5244
const setCollapsedState = (path: string[], collapsed: boolean) => {
5345
setCollapsedStateRaw(prev => ({...prev, [path.join(".")]: collapsed}))
@@ -65,65 +57,47 @@ export const DataTypeJSONInputComponent: React.FC<DataTypeJSONInputComponentProp
6557
key={`edit-dialog-${editEntry?.path.join("-")}-${editDialogOpen}`}
6658
open={editDialogOpen}
6759
entry={editEntry}
68-
value={value as any}
60+
value={value as LiteralValue}
6961
onOpenChange={open => setEditDialogOpen(open)}
70-
onObjectChange={v => {
71-
formValidation?.setValue?.(v)
72-
setValue(v ?? null)
73-
// @ts-ignore
74-
onChange?.()
75-
}}
62+
onObjectChange={onChangeDebounced}
7663
/>
7764
)}
7865
<InputLabel>{title}</InputLabel>
7966
<InputDescription>{description}</InputDescription>
80-
<Card color="secondary" paddingSize="xs">
81-
<Flex style={{gap: ".7rem"}} align="center" justify="space-between">
82-
<Flex style={{gap: ".35rem"}} align="center">
83-
<Text>{"Object"}</Text>
84-
</Flex>
85-
<ButtonGroup color={"primary"}>
86-
<FunctionSuggestionMenuComponent onSuggestionSelect={suggestion => {
87-
formValidation?.setValue?.(suggestion.value)
88-
setValue(suggestion.value)
89-
// @ts-ignore
90-
onChange?.()
91-
}}
92-
triggerContent={<Button paddingSize="xxs" variant="filled"
93-
color="secondary"
94-
onClick={() => setEditDialogOpen(true)}>
95-
<IconAlignLeft size={13}/>
96-
</Button>}/>
97-
<Button paddingSize="xxs"
98-
variant="filled"
99-
disabled={value?.__typename != "LiteralValue"}
100-
color="secondary"
101-
onClick={() => setEditDialogOpen(true)}>
102-
<IconEdit size={13}/>
103-
</Button>
104-
<Button paddingSize="xxs" variant="filled" color="secondary">
105-
<IconX size={13}/>
106-
</Button>
107-
</ButtonGroup>
108-
</Flex>
109-
<Card paddingSize="xs" mt={0.7} mb={-0.55} mx={-0.55}>
110-
{value?.__typename === "NodeFunction" || value?.__typename === "NodeFunctionIdWrapper" ? (
111-
<NodeBadgeComponent value={value}/>
112-
) : value?.__typename === "ReferenceValue" ? (
113-
<ReferenceBadgeComponent value={value}/>
114-
) : (
115-
<DataTypeJSONInputTreeComponent
116-
object={value as any}
117-
onEntryClick={handleEntryClick}
118-
collapsedState={collapsedState}
119-
setCollapsedState={setCollapsedState}
120-
/>
121-
)}
122-
</Card>
123-
</Card>
124-
{!formValidation?.valid && formValidation?.notValidMessage && (
125-
<InputMessage>{formValidation.notValidMessage}</InputMessage>
126-
)}
67+
<DataTypeInputValueComponent inside
68+
initialValue={value}
69+
onChange={onChangeDebounced}
70+
suggestions={suggestions}
71+
formValidation={formValidation}>
72+
<DataTypeJSONInputTreeComponent
73+
object={value as LiteralValue}
74+
onEntryClick={handleEntryClick}
75+
collapsedState={collapsedState}
76+
setCollapsedState={setCollapsedState}
77+
/>
78+
<Spacing spacing={"xxs"}/>
79+
</DataTypeInputValueComponent>
12780
</>
12881
)
12982
}
83+
84+
85+
//TODO: only if required
86+
const generateDefaultDataValue = (schema: DataInput): LiteralValue => {
87+
return {
88+
__typename: "LiteralValue",
89+
value: {
90+
...(Object.entries(schema.properties ?? {})?.map(([key, propSchema]) => {
91+
if (!Array.isArray(propSchema)) {
92+
if (propSchema.input === "data") {
93+
return {[key]: generateDefaultDataValue(propSchema).value}
94+
}
95+
if (propSchema.input === "list") {
96+
return {[key]: []}
97+
}
98+
return {[key]: null}
99+
}
100+
}))
101+
}
102+
}
103+
}

0 commit comments

Comments
 (0)