From d824286049990eed0ee6fb07d94ef4a19b33d24b Mon Sep 17 00:00:00 2001 From: nicosammito Date: Fri, 22 May 2026 19:11:22 +0200 Subject: [PATCH 1/4] feat: add runtimeModule field to fragments for enhanced runtime data representation --- .../services/fragments/DataType.basic.fragment.graphql | 4 ++++ .../datatype/services/fragments/DataType.fragment.graphql | 5 +++++ .../flowtype/services/fragments/FlowType.fragment.graphql | 4 ++++ .../function/services/fragments/Function.fragment.graphql | 8 ++++++++ 4 files changed, 21 insertions(+) diff --git a/src/packages/ce/src/datatype/services/fragments/DataType.basic.fragment.graphql b/src/packages/ce/src/datatype/services/fragments/DataType.basic.fragment.graphql index 17cd155d..486c3296 100644 --- a/src/packages/ce/src/datatype/services/fragments/DataType.basic.fragment.graphql +++ b/src/packages/ce/src/datatype/services/fragments/DataType.basic.fragment.graphql @@ -28,4 +28,8 @@ fragment BasicDataType on DataType { runtime { id } + runtimeModule { + __typename + id + } } \ No newline at end of file diff --git a/src/packages/ce/src/datatype/services/fragments/DataType.fragment.graphql b/src/packages/ce/src/datatype/services/fragments/DataType.fragment.graphql index defb79ef..c056f637 100644 --- a/src/packages/ce/src/datatype/services/fragments/DataType.fragment.graphql +++ b/src/packages/ce/src/datatype/services/fragments/DataType.fragment.graphql @@ -32,6 +32,11 @@ fragment DataType on DataType { id } + runtimeModule { + __typename + id + } + rules (first: $firstRule, after: $afterRule) { __typename count diff --git a/src/packages/ce/src/flowtype/services/fragments/FlowType.fragment.graphql b/src/packages/ce/src/flowtype/services/fragments/FlowType.fragment.graphql index fc40077b..4520788e 100644 --- a/src/packages/ce/src/flowtype/services/fragments/FlowType.fragment.graphql +++ b/src/packages/ce/src/flowtype/services/fragments/FlowType.fragment.graphql @@ -27,6 +27,10 @@ fragment FlowType on FlowType { runtime { id } + runtimeModule { + __typename + id + } signature flowTypeSettings { __typename diff --git a/src/packages/ce/src/function/services/fragments/Function.fragment.graphql b/src/packages/ce/src/function/services/fragments/Function.fragment.graphql index 8305a6cb..61568e9e 100644 --- a/src/packages/ce/src/function/services/fragments/Function.fragment.graphql +++ b/src/packages/ce/src/function/services/fragments/Function.fragment.graphql @@ -37,6 +37,14 @@ fragment Function on FunctionDefinition { __typename } + runtime { + id + } + runtimeModule { + __typename + id + } + parameterDefinitions (first: $firstParameterDefinition, after: $afterParameterDefinition) { nodes { id From f19b071bff8afec65425962fa02cc13466ce91ff Mon Sep 17 00:00:00 2001 From: nicosammito Date: Fri, 22 May 2026 19:11:28 +0200 Subject: [PATCH 2/4] feat: add Module fragment and service for enhanced module data handling --- .../ce/src/module/services/Module.service.ts | 59 +++++++++++++++++++ .../fragments/Module.fragment.graphql | 25 ++++++++ .../services/queries/Modules.query.graphql | 36 +++++++++++ 3 files changed, 120 insertions(+) create mode 100644 src/packages/ce/src/module/services/Module.service.ts create mode 100644 src/packages/ce/src/module/services/fragments/Module.fragment.graphql create mode 100644 src/packages/ce/src/module/services/queries/Modules.query.graphql diff --git a/src/packages/ce/src/module/services/Module.service.ts b/src/packages/ce/src/module/services/Module.service.ts new file mode 100644 index 00000000..dd6c6108 --- /dev/null +++ b/src/packages/ce/src/module/services/Module.service.ts @@ -0,0 +1,59 @@ +import {ReactiveArrayService, ReactiveArrayStore} from "@code0-tech/pictor"; +import {Namespace, NamespaceProject, Query, RuntimeModule} from "@code0-tech/sagittarius-graphql-types"; +import {GraphqlClient} from "@core/util/graphql-client"; +import {View} from "@code0-tech/pictor/dist/utils/view"; +import modulesQuery from "@edition/module/services/queries/Modules.query.graphql" + +export type ModuleDependencies = { + namespaceId: Namespace['id'] + projectId: NamespaceProject['id'] +} + +export class ModuleService extends ReactiveArrayService { + + private readonly client: GraphqlClient + private i = 0 + + constructor(client: GraphqlClient, store: ReactiveArrayStore>) { + super(store) + this.client = client + } + + values(dependencies?: ModuleDependencies): RuntimeModule[] { + const modules = super.values() + if (!dependencies?.namespaceId || !dependencies.projectId) return modules + + this.client.query({ + query: modulesQuery, + variables: { + namespaceId: dependencies?.namespaceId, + projectId: dependencies.projectId, + + firstRuntime: 50, + afterRuntime: null, + + firstModule: 50, + afterModule: null, + } + }).then(res => { + const nodes = res.data?.namespace?.project?.runtimes?.nodes?.flatMap(runtime => runtime?.modules?.nodes ?? []) ?? [] + nodes.forEach(module => { + if (module && !this.hasById(module.id)) { + this.set(this.i++, new View(module)) + } + }) + }) + + return modules + } + + hasById(id: RuntimeModule["id"]): boolean { + const module = super.values().find(m => m.id === id) + return module !== undefined + } + + getById(id: RuntimeModule['id'], dependencies?: ModuleDependencies): RuntimeModule | undefined { + return this.values(dependencies).find(module => module.id === id) + } + +} \ No newline at end of file diff --git a/src/packages/ce/src/module/services/fragments/Module.fragment.graphql b/src/packages/ce/src/module/services/fragments/Module.fragment.graphql new file mode 100644 index 00000000..07013f7f --- /dev/null +++ b/src/packages/ce/src/module/services/fragments/Module.fragment.graphql @@ -0,0 +1,25 @@ +fragment Module on RuntimeModule { + __typename + id + createdAt + updatedAt + identifier + version + author + documentation + icon + + names { + code + content + __typename + } + descriptions { + code + content + __typename + } + runtime { + id + } +} \ No newline at end of file diff --git a/src/packages/ce/src/module/services/queries/Modules.query.graphql b/src/packages/ce/src/module/services/queries/Modules.query.graphql new file mode 100644 index 00000000..1d381d50 --- /dev/null +++ b/src/packages/ce/src/module/services/queries/Modules.query.graphql @@ -0,0 +1,36 @@ +#import "../fragments/Module.fragment.graphql" + +query Modules ( + $namespaceId: NamespaceID! + $projectId: NamespaceProjectID! + $firstRuntime: Int! + $afterRuntime: String + $firstModule: Int! + $afterModule: String +) { + namespace(id: $namespaceId) { + project(id: $projectId) { + runtimes(first: $firstRuntime, after: $afterRuntime) { + __typename + count + nodes { + modules(first: $firstModule, after: $afterModule) { + __typename + count + nodes { + ...Module + } + pageInfo { + endCursor + hasNextPage + } + } + } + pageInfo { + endCursor + hasNextPage + } + } + } + } +} \ No newline at end of file From 1846340a36dc7c6feb99c834ddc7c429b78bfeae Mon Sep 17 00:00:00 2001 From: nicosammito Date: Fri, 22 May 2026 19:16:14 +0200 Subject: [PATCH 3/4] feat: add Module service to FlowLayout for enhanced module data handling --- src/app/(flow)/layout.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/app/(flow)/layout.tsx b/src/app/(flow)/layout.tsx index 32c81922..77a0749f 100644 --- a/src/app/(flow)/layout.tsx +++ b/src/app/(flow)/layout.tsx @@ -12,7 +12,7 @@ import { FunctionDefinition, Namespace, NamespaceProject, - Runtime, User + Runtime, RuntimeModule, User } from "@code0-tech/sagittarius-graphql-types"; import {usePersistentReactiveArrayService} from "@/hooks/usePersistentReactiveArrayService"; import {UserService} from "@edition/user/services/User.service"; @@ -33,6 +33,7 @@ import {ProjectView} from "@edition/project/services/Project.view"; import {RoleView} from "@edition/role/services/Role.view"; import {useUserSession} from "@edition/user/hooks/User.session.hook"; import {Layout} from "@code0-tech/pictor/dist/components/layout/Layout"; +import {ModuleService} from "@ce/module/services/Module.service"; export default function FlowLayout({bar, tab, children}: { bar: React.ReactNode, @@ -66,6 +67,7 @@ export default function FlowLayout({bar, tab, children}: { const functions = usePersistentReactiveArrayService(`dashboard::functions::${currentSession?.id}`, (store) => new FunctionService(graphqlClient, store)) const datatype = usePersistentReactiveArrayService(`dashboard::datatypes::${currentSession?.id}`, (store) => new DatatypeService(graphqlClient, store)) const flowtype = usePersistentReactiveArrayService(`dashboard::flowtypes::${currentSession?.id}`, (store) => new FlowTypeService(graphqlClient, store)) + const module = usePersistentReactiveArrayService(`dashboard::modules::${currentSession?.id}`, (store) => new ModuleService(graphqlClient, store)) const runtimeId = React.useMemo(() => project[1].getById(projectId, {namespaceId})?.primaryRuntime?.id, [projectId, project[0], namespaceId]) @@ -77,10 +79,11 @@ export default function FlowLayout({bar, tab, children}: { functions[1].values({namespaceId, projectId, runtimeId}) datatype[1].values({namespaceId, projectId, runtimeId}) flowtype[1].values({namespaceId, projectId, runtimeId}) + module[1].values({namespaceId, projectId}) }, [runtimeId, namespaceId, projectId, currentSession, flow, functions, datatype, flowtype]) return + services={[user, organization, member, namespace, runtime, project, role, flow, functions, datatype, flowtype, module]}>
Date: Fri, 22 May 2026 22:39:30 +0200 Subject: [PATCH 4/4] feat: enhance suggestion handling by updating types and grouping logic for improved data representation --- .../panels/FlowPanelControlComponent.tsx | 13 ++- .../FunctionSuggestionComponent.view.ts | 25 ----- .../FunctionSuggestionMenuComponent.tsx | 44 --------- .../FunctionSuggestionMenuComponent.util.tsx | 69 -------------- .../FunctionSuggestionMenuFooterComponent.tsx | 50 ---------- .../FunctionSuggestionSearchBarComponent.tsx | 18 ---- .../FunctionSuggestionSearchInput.style.scss | 18 ---- ...FunctionSuggestionSearchInputComponent.tsx | 39 -------- .../components/suggestion/Suggestion.util.tsx | 92 ++++++++++++------- .../suggestion/SuggestionDialogComponent.tsx | 14 +-- .../hooks/Function.suggestion.hook.ts | 16 +--- 11 files changed, 73 insertions(+), 325 deletions(-) delete mode 100644 src/packages/ce/src/function/components/suggestion/FunctionSuggestionComponent.view.ts delete mode 100644 src/packages/ce/src/function/components/suggestion/FunctionSuggestionMenuComponent.tsx delete mode 100644 src/packages/ce/src/function/components/suggestion/FunctionSuggestionMenuComponent.util.tsx delete mode 100644 src/packages/ce/src/function/components/suggestion/FunctionSuggestionMenuFooterComponent.tsx delete mode 100644 src/packages/ce/src/function/components/suggestion/FunctionSuggestionSearchBarComponent.tsx delete mode 100644 src/packages/ce/src/function/components/suggestion/FunctionSuggestionSearchInput.style.scss delete mode 100644 src/packages/ce/src/function/components/suggestion/FunctionSuggestionSearchInputComponent.tsx diff --git a/src/packages/ce/src/flow/components/panels/FlowPanelControlComponent.tsx b/src/packages/ce/src/flow/components/panels/FlowPanelControlComponent.tsx index b61286a0..46535133 100644 --- a/src/packages/ce/src/flow/components/panels/FlowPanelControlComponent.tsx +++ b/src/packages/ce/src/flow/components/panels/FlowPanelControlComponent.tsx @@ -1,5 +1,5 @@ import React from "react"; -import {Flow, NodeFunction} from "@code0-tech/sagittarius-graphql-types"; +import {Flow, LiteralValue, NodeFunction, ReferenceValue} from "@code0-tech/sagittarius-graphql-types"; import { Badge, Button, @@ -15,7 +15,6 @@ import {Panel} from "@xyflow/react"; import {ButtonGroup} from "@code0-tech/pictor/dist/components/button-group/ButtonGroup"; import {FlowService} from "@edition/flow/services/Flow.service"; import {SuggestionDialogComponent} from "@edition/function/components/suggestion/SuggestionDialogComponent"; -import {FunctionSuggestion} from "@edition/function/components/suggestion/FunctionSuggestionComponent.view"; import {Suggestion} from "@edition/function/components/suggestion/Suggestion.util"; import {useHotkeys} from "react-hotkeys-hook"; import {useSelectedFunctionNode} from "@edition/function/hooks/FunctionNode.selected.hook"; @@ -51,14 +50,14 @@ export const FlowPanelControlComponent: React.FC }) }, [selectedNode, flowService, flowStore]) - const addNodeToFlow = React.useCallback((suggestion: FunctionSuggestion | Suggestion) => { - if (flowId && suggestion.value.__typename === "NodeFunction" && selectedNode?.id.includes("NodeFunction")) { + const addNodeToFlow = React.useCallback((suggestion: NodeFunction | ReferenceValue | LiteralValue) => { + if (flowId && suggestion.__typename === "NodeFunction" && selectedNode?.id.includes("NodeFunction")) { startTransition(async () => { - await flowService.addNextNodeById(flowId, selectedNode?.id as NodeFunction['id'], suggestion.value as NodeFunction) + await flowService.addNextNodeById(flowId, selectedNode?.id as NodeFunction['id'], suggestion as NodeFunction) }) - } else if (suggestion.value.__typename === "NodeFunction") { + } else if (suggestion.__typename === "NodeFunction") { startTransition(async () => { - await flowService.addNextNodeById(flowId, null, suggestion.value as NodeFunction) + await flowService.addNextNodeById(flowId, null, suggestion as NodeFunction) }) } }, [flowId, flowService, flowStore, selectedNode]) diff --git a/src/packages/ce/src/function/components/suggestion/FunctionSuggestionComponent.view.ts b/src/packages/ce/src/function/components/suggestion/FunctionSuggestionComponent.view.ts deleted file mode 100644 index b4a325e5..00000000 --- a/src/packages/ce/src/function/components/suggestion/FunctionSuggestionComponent.view.ts +++ /dev/null @@ -1,25 +0,0 @@ -import type { - LiteralValue, - NodeFunction, - ReferenceValue -} from "@code0-tech/sagittarius-graphql-types"; -import React from "react"; - -export enum FunctionSuggestionType { - REF_OBJECT, - VALUE, - FUNCTION, - FUNCTION_COMBINATION, - DATA_TYPE, -} - -export interface FunctionSuggestion { - displayText: string[] - path: number[] - value: LiteralValue | ReferenceValue | NodeFunction - type: FunctionSuggestionType - icon?: string - aliases?: string[] - description?: string - definitionSource?: string -} \ No newline at end of file diff --git a/src/packages/ce/src/function/components/suggestion/FunctionSuggestionMenuComponent.tsx b/src/packages/ce/src/function/components/suggestion/FunctionSuggestionMenuComponent.tsx deleted file mode 100644 index 6bfce813..00000000 --- a/src/packages/ce/src/function/components/suggestion/FunctionSuggestionMenuComponent.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import React from "react"; -import {FunctionSuggestion} from "./FunctionSuggestionComponent.view"; -import {toInputSuggestions} from "./FunctionSuggestionMenuComponent.util"; -import {FunctionSuggestionSearchBarComponent} from "./FunctionSuggestionSearchBarComponent"; -import { - Card, InputSuggestion, - InputSuggestionMenuContent, - InputSuggestionMenuContentItems, - InputSuggestionMenuContentItemsHandle, - Menu, - MenuPortal, - MenuTrigger -} from "@code0-tech/pictor"; - -export interface FunctionSuggestionMenuComponentProps { - triggerContent: React.ReactNode - suggestions?: InputSuggestion[] - onSuggestionSelect?: (suggestion: FunctionSuggestion) => void -} - -export const FunctionSuggestionMenuComponent: React.FC = (props) => { - - const {suggestions = [], triggerContent, onSuggestionSelect = () => null} = props - - return - - {triggerContent} - - - - - { - onSuggestionSelect(suggestion.value) - }} - /> - - - - - - -} \ No newline at end of file diff --git a/src/packages/ce/src/function/components/suggestion/FunctionSuggestionMenuComponent.util.tsx b/src/packages/ce/src/function/components/suggestion/FunctionSuggestionMenuComponent.util.tsx deleted file mode 100644 index 039b70b1..00000000 --- a/src/packages/ce/src/function/components/suggestion/FunctionSuggestionMenuComponent.util.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import {FunctionSuggestion, FunctionSuggestionType} from "./FunctionSuggestionComponent.view"; -import React from "react"; -import {IconCircleDot, IconNote, IconVariable} from "@tabler/icons-react"; -import {InputSuggestion, Text} from "@code0-tech/pictor"; -import {ReferenceBadgeComponent} from "@edition/datatype/components/badges/ReferenceBadgeComponent"; -import {LiteralValue, ReferenceValue} from "@code0-tech/sagittarius-graphql-types"; -import {icon, IconString} from "@core/util/icons"; - -export const toInputSuggestions = (suggestions: FunctionSuggestion[]): InputSuggestion[] => { - - const staticGroupLabels: Partial> = { - [FunctionSuggestionType.VALUE]: "Values", - [FunctionSuggestionType.REF_OBJECT]: "Variables", - [FunctionSuggestionType.DATA_TYPE]: "Datatypes", - } - - return suggestions.map(suggestion => { - - const iconMap: Record = { - [FunctionSuggestionType.FUNCTION]: , - [FunctionSuggestionType.FUNCTION_COMBINATION]: , - [FunctionSuggestionType.REF_OBJECT]: , - [FunctionSuggestionType.VALUE]: , - [FunctionSuggestionType.DATA_TYPE]: , - } - - const DisplayIcon = icon(suggestion?.icon as IconString) - - const children: React.ReactNode = <> - {suggestion?.icon ? : iconMap[suggestion.type]} - { - suggestion.type === FunctionSuggestionType.REF_OBJECT ? ( - - ) : suggestion.type === FunctionSuggestionType.VALUE ? ( - {String((suggestion.value as LiteralValue).value)} - ) : suggestion.type === FunctionSuggestionType.FUNCTION ? ( - {String(suggestion.displayText)} - ) : null - } - - - let groupLabel: string | undefined = staticGroupLabels[suggestion.type] - - if (suggestion.type === FunctionSuggestionType.FUNCTION || suggestion.type === FunctionSuggestionType.FUNCTION_COMBINATION) { - const runtimeIdentifier = suggestion.value.__typename === "NodeFunction" - ? suggestion.value.functionDefinition?.identifier - : undefined - - - if (runtimeIdentifier) { - const [runtime, pkg] = runtimeIdentifier.split("::") - if (runtime && pkg) { - groupLabel = `${runtime}::${pkg}` - } - } - } - - return { - children, - insertMode: "replace", - valueData: { - ...suggestion, - icon: "" - }, - value: suggestion.value, - groupBy: groupLabel, - }; - }) -} diff --git a/src/packages/ce/src/function/components/suggestion/FunctionSuggestionMenuFooterComponent.tsx b/src/packages/ce/src/function/components/suggestion/FunctionSuggestionMenuFooterComponent.tsx deleted file mode 100644 index 41e6f8be..00000000 --- a/src/packages/ce/src/function/components/suggestion/FunctionSuggestionMenuFooterComponent.tsx +++ /dev/null @@ -1,50 +0,0 @@ -"use client"; - -import React from "react"; -import { - IconArrowsShuffle, - IconBulb, - IconCircleDot, - IconCirclesRelation, - IconCornerDownLeft, - IconFileFunctionFilled -} from "@tabler/icons-react"; -import {Flex, MenuLabel, Text, Tooltip, TooltipContent, TooltipPortal, TooltipTrigger} from "@code0-tech/pictor"; - -export const FunctionSuggestionMenuFooterComponent: React.FC = () => { - return - - Press to insert - - - - - - - - - - - FUNCTION - - - - FUNCTION COMBINATION - - - - VARIABLE - - - - VALUE - - - - - - - - - -} \ No newline at end of file diff --git a/src/packages/ce/src/function/components/suggestion/FunctionSuggestionSearchBarComponent.tsx b/src/packages/ce/src/function/components/suggestion/FunctionSuggestionSearchBarComponent.tsx deleted file mode 100644 index bcb96759..00000000 --- a/src/packages/ce/src/function/components/suggestion/FunctionSuggestionSearchBarComponent.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import React from "react"; -import {FunctionSuggestionSearchInputComponent} from "./FunctionSuggestionSearchInputComponent"; -import {IconSearch} from "@tabler/icons-react"; -import {Component} from "@code0-tech/pictor"; - -export interface FunctionSuggestionSearchBarProps extends Component { - onType: (event: React.KeyboardEvent) => void -} - -export const FunctionSuggestionSearchBarComponent: React.FC = (props) => { - return props.onType(event)} - clearable - style={{background: "none", boxShadow: "none"}} - autoFocus - left={} - /> -} \ No newline at end of file diff --git a/src/packages/ce/src/function/components/suggestion/FunctionSuggestionSearchInput.style.scss b/src/packages/ce/src/function/components/suggestion/FunctionSuggestionSearchInput.style.scss deleted file mode 100644 index 46def7e6..00000000 --- a/src/packages/ce/src/function/components/suggestion/FunctionSuggestionSearchInput.style.scss +++ /dev/null @@ -1,18 +0,0 @@ -@use "@core/style/helpers"; -@use "@core/style/box"; -@use "@core/style/variables"; - -.d-flow-suggestion-search-input { - border: none !important; - background: none !important; - margin: -1 * variables.$xxs; - padding-left: variables.$xxs; - padding-right: variables.$xxs; - border-radius: 0 !important; - box-shadow: none !important; - - > input { - padding-top: 0 !important; - padding-bottom: 0 !important; - } -} \ No newline at end of file diff --git a/src/packages/ce/src/function/components/suggestion/FunctionSuggestionSearchInputComponent.tsx b/src/packages/ce/src/function/components/suggestion/FunctionSuggestionSearchInputComponent.tsx deleted file mode 100644 index a51548e9..00000000 --- a/src/packages/ce/src/function/components/suggestion/FunctionSuggestionSearchInputComponent.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import React, {RefObject} from "react"; -import {IconX} from "@tabler/icons-react"; -import "./FunctionSuggestionSearchInput.style.scss" -import {clearInputElement} from "@code0-tech/pictor/dist/components/form/Input.utils"; -import {Button, Input, InputProps} from "@code0-tech/pictor"; - -interface FunctionSuggestionSearchInputComponentProps extends Omit, "wrapperComponent" | "type"> { - //defaults to false - clearable?: boolean -} - -//@ts-ignore -export const FunctionSuggestionSearchInputComponent: React.ForwardRefExoticComponent = React.forwardRef((props, ref: RefObject) => { - ref = ref || React.useRef(null) - - const { - clearable = false, - right, - ...rest - } = props - - const toClearable = () => { - clearInputElement(ref.current) - } - - const rightAction = [right] - clearable && rightAction.push() - - - return } - {...rest} - /> -}) diff --git a/src/packages/ce/src/function/components/suggestion/Suggestion.util.tsx b/src/packages/ce/src/function/components/suggestion/Suggestion.util.tsx index 69e225e0..fbbf13dd 100644 --- a/src/packages/ce/src/function/components/suggestion/Suggestion.util.tsx +++ b/src/packages/ce/src/function/components/suggestion/Suggestion.util.tsx @@ -1,5 +1,7 @@ import {LiteralValue, NodeFunction, ReferenceValue} from "@code0-tech/sagittarius-graphql-types"; -import {FunctionSuggestion} from "@edition/function/components/suggestion/FunctionSuggestionComponent.view"; +import {useService, useStore} from "@code0-tech/pictor"; +import {ModuleService} from "@ce/module/services/Module.service"; +import {FunctionService} from "@ce/function/services/Function.service"; import React from "react"; export interface Suggestion { @@ -17,46 +19,68 @@ export interface SuggestionGroup { icon?: string } -export const getMappedSuggestions = (suggestions: FunctionSuggestion[]): SuggestionGroup[] => { +export const useMappedSuggestions = (suggestions: (NodeFunction | ReferenceValue | LiteralValue)[]): SuggestionGroup[] => { - const mappedSuggestions: Suggestion[] = suggestions.map((suggestion) => { - return { - value: suggestion.value, - icon: suggestion.icon, - displayMessage: suggestion.displayText.join(" "), - aliases: suggestion.aliases || [], - definitionSource: suggestion.definitionSource || "All", - description: suggestion.description, - } - }) + const moduleService = useService(ModuleService) + const moduleStore = useStore(ModuleService) + const functionService = useService(FunctionService) + const functionStore = useStore(FunctionService) - const groupedBySource = mappedSuggestions.reduce((acc, suggestion) => { - const source = suggestion.definitionSource - const runtimeIdentifier = suggestion.value.__typename === "NodeFunction" - ? suggestion.value.functionDefinition?.identifier - : undefined + const modules = React.useMemo( + () => moduleService.values(), + [moduleService, moduleStore] + ) - if (!acc[source]) { - acc[source] = [] - } + const functions = React.useMemo( + () => functionService.values(), + [functionService, functionStore] + ) + + const mappedSuggestions: Suggestion[] = suggestions.map((suggestion) => { - if (runtimeIdentifier) { - const [_, pkg] = runtimeIdentifier.split("::") - const identifier = `${pkg[0].toUpperCase()}${pkg.slice(1)}` - if (!acc[identifier]) { - acc[identifier] = [] + if (suggestion.__typename === "NodeFunction") { + const functionDefinition = functions.find(f => f.id === suggestion.functionDefinition?.id) + const module = modules.find(m => m.id === functionDefinition?.runtimeModule?.id) + + return { + value: suggestion, + icon: functionDefinition?.displayIcon, + displayMessage: functionDefinition?.names?.[0].content, + aliases: functionDefinition?.aliases?.[0].content?.split(";"), + definitionSource: module?.id, + description: functionDefinition?.descriptions?.[0].content, } - acc[identifier].push(suggestion) } - acc[source].push(suggestion) - return acc - }, {} as Record) + return null + }).filter((Boolean)) as Suggestion[] + + const groupedByModule = new Map() + + mappedSuggestions.forEach((suggestion) => { + const moduleId = suggestion.definitionSource + const module = modules.find(m => m.id === moduleId) + if (!groupedByModule.has(moduleId)) { + groupedByModule.set(moduleId, { + suggestions: [], + module: module + }) + } + + groupedByModule.get(moduleId)!.suggestions.push(suggestion) + }) - return Object.entries(groupedBySource).map(([source, suggestions]) => ({ - suggestions, - displayMessage: source, - icon: source === "All" ? "" : suggestions[0]?.icon, - })) + return [ + { + suggestions: mappedSuggestions, + displayMessage: "All", + icon: undefined + }, + ...Array.from(groupedByModule.values()).map((group) => ({ + suggestions: group.suggestions, + displayMessage: group.module?.names?.[0].content, + icon: group.module?.icon + })) + ] } \ No newline at end of file diff --git a/src/packages/ce/src/function/components/suggestion/SuggestionDialogComponent.tsx b/src/packages/ce/src/function/components/suggestion/SuggestionDialogComponent.tsx index 480e3be7..ad93f269 100644 --- a/src/packages/ce/src/function/components/suggestion/SuggestionDialogComponent.tsx +++ b/src/packages/ce/src/function/components/suggestion/SuggestionDialogComponent.tsx @@ -1,6 +1,5 @@ import React from "react"; -import {FunctionSuggestion} from "@edition/function/components/suggestion/FunctionSuggestionComponent.view"; -import {getMappedSuggestions, Suggestion} from "@edition/function/components/suggestion/Suggestion.util"; +import {Suggestion, useMappedSuggestions} from "@edition/function/components/suggestion/Suggestion.util"; import { Badge, Button, @@ -9,7 +8,8 @@ import { CommandEmpty, CommandInput, CommandItem, - CommandList, CommandSeparator, + CommandList, + CommandSeparator, Flex, hashToColor, ScrollArea, @@ -23,9 +23,10 @@ import {Layout} from "@code0-tech/pictor/dist/components/layout/Layout"; import {Tab, TabList, TabTrigger} from "@code0-tech/pictor/dist/components/tab/Tab"; import {icon, IconString} from "@core/util/icons"; import {IconArrowsUpDown, IconCornerDownLeft, IconSearch} from "@tabler/icons-react"; +import {LiteralValue, NodeFunction, ReferenceValue} from "@code0-tech/sagittarius-graphql-types"; export interface SuggestionDialogComponentProps { - suggestions?: FunctionSuggestion[] + suggestions?: (NodeFunction | ReferenceValue | LiteralValue)[] open?: boolean onOpenChange?: (open: boolean) => void onSuggestionSelect?: (suggestion: Suggestion) => void @@ -41,7 +42,7 @@ export const SuggestionDialogComponent: React.FC setSuggestionDialogOpen(open) }, [open]) - const suggestions = getMappedSuggestions(props.suggestions || []) + const suggestions = useMappedSuggestions(props.suggestions || []) const [currentTab, setCurrentTab] = React.useState("group-0") const [holdCurrentTab, setHoldCurrentTab] = React.useState("group-0") @@ -123,7 +124,8 @@ export const SuggestionDialogComponent: React.FC }}> - + {suggestion.displayMessage} diff --git a/src/packages/ce/src/function/hooks/Function.suggestion.hook.ts b/src/packages/ce/src/function/hooks/Function.suggestion.hook.ts index 190b4553..c08606e3 100644 --- a/src/packages/ce/src/function/hooks/Function.suggestion.hook.ts +++ b/src/packages/ce/src/function/hooks/Function.suggestion.hook.ts @@ -2,8 +2,6 @@ import {useService, useStore} from "@code0-tech/pictor"; import {FunctionService} from "@edition/function/services/Function.service"; import {NodeFunction} from "@code0-tech/sagittarius-graphql-types"; import React from "react"; -import {FunctionSuggestionType} from "@edition/function/components/suggestion/FunctionSuggestionComponent.view"; -import {FALLBACK_FUNCTION_NAME} from "@core/util/fallback-translations"; export const useFunctionSuggestions = () => { @@ -51,18 +49,6 @@ export const useFunctionSuggestions = () => { if (packageCmp !== 0) return packageCmp; return fA.localeCompare(fB); - }).map(suggestion => { - - const functionDefinition = functionService.getById(suggestion.functionDefinition?.id) - return { - path: [], - type: FunctionSuggestionType.FUNCTION, - displayText: [functionDefinition?.names?.[0]?.content ?? FALLBACK_FUNCTION_NAME], - value: suggestion, - icon: functionDefinition?.displayIcon || "", - aliases: functionDefinition?.aliases?.map((a) => a.content).flatMap(a => a?.split(";") ?? ""), - description: functionDefinition?.descriptions?.[0]?.content || "", - } - }), [nodes]); + }), [nodes]) } \ No newline at end of file