Skip to content

Commit 27cbc72

Browse files
authored
Merge pull request #216 from code0-tech/feat/#198
New select and primitive inputs
2 parents 41f874e + f3c6833 commit 27cbc72

37 files changed

Lines changed: 867 additions & 1010 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.6.0
7+
NEXT_PUBLIC_PICTOR_VERSION=0.7.0
88
NEXT_PUBLIC_ALLOWED_REDIRECT_DOMAINS=*.code0.tech,*.codezero.build
99

1010
NEXT_PUBLIC_OTEL_SERVICE_NAME=#"sculptor-client"

package-lock.json

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

package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
},
1616
"dependencies": {
1717
"@apollo/client": "^4.0.9",
18-
"@code0-tech/pictor": "^0.6.4",
19-
"@code0-tech/triangulum": "^0.13.3",
18+
"@code0-tech/pictor": "^0.7.2",
19+
"@code0-tech/triangulum": "^0.14.3",
2020
"@codemirror/lang-javascript": "^6.2.5",
2121
"@codemirror/lint": "^6.9.5",
2222
"@opentelemetry/api": "^1.9.1",
@@ -32,6 +32,7 @@
3232
"graphql": "^16.12.0",
3333
"graphql-tag": "^2.12.6",
3434
"ldrs": "^1.1.9",
35+
"lodash": "^4.18.1",
3536
"next": "16.2.3",
3637
"prettier": "^3.8.1",
3738
"react": "19.2.5",
@@ -42,6 +43,7 @@
4243
"use-debounce": "^10.1.1"
4344
},
4445
"devDependencies": {
46+
"@types/lodash": "^4.17.24",
4547
"@types/node": "^24.0.0",
4648
"@types/react": "^19",
4749
"@types/react-dom": "^19",

src/app/global.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,8 @@ a {
1818
&:hover {
1919
text-decoration: underline;
2020
}
21+
}
22+
23+
.scroll-area__viewport > div {
24+
display: block !important;
2125
}

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

Lines changed: 30 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,47 @@
1-
import {Flow, NodeFunction} from "@code0-tech/sagittarius-graphql-types";
21
import React from "react";
32
import {DataTypeTextInputComponent} from "./text/DataTypeTextInputComponent";
4-
import {InputProps, useService, useStore} from "@code0-tech/pictor";
5-
import {FlowService} from "@edition/flow/services/Flow.service";
6-
import {DatatypeService} from "@edition/datatype/services/Datatype.service";
7-
import {FunctionService} from "@edition/function/services/Function.service";
8-
import {DataTypeVariant, getTypesFromFunction, getTypeVariant} from "@code0-tech/triangulum";
9-
import {DataTypeJSONInputComponent} from "@edition/datatype/components/inputs/json/DataTypeJSONInputComponent";
10-
11-
export interface DataTypeInputComponentProps extends Omit<InputProps<any | null>, "wrapperComponent" | "type"> {
12-
flowId: Flow['id']
13-
nodeId?: NodeFunction['id'] //TODO if undefined we need to get infos from trigger
14-
parameterIndex: number
3+
import {NodeSchema} from "@code0-tech/triangulum";
4+
import {LiteralValue, NodeFunction, NodeParameterValue, ReferenceValue} from "@code0-tech/sagittarius-graphql-types";
5+
import {DataTypeBooleanInputComponent} from "@edition/datatype/components/inputs/boolean/DataTypeBooleanInputComponent";
6+
import {DataTypeSelectInputComponent} from "@edition/datatype/components/inputs/select/DataTypeSelectInputComponent";
7+
import {InputWrapperProps} from "@code0-tech/pictor/dist/components/form/InputWrapper";
8+
import {DataTypeNumberInputComponent} from "@edition/datatype/components/inputs/number/DataTypeNumberInputComponent";
9+
10+
export interface DataTypeInputComponentProps extends Omit<InputWrapperProps<NodeParameterValue | NodeFunction>, "wrapperComponent" | "onChange"> {
11+
schema: NodeSchema
1512
clearable?: boolean
13+
onChange?: (value: ReferenceValue | LiteralValue | NodeFunction | undefined) => void
14+
suggestions?: (NodeFunction | ReferenceValue | LiteralValue)[]
1615
onClear?: (event: React.MouseEvent<HTMLButtonElement>) => void
1716
}
1817

1918
export const DataTypeInputComponent: React.FC<DataTypeInputComponentProps> = (props) => {
2019

21-
const {flowId, nodeId, parameterIndex, ...rest} = props
22-
23-
const flowService = useService(FlowService)
24-
const flowStore = useStore(FlowService)
25-
const dataTypeStore = useStore(DatatypeService)
26-
const dataTypeService = useService(DatatypeService)
27-
const functionStore = useStore(FunctionService)
28-
const functionService = useService(FunctionService)
29-
30-
const flow = React.useMemo(
31-
() => flowId ? flowService.getById(flowId) : undefined,
32-
[flowStore, flowId]
33-
)
34-
35-
const node = React.useMemo(
36-
() => nodeId && flowId ? flowService.getNodeById(flowId, nodeId) : undefined,
37-
[flowStore, flowId, nodeId]
38-
)
39-
40-
const functionDefinition = React.useMemo(
41-
() => node ? functionService.getById(node?.functionDefinition?.id) : undefined,
42-
[functionStore, node]
43-
)
44-
45-
const types = React.useMemo(
46-
() => nodeId ? getTypesFromFunction(functionDefinition!) : undefined,
47-
[functionDefinition, nodeId]
48-
)
20+
const {schema, ...rest} = props
4921

50-
const dataTypeVariant = React.useMemo(
51-
() => types ? getTypeVariant(types.parameters[parameterIndex], dataTypeService.values())[0].variant : undefined,
52-
[dataTypeStore, types]
53-
)
22+
const suggestions = schema?.schema?.suggestions as (NodeFunction | ReferenceValue | LiteralValue)[]
5423

55-
switch (dataTypeVariant) {
56-
case DataTypeVariant.ARRAY:
57-
case DataTypeVariant.OBJECT:
58-
return <DataTypeJSONInputComponent
59-
flowId={flowId}
60-
nodeId={nodeId}
61-
parameterIndex={parameterIndex}
24+
switch (schema?.schema?.input) {
25+
case "boolean":
26+
return <DataTypeBooleanInputComponent
27+
schema={schema}
28+
suggestions={suggestions}
6229
{...rest}
6330
/>
31+
case "select":
32+
return <DataTypeSelectInputComponent
33+
schema={schema}
34+
suggestions={suggestions}
35+
{...rest}/>
36+
case "number":
37+
return <DataTypeNumberInputComponent
38+
schema={schema}
39+
suggestions={suggestions}
40+
{...rest}/>
6441
default:
6542
return <DataTypeTextInputComponent
66-
flowId={flowId}
67-
nodeId={nodeId}
68-
parameterIndex={parameterIndex}
43+
suggestions={suggestions}
44+
schema={schema}
6945
{...rest}
7046
/>
7147
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import {LiteralValue, NodeFunction, ReferenceValue} from "@code0-tech/sagittarius-graphql-types";
2+
import React from "react";
3+
import {IconVariable, IconX} from "@tabler/icons-react";
4+
import {ReferenceBadgeComponent} from "@edition/datatype/components/badges/ReferenceBadgeComponent";
5+
import {
6+
Button,
7+
ButtonGroup,
8+
Flex,
9+
Menu,
10+
MenuContent,
11+
MenuItem,
12+
MenuPortal,
13+
MenuTrigger,
14+
Text,
15+
Tooltip,
16+
TooltipContent,
17+
TooltipPortal,
18+
TooltipTrigger
19+
} from "@code0-tech/pictor"
20+
21+
export interface DataTypeInputControlsComponentProps {
22+
suggestions?: (NodeFunction | ReferenceValue | LiteralValue)[]
23+
onSelect?: (value: NodeFunction | ReferenceValue | LiteralValue | undefined) => void
24+
}
25+
26+
export const DataTypeInputControlsComponent: React.FC<DataTypeInputControlsComponentProps> = (props) => {
27+
28+
const {suggestions, onSelect} = props
29+
30+
const filteredSuggestions = React.useMemo(() => {
31+
if (!suggestions) return []
32+
return suggestions.filter(suggest => suggest.__typename === "LiteralValue" || suggest.__typename === "ReferenceValue")
33+
}, [suggestions])
34+
35+
return <ButtonGroup color={"primary"}>
36+
<Menu>
37+
<Tooltip>
38+
<TooltipTrigger asChild>
39+
<MenuTrigger asChild disabled={filteredSuggestions.length <= 0}>
40+
<Button paddingSize={"xxs"}>
41+
<IconVariable size={13}/>
42+
</Button>
43+
</MenuTrigger>
44+
</TooltipTrigger>
45+
<TooltipPortal>
46+
<TooltipContent side={"top"} sideOffset={8}>
47+
{filteredSuggestions.length <= 0 ? <Text>
48+
No suggestion available
49+
</Text> : <Text>
50+
Suggestions for this parameter
51+
</Text>}
52+
</TooltipContent>
53+
</TooltipPortal>
54+
</Tooltip>
55+
<MenuPortal>
56+
<MenuContent>
57+
{filteredSuggestions?.map((suggest, index) => {
58+
if (suggest.__typename === "LiteralValue") {
59+
return <MenuItem onSelect={() => onSelect?.(suggest)}>
60+
<Flex style={{gap: "0.35rem"}} align={"center"}>
61+
{(suggest)?.value.toString()}
62+
</Flex>
63+
</MenuItem>
64+
}
65+
66+
if (suggest.__typename === "ReferenceValue") {
67+
return <MenuItem onSelect={() => onSelect?.(suggest)}>
68+
<ReferenceBadgeComponent value={suggest}/>
69+
</MenuItem>
70+
}
71+
})}
72+
</MenuContent>
73+
</MenuPortal>
74+
</Menu>
75+
<Button paddingSize={"xxs"} onClick={() => {
76+
onSelect?.(undefined)
77+
}}>
78+
<IconX size={13}/>
79+
</Button>
80+
</ButtonGroup>
81+
82+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import React from "react";
2+
import {InputWrapper} from "@code0-tech/pictor/dist/components/form/InputWrapper";
3+
import {DataTypeInputComponentProps} from "@edition/datatype/components/inputs/DataTypeInputComponent";
4+
import {DataTypeInputControlsComponent} from "@edition/datatype/components/inputs/DataTypeInputControlsComponent";
5+
import {NodeBadgeComponent} from "@edition/datatype/components/badges/NodeBadgeComponent";
6+
import {ReferenceBadgeComponent} from "@edition/datatype/components/badges/ReferenceBadgeComponent";
7+
8+
export interface DataTypeInputValueComponentProps extends Omit<DataTypeInputComponentProps, 'schema'> {
9+
children?: React.ReactNode
10+
inside?: boolean
11+
}
12+
13+
export const DataTypeInputValueComponent: React.FC<DataTypeInputValueComponentProps> = (props) => {
14+
15+
const {children, inside = false, initialValue, suggestions, onChange, formValidation} = props
16+
17+
return inside || initialValue?.__typename === "NodeFunction" || initialValue?.__typename === "NodeFunctionIdWrapper" || initialValue?.__typename === "ReferenceValue" ?
18+
<InputWrapper formValidation={{...formValidation, setValue: undefined}} right={
19+
<DataTypeInputControlsComponent suggestions={suggestions} onSelect={onChange}/>
20+
} rightType={"action"}>
21+
<div style={{alignSelf: "center", flex: "1 1 auto"}}>
22+
{
23+
initialValue?.__typename === "NodeFunction" || initialValue?.__typename === "NodeFunctionIdWrapper" ? (
24+
<NodeBadgeComponent value={initialValue}/>
25+
) : initialValue?.__typename === "ReferenceValue" ? (
26+
<ReferenceBadgeComponent value={initialValue}/>
27+
) : inside ? children : null
28+
}
29+
</div>
30+
</InputWrapper> : children
31+
32+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import React from "react";
2+
import {DataTypeInputComponentProps} from "@edition/datatype/components/inputs/DataTypeInputComponent";
3+
import {InputDescription, InputLabel, SegmentedControl, SegmentedControlItem} from "@code0-tech/pictor";
4+
import {useDebouncedCallback} from "use-debounce";
5+
import {LiteralValue, NodeFunction, ReferenceValue} from "@code0-tech/sagittarius-graphql-types";
6+
import {DataTypeInputValueComponent} from "@edition/datatype/components/inputs/DataTypeInputValueComponent";
7+
8+
export type DataTypeBooleanInputComponentProps = DataTypeInputComponentProps
9+
10+
export const DataTypeBooleanInputComponent: React.FC<DataTypeBooleanInputComponentProps> = (props) => {
11+
12+
const {suggestions, initialValue, title, description, formValidation, onChange} = props
13+
14+
const onChangeDebounced = useDebouncedCallback((value: string | LiteralValue | NodeFunction | ReferenceValue | undefined) => {
15+
16+
if (typeof value === "string") {
17+
const boolValue: LiteralValue | undefined = value && ["true", "false"].includes(value) ? {
18+
__typename: "LiteralValue",
19+
value: value === "true"
20+
} : undefined
21+
22+
formValidation?.setValue?.(boolValue)
23+
onChange?.(boolValue)
24+
} else {
25+
formValidation?.setValue?.(value)
26+
onChange?.(value)
27+
}
28+
29+
}, 200)
30+
31+
return React.useMemo(() => <>
32+
<InputLabel>{title}</InputLabel>
33+
<InputDescription>{description}</InputDescription>
34+
<DataTypeInputValueComponent inside initialValue={initialValue} onChange={onChangeDebounced}
35+
suggestions={suggestions} formValidation={formValidation}>
36+
<SegmentedControl type={"single"}
37+
h={"100%"}
38+
ml={-0.35}
39+
bg={"transparent"}
40+
style={{boxShadow: "none"}}
41+
value={(initialValue as LiteralValue)?.value?.toString() ?? ""}
42+
onValueChange={onChangeDebounced}>
43+
<SegmentedControlItem w={"100%"} value={"true"}>
44+
True
45+
</SegmentedControlItem>
46+
<SegmentedControlItem w={"100%"} value={"false"}>
47+
False
48+
</SegmentedControlItem>
49+
</SegmentedControl>
50+
</DataTypeInputValueComponent>
51+
</>, [formValidation, initialValue])
52+
53+
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import React, {useCallback, useMemo} from "react";
22
import {tags as t} from "@lezer/highlight";
33
import {Badge, hashToColor, useService, useStore} from "@code0-tech/pictor";
4-
import {Editor, EditorInputProps, EditorTokenHighlights} from "@code0-tech/pictor/dist/components/editor/Editor";
4+
import {Editor, EditorProps, EditorTokenHighlights} from "@code0-tech/pictor/dist/components/editor/Editor";
55
import {StreamLanguage} from "@codemirror/language";
66
import {CompletionContext, CompletionResult} from "@codemirror/autocomplete";
77
import {DatatypeService} from "@edition/datatype/services/Datatype.service";
88

9-
export interface DataTypeTypeEditorInputProps extends EditorInputProps {
9+
export interface DataTypeTypeEditorInputProps extends EditorProps {
1010
value: string | null
1111
isTechnicalType?: boolean
1212
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ export const DataTypeTypeInputComponent: React.FC<DataTypeJSONInputComponentProp
5353
)
5454

5555
React.useEffect(() => {
56-
formValidation?.setValue(type)
56+
formValidation?.setValue?.(type)
5757
const timeout = setTimeout(() => {
5858
// @ts-ignore
5959
onChange?.()

0 commit comments

Comments
 (0)