From d800b02b4b368af310644d938cc201bcc0261224 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Thu, 4 Jun 2026 20:56:42 +0200 Subject: [PATCH 01/54] feat: update PICTOR version in environment configuration to 0.9.2 --- .env.local | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.local b/.env.local index 2c340b54..08b5e666 100644 --- a/.env.local +++ b/.env.local @@ -4,7 +4,7 @@ NEXT_PUBLIC_EDITION=ce SAGITTARIUS_GRAPHQL_URL=http://localhost:80/graphql NEXT_PUBLIC_SCULPTOR_VERSION=0.0.0 -NEXT_PUBLIC_PICTOR_VERSION=0.9.1 +NEXT_PUBLIC_PICTOR_VERSION=0.9.2 NEXT_PUBLIC_ALLOWED_REDIRECT_DOMAINS=*.code0.tech,*.codezero.build NEXT_PUBLIC_OTEL_SERVICE_NAME=#"sculptor-client" From d7c20bf64cb86c76d47763f23d289326a2b53ebb Mon Sep 17 00:00:00 2001 From: nicosammito Date: Thu, 4 Jun 2026 20:56:52 +0200 Subject: [PATCH 02/54] feat: add execution results and node results fields to Flow fragment and service --- .../ce/src/flow/services/Flow.service.ts | 6 ++ .../services/fragments/Flow.fragment.graphql | 74 +++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/src/packages/ce/src/flow/services/Flow.service.ts b/src/packages/ce/src/flow/services/Flow.service.ts index 374b56dc..3c67219a 100644 --- a/src/packages/ce/src/flow/services/Flow.service.ts +++ b/src/packages/ce/src/flow/services/Flow.service.ts @@ -74,6 +74,12 @@ export class FlowService extends ReactiveArrayService { const nodes = res.data?.namespace?.project?.flows?.nodes ?? [] diff --git a/src/packages/ce/src/flow/services/fragments/Flow.fragment.graphql b/src/packages/ce/src/flow/services/fragments/Flow.fragment.graphql index 9621cf68..a38f9ce1 100644 --- a/src/packages/ce/src/flow/services/fragments/Flow.fragment.graphql +++ b/src/packages/ce/src/flow/services/fragments/Flow.fragment.graphql @@ -103,6 +103,80 @@ fragment Flow on Flow { type { id } + executionResults (first: $firstExecution, after: $afterExecution) { + __typename + count + nodes { + __typename + id + createdAt + updatedAt + startedAt + finishedAt + input + success + + flow { + __typename + id + } + error { + __typename + category + code + dependencies + details + message + timestamp + version + } + nodeResults(first: $firstNodeResult, after: $afterNodeResult) { + __typename + count + nodes { + __typename + id + createdAt + updatedAt + startedAt + finishedAt + position + success + parameterResults { + __typename + id + createdAt + updatedAt + value + position + } + nodeFunction { + __typename + id + } + error { + __typename + category + code + dependencies + details + message + timestamp + version + } + } + pageInfo { + __typename + endCursor + hasNextPage + } + } + } + pageInfo { + endCursor + hasNextPage + } + } validationStatus disabledReason updatedAt From 679f24306b885703978b79788ee51a98f0239c4e Mon Sep 17 00:00:00 2001 From: nicosammito Date: Thu, 4 Jun 2026 20:56:59 +0200 Subject: [PATCH 03/54] feat: update PICTOR and triangulum dependencies to latest versions --- package-lock.json | 24 ++++++++++++------------ package.json | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7f653d48..f3181a15 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,8 +9,8 @@ "version": "0.0.0", "dependencies": { "@apollo/client": "^4.0.9", - "@code0-tech/pictor": "^0.9.1", - "@code0-tech/triangulum": "^0.19.1", + "@code0-tech/pictor": "^0.9.2", + "@code0-tech/triangulum": "^0.20.0", "@codemirror/lang-javascript": "^6.2.5", "@codemirror/lint": "^6.9.5", "@opentelemetry/api": "^1.9.1", @@ -415,9 +415,9 @@ } }, "node_modules/@code0-tech/pictor": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/@code0-tech/pictor/-/pictor-0.9.1.tgz", - "integrity": "sha512-HBu2bXEcjhsd9Er/n77OTmgXODDBLSdIhUxJ4ifh6nmkao68h12Sr1e9SIyJ7Lj19aZbeT3NkHxArU8/kPcZ2g==", + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@code0-tech/pictor/-/pictor-0.9.2.tgz", + "integrity": "sha512-X9Pr+DUbvp1hCbg60SvhE+vYP0aSZFoIuYvLjCPvgS+xWbjP3olWB9rZLnhL/JLm4ypGkQsVbp8RRmPc4d1xrg==", "dependencies": { "@radix-ui/react-progress": "^1.1.8" }, @@ -457,17 +457,17 @@ } }, "node_modules/@code0-tech/sagittarius-graphql-types": { - "version": "0.0.0-experimental-2562772880-472cd96c80b0119354b8243f2ab3a1586d2c54ea", - "resolved": "https://registry.npmjs.org/@code0-tech/sagittarius-graphql-types/-/sagittarius-graphql-types-0.0.0-experimental-2562772880-472cd96c80b0119354b8243f2ab3a1586d2c54ea.tgz", - "integrity": "sha512-IQXj364mTjkqGg5gF+QAZq0lLbN8zu+HZGvSx7D+2f7PcdeetK1LU3Q395+AkGRzAx7D7NqMJb/Iykm8ZGXvdw==", + "version": "0.0.0-experimental-2571203559-cd92ea1ca9e0c8a1b3d725241b811bdc01f93e2a", + "resolved": "https://registry.npmjs.org/@code0-tech/sagittarius-graphql-types/-/sagittarius-graphql-types-0.0.0-experimental-2571203559-cd92ea1ca9e0c8a1b3d725241b811bdc01f93e2a.tgz", + "integrity": "sha512-BghG80JfwZO5Ec0n7Ph50hhuws4YEIVUnVeZ6vio4KRJN4rYxG41TsU25Pic4MKS8OdCLwcRaXN/zXZDkif6Cw==", "peer": true }, "node_modules/@code0-tech/triangulum": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@code0-tech/triangulum/-/triangulum-0.19.1.tgz", - "integrity": "sha512-nnHJ95w/8+yPmnDcaUq0f1UvgeXo0DAw/R1e3X1D9kb3OnH1fzN9sqbHt9k2HHFlQtAm6MnyQ2YsV4geNvexBw==", + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@code0-tech/triangulum/-/triangulum-0.20.0.tgz", + "integrity": "sha512-rW65ogVUB8mM44ZRnMCsWy++fChbWhZuu5WyxV1pOOoKpKvodNIbY7AVFEjw8Kt702W3kCY7LLatn43UwTfyhQ==", "peerDependencies": { - "@code0-tech/sagittarius-graphql-types": "0.0.0-experimental-2562772880-472cd96c80b0119354b8243f2ab3a1586d2c54ea", + "@code0-tech/sagittarius-graphql-types": "0.0.0-experimental-2571203559-cd92ea1ca9e0c8a1b3d725241b811bdc01f93e2a", "@typescript/vfs": "^1.6.4", "lossless-json": "^4.3.0", "typescript": "^5.9.3 || ^6.0.2" diff --git a/package.json b/package.json index a513e3c8..d69ef3d0 100644 --- a/package.json +++ b/package.json @@ -15,8 +15,8 @@ }, "dependencies": { "@apollo/client": "^4.0.9", - "@code0-tech/pictor": "^0.9.1", - "@code0-tech/triangulum": "^0.19.1", + "@code0-tech/pictor": "^0.9.2", + "@code0-tech/triangulum": "^0.20.0", "@codemirror/lang-javascript": "^6.2.5", "@codemirror/lint": "^6.9.5", "@opentelemetry/api": "^1.9.1", From eaf7fcebb3a2e935047d076f7d78aa6c6dcf6973 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Thu, 4 Jun 2026 20:57:06 +0200 Subject: [PATCH 04/54] feat: add pagination fields for execution and node results in Flows query --- .../ce/src/flow/services/queries/Flows.query.graphql | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/packages/ce/src/flow/services/queries/Flows.query.graphql b/src/packages/ce/src/flow/services/queries/Flows.query.graphql index ea68d722..6f0df1dc 100644 --- a/src/packages/ce/src/flow/services/queries/Flows.query.graphql +++ b/src/packages/ce/src/flow/services/queries/Flows.query.graphql @@ -3,15 +3,24 @@ query Flows ( $namespaceId: NamespaceID! $projectId: NamespaceProjectID! + $firstFlow: Int! $afterFlow: String + $firstNode: Int!, $afterNode: String, + $firstNodeParameter: Int!, $afterNodeParameter: String, $firstSetting: Int!, $afterSetting: String, + + $firstExecution: Int!, + $afterExecution: String + + $firstNodeResult: Int!, + $afterNodeResult: String ) { namespace(id: $namespaceId) { project(id: $projectId) { From e06a5bfb48ca7120e07d72b050a24351e64c968e Mon Sep 17 00:00:00 2001 From: nicosammito Date: Thu, 4 Jun 2026 20:57:13 +0200 Subject: [PATCH 05/54] feat: add FlowExecutionResultView component to display execution results and integrate with FlowBuilder --- .../[projectId]/flow/[flowId]/page.tsx | 55 +- .../flow/views/FlowExecutionResultView.tsx | 706 ++++++++++++++++++ 2 files changed, 749 insertions(+), 12 deletions(-) create mode 100644 src/packages/ce/src/flow/views/FlowExecutionResultView.tsx diff --git a/src/app/(flow)/namespace/[namespaceId]/project/[projectId]/flow/[flowId]/page.tsx b/src/app/(flow)/namespace/[namespaceId]/project/[projectId]/flow/[flowId]/page.tsx index 8bf57d53..6834b2c4 100644 --- a/src/app/(flow)/namespace/[namespaceId]/project/[projectId]/flow/[flowId]/page.tsx +++ b/src/app/(flow)/namespace/[namespaceId]/project/[projectId]/flow/[flowId]/page.tsx @@ -2,10 +2,24 @@ import { Button, + Card, Flex, + Gantt, + getRelativeValue, + hashToColor, Spacing, Text, + Tooltip, TooltipContent, TooltipPortal, + TooltipTrigger, + withAlpha, } from "@code0-tech/pictor"; import React from "react"; -import {IconDatabase, IconFile, IconMessageChatbot} from "@tabler/icons-react"; +import { + IconArrowRampRight2, + IconBrandDiscord, IconBrandTeams, + IconDatabase, + IconFile, + IconPlayerPlay, + IconTextGrammar +} from "@tabler/icons-react"; import {useParams} from "next/navigation"; import {Flow} from "@code0-tech/sagittarius-graphql-types"; import {FlowBuilderComponent} from "@edition/flow/components/builder/FlowBuilderComponent"; @@ -16,6 +30,8 @@ import { ResizablePanelGroup } from "@code0-tech/pictor/dist/components/resizable/Resizable"; import {Layout} from "@code0-tech/pictor/dist/components/layout/Layout"; +import {Editor} from "@code0-tech/pictor/dist/components/editor/Editor"; +import {FlowExecutionResultView} from "@edition/flow/views/FlowExecutionResultView"; export default function Page() { @@ -24,31 +40,46 @@ export default function Page() { const flowIndex = params.flowId as any as number const flowId: Flow['id'] = `gid://sagittarius/Flow/${flowIndex}` - const [show, setShow] = React.useState(false); + const [tab, setTab] = React.useState(undefined); return - - - }> - - + + + + + + { + tab === "execution" && ( + <> + + + + + + ) + } + - {show && ( + {tab === "file" && ( <> - + diff --git a/src/packages/ce/src/flow/views/FlowExecutionResultView.tsx b/src/packages/ce/src/flow/views/FlowExecutionResultView.tsx new file mode 100644 index 00000000..89f8257e --- /dev/null +++ b/src/packages/ce/src/flow/views/FlowExecutionResultView.tsx @@ -0,0 +1,706 @@ +import React from "react"; +import {useParams} from "next/navigation"; +import {Flow, Namespace, NamespaceProject} from "@code0-tech/sagittarius-graphql-types"; +import { + Button, + Card, + Flex, + Gantt, + getRelativeValue, + hashToColor, + Menu, + MenuContent, + MenuItem, + MenuPortal, + MenuTrigger, + Spacing, + Text, + Tooltip, + TooltipContent, + TooltipPortal, + TooltipTrigger, + useService, + useStore, + withAlpha +} from "@code0-tech/pictor"; +import {FlowService} from "@edition/flow/services/Flow.service"; +import { + IconArrowRampRight2, + IconBrandDiscord, + IconBrandTeams, + IconDatabase, + IconPlayerPlayFilled, + IconPlus, + IconTextGrammar +} from "@tabler/icons-react"; +import {Editor} from "@code0-tech/pictor/dist/components/editor/Editor"; +import { + FileTabs, + FileTabsContent, + FileTabsList, + FileTabsTrigger +} from "@code0-tech/pictor/dist/components/file-tabs/FileTabs"; +import {Layout} from "@code0-tech/pictor/dist/components/layout/Layout"; +import {formatDistanceToNow} from "date-fns"; + +export const FlowExecutionResultView: React.FC = () => { + + const params = useParams() + const flowService = useService(FlowService) + const flowStore = useStore(FlowService) + const [activeTab, setActiveTab] = React.useState() + + const namespaceIndex = params.namespaceId as any as number + const projectIndex = params.projectId as any as number + const flowIndex = params.flowId as any as number + const flowId: Flow['id'] = `gid://sagittarius/Flow/${flowIndex}` + const namespaceId: Namespace['id'] = `gid://sagittarius/Namespace/${namespaceIndex}` + const projectId: NamespaceProject['id'] = `gid://sagittarius/NamespaceProject/${projectIndex}` + + const flow = React.useMemo( + () => flowService.getById(flowId, { + namespaceId, + projectId + }), + [flowStore, namespaceId, projectId, flowId] + ) + + const flowExecutionResults = React.useMemo( + () => flow?.executionResults?.nodes ?? [], + [flow] + ) + + return <> + { + setActiveTab(value) + }} + > + + + + + + + {flowExecutionResults.map(result => { + return { + setActiveTab(result?.id!) + }}> + + {result?.id} + + + })} + + + + } + > + + + + #1 + + + {formatDistanceToNow("Thu Jun 04 2026 17:56:20 GMT+0000")} ago + + + {flowExecutionResults.map(result => { + return + + {result?.id} + + + })} + }> + <> + + + {(item) => item.type === "group" ? ( + { + const element = document.getElementById(`group-target-${item.data.displayMessage}`) + element?.scrollIntoView({behavior: "smooth"}) + }}> + + <> + + + ) : ( + + + + + + + {item.data.icon && React.createElement(item.data.icon, { + color: hashToColor(item.id), + size: 16, + style: {minWidth: "13px", minHeight: "13px"} + })} + + {item.data.displayMessage} + + + + {getRelativeValue(item.end - item.start)} + + + + + + + + + {item.data.icon && React.createElement(item.data.icon, { + color: hashToColor(item.id), + size: 16, + style: {minWidth: "16px", minHeight: "16px", marginTop: "2px"} + })} + + {item.data.displayMessage} + + + + + + + + + + + + + + + + + + +
+ + Start time + + + + {getRelativeValue(item.start)} + +
+ + End time + + + + {getRelativeValue(item.end)} + +
+ + Duration + + + + {getRelativeValue(item.end - item.start)} + +
+ + + <> + + Parameters + + {item.data.parameters?.map((item: any, index: number) => ( +
+ + {item.name} + + +
+ ))} + + + + { + item.data.result && ( +
+ + Result + + +
+ ) + } +
+
+
+ )} +
+
+ {flowExecutionResults.map(result => { + return + + {(item) => item.type === "group" ? ( + { + const element = document.getElementById(`group-target-${item.data.displayMessage}`) + element?.scrollIntoView({behavior: "smooth"}) + }}> + + <> + + + ) : ( + + + + + + + {item.data.icon && React.createElement(item.data.icon, { + color: hashToColor(item.id), + size: 16, + style: {minWidth: "13px", minHeight: "13px"} + })} + + {item.data.displayMessage} + + + + {getRelativeValue(item.end - item.start)} + + + + + + + + + {item.data.icon && React.createElement(item.data.icon, { + color: hashToColor(item.id), + size: 16, + style: {minWidth: "16px", minHeight: "16px", marginTop: "2px"} + })} + + {item.data.displayMessage} + + + + + + + + + + + + + + + + + + +
+ + Start time + + + + {getRelativeValue(item.start)} + +
+ + End time + + + + {getRelativeValue(item.end)} + +
+ + Duration + + + + {getRelativeValue(item.end - item.start)} + +
+ + + <> + + Parameters + + {item.data.parameters?.map((item: any, index: number) => ( +
+ + {item.name} + + +
+ ))} + + + + { + item.data.result && ( +
+ + Result + + +
+ ) + } +
+
+
+ )} +
+
+ })} + +
+ +
+ + +} \ No newline at end of file From b368088cda7565864268377ca5498672577ac750 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Fri, 5 Jun 2026 00:18:37 +0200 Subject: [PATCH 06/54] feat: enhance FlowExecutionResultView with Gantt chart integration and memoized flow execution results --- .../flow/views/FlowExecutionResultView.tsx | 36 ++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/src/packages/ce/src/flow/views/FlowExecutionResultView.tsx b/src/packages/ce/src/flow/views/FlowExecutionResultView.tsx index 89f8257e..2ead8f05 100644 --- a/src/packages/ce/src/flow/views/FlowExecutionResultView.tsx +++ b/src/packages/ce/src/flow/views/FlowExecutionResultView.tsx @@ -1,6 +1,12 @@ import React from "react"; import {useParams} from "next/navigation"; -import {Flow, Namespace, NamespaceProject} from "@code0-tech/sagittarius-graphql-types"; +import { + Flow, + FunctionDefinition, + Namespace, + NamespaceProject, + NodeFunction +} from "@code0-tech/sagittarius-graphql-types"; import { Button, Card, @@ -42,6 +48,16 @@ import { } from "@code0-tech/pictor/dist/components/file-tabs/FileTabs"; import {Layout} from "@code0-tech/pictor/dist/components/layout/Layout"; import {formatDistanceToNow} from "date-fns"; +import {GanttItem} from "@code0-tech/pictor/dist/components/gantt/GanttItem"; + +export interface NodeGanttItem extends GanttItem { + data?: { + displayMessage: string + color: string + node: NodeFunction + function: FunctionDefinition + } +} export const FlowExecutionResultView: React.FC = () => { @@ -70,6 +86,24 @@ export const FlowExecutionResultView: React.FC = () => { [flow] ) + const activeFlowExecutionResult = React.useMemo( + () => flowExecutionResults.find?.(result => result?.id === activeTab), + [flowExecutionResults, activeTab] + ) + + const ganttItems = React.useMemo( + () => { + return [ + { + id: activeFlowExecutionResult?.id as string, + start: 0, + end: 0 + } + ] + }, + [] + ) + return <> Date: Fri, 5 Jun 2026 18:53:06 +0200 Subject: [PATCH 07/54] feat: update Project service and GraphQL schema to handle moduleConfigurations in runtime assignments --- .../ce/src/project/services/Project.service.ts | 11 +++-------- .../Project.updateModuleConfiguration.graphql | 9 +++++---- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/packages/ce/src/project/services/Project.service.ts b/src/packages/ce/src/project/services/Project.service.ts index af3813c2..668922c4 100644 --- a/src/packages/ce/src/project/services/Project.service.ts +++ b/src/packages/ce/src/project/services/Project.service.ts @@ -177,7 +177,7 @@ export class ProjectService extends ReactiveArrayService p.runtimeAssignments?.nodes?.map(rA => rA?.id).includes(payload.namespaceProjectRuntimeAssignmentId)) const index = super.values().findIndex(p => p.runtimeAssignments?.nodes?.map(rA => rA?.id).includes(payload.namespaceProjectRuntimeAssignmentId)) @@ -188,14 +188,9 @@ export class ProjectService extends ReactiveArrayService rA?.id !== payload.namespaceProjectRuntimeAssignmentId) ?? []), { - ...result?.data.namespacesProjectsRuntimeAssignmentsUpdateModuleConfigurations.namespaceProjectRuntimeAssignment, + ...(project?.runtimeAssignments?.nodes?.find(rA => rA?.id === payload.namespaceProjectRuntimeAssignmentId) ?? {}), moduleConfigurations: { - nodes: payload.moduleConfigurations.map((config, index) => { - return { - ...project?.runtimeAssignments?.nodes?.find(rA => rA?.id === payload.namespaceProjectRuntimeAssignmentId)?.moduleConfigurations?.nodes?.find(mC => mC?.definition?.id === config.moduleConfigurationDefinitionId), - value: config.value - } as ModuleConfiguration - }) + nodes: result.data.namespacesProjectsRuntimeAssignmentsUpdateModuleConfigurations.moduleConfigurations } } ] diff --git a/src/packages/ce/src/project/services/mutations/Project.updateModuleConfiguration.graphql b/src/packages/ce/src/project/services/mutations/Project.updateModuleConfiguration.graphql index 4546b9a0..17a6f87a 100644 --- a/src/packages/ce/src/project/services/mutations/Project.updateModuleConfiguration.graphql +++ b/src/packages/ce/src/project/services/mutations/Project.updateModuleConfiguration.graphql @@ -12,14 +12,15 @@ mutation projectUpdateModuleConfiguration($namespaceProjectRuntimeAssignmentId: } } } - namespaceProjectRuntimeAssignment { + moduleConfigurations { __typename id - compatible - updatedAt createdAt - runtime { + updatedAt + value + definition { id + identifier } } } From e59aed2065e90adc88d64a3f3a84b243d2f5556c Mon Sep 17 00:00:00 2001 From: nicosammito Date: Sat, 6 Jun 2026 01:04:17 +0200 Subject: [PATCH 08/54] feat: update PICTOR version to 0.10.3 in environment configuration --- .env.local | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.local b/.env.local index 08b5e666..f8c71bbc 100644 --- a/.env.local +++ b/.env.local @@ -4,7 +4,7 @@ NEXT_PUBLIC_EDITION=ce SAGITTARIUS_GRAPHQL_URL=http://localhost:80/graphql NEXT_PUBLIC_SCULPTOR_VERSION=0.0.0 -NEXT_PUBLIC_PICTOR_VERSION=0.9.2 +NEXT_PUBLIC_PICTOR_VERSION=0.10.3 NEXT_PUBLIC_ALLOWED_REDIRECT_DOMAINS=*.code0.tech,*.codezero.build NEXT_PUBLIC_OTEL_SERVICE_NAME=#"sculptor-client" From bf6dcf7214136ca846ecd78bcda39dd9be83a88b Mon Sep 17 00:00:00 2001 From: nicosammito Date: Sat, 6 Jun 2026 01:06:22 +0200 Subject: [PATCH 09/54] feat: enhance ApplicationBarView with dynamic navigation buttons and user namespace handling --- .../application/views/ApplicationBarView.tsx | 44 ++++++++++++++++--- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/src/packages/ce/src/application/views/ApplicationBarView.tsx b/src/packages/ce/src/application/views/ApplicationBarView.tsx index 2ed4a4ba..fc6f0a17 100644 --- a/src/packages/ce/src/application/views/ApplicationBarView.tsx +++ b/src/packages/ce/src/application/views/ApplicationBarView.tsx @@ -1,14 +1,16 @@ "use client" -import {Button, Flex, MenuItem, MenuSeparator, useService, useStore} from "@code0-tech/pictor"; +import {Button, Flex, MenuItem, MenuSeparator, Text, useService, useStore} from "@code0-tech/pictor"; import {UserService} from "@edition/user/services/User.service"; -import {useRouter} from "next/navigation"; +import {useParams, useRouter} from "next/navigation"; import React from "react"; import Link from "next/link"; import {IconBuilding, IconFolders, IconInbox, IconLogout, IconSearch, IconUser} from "@tabler/icons-react"; import {ApplicationBreadcrumbView} from "@edition/application/views/ApplicationBreadcrumbView"; import UserMenuComponent from "@edition/user/components/UserMenuComponent"; import {useUserSession} from "@edition/user/hooks/User.session.hook"; +import {Island} from "@code0-tech/pictor/dist/components/island/Island"; +import {ButtonGroup} from "@code0-tech/pictor/dist/components/button-group/ButtonGroup"; export const ApplicationBarView: React.FC = () => { @@ -17,10 +19,14 @@ export const ApplicationBarView: React.FC = () => { const userStore = useStore(UserService) const router = useRouter() const [loading, startTransition] = React.useTransition() + const params = useParams() + const namespaceIndex = params.namespaceId as string | undefined + const projectIndex = params.projectId as string | undefined const currentUser = React.useMemo(() => userService.getById(currentSession?.user?.id), [userStore, currentSession]) - const namespaceIndex = React.useMemo(() => currentUser?.namespace?.id?.match(/Namespace\/(\d+)$/)?.[1], [currentUser]) + const userNamespaceIndex = React.useMemo(() => currentUser?.namespace?.id?.match(/Namespace\/(\d+)$/)?.[1], [currentUser]) const userIndex = currentUser?.id?.match(/User\/(\d+)$/)?.[1] + const currentStep = projectIndex ? "project" : namespaceIndex ? "namespace" : "home"; const userMenu = React.useMemo(() => { @@ -51,7 +57,7 @@ export const ApplicationBarView: React.FC = () => { Organizations - + Personal Workspace @@ -61,10 +67,36 @@ export const ApplicationBarView: React.FC = () => { Logout - }, [currentUser, currentSession, namespaceIndex]) + }, [currentUser, currentSession, userNamespaceIndex]) - return + return + + + + + {namespaceIndex ? ( + + ) : (null as any)} + {namespaceIndex && projectIndex ? ( + + ) : (null as any)} + + + + - + )} From cd272342f4f0cc1860d4e17028f53fb3321b7e11 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Sat, 6 Jun 2026 01:07:18 +0200 Subject: [PATCH 15/54] feat: replace toast notifications with island notifications in FlowFolderView and optimize imports --- src/packages/ce/src/flow/views/FlowFolderView.tsx | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/packages/ce/src/flow/views/FlowFolderView.tsx b/src/packages/ce/src/flow/views/FlowFolderView.tsx index c41639b4..b8270c3c 100644 --- a/src/packages/ce/src/flow/views/FlowFolderView.tsx +++ b/src/packages/ce/src/flow/views/FlowFolderView.tsx @@ -5,7 +5,6 @@ import { Button, Flex, Text, - toast, Tooltip, TooltipArrow, TooltipContent, @@ -26,6 +25,7 @@ import { FlowFolderContextMenuComponentItemData } from "@edition/flow/components/folder/FlowFolderContextMenuComponent"; import {Layout} from "@code0-tech/pictor/dist/components/layout/Layout"; +import {addIslandSuccessNotification} from "@code0-tech/pictor/dist/components/island/Island.hook"; export const FlowFolderView: React.FC = () => { @@ -55,10 +55,8 @@ export const FlowFolderView: React.FC = () => { flowId: flow.id! }).then(payload => { if ((payload?.errors?.length ?? 0) <= 0) { - toast({ - title: "The flow was successfully deleted.", - color: "success", - dismissible: true, + addIslandSuccessNotification({ + message: "Deleted flow" }) router.push(`/namespace/${namespaceIndex}/project/${projectIndex}/flow`) } @@ -79,7 +77,8 @@ export const FlowFolderView: React.FC = () => { - - {getCurrentZoomInPercent()}% + {zoomDisplay} From d17478081d56912169036b02b76c6efd61a3521b Mon Sep 17 00:00:00 2001 From: nicosammito Date: Sat, 6 Jun 2026 02:14:29 +0200 Subject: [PATCH 33/54] feat: only import used methods --- .../ce/src/flow/components/builder/FlowBuilderComponent.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/packages/ce/src/flow/components/builder/FlowBuilderComponent.tsx b/src/packages/ce/src/flow/components/builder/FlowBuilderComponent.tsx index db2b3339..b92a592c 100644 --- a/src/packages/ce/src/flow/components/builder/FlowBuilderComponent.tsx +++ b/src/packages/ce/src/flow/components/builder/FlowBuilderComponent.tsx @@ -613,7 +613,7 @@ export const FlowBuilderComponent: React.FC = (props) => { const InternalFlowBuilder: React.FC = (props) => { const {flowId, namespaceId, projectId, ...rest} = props - const {setCenter, getInternalNode, getZoom} = useReactFlow(); + const {getZoom} = useReactFlow(); const nodeTypes = React.useMemo(() => ({ default: FunctionNodeDefaultComponent, From be3581dff4328eb6ff0d048c35f39d6e4ce24750 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Sat, 6 Jun 2026 02:14:42 +0200 Subject: [PATCH 34/54] feat: safari GPU acceleration --- .../builder/FlowBuilderComponent.style.scss | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/packages/ce/src/flow/components/builder/FlowBuilderComponent.style.scss b/src/packages/ce/src/flow/components/builder/FlowBuilderComponent.style.scss index 23cc1e64..4767bdfb 100644 --- a/src/packages/ce/src/flow/components/builder/FlowBuilderComponent.style.scss +++ b/src/packages/ce/src/flow/components/builder/FlowBuilderComponent.style.scss @@ -1,15 +1,29 @@ .flow { overflow: hidden; + position: relative; + + .react-flow__viewport { + will-change: transform; + -webkit-will-change: transform; + -webkit-font-smoothing: antialiased; + -webkit-text-size-adjust: 100%; + } &[data-tree-visibility=false] { .react-flow__node, .react-flow__edgelabel-renderer, .react-flow__edge { opacity: 0; + pointer-events: none; + will-change: opacity, stroke-dashoffset; + -webkit-will-change: opacity, stroke-dashoffset; } } &[data-tree-visibility=true] { .react-flow__node, .react-flow__edgelabel-renderer, .react-flow__edge { - opacity: 100%; + opacity: 1; + pointer-events: auto; + will-change: opacity, stroke-dashoffset; + -webkit-will-change: opacity, stroke-dashoffset; } } From b51357cfc2c4b336c73418941a50fb128f26b5b0 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Sat, 6 Jun 2026 02:33:04 +0200 Subject: [PATCH 35/54] feat: changed xxl from 2 to 3 --- src/packages/ce/src/module/pages/ModulesPage.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/packages/ce/src/module/pages/ModulesPage.tsx b/src/packages/ce/src/module/pages/ModulesPage.tsx index 0c6e91bb..bcdeafed 100644 --- a/src/packages/ce/src/module/pages/ModulesPage.tsx +++ b/src/packages/ce/src/module/pages/ModulesPage.tsx @@ -75,7 +75,7 @@ export const ModulesPage: React.FC = () => { const DisplayIcon = icon(module.icon as IconString) - return + return @@ -139,7 +139,7 @@ export const ModulesPage: React.FC = () => { }) } - + Are you missing a plugin? From ff94450277faa52eb57e9a7a6d87167962449706 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Sun, 7 Jun 2026 14:45:52 +0200 Subject: [PATCH 36/54] feat: removed execution result pagination --- src/packages/ce/src/flow/services/Flow.service.ts | 3 --- .../ce/src/flow/services/fragments/Flow.fragment.graphql | 6 +++++- .../ce/src/flow/services/queries/Flows.query.graphql | 3 --- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/packages/ce/src/flow/services/Flow.service.ts b/src/packages/ce/src/flow/services/Flow.service.ts index 3c67219a..a30d22cb 100644 --- a/src/packages/ce/src/flow/services/Flow.service.ts +++ b/src/packages/ce/src/flow/services/Flow.service.ts @@ -75,9 +75,6 @@ export class FlowService extends ReactiveArrayService Date: Sun, 7 Jun 2026 14:46:14 +0200 Subject: [PATCH 37/54] fix: problem with node update and change to selection state --- .../ce/src/flow/components/builder/FlowBuilderComponent.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/packages/ce/src/flow/components/builder/FlowBuilderComponent.tsx b/src/packages/ce/src/flow/components/builder/FlowBuilderComponent.tsx index b92a592c..11ec45b1 100644 --- a/src/packages/ce/src/flow/components/builder/FlowBuilderComponent.tsx +++ b/src/packages/ce/src/flow/components/builder/FlowBuilderComponent.tsx @@ -683,6 +683,7 @@ const InternalFlowBuilder: React.FC = (props) => { const localNodes = initialNodes.map(value => { const nodeEls = !value.measured ? document.querySelectorAll("[data-id='" + value.id + "']") : []; return { + ...nodes.find(node => node.id === value.id), ...value, measured: { width: value.measured?.width ?? (nodeEls[0] as any)?.clientWidth ?? 0, From d9598cd41e8e6ddc0352514665b1d3feaa4f61cc Mon Sep 17 00:00:00 2001 From: nicosammito Date: Sun, 7 Jun 2026 14:46:37 +0200 Subject: [PATCH 38/54] feat: Execution result view --- .../flow/views/FlowExecutionResultView.tsx | 892 ++++++------------ 1 file changed, 273 insertions(+), 619 deletions(-) diff --git a/src/packages/ce/src/flow/views/FlowExecutionResultView.tsx b/src/packages/ce/src/flow/views/FlowExecutionResultView.tsx index 2ead8f05..b79500c4 100644 --- a/src/packages/ce/src/flow/views/FlowExecutionResultView.tsx +++ b/src/packages/ce/src/flow/views/FlowExecutionResultView.tsx @@ -1,14 +1,18 @@ import React from "react"; import {useParams} from "next/navigation"; import { + ExecutionError, + ExecutionParameterResult, + ExecutionResult, Flow, - FunctionDefinition, + Maybe, Namespace, NamespaceProject, NodeFunction } from "@code0-tech/sagittarius-graphql-types"; import { Button, + ButtonGroup, Card, Flex, Gantt, @@ -30,15 +34,7 @@ import { withAlpha } from "@code0-tech/pictor"; import {FlowService} from "@edition/flow/services/Flow.service"; -import { - IconArrowRampRight2, - IconBrandDiscord, - IconBrandTeams, - IconDatabase, - IconPlayerPlayFilled, - IconPlus, - IconTextGrammar -} from "@tabler/icons-react"; +import {IconPlus} from "@tabler/icons-react"; import {Editor} from "@code0-tech/pictor/dist/components/editor/Editor"; import { FileTabs, @@ -47,15 +43,20 @@ import { FileTabsTrigger } from "@code0-tech/pictor/dist/components/file-tabs/FileTabs"; import {Layout} from "@code0-tech/pictor/dist/components/layout/Layout"; -import {formatDistanceToNow} from "date-fns"; import {GanttItem} from "@code0-tech/pictor/dist/components/gantt/GanttItem"; +import {FALLBACK_FLOW_TYPE_NAME, FALLBACK_FUNCTION_NAME} from "@core/util/fallback-translations"; +import {FunctionService} from "@edition/function/services/Function.service"; +import {ProjectService} from "@edition/project/services/Project.service"; +import Link from "next/link"; export interface NodeGanttItem extends GanttItem { data?: { displayMessage: string color: string - node: NodeFunction - function: FunctionDefinition + node?: Maybe + input?: ExecutionParameterResult[] | object + success?: object + error?: Maybe } } @@ -64,6 +65,10 @@ export const FlowExecutionResultView: React.FC = () => { const params = useParams() const flowService = useService(FlowService) const flowStore = useStore(FlowService) + const functionService = useService(FunctionService) + const functionStore = useStore(FunctionService) + const projectService = useService(ProjectService) + const projectStore = useStore(ProjectService) const [activeTab, setActiveTab] = React.useState() const namespaceIndex = params.namespaceId as any as number @@ -81,25 +86,61 @@ export const FlowExecutionResultView: React.FC = () => { [flowStore, namespaceId, projectId, flowId] ) - const flowExecutionResults = React.useMemo( - () => flow?.executionResults?.nodes ?? [], - [flow] + const project = React.useMemo( + () => projectService.getById(projectId, {namespaceId}), + [projectId, projectStore] ) - const activeFlowExecutionResult = React.useMemo( - () => flowExecutionResults.find?.(result => result?.id === activeTab), - [flowExecutionResults, activeTab] + const functions = React.useMemo( + () => functionService.values({ + namespaceId, + projectId, + runtimeId: project?.primaryRuntime?.id + }), + [project, functionStore] ) - const ganttItems = React.useMemo( + const flowExecutionResults = React.useMemo( + () => flow?.executionResults?.nodes ?? [], + [flow?.executionResults?.nodes] + ) + + const ganttItems = React.useMemo>( () => { - return [ + return new Map(flowExecutionResults.map(result => [result?.id, [ { - id: activeFlowExecutionResult?.id as string, + id: result?.id as string, + type: "trigger", start: 0, - end: 0 - } - ] + end: 0, + data: { + displayMessage: result?.flow?.name ?? FALLBACK_FLOW_TYPE_NAME, + color: hashToColor(result?.flow?.name ?? ""), + success: result?.success, + input: result?.input, + error: result?.error, + } + }, + ...(result?.nodeResults?.nodes?.map?.(nodeResult => { + return { + id: nodeResult?.id as string, + type: "node", + start: 0, + end: 0, + data: { + displayMessage: nodeResult?.nodeFunction?.functionDefinition?.names?.[0].content ?? FALLBACK_FUNCTION_NAME, + color: hashToColor(nodeResult?.nodeFunction?.id ?? ""), + node: { + ...flow?.nodes?.nodes?.find(n => n?.id === nodeResult?.nodeFunction?.id), + functionDefinition: functions.find(f => f.id === nodeResult?.nodeFunction?.functionDefinition?.id) + }, + success: nodeResult?.success, + input: nodeResult?.parameterResults ?? [], + error: nodeResult?.error, + } + } + }) ?? []) + ]])) }, [] ) @@ -113,624 +154,237 @@ export const FlowExecutionResultView: React.FC = () => { > - - - - - - {flowExecutionResults.map(result => { - return { - setActiveTab(result?.id!) - }}> - - {result?.id} - - - })} - - - + ganttItems.size > 0 ? ( + + + + + + + {flowExecutionResults.map(result => { + return { + setActiveTab(result?.id!) + }}> + + {result?.id} + + + })} + + + + ) : null } > - - - - #1 - - - {formatDistanceToNow("Thu Jun 04 2026 17:56:20 GMT+0000")} ago - - - {flowExecutionResults.map(result => { - return + {Array.from(ganttItems)?.map(([id]) => { + return - {result?.id} + {id} })} }> <> - - - {(item) => item.type === "group" ? ( - { - const element = document.getElementById(`group-target-${item.data.displayMessage}`) - element?.scrollIntoView({behavior: "smooth"}) - }}> - - <> - - - ) : ( - - + { + ganttItems.size > 0 ? Array.from(ganttItems)?.map(([id, items]) => { + return + + {(item) => item.type === "group" ? ( - { + const element = document.getElementById(`group-target-${item.data.displayMessage}`) + element?.scrollIntoView({behavior: "smooth"}) + }}> + - - + <> + + + ) : ( + + + + + + + {item.data.icon && React.createElement(item.data.icon, { + color: hashToColor(item.id), + size: 16, + style: {minWidth: "13px", minHeight: "13px"} + })} + + {item.data.displayMessage} + + + + {getRelativeValue(item.end - item.start)} + + + + + + + + {item.data.icon && React.createElement(item.data.icon, { color: hashToColor(item.id), size: 16, - style: {minWidth: "13px", minHeight: "13px"} + style: { + minWidth: "16px", + minHeight: "16px", + marginTop: "2px" + } })} {item.data.displayMessage} - - {getRelativeValue(item.end - item.start)} - - - - - - - - - {item.data.icon && React.createElement(item.data.icon, { - color: hashToColor(item.id), - size: 16, - style: {minWidth: "16px", minHeight: "16px", marginTop: "2px"} - })} - - {item.data.displayMessage} - - - - - - - - - - - - - - - - - - -
- - Start time - - - - {getRelativeValue(item.start)} - -
- - End time - - - - {getRelativeValue(item.end)} - -
- - Duration - - - - {getRelativeValue(item.end - item.start)} - -
- + + + + + + + + + + + + + + + + +
+ + Start time + + + + {getRelativeValue(item.start)} + +
+ + End time + + + + {getRelativeValue(item.end)} + +
+ + Duration + + + + {getRelativeValue(item.end - item.start)} + +
+ - <> - - Parameters - - {item.data.parameters?.map((item: any, index: number) => ( -
- - {item.name} - - -
- ))} - - - - { - item.data.result && ( -
+ <> - Result - - -
- ) - } -
-
- - )} - - - {flowExecutionResults.map(result => { - return - - {(item) => item.type === "group" ? ( - { - const element = document.getElementById(`group-target-${item.data.displayMessage}`) - element?.scrollIntoView({behavior: "smooth"}) - }}> - - <> - - - ) : ( - - - - - - - {item.data.icon && React.createElement(item.data.icon, { - color: hashToColor(item.id), - size: 16, - style: {minWidth: "13px", minHeight: "13px"} - })} - - {item.data.displayMessage} - - - - {getRelativeValue(item.end - item.start)} + Parameters - - - - - - - - {item.data.icon && React.createElement(item.data.icon, { - color: hashToColor(item.id), - size: 16, - style: {minWidth: "16px", minHeight: "16px", marginTop: "2px"} - })} - - {item.data.displayMessage} - - - - - - - - - - - - - - - - - - -
- - Start time - - - - {getRelativeValue(item.start)} - -
- - End time - - - - {getRelativeValue(item.end)} - -
- - Duration - - - - {getRelativeValue(item.end - item.start)} - -
- + {item.data.parameters?.map((item: any, index: number) => ( +
+ + {item.name} + + +
+ ))} + - <> - - Parameters - - {item.data.parameters?.map((item: any, index: number) => ( -
- - {item.name} - - -
- ))} - - - - { - item.data.result && ( -
- - Result - - -
- ) - } -
-
-
- )} -
-
- })} + + { + item.data.result && ( +
+ + Result + + +
+ ) + } + + + + )} + + + }) : ( + + + + No execution results available + + + + To see the execution results, you need to execute the flow at least once.
+ Once you have execution results, they will be displayed here in a Gantt chart. +
+ + + + + + + +
+
+ ) + }
From b1a44a6bac01175a6705350cc6b807164f0bdd8e Mon Sep 17 00:00:00 2001 From: nicosammito Date: Sun, 7 Jun 2026 14:47:04 +0200 Subject: [PATCH 39/54] feat: showing active tab for current selected node --- .../files/FunctionFilesComponent.tsx | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/packages/ce/src/function/components/files/FunctionFilesComponent.tsx b/src/packages/ce/src/function/components/files/FunctionFilesComponent.tsx index faad1e40..84709c8a 100644 --- a/src/packages/ce/src/function/components/files/FunctionFilesComponent.tsx +++ b/src/packages/ce/src/function/components/files/FunctionFilesComponent.tsx @@ -2,6 +2,7 @@ import React from "react"; import {Flow, Namespace, NamespaceProject, NodeFunction} from "@code0-tech/sagittarius-graphql-types"; import { Button, + Flex, hashToColor, Menu, MenuContent, @@ -10,6 +11,7 @@ import { MenuPortal, MenuSeparator, MenuTrigger, + Spacing, Text, useService, useStore @@ -51,7 +53,7 @@ export const FunctionFilesComponent: React.FC = (pr const functionStore = useStore(FunctionService) const id = React.useId() - const [activeTab, setActiveTab] = React.useState() + const [activeTab, setActiveTab] = React.useState(undefined) const reactFlow = useReactFlow() const selectedNode = useSelectedFunctionNode() @@ -99,7 +101,7 @@ export const FunctionFilesComponent: React.FC = (pr }, [activeTab]) React.useEffect(() => { - if (selectedNode) setActiveTab(selectedNode.id) + setActiveTab(selectedNode?.id ?? undefined) }, [selectedNode?.id]) return ( @@ -168,6 +170,24 @@ export const FunctionFilesComponent: React.FC = (pr } }> <> + { + !activeTab ? ( + + + + Select a node for editing + + + + To edit the properties of a node, select the node in the flow editor or select + it from the list of nodes in the dropdown above. + + + + ) : null + } Date: Sun, 7 Jun 2026 14:47:18 +0200 Subject: [PATCH 40/54] feat: updating triangulum --- package-lock.json | 16 ++++++++-------- package.json | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index b87e56b9..5d65c254 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "dependencies": { "@apollo/client": "^4.0.9", "@code0-tech/pictor": "^0.10.3", - "@code0-tech/triangulum": "^0.20.0", + "@code0-tech/triangulum": "^0.21.0", "@codemirror/lang-javascript": "^6.2.5", "@codemirror/lint": "^6.9.5", "@opentelemetry/api": "^1.9.1", @@ -458,17 +458,17 @@ } }, "node_modules/@code0-tech/sagittarius-graphql-types": { - "version": "0.0.0-experimental-2571203559-cd92ea1ca9e0c8a1b3d725241b811bdc01f93e2a", - "resolved": "https://registry.npmjs.org/@code0-tech/sagittarius-graphql-types/-/sagittarius-graphql-types-0.0.0-experimental-2571203559-cd92ea1ca9e0c8a1b3d725241b811bdc01f93e2a.tgz", - "integrity": "sha512-BghG80JfwZO5Ec0n7Ph50hhuws4YEIVUnVeZ6vio4KRJN4rYxG41TsU25Pic4MKS8OdCLwcRaXN/zXZDkif6Cw==", + "version": "0.0.0-experimental-2582109569-38e1d72f4da56c283939e29bd04569a23f5a608f", + "resolved": "https://registry.npmjs.org/@code0-tech/sagittarius-graphql-types/-/sagittarius-graphql-types-0.0.0-experimental-2582109569-38e1d72f4da56c283939e29bd04569a23f5a608f.tgz", + "integrity": "sha512-2ftpmlRDRPtMchkAU9bV2Bbntbv2Zq9JvQRP1LWAeCcswp2xXAOZMqqu6utIoUK0bkELa2dinFOAvFXplTvvag==", "peer": true }, "node_modules/@code0-tech/triangulum": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@code0-tech/triangulum/-/triangulum-0.20.0.tgz", - "integrity": "sha512-rW65ogVUB8mM44ZRnMCsWy++fChbWhZuu5WyxV1pOOoKpKvodNIbY7AVFEjw8Kt702W3kCY7LLatn43UwTfyhQ==", + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/@code0-tech/triangulum/-/triangulum-0.21.0.tgz", + "integrity": "sha512-YROmoNf6/dH0JIMXyoEzgiEKSZrxVTB59kBEMQgxLz5aFqPVGBXU9d2TAsohTggK9CXGqRvExRKja9GqQirn0w==", "peerDependencies": { - "@code0-tech/sagittarius-graphql-types": "0.0.0-experimental-2571203559-cd92ea1ca9e0c8a1b3d725241b811bdc01f93e2a", + "@code0-tech/sagittarius-graphql-types": "0.0.0-experimental-2582109569-38e1d72f4da56c283939e29bd04569a23f5a608f", "@typescript/vfs": "^1.6.4", "lossless-json": "^4.3.0", "typescript": "^5.9.3 || ^6.0.2" diff --git a/package.json b/package.json index 0298e678..1f9cd5c2 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "dependencies": { "@apollo/client": "^4.0.9", "@code0-tech/pictor": "^0.10.3", - "@code0-tech/triangulum": "^0.20.0", + "@code0-tech/triangulum": "^0.21.0", "@codemirror/lang-javascript": "^6.2.5", "@codemirror/lint": "^6.9.5", "@opentelemetry/api": "^1.9.1", From 66bf0a47b0b6529f876ceb2dd6e5cbe007eee85e Mon Sep 17 00:00:00 2001 From: nicosammito Date: Sun, 7 Jun 2026 14:49:34 +0200 Subject: [PATCH 41/54] feat: removed unnecessary tranisation --- .../panels/FlowPanelUpdateComponent.tsx | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/packages/ce/src/flow/components/panels/FlowPanelUpdateComponent.tsx b/src/packages/ce/src/flow/components/panels/FlowPanelUpdateComponent.tsx index f77ce92d..9f1f71aa 100644 --- a/src/packages/ce/src/flow/components/panels/FlowPanelUpdateComponent.tsx +++ b/src/packages/ce/src/flow/components/panels/FlowPanelUpdateComponent.tsx @@ -47,17 +47,15 @@ export const FlowPanelUpdateComponent: React.FC = if (!flowId) return - startTransition(async () => { - flowService.flowUpdate({ - flowInput: flowInput!, - flowId: flowId! - }).then(payload => { - if ((payload?.errors?.length ?? 0) <= 0) { - addIslandSuccessNotification({ - message: "Synced flow" - }) - } - }) + flowService.flowUpdate({ + flowInput: flowInput!, + flowId: flowId! + }).then(payload => { + if ((payload?.errors?.length ?? 0) <= 0) { + addIslandSuccessNotification({ + message: "Synced flow" + }) + } }) }, [flowId, flowService]) From 61442cf4bc8dbc059b9ee5b887f11973f6091d02 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Sun, 7 Jun 2026 19:46:50 +0200 Subject: [PATCH 42/54] feat: changes to execution view --- .../flow/views/FlowExecutionResultView.tsx | 332 +++++++++--------- 1 file changed, 172 insertions(+), 160 deletions(-) diff --git a/src/packages/ce/src/flow/views/FlowExecutionResultView.tsx b/src/packages/ce/src/flow/views/FlowExecutionResultView.tsx index b79500c4..91d01e58 100644 --- a/src/packages/ce/src/flow/views/FlowExecutionResultView.tsx +++ b/src/packages/ce/src/flow/views/FlowExecutionResultView.tsx @@ -8,7 +8,8 @@ import { Maybe, Namespace, NamespaceProject, - NodeFunction + NodeFunction, + ParameterDefinition } from "@code0-tech/sagittarius-graphql-types"; import { Button, @@ -34,7 +35,7 @@ import { withAlpha } from "@code0-tech/pictor"; import {FlowService} from "@edition/flow/services/Flow.service"; -import {IconPlus} from "@tabler/icons-react"; +import {IconPlayerPlayFilled, IconPlus} from "@tabler/icons-react"; import {Editor} from "@code0-tech/pictor/dist/components/editor/Editor"; import { FileTabs, @@ -48,12 +49,15 @@ import {FALLBACK_FLOW_TYPE_NAME, FALLBACK_FUNCTION_NAME} from "@core/util/fallba import {FunctionService} from "@edition/function/services/Function.service"; import {ProjectService} from "@edition/project/services/Project.service"; import Link from "next/link"; +import {FlowTypeService} from "@edition/flowtype/services/FlowType.service"; +import {icon} from "@core/util/icons"; +import {formatDistanceToNow} from "date-fns"; export interface NodeGanttItem extends GanttItem { data?: { displayMessage: string color: string - node?: Maybe + payload?: Maybe | Maybe input?: ExecutionParameterResult[] | object success?: object error?: Maybe @@ -67,6 +71,8 @@ export const FlowExecutionResultView: React.FC = () => { const flowStore = useStore(FlowService) const functionService = useService(FunctionService) const functionStore = useStore(FunctionService) + const flowTypeService = useService(FlowTypeService) + const flowTypeStore = useStore(FlowTypeService) const projectService = useService(ProjectService) const projectStore = useStore(ProjectService) const [activeTab, setActiveTab] = React.useState() @@ -91,6 +97,15 @@ export const FlowExecutionResultView: React.FC = () => { [projectId, projectStore] ) + const flowTypes = React.useMemo( + () => flowTypeService.values({ + namespaceId, + projectId, + runtimeId: project?.primaryRuntime?.id + }), + [project, flowTypeStore] + ) + const functions = React.useMemo( () => functionService.values({ namespaceId, @@ -101,7 +116,7 @@ export const FlowExecutionResultView: React.FC = () => { ) const flowExecutionResults = React.useMemo( - () => flow?.executionResults?.nodes ?? [], + () => [...(flow?.executionResults?.nodes ?? [])]?.reverse() ?? [], [flow?.executionResults?.nodes] ) @@ -112,27 +127,35 @@ export const FlowExecutionResultView: React.FC = () => { id: result?.id as string, type: "trigger", start: 0, - end: 0, + end: (result?.finishedAt ?? 0) - (result?.startedAt ?? 0), data: { - displayMessage: result?.flow?.name ?? FALLBACK_FLOW_TYPE_NAME, + displayMessage: flowTypes.find(fT => fT.id === flow?.type?.id)?.names?.[0].content ?? FALLBACK_FLOW_TYPE_NAME, color: hashToColor(result?.flow?.name ?? ""), + payload: { + ...flow, + type: flowTypes.find(fT => fT.id === flow?.type?.id) + }, success: result?.success, input: result?.input, error: result?.error, } }, ...(result?.nodeResults?.nodes?.map?.(nodeResult => { + + const node = flow?.nodes?.nodes?.find(n => n?.id === nodeResult?.nodeFunction?.id) + const funktion = functions.find(f => f.id === nodeResult?.nodeFunction?.functionDefinition?.id) + return { id: nodeResult?.id as string, type: "node", - start: 0, - end: 0, + start: (nodeResult?.startedAt ?? 0) - (result?.startedAt ?? 0), + end: (nodeResult?.finishedAt ?? 0) - (result?.startedAt ?? 0), data: { - displayMessage: nodeResult?.nodeFunction?.functionDefinition?.names?.[0].content ?? FALLBACK_FUNCTION_NAME, + displayMessage: funktion?.names?.[0].content ?? FALLBACK_FUNCTION_NAME, color: hashToColor(nodeResult?.nodeFunction?.id ?? ""), - node: { - ...flow?.nodes?.nodes?.find(n => n?.id === nodeResult?.nodeFunction?.id), - functionDefinition: functions.find(f => f.id === nodeResult?.nodeFunction?.functionDefinition?.id) + payload: { + ...node, + functionDefinition: funktion }, success: nodeResult?.success, input: nodeResult?.parameterResults ?? [], @@ -142,12 +165,13 @@ export const FlowExecutionResultView: React.FC = () => { }) ?? []) ]])) }, - [] + [flowExecutionResults, flowTypes, flow, functions] ) return <> { setActiveTab(value) }} @@ -178,12 +202,21 @@ export const FlowExecutionResultView: React.FC = () => { ) : null } > - {Array.from(ganttItems)?.map(([id]) => { + {Array.from(ganttItems)?.map(([id, items]) => { + + const execution = flowExecutionResults.find(execution => execution?.id === id) + return - - {id} - + + + + #{id?.match(/ExecutionResult\/(\d+)$/)?.[1]} + + + {formatDistanceToNow(execution?.createdAt ?? "")} + + })} }> @@ -195,166 +228,145 @@ export const FlowExecutionResultView: React.FC = () => { value={id!} key={id}> - {(item) => item.type === "group" ? ( - { - const element = document.getElementById(`group-target-${item.data.displayMessage}`) - element?.scrollIntoView({behavior: "smooth"}) - }}> - - <> - - - ) : ( - - - - - - - {item.data.icon && React.createElement(item.data.icon, { - color: hashToColor(item.id), - size: 16, - style: {minWidth: "13px", minHeight: "13px"} - })} + {(item) => { + + if (item.type === "group") { + return { + const element = document.getElementById(`group-target-${item.data.displayMessage}`) + element?.scrollIntoView({behavior: "smooth"}) + }}> + + <> + + + } else { + + const DisplayIcon = icon( + item.type === "node" ? item?.data?.payload?.functionDefinition?.displayIcon : item?.data?.payload?.type?.displayIcon, + ) + + return + + + + + + + + {item.data.displayMessage} + + + + {getRelativeValue(item.end - item.start)} + + + + + + + + + + - {item.data.displayMessage} + {item?.data?.displayMessage} - + {getRelativeValue(item.end - item.start)} - - - - - - - {item.data.icon && React.createElement(item.data.icon, { - color: hashToColor(item.id), - size: 16, - style: { - minWidth: "16px", - minHeight: "16px", - marginTop: "2px" - } - })} - - {item.data.displayMessage} - - - - - - - - - - - - - - - - - - -
- - Start time - - - - {getRelativeValue(item.start)} - -
- - End time - - - - {getRelativeValue(item.end)} - -
- - Duration - - - - {getRelativeValue(item.end - item.start)} - -
- + - <> - - Parameters - - {item.data.parameters?.map((item: any, index: number) => ( -
- - {item.name} - - -
- ))} - + <> + + {item.type === "node" ? "Parameters" : "Input"} + + {item.type === "node" ? item.data.input?.map((input: ExecutionParameterResult, index: number) => { - - { - item.data.result && ( -
- - Result - + const parameter: ParameterDefinition = item?.data?.payload?.functionDefinition?.parameterDefinitions?.nodes?.[index] + + return
+ + {parameter?.names?.[0]?.content} + + +
+ + }) : item.type === "trigger" ? ( -
- ) - } -
-
-
- )} + ) : null} + + + + { + item.data.success && ( +
+ + Result + + +
+ ) + } + + + + } + }}
}) : ( From c5b6f3ff8b3e55aebe6712f8785f2127dafd8541 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Sun, 7 Jun 2026 19:47:07 +0200 Subject: [PATCH 43/54] feat: adding value display to trigger node --- .../nodes/FunctionNodeTriggerComponent.tsx | 62 +++++++++++++++++-- 1 file changed, 58 insertions(+), 4 deletions(-) diff --git a/src/packages/ce/src/function/components/nodes/FunctionNodeTriggerComponent.tsx b/src/packages/ce/src/function/components/nodes/FunctionNodeTriggerComponent.tsx index 2afd13ff..bd737d58 100644 --- a/src/packages/ce/src/function/components/nodes/FunctionNodeTriggerComponent.tsx +++ b/src/packages/ce/src/function/components/nodes/FunctionNodeTriggerComponent.tsx @@ -7,10 +7,13 @@ import {FlowService} from "@edition/flow/services/Flow.service"; import {IconVariable} from "@tabler/icons-react"; import {NodeFunction} from "@code0-tech/sagittarius-graphql-types"; import {icon, IconString} from "@core/util/icons"; -import {FALLBACK_FLOW_TYPE_DISPLAY_MESSAGE} from "@core/util/fallback-translations"; +import {FALLBACK_FLOW_TYPE_DISPLAY_MESSAGE, FALLBACK_FLOW_TYPE_NAME} from "@core/util/fallback-translations"; import {useFlowValidation} from "@edition/flow/hooks/Flow.validation.hook"; import {underlineBySeverity} from "@core/util/inspection"; import {useSelectedFunctionNode} from "@edition/function/hooks/FunctionNode.selected.hook"; +import {LiteralBadgeComponent} from "@edition/datatype/components/badges/LiteralBadgeComponent"; +import {ReferenceBadgeComponent} from "@edition/datatype/components/badges/ReferenceBadgeComponent"; +import {NodeBadgeComponent} from "@edition/datatype/components/badges/NodeBadgeComponent"; export type FunctionNodeTriggerComponentProps = NodeProps> @@ -40,6 +43,59 @@ export const FunctionNodeTriggerComponent: React.FC + str + .split(/(\$\{[^}]+\})/) + .filter(Boolean) + .flatMap(part => + part.startsWith("${") + ? [part.slice(2, -1)] // variable name ohne ${} + : part.split(/(\s*,\s*)/) // Kommas einzeln extrahieren + .filter(Boolean) + .flatMap(p => p.trim() === "," ? [","] : p.trim() ? [p.trim()] : []) + ) + + const displayMessage = React.useMemo(() => splitTemplate(definition?.displayMessages?.[0]?.content ?? FALLBACK_FLOW_TYPE_DISPLAY_MESSAGE).map(item => { + + const nodeParameter = flow?.settings?.nodes?.find((_, index) => { + const parameterDefinition = definition?.flowTypeSettings?.[index] + return parameterDefinition?.identifier == item + }) + + const parameterDefinition = definition?.flowTypeSettings?.find(pd => pd?.identifier == item) + const parameterIndex = parameterDefinition ? definition?.flowTypeSettings?.findIndex(p => p?.id === parameterDefinition.id) : undefined + const parameterValidation = validation?.filter(v => v.parameterIndex === parameterIndex && !v.nodeId) + const decorationStyle: CSSProperties = + parameterValidation?.length + ? underlineBySeverity[parameterValidation[0].type] + : {}; + + if (parameterDefinition) { + switch (nodeParameter?.value?.__typename) { + case "LiteralValue": + return
+ +
+ case "ReferenceValue": + return
+ +
+ case "SubFlowValue": + return
+ +
+ } + return
+ + + {item} + + +
+ } + return " " + String(item) + " " + }), [flowStore, data, definition, validation]) + const isReferenced = React.useMemo(() => { const activeNode = flowService.getNodeById(data.flowId, selectedNode?.id as NodeFunction['id']) @@ -75,9 +131,7 @@ export const FunctionNodeTriggerComponent: React.FC - - {definition?.displayMessages?.[0]?.content ?? FALLBACK_FLOW_TYPE_DISPLAY_MESSAGE} - + {flow ? displayMessage : definition?.names?.[0].content ?? FALLBACK_FLOW_TYPE_NAME} { From dca33c5702debe5e489ec218cb16677244dcdb45 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Tue, 9 Jun 2026 15:40:52 +0200 Subject: [PATCH 44/54] feat: updating triangulum and adding usehook library --- package-lock.json | 30 ++++++++++++++++++++++-------- package.json | 3 ++- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5d65c254..faeec56f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "dependencies": { "@apollo/client": "^4.0.9", "@code0-tech/pictor": "^0.10.3", - "@code0-tech/triangulum": "^0.21.0", + "@code0-tech/triangulum": "^0.22.0", "@codemirror/lang-javascript": "^6.2.5", "@codemirror/lint": "^6.9.5", "@opentelemetry/api": "^1.9.1", @@ -21,6 +21,7 @@ "@opentelemetry/instrumentation-fetch": "^0.218.0", "@opentelemetry/instrumentation-xml-http-request": "^0.218.0", "@opentelemetry/sdk-trace-web": "^2.6.1", + "@uidotdev/usehooks": "^2.4.1", "@vercel/otel": "^2.1.1", "@xyflow/react": "^12.11.0", "date-fns": "^4.1.0", @@ -458,17 +459,17 @@ } }, "node_modules/@code0-tech/sagittarius-graphql-types": { - "version": "0.0.0-experimental-2582109569-38e1d72f4da56c283939e29bd04569a23f5a608f", - "resolved": "https://registry.npmjs.org/@code0-tech/sagittarius-graphql-types/-/sagittarius-graphql-types-0.0.0-experimental-2582109569-38e1d72f4da56c283939e29bd04569a23f5a608f.tgz", - "integrity": "sha512-2ftpmlRDRPtMchkAU9bV2Bbntbv2Zq9JvQRP1LWAeCcswp2xXAOZMqqu6utIoUK0bkELa2dinFOAvFXplTvvag==", + "version": "0.0.0-experimental-2585797094-74c645eca45310e3506df6a95c4fab1a2d6abbc7", + "resolved": "https://registry.npmjs.org/@code0-tech/sagittarius-graphql-types/-/sagittarius-graphql-types-0.0.0-experimental-2585797094-74c645eca45310e3506df6a95c4fab1a2d6abbc7.tgz", + "integrity": "sha512-nWg7Jb1bKd49fTb2vGuKk0KPN9mkM+y2EK4z8VVNk21J2xwIb47NazJuP9V8o4WZgCbg4d486IqHDRa5uJweiQ==", "peer": true }, "node_modules/@code0-tech/triangulum": { - "version": "0.21.0", - "resolved": "https://registry.npmjs.org/@code0-tech/triangulum/-/triangulum-0.21.0.tgz", - "integrity": "sha512-YROmoNf6/dH0JIMXyoEzgiEKSZrxVTB59kBEMQgxLz5aFqPVGBXU9d2TAsohTggK9CXGqRvExRKja9GqQirn0w==", + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@code0-tech/triangulum/-/triangulum-0.22.0.tgz", + "integrity": "sha512-XF1MnG8IA2LvJ0IhA/YBzcH8meXUUpJ5gSwOpABhD8H0Fb4IJPynwm1KmMh977fTAH7j+aD6RpEqdZTU8NUw1w==", "peerDependencies": { - "@code0-tech/sagittarius-graphql-types": "0.0.0-experimental-2582109569-38e1d72f4da56c283939e29bd04569a23f5a608f", + "@code0-tech/sagittarius-graphql-types": "0.0.0-experimental-2585797094-74c645eca45310e3506df6a95c4fab1a2d6abbc7", "@typescript/vfs": "^1.6.4", "lossless-json": "^4.3.0", "typescript": "^5.9.3 || ^6.0.2" @@ -3794,6 +3795,19 @@ "typescript": "*" } }, + "node_modules/@uidotdev/usehooks": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@uidotdev/usehooks/-/usehooks-2.4.1.tgz", + "integrity": "sha512-1I+RwWyS+kdv3Mv0Vmc+p0dPYH0DTRAo04HLyXReYBL9AeseDWUJyi4THuksBJcu9F0Pih69Ak150VDnqbVnXg==", + "license": "MIT", + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, "node_modules/@uiw/codemirror-extensions-basic-setup": { "version": "4.25.10", "resolved": "https://registry.npmjs.org/@uiw/codemirror-extensions-basic-setup/-/codemirror-extensions-basic-setup-4.25.10.tgz", diff --git a/package.json b/package.json index 1f9cd5c2..c81b86a4 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "dependencies": { "@apollo/client": "^4.0.9", "@code0-tech/pictor": "^0.10.3", - "@code0-tech/triangulum": "^0.21.0", + "@code0-tech/triangulum": "^0.22.0", "@codemirror/lang-javascript": "^6.2.5", "@codemirror/lint": "^6.9.5", "@opentelemetry/api": "^1.9.1", @@ -27,6 +27,7 @@ "@opentelemetry/instrumentation-fetch": "^0.218.0", "@opentelemetry/instrumentation-xml-http-request": "^0.218.0", "@opentelemetry/sdk-trace-web": "^2.6.1", + "@uidotdev/usehooks": "^2.4.1", "@vercel/otel": "^2.1.1", "@xyflow/react": "^12.11.0", "date-fns": "^4.1.0", From b517b56121372cf3c4e81b7f4790a455570d7349 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Tue, 9 Jun 2026 15:41:13 +0200 Subject: [PATCH 45/54] feat: adding support for module definitons --- .../ce/src/module/services/Module.service.ts | 5 ++++- .../services/fragments/Module.fragment.graphql | 12 ++++++++++++ .../fragments/ModuleDefinition.fragment.graphql | 9 +++++++++ .../module/services/queries/Modules.query.graphql | 2 ++ 4 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 src/packages/ce/src/module/services/fragments/ModuleDefinition.fragment.graphql diff --git a/src/packages/ce/src/module/services/Module.service.ts b/src/packages/ce/src/module/services/Module.service.ts index 4283f331..3ea3fe42 100644 --- a/src/packages/ce/src/module/services/Module.service.ts +++ b/src/packages/ce/src/module/services/Module.service.ts @@ -40,7 +40,10 @@ export class ModuleService extends ReactiveArrayService { const nodes = res.data?.namespace?.project?.runtimes?.nodes?.flatMap(runtime => runtime?.modules?.nodes ?? []) ?? [] diff --git a/src/packages/ce/src/module/services/fragments/Module.fragment.graphql b/src/packages/ce/src/module/services/fragments/Module.fragment.graphql index 5c0040c4..500fbb35 100644 --- a/src/packages/ce/src/module/services/fragments/Module.fragment.graphql +++ b/src/packages/ce/src/module/services/fragments/Module.fragment.graphql @@ -1,4 +1,5 @@ #import "@edition/module/services/fragments/ModuleConfiguration.fragment.graphql" +#import "@edition/module/services/fragments/ModuleDefinition.fragment.graphql" fragment Module on RuntimeModule { __typename @@ -30,6 +31,17 @@ fragment Module on RuntimeModule { functionDefinitions { count } + definitions(first: $firstDefinition, after: $afterDefinition) { + __typename + count + nodes { + ...ModuleDefinition + } + pageInfo { + endCursor + hasNextPage + } + } configurationDefinitions (first: $firstConfiguration, after: $afterConfiguration) { __typename count diff --git a/src/packages/ce/src/module/services/fragments/ModuleDefinition.fragment.graphql b/src/packages/ce/src/module/services/fragments/ModuleDefinition.fragment.graphql new file mode 100644 index 00000000..b6ffd859 --- /dev/null +++ b/src/packages/ce/src/module/services/fragments/ModuleDefinition.fragment.graphql @@ -0,0 +1,9 @@ +fragment ModuleDefinition on RuntimeModuleDefinition { + __typename + id + createdAt + updatedAt + endpoint + host + port +} \ 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 index 3847242c..427afc94 100644 --- a/src/packages/ce/src/module/services/queries/Modules.query.graphql +++ b/src/packages/ce/src/module/services/queries/Modules.query.graphql @@ -9,6 +9,8 @@ query Modules ( $afterModule: String $firstConfiguration: Int! $afterConfiguration: String + $firstDefinition: Int! + $afterDefinition: String ) { namespace(id: $namespaceId) { project(id: $projectId) { From e76f6766e86c792eecd935bc14692691b598f38f Mon Sep 17 00:00:00 2001 From: nicosammito Date: Tue, 9 Jun 2026 15:41:29 +0200 Subject: [PATCH 46/54] feat: showing primary endpoint --- .../panels/FlowPanelControlComponent.tsx | 125 +++++++++++++++++- .../nodes/FunctionNodeTriggerComponent.tsx | 95 ++++++++++--- 2 files changed, 196 insertions(+), 24 deletions(-) diff --git a/src/packages/ce/src/flow/components/panels/FlowPanelControlComponent.tsx b/src/packages/ce/src/flow/components/panels/FlowPanelControlComponent.tsx index 68c277f5..23e75fa2 100644 --- a/src/packages/ce/src/flow/components/panels/FlowPanelControlComponent.tsx +++ b/src/packages/ce/src/flow/components/panels/FlowPanelControlComponent.tsx @@ -1,8 +1,17 @@ import React from "react"; -import {Flow, LiteralValue, NodeFunction, ReferenceValue, SubFlowValue} from "@code0-tech/sagittarius-graphql-types"; +import { + Flow, + LiteralValue, + Namespace, + NamespaceProject, + NodeFunction, + ReferenceValue, + SubFlowValue +} from "@code0-tech/sagittarius-graphql-types"; import { Badge, Button, + Spacing, Text, Tooltip, TooltipContent, @@ -15,10 +24,16 @@ 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 {Suggestion} from "@edition/function/components/suggestion/Suggestion.util"; import {useHotkeys} from "react-hotkeys-hook"; import {useSelectedFunctionNode} from "@edition/function/hooks/FunctionNode.selected.hook"; import {useFunctionSuggestions} from "@edition/function/hooks/Function.suggestion.hook"; +import {useParams} from "next/navigation"; +import {FlowTypeService} from "@edition/flowtype/services/FlowType.service"; +import {ProjectService} from "@edition/project/services/Project.service"; +import {ModuleService} from "@edition/module/services/Module.service"; +import {IconCheck, IconCopy} from "@tabler/icons-react"; +import {InputWrapper} from "@code0-tech/pictor/dist/components/form/InputWrapper"; +import {useCopyToClipboard} from "@uidotdev/usehooks"; export interface FlowPanelControlComponentProps { flowId: Flow['id'] @@ -30,17 +45,71 @@ export const FlowPanelControlComponent: React.FC const {flowId} = props //services and stores + const params = useParams() const flowService = useService(FlowService) const flowStore = useStore(FlowService) + const flowTypeService = useService(FlowTypeService) + const flowTypeStore = useStore(FlowTypeService) + const projectService = useService(ProjectService) + const projectStore = useStore(ProjectService) + const moduleService = useService(ModuleService) + const moduleStore = useStore(ModuleService) + + const [copiedText, copyToClipboard] = useCopyToClipboard(); + const hasCopiedText = Boolean(copiedText); const [, startTransition] = React.useTransition() const [suggestionDialogOpen, setSuggestionDialogOpen] = React.useState(false) const [addNextNodeTooltipOpen, setAddNextNodeTooltipOpen] = React.useState(false) + const namespaceIndex = params.namespaceId as any as number + const projectIndex = params.projectId as any as number + const namespaceId: Namespace['id'] = `gid://sagittarius/Namespace/${namespaceIndex}` + const projectId: NamespaceProject['id'] = `gid://sagittarius/NamespaceProject/${projectIndex}` + //memoized values const selectedNode = useSelectedFunctionNode() - const result = useFunctionSuggestions() + const flow = React.useMemo( + () => flowService.getById(flowId, { + namespaceId, + projectId + }), + [flowId, flowStore, namespaceId, projectId] + ) + + const project = React.useMemo( + () => projectService.getById(projectId, { + namespaceId + }), + [projectId, namespaceId, projectStore] + ) + + const flowType = React.useMemo( + () => flowTypeService.getById(flow?.type?.id, { + namespaceId, + projectId, + runtimeId: project?.primaryRuntime?.id + }), + [flow?.type?.id, namespaceId, projectId, project?.primaryRuntime?.id, flowTypeStore] + ) + + const module = React.useMemo( + () => moduleService.getById(flowType?.runtimeModule?.id, { + namespaceId: namespaceId, + projectId: projectId, + runtimeId: project?.primaryRuntime?.id + }), + [flowType?.runtimeModule?.id, namespaceId, projectId, project?.primaryRuntime?.id, moduleStore] + ) + + let endpoint = `http://${module?.definitions?.nodes?.[0]?.host}:${module?.definitions?.nodes?.[0]?.port}${module?.definitions?.nodes?.[0]?.endpoint}` + .replace("${{project_slug}}", project?.slug ?? "${{project_slug}}") + + flow?.settings?.nodes?.forEach(setting => { + endpoint = endpoint.replace(`\${{${setting?.flowSettingIdentifier}}}`, setting?.value) + }) + //callbacks const deleteActiveNode = React.useCallback(() => { if (!selectedNode) return @@ -83,7 +152,7 @@ export const FlowPanelControlComponent: React.FC disabled={!selectedNode} onClick={deleteActiveNode} paddingSize={"xxs"} - variant={"filled"} + variant={"none"} color={"error"}> Delete node @@ -99,11 +168,11 @@ export const FlowPanelControlComponent: React.FC + + + + + Execute the flow to see the results
in the runtime. +
+ + + + + }> +
+ + {endpoint} + +
+ +
+
+
+ + ) : (null as any)} + + + } diff --git a/src/packages/ce/src/function/components/nodes/FunctionNodeTriggerComponent.tsx b/src/packages/ce/src/function/components/nodes/FunctionNodeTriggerComponent.tsx index bd737d58..76375a8b 100644 --- a/src/packages/ce/src/function/components/nodes/FunctionNodeTriggerComponent.tsx +++ b/src/packages/ce/src/function/components/nodes/FunctionNodeTriggerComponent.tsx @@ -1,11 +1,11 @@ import React, {CSSProperties, memo} from "react"; import {Handle, Node, NodeProps, Position} from "@xyflow/react"; -import {Badge, Card, Flex, Text, useService, useStore as usePictorStore} from "@code0-tech/pictor"; +import {Badge, Card, Flex, Text, useService, useStore, useStore as usePictorStore} from "@code0-tech/pictor"; import {FunctionNodeComponentProps} from "@edition/function/components/nodes/FunctionNodeComponent"; import {FlowTypeService} from "@edition/flowtype/services/FlowType.service"; import {FlowService} from "@edition/flow/services/Flow.service"; import {IconVariable} from "@tabler/icons-react"; -import {NodeFunction} from "@code0-tech/sagittarius-graphql-types"; +import {Namespace, NamespaceProject, NodeFunction} from "@code0-tech/sagittarius-graphql-types"; import {icon, IconString} from "@core/util/icons"; import {FALLBACK_FLOW_TYPE_DISPLAY_MESSAGE, FALLBACK_FLOW_TYPE_NAME} from "@core/util/fallback-translations"; import {useFlowValidation} from "@edition/flow/hooks/Flow.validation.hook"; @@ -14,6 +14,9 @@ import {useSelectedFunctionNode} from "@edition/function/hooks/FunctionNode.sele import {LiteralBadgeComponent} from "@edition/datatype/components/badges/LiteralBadgeComponent"; import {ReferenceBadgeComponent} from "@edition/datatype/components/badges/ReferenceBadgeComponent"; import {NodeBadgeComponent} from "@edition/datatype/components/badges/NodeBadgeComponent"; +import {useParams} from "next/navigation"; +import {ProjectService} from "@edition/project/services/Project.service"; +import {ModuleService} from "@edition/module/services/Module.service"; export type FunctionNodeTriggerComponentProps = NodeProps> @@ -21,14 +24,63 @@ export type FunctionNodeTriggerComponentProps = NodeProps = memo((props) => { const {data, id, selected} = props + + const params = useParams() const flowTypeService = useService(FlowTypeService) const flowTypeStore = usePictorStore(FlowTypeService) const flowService = useService(FlowService) const flowStore = usePictorStore(FlowService) + const projectService = useService(ProjectService) + const projectStore = useStore(ProjectService) + const moduleService = useService(ModuleService) + const moduleStore = useStore(ModuleService) + + const namespaceIndex = params.namespaceId as any as number + const projectIndex = params.projectId as any as number + const namespaceId: Namespace['id'] = `gid://sagittarius/Namespace/${namespaceIndex}` + const projectId: NamespaceProject['id'] = `gid://sagittarius/NamespaceProject/${projectIndex}` + + const flow = React.useMemo( + () => flowService.getById(data.flowId, { + namespaceId, + projectId + }), + [data.flowId, namespaceId, projectId, flowStore] + ) + + const project = React.useMemo( + () => projectService.getById(projectId, { + namespaceId + }), + [projectId, namespaceId, projectStore] + ) + + const flowType = React.useMemo( + () => flowTypeService.getById(flow?.type?.id, { + namespaceId, + projectId, + runtimeId: project?.primaryRuntime?.id + }), + [flow?.type?.id, namespaceId, projectId, project?.primaryRuntime?.id, flowTypeStore] + ) - const flow = React.useMemo(() => flowService.getById(data.flowId), [flowStore, data]) - const definition = React.useMemo(() => flow ? flowTypeService.getById(flow.type?.id) : undefined, [flowTypeStore, flow]) - const DisplayIcon = icon(definition?.displayIcon as IconString) + const module = React.useMemo( + () => moduleService.getById(flowType?.runtimeModule?.id, { + namespaceId: namespaceId, + projectId: projectId, + runtimeId: project?.primaryRuntime?.id + }), + [flowType?.runtimeModule?.id, namespaceId, projectId, project?.primaryRuntime?.id, moduleStore] + ) + + let endpoint = `http://${module?.definitions?.nodes?.[0]?.host}:${module?.definitions?.nodes?.[0]?.port}${module?.definitions?.nodes?.[0]?.endpoint}` + .replace("${{project_slug}}", project?.slug ?? "${{project_slug}}") + + flow?.settings?.nodes?.forEach(setting => { + endpoint = endpoint.replace(`\${{${setting?.flowSettingIdentifier}}}`, setting?.value) + }) + + const DisplayIcon = icon(flowType?.displayIcon as IconString) const validation = useFlowValidation(data.flowId) const triggerValidations = React.useMemo( @@ -55,15 +107,15 @@ export const FunctionNodeTriggerComponent: React.FC p.trim() === "," ? [","] : p.trim() ? [p.trim()] : []) ) - const displayMessage = React.useMemo(() => splitTemplate(definition?.displayMessages?.[0]?.content ?? FALLBACK_FLOW_TYPE_DISPLAY_MESSAGE).map(item => { + const displayMessage = React.useMemo(() => splitTemplate(flowType?.displayMessages?.[0]?.content ?? FALLBACK_FLOW_TYPE_DISPLAY_MESSAGE).map(item => { const nodeParameter = flow?.settings?.nodes?.find((_, index) => { - const parameterDefinition = definition?.flowTypeSettings?.[index] + const parameterDefinition = flowType?.flowTypeSettings?.[index] return parameterDefinition?.identifier == item }) - const parameterDefinition = definition?.flowTypeSettings?.find(pd => pd?.identifier == item) - const parameterIndex = parameterDefinition ? definition?.flowTypeSettings?.findIndex(p => p?.id === parameterDefinition.id) : undefined + const parameterDefinition = flowType?.flowTypeSettings?.find(pd => pd?.identifier == item) + const parameterIndex = parameterDefinition ? flowType?.flowTypeSettings?.findIndex(p => p?.id === parameterDefinition.id) : undefined const parameterValidation = validation?.filter(v => v.parameterIndex === parameterIndex && !v.nodeId) const decorationStyle: CSSProperties = parameterValidation?.length @@ -94,7 +146,7 @@ export const FunctionNodeTriggerComponent: React.FC } return " " + String(item) + " " - }), [flowStore, data, definition, validation]) + }), [flowStore, data, flowType, validation]) const isReferenced = React.useMemo(() => { @@ -121,17 +173,24 @@ export const FunctionNodeTriggerComponent: React.FC - - Starting node - + + + Flow trigger + + {module?.definitions?.nodes?.[0] && ( + + {endpoint} + + )} + - {flow ? displayMessage : definition?.names?.[0].content ?? FALLBACK_FLOW_TYPE_NAME} + {flow ? displayMessage : flowType?.names?.[0].content ?? FALLBACK_FLOW_TYPE_NAME} { From b16ad37bfc8f8e2cb49d18a65691d7269e175fe3 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Fri, 12 Jun 2026 11:23:15 +0200 Subject: [PATCH 47/54] feat: adding support for function within execution result --- .../services/fragments/Flow.fragment.graphql | 4 +++ .../flow/views/FlowExecutionResultView.tsx | 25 ++++++++++++++++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/packages/ce/src/flow/services/fragments/Flow.fragment.graphql b/src/packages/ce/src/flow/services/fragments/Flow.fragment.graphql index 791a8ebf..db441771 100644 --- a/src/packages/ce/src/flow/services/fragments/Flow.fragment.graphql +++ b/src/packages/ce/src/flow/services/fragments/Flow.fragment.graphql @@ -150,6 +150,10 @@ fragment Flow on Flow { value position } + functionDefinition { + __typename + id + } nodeFunction { __typename id diff --git a/src/packages/ce/src/flow/views/FlowExecutionResultView.tsx b/src/packages/ce/src/flow/views/FlowExecutionResultView.tsx index 91d01e58..c79c8258 100644 --- a/src/packages/ce/src/flow/views/FlowExecutionResultView.tsx +++ b/src/packages/ce/src/flow/views/FlowExecutionResultView.tsx @@ -4,7 +4,7 @@ import { ExecutionError, ExecutionParameterResult, ExecutionResult, - Flow, + Flow, FunctionDefinition, Maybe, Namespace, NamespaceProject, @@ -57,7 +57,7 @@ export interface NodeGanttItem extends GanttItem { data?: { displayMessage: string color: string - payload?: Maybe | Maybe + payload?: Maybe | Maybe | Maybe input?: ExecutionParameterResult[] | object success?: object error?: Maybe @@ -142,6 +142,25 @@ export const FlowExecutionResultView: React.FC = () => { }, ...(result?.nodeResults?.nodes?.map?.(nodeResult => { + if (nodeResult?.functionDefinition) { + const funktion = functions.find(f => f.id === nodeResult?.functionDefinition?.id) + + return { + id: nodeResult?.id as string, + type: "function", + start: (nodeResult?.startedAt ?? 0) - (result?.startedAt ?? 0), + end: (nodeResult?.finishedAt ?? 0) - (result?.startedAt ?? 0), + data: { + displayMessage: funktion?.names?.[0].content ?? FALLBACK_FUNCTION_NAME, + color: hashToColor(funktion?.identifier ?? ""), + payload: funktion, + success: nodeResult?.success, + input: nodeResult?.parameterResults ?? [], + error: nodeResult?.error, + } + } + } + const node = flow?.nodes?.nodes?.find(n => n?.id === nodeResult?.nodeFunction?.id) const funktion = functions.find(f => f.id === nodeResult?.nodeFunction?.functionDefinition?.id) @@ -252,7 +271,7 @@ export const FlowExecutionResultView: React.FC = () => { } else { const DisplayIcon = icon( - item.type === "node" ? item?.data?.payload?.functionDefinition?.displayIcon : item?.data?.payload?.type?.displayIcon, + item.type === "node" ? item?.data?.payload?.functionDefinition?.displayIcon : item.type === "function" ? item?.data?.payload?.displayIcon : item?.data?.payload?.type?.displayIcon, ) return From ecb90ee3bc711894f1315d53874385d30ca940ee Mon Sep 17 00:00:00 2001 From: nicosammito Date: Sat, 13 Jun 2026 15:48:42 +0200 Subject: [PATCH 48/54] feat: switching out tooltip with dialog for execution info --- .../panels/FlowPanelControlComponent.tsx | 52 +++++++++++-------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/src/packages/ce/src/flow/components/panels/FlowPanelControlComponent.tsx b/src/packages/ce/src/flow/components/panels/FlowPanelControlComponent.tsx index 23e75fa2..3c5a770c 100644 --- a/src/packages/ce/src/flow/components/panels/FlowPanelControlComponent.tsx +++ b/src/packages/ce/src/flow/components/panels/FlowPanelControlComponent.tsx @@ -11,6 +11,11 @@ import { import { Badge, Button, + Dialog, + DialogContent, + DialogOverlay, + DialogPortal, + DialogTrigger, Spacing, Text, Tooltip, @@ -186,8 +191,8 @@ export const FlowPanelControlComponent: React.FC {module?.definitions?.nodes?.[0] ? ( - - + + - - - - - Execute the flow to see the results
in the runtime. -
- - - - - }> + + + + + + setting?.flowSettingIdentifier === "httpMethod")?.value ? ( + + {flow?.settings?.nodes?.find(setting => setting?.flowSettingIdentifier === "httpMethod")?.value} + + ) : undefined} + right={ + + + + }>
-
-
-
+ + + ) : (null as any)} - From d1ba9e9a6046db17ded0b7e9f88081b0370a6ff9 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Sat, 13 Jun 2026 15:49:03 +0200 Subject: [PATCH 49/54] feat: correct handling of flow settings to display values within node --- .../nodes/FunctionNodeTriggerComponent.tsx | 23 ++++--------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/src/packages/ce/src/function/components/nodes/FunctionNodeTriggerComponent.tsx b/src/packages/ce/src/function/components/nodes/FunctionNodeTriggerComponent.tsx index 76375a8b..a08406bb 100644 --- a/src/packages/ce/src/function/components/nodes/FunctionNodeTriggerComponent.tsx +++ b/src/packages/ce/src/function/components/nodes/FunctionNodeTriggerComponent.tsx @@ -123,26 +123,11 @@ export const FunctionNodeTriggerComponent: React.FC - - - case "ReferenceValue": - return
- -
- case "SubFlowValue": - return
- -
- } return
- - - {item} - - +
} return " " + String(item) + " " From fc9fa315bb90c3cf505430407aae8435ea34a74a Mon Sep 17 00:00:00 2001 From: nicosammito Date: Sat, 13 Jun 2026 18:07:19 +0200 Subject: [PATCH 50/54] feat: deactivate deleteKeyCode --- .../ce/src/flow/components/builder/FlowBuilderComponent.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/packages/ce/src/flow/components/builder/FlowBuilderComponent.tsx b/src/packages/ce/src/flow/components/builder/FlowBuilderComponent.tsx index 11ec45b1..874057cb 100644 --- a/src/packages/ce/src/flow/components/builder/FlowBuilderComponent.tsx +++ b/src/packages/ce/src/flow/components/builder/FlowBuilderComponent.tsx @@ -740,6 +740,7 @@ const InternalFlowBuilder: React.FC = (props) => { nodes={nodes} edges={edges} panOnDrag={showTree} + deleteKeyCode={null} selectionKeyCode={null} zoomOnScroll={showTree} zoomOnPinch={showTree} From 299dbd8734ef0536d5df7ce849e9447edd186cd2 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Sat, 13 Jun 2026 18:07:33 +0200 Subject: [PATCH 51/54] feat: changing design of square node --- .../components/nodes/FunctionNodeSquareComponent.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/packages/ce/src/function/components/nodes/FunctionNodeSquareComponent.tsx b/src/packages/ce/src/function/components/nodes/FunctionNodeSquareComponent.tsx index 1e732fad..baad4239 100644 --- a/src/packages/ce/src/function/components/nodes/FunctionNodeSquareComponent.tsx +++ b/src/packages/ce/src/function/components/nodes/FunctionNodeSquareComponent.tsx @@ -79,7 +79,7 @@ export const FunctionNodeSquareComponent: React.FC + @@ -133,9 +133,9 @@ export const FunctionNodeSquareComponent: React.FC - {definition?.names?.[0]?.content ?? FALLBACK_FUNCTION_NAME} + {definition?.names?.[0]?.content ?? FALLBACK_FUNCTION_NAME} ); }) From 491dde61bcdf2fe5772df427a674dc3cf44f62a9 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Sat, 13 Jun 2026 18:22:07 +0200 Subject: [PATCH 52/54] feat: fixing icon size to 16px --- .../ce/src/flow/views/FlowExecutionResultView.tsx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/packages/ce/src/flow/views/FlowExecutionResultView.tsx b/src/packages/ce/src/flow/views/FlowExecutionResultView.tsx index c79c8258..b071de74 100644 --- a/src/packages/ce/src/flow/views/FlowExecutionResultView.tsx +++ b/src/packages/ce/src/flow/views/FlowExecutionResultView.tsx @@ -294,6 +294,10 @@ export const FlowExecutionResultView: React.FC = () => { justify={"start"} style={{gap: "0.7rem"}}> { style={{gap: "0.7rem"}}> Date: Sat, 13 Jun 2026 18:24:03 +0200 Subject: [PATCH 53/54] feat: make tabs toggle able --- .../[namespaceId]/project/[projectId]/flow/[flowId]/page.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/(flow)/namespace/[namespaceId]/project/[projectId]/flow/[flowId]/page.tsx b/src/app/(flow)/namespace/[namespaceId]/project/[projectId]/flow/[flowId]/page.tsx index 6834b2c4..66f36731 100644 --- a/src/app/(flow)/namespace/[namespaceId]/project/[projectId]/flow/[flowId]/page.tsx +++ b/src/app/(flow)/namespace/[namespaceId]/project/[projectId]/flow/[flowId]/page.tsx @@ -45,11 +45,11 @@ export default function Page() { return - - From f6cf8c59d5eb643dc3f0f7303907f8fe694a6019 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Sat, 13 Jun 2026 18:35:11 +0200 Subject: [PATCH 54/54] feat: changing padding of tabs and deleting old license pages in cloud --- .../[projectId]/flow/[flowId]/page.tsx | 29 ++---- .../namespace/pages/NamespaceSettingsPage.tsx | 2 +- .../ce/src/role/pages/RoleSettingsPage.tsx | 2 +- .../src/runtime/pages/RuntimeSettingsPage.tsx | 2 +- .../ApplicationMiddlewareComponent.tsx | 10 ++ .../components/LicensesDataTableComponent.tsx | 79 ---------------- .../LicensesDataTableFilterInputComponent.tsx | 0 .../LicensesDataTableRowComponent.tsx | 30 ------ .../cloud/src/license/pages/LicensesPage.tsx | 16 ---- .../cloud/src/license/views/LicensesView.tsx | 43 --------- .../src/license/views/NamespaceTabView.tsx | 94 ------------------- .../namespace/pages/NamespaceSettingsPage.tsx | 2 +- 12 files changed, 21 insertions(+), 288 deletions(-) create mode 100644 src/packages/cloud/src/application/components/ApplicationMiddlewareComponent.tsx delete mode 100644 src/packages/cloud/src/license/components/LicensesDataTableComponent.tsx delete mode 100644 src/packages/cloud/src/license/components/LicensesDataTableFilterInputComponent.tsx delete mode 100644 src/packages/cloud/src/license/components/LicensesDataTableRowComponent.tsx delete mode 100644 src/packages/cloud/src/license/pages/LicensesPage.tsx delete mode 100644 src/packages/cloud/src/license/views/LicensesView.tsx delete mode 100644 src/packages/cloud/src/license/views/NamespaceTabView.tsx diff --git a/src/app/(flow)/namespace/[namespaceId]/project/[projectId]/flow/[flowId]/page.tsx b/src/app/(flow)/namespace/[namespaceId]/project/[projectId]/flow/[flowId]/page.tsx index 66f36731..1d2bde01 100644 --- a/src/app/(flow)/namespace/[namespaceId]/project/[projectId]/flow/[flowId]/page.tsx +++ b/src/app/(flow)/namespace/[namespaceId]/project/[projectId]/flow/[flowId]/page.tsx @@ -1,25 +1,8 @@ "use client" -import { - Button, - Card, - Flex, - Gantt, - getRelativeValue, - hashToColor, Spacing, Text, - Tooltip, TooltipContent, TooltipPortal, - TooltipTrigger, - withAlpha, -} from "@code0-tech/pictor"; +import {Button, Flex,} from "@code0-tech/pictor"; import React from "react"; -import { - IconArrowRampRight2, - IconBrandDiscord, IconBrandTeams, - IconDatabase, - IconFile, - IconPlayerPlay, - IconTextGrammar -} from "@tabler/icons-react"; +import {IconFile, IconPlayerPlay} from "@tabler/icons-react"; import {useParams} from "next/navigation"; import {Flow} from "@code0-tech/sagittarius-graphql-types"; import {FlowBuilderComponent} from "@edition/flow/components/builder/FlowBuilderComponent"; @@ -30,7 +13,6 @@ import { ResizablePanelGroup } from "@code0-tech/pictor/dist/components/resizable/Resizable"; import {Layout} from "@code0-tech/pictor/dist/components/layout/Layout"; -import {Editor} from "@code0-tech/pictor/dist/components/editor/Editor"; import {FlowExecutionResultView} from "@edition/flow/views/FlowExecutionResultView"; export default function Page() { @@ -45,11 +27,14 @@ export default function Page() { return - - diff --git a/src/packages/ce/src/namespace/pages/NamespaceSettingsPage.tsx b/src/packages/ce/src/namespace/pages/NamespaceSettingsPage.tsx index d1c8a96f..1a1235eb 100644 --- a/src/packages/ce/src/namespace/pages/NamespaceSettingsPage.tsx +++ b/src/packages/ce/src/namespace/pages/NamespaceSettingsPage.tsx @@ -40,7 +40,7 @@ export const NamespaceSettingsPage: React.FC = () => { - <> diff --git a/src/packages/ce/src/role/pages/RoleSettingsPage.tsx b/src/packages/ce/src/role/pages/RoleSettingsPage.tsx index cdd74e93..8a66870b 100644 --- a/src/packages/ce/src/role/pages/RoleSettingsPage.tsx +++ b/src/packages/ce/src/role/pages/RoleSettingsPage.tsx @@ -48,7 +48,7 @@ export const RoleSettingsPage: React.FC = () => { - diff --git a/src/packages/ce/src/runtime/pages/RuntimeSettingsPage.tsx b/src/packages/ce/src/runtime/pages/RuntimeSettingsPage.tsx index b5dae4fd..ea3195b3 100644 --- a/src/packages/ce/src/runtime/pages/RuntimeSettingsPage.tsx +++ b/src/packages/ce/src/runtime/pages/RuntimeSettingsPage.tsx @@ -126,7 +126,7 @@ export const RuntimeSettingsPage: React.FC = () => { - <> diff --git a/src/packages/cloud/src/application/components/ApplicationMiddlewareComponent.tsx b/src/packages/cloud/src/application/components/ApplicationMiddlewareComponent.tsx new file mode 100644 index 00000000..8f3a21e7 --- /dev/null +++ b/src/packages/cloud/src/application/components/ApplicationMiddlewareComponent.tsx @@ -0,0 +1,10 @@ +"use client" + +import React from "react"; +import { + ApplicationMiddlewareComponent as CEApplicationMiddlewareComponent, + ApplicationMiddlewareProps as CEApplicationMiddlewareProps +} from "@ce-internal/application/components/ApplicationMiddlewareComponent" + + +export const ApplicationMiddlewareComponent: React.FC = CEApplicationMiddlewareComponent \ No newline at end of file diff --git a/src/packages/cloud/src/license/components/LicensesDataTableComponent.tsx b/src/packages/cloud/src/license/components/LicensesDataTableComponent.tsx deleted file mode 100644 index 3d064ca6..00000000 --- a/src/packages/cloud/src/license/components/LicensesDataTableComponent.tsx +++ /dev/null @@ -1,79 +0,0 @@ -"use client" - -import React from "react"; -import { - AuroraBackground, - Button, - ButtonGroup, - DataTable, - DataTableColumn, - Flex, - Spacing, - Text, - useService, - useStore -} from "@code0-tech/pictor"; -import {DataTableFilterProps, DataTableSortProps} from "@code0-tech/pictor/dist/components/data-table/DataTable"; -import {Namespace, License} from "@code0-tech/sagittarius-graphql-types"; -import {NamespaceService} from "@edition/namespace/services/Namespace.service"; -import {LicensesDataTableRowComponent} from "@cloud-internal/license/components/LicensesDataTableRowComponent"; -import Link from "next/link"; - -export interface LicensesDataTableComponentProps { - namespaceId: Namespace['id'] - sort?: DataTableSortProps - filter?: DataTableFilterProps - preFilter?: (project: License, index: number) => boolean - onSelect?: (item: License | undefined) => void -} - -export const LicensesDataTableComponent: React.FC = (props) => { - - const {namespaceId, sort, filter, preFilter = () => true, onSelect} = props - - const namespaceService = useService(NamespaceService) - const namespaceStore = useStore(NamespaceService) - - const licenses = React.useMemo( - () => namespaceService.getById(namespaceId)?.licenses?.nodes as License[] ?? [], - [namespaceStore] - ) - - return - - - No license connected yet - - - - To use the cloud features, you need to have at least one license connected to your
- namespace. -
- - - - - - - - - -
- - } - onSelect={(item) => item && onSelect?.(item)} - data={licenses?.filter(preFilter)}> - {(license, index) => { - return - }} -
- -} \ No newline at end of file diff --git a/src/packages/cloud/src/license/components/LicensesDataTableFilterInputComponent.tsx b/src/packages/cloud/src/license/components/LicensesDataTableFilterInputComponent.tsx deleted file mode 100644 index e69de29b..00000000 diff --git a/src/packages/cloud/src/license/components/LicensesDataTableRowComponent.tsx b/src/packages/cloud/src/license/components/LicensesDataTableRowComponent.tsx deleted file mode 100644 index 9daefc0b..00000000 --- a/src/packages/cloud/src/license/components/LicensesDataTableRowComponent.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import React from "react"; -import {Namespace, License} from "@code0-tech/sagittarius-graphql-types"; -import {DataTableColumn, useService, useStore} from "@code0-tech/pictor"; -import {NamespaceService} from "@edition/namespace/services/Namespace.service"; - -export interface LicensesDataTableRowComponentProps { - namespaceId: Namespace['id'] - licenseId: License['id'] -} - -export const LicensesDataTableRowComponent: React.FC = (props) => { - - const {namespaceId, licenseId} = props - - const namespaceService = useService(NamespaceService) - const namespaceStore = useStore(NamespaceService) - - const license = React.useMemo( - () => namespaceService.getById(namespaceId)?.licenses?.nodes?.find(license => license?.id === licenseId) as License, - [namespaceStore, namespaceId, licenseId] - ) - - //TODO: fetch license details from the license service and display them here - - return <> - - - - -} \ No newline at end of file diff --git a/src/packages/cloud/src/license/pages/LicensesPage.tsx b/src/packages/cloud/src/license/pages/LicensesPage.tsx deleted file mode 100644 index f8fa6649..00000000 --- a/src/packages/cloud/src/license/pages/LicensesPage.tsx +++ /dev/null @@ -1,16 +0,0 @@ -"use client" - -import React from "react"; -import {LicensesView} from "@cloud-internal/license/views/LicensesView"; - -export const LicensesPage: React.FC = () => { - return
- -
-} \ No newline at end of file diff --git a/src/packages/cloud/src/license/views/LicensesView.tsx b/src/packages/cloud/src/license/views/LicensesView.tsx deleted file mode 100644 index 46304198..00000000 --- a/src/packages/cloud/src/license/views/LicensesView.tsx +++ /dev/null @@ -1,43 +0,0 @@ -"use client" - -import React from "react"; -import {AuroraBackground, Button, ButtonGroup, Flex, Spacing, Text} from "@code0-tech/pictor"; -import Link from "next/link"; -import {LicensesDataTableComponent} from "@cloud-internal/license/components/LicensesDataTableComponent"; -import {useParams} from "next/navigation"; -import {Namespace} from "@code0-tech/sagittarius-graphql-types"; - -export const LicensesView: React.FC = () => { - - const params = useParams() - const namespaceIndex = params.namespaceId as any as number - const namespaceId: Namespace['id'] = `gid://sagittarius/Namespace/${namespaceIndex}` - - return <> - - - - Licenses - - - Manage members that belong to this namespace. You can add new members and manage their permissions. - - - - - - - - - - - - - - -} \ No newline at end of file diff --git a/src/packages/cloud/src/license/views/NamespaceTabView.tsx b/src/packages/cloud/src/license/views/NamespaceTabView.tsx deleted file mode 100644 index ca24b0e4..00000000 --- a/src/packages/cloud/src/license/views/NamespaceTabView.tsx +++ /dev/null @@ -1,94 +0,0 @@ -"use client" - -import React from "react"; -import {Button, useService, useStore} from "@code0-tech/pictor"; -import {Tab, TabList, TabTrigger} from "@code0-tech/pictor/dist/components/tab/Tab"; -import { - IconFolders, - IconHome, - IconLicense, - IconServer, - IconSettings, - IconUserCog, - IconUsers -} from "@tabler/icons-react"; -import {useParams, usePathname, useRouter} from "next/navigation"; -import {NamespaceService} from "@edition/namespace/services/Namespace.service"; -import {OrganizationService} from "@edition/organization/services/Organization.service"; - -export const NamespaceTabView: React.FC = () => { - - const pathname = usePathname() - const router = useRouter() - const params = useParams() - const namespaceId = params.namespaceId as any - - const namespaceService = useService(NamespaceService) - const namespaceStore = useStore(NamespaceService) - const organizationService = useService(OrganizationService) - const organizationStore = useStore(OrganizationService) - - const namespace = React.useMemo(() => namespaceService.getById(`gid://sagittarius/Namespace/${namespaceId}`), [namespaceStore, namespaceId]) - const parentOrganization = React.useMemo(() => namespace?.parent?.__typename === "Organization" ? organizationService.getById(namespace?.parent?.id) : null, [organizationStore, namespace]) - - const baseLink = `/namespace/${namespaceId}` - const defaultValue = pathname.includes("projects") ? "projects" - : pathname.includes("members") ? "members" - : pathname.includes("roles") ? "roles" - : pathname.includes("runtimes") ? "runtimes" - : pathname.includes("licenses") ? "licenses" - : pathname.includes("settings") ? "settings" - : "overview" - - const settings = React.useMemo(() => { - return namespace?.parent?.__typename == "Organization" - && parentOrganization - && ( - parentOrganization.userAbilities?.deleteOrganization - || parentOrganization?.userAbilities?.updateOrganization - //TODO add license check for enterprise features - ) ? ( - - - - ) : null - }, [namespace, parentOrganization]) - - return - - - - - - - - - - - - - - - - - - - - {settings} - - -} \ No newline at end of file diff --git a/src/packages/cloud/src/namespace/pages/NamespaceSettingsPage.tsx b/src/packages/cloud/src/namespace/pages/NamespaceSettingsPage.tsx index a919ca9e..e5caae5a 100644 --- a/src/packages/cloud/src/namespace/pages/NamespaceSettingsPage.tsx +++ b/src/packages/cloud/src/namespace/pages/NamespaceSettingsPage.tsx @@ -41,7 +41,7 @@ export const NamespaceSettingsPage: React.FC = () => { - <>