diff --git a/package-lock.json b/package-lock.json index a242dea9..d35a450e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ "@ariakit/react": "^0.4.17", "@babel/plugin-proposal-decorators": "^7.28.0", "@babel/plugin-transform-class-properties": "^7.27.1", - "@code0-tech/sagittarius-graphql-types": "^0.0.0-00f33663039d78ad59e95306730878c687de5c48", + "@code0-tech/sagittarius-graphql-types": "^0.0.0-65144a9920c6a8de3bcf24acdcb8eec4158cef73", "@dagrejs/dagre": "^1.1.5", "@mdx-js/react": "^3.1.1", "@radix-ui/react-checkbox": "^1.3.3", @@ -2287,9 +2287,9 @@ } }, "node_modules/@code0-tech/sagittarius-graphql-types": { - "version": "0.0.0-00f33663039d78ad59e95306730878c687de5c48", - "resolved": "https://registry.npmjs.org/@code0-tech/sagittarius-graphql-types/-/sagittarius-graphql-types-0.0.0-00f33663039d78ad59e95306730878c687de5c48.tgz", - "integrity": "sha512-g8bv5KWq+c8jd9Gb+86O3TT/Dcvt2injJcZ5aFJkN8ZZz/4VsA0EcC3h/hCsoiBIEquvAdQQVFriNAbC0JrKRA==" + "version": "0.0.0-65144a9920c6a8de3bcf24acdcb8eec4158cef73", + "resolved": "https://registry.npmjs.org/@code0-tech/sagittarius-graphql-types/-/sagittarius-graphql-types-0.0.0-65144a9920c6a8de3bcf24acdcb8eec4158cef73.tgz", + "integrity": "sha512-MZZHi02S0Q3qmNkbigN9aq7j1KcEc62aoSKrjWVUoUYoaLMLa60lHda3cb0/D4Fes+zvNyLnAogdaO7Mjos8Vg==" }, "node_modules/@code0-tech/tucana": { "version": "0.0.37", @@ -6779,7 +6779,8 @@ "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true + "dev": true, + "peer": true }, "node_modules/@types/junit-report-builder": { "version": "3.0.2", @@ -7334,6 +7335,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -7365,6 +7367,7 @@ "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", "dev": true, + "peer": true, "dependencies": { "ajv": "^8.0.0" }, @@ -7382,6 +7385,7 @@ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", "dev": true, + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3" }, @@ -9633,7 +9637,8 @@ "type": "opencollective", "url": "https://opencollective.com/fastify" } - ] + ], + "peer": true }, "node_modules/fastq": { "version": "1.19.1", @@ -15322,6 +15327,7 @@ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.0.tgz", "integrity": "sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==", "dev": true, + "peer": true, "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", diff --git a/package.json b/package.json index de09ee69..78cbc1b5 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "@ariakit/react": "^0.4.17", "@babel/plugin-proposal-decorators": "^7.28.0", "@babel/plugin-transform-class-properties": "^7.27.1", - "@code0-tech/sagittarius-graphql-types": "^0.0.0-00f33663039d78ad59e95306730878c687de5c48", + "@code0-tech/sagittarius-graphql-types": "^0.0.0-65144a9920c6a8de3bcf24acdcb8eec4158cef73", "@dagrejs/dagre": "^1.1.5", "@mdx-js/react": "^3.1.1", "@radix-ui/react-checkbox": "^1.3.3", diff --git a/src/components/d-flow/viewport/DFlowViewport.edges.hook.ts b/src/components/d-flow/DFlow.edges.hook.ts similarity index 95% rename from src/components/d-flow/viewport/DFlowViewport.edges.hook.ts rename to src/components/d-flow/DFlow.edges.hook.ts index 28ad3bb8..6e04546f 100644 --- a/src/components/d-flow/viewport/DFlowViewport.edges.hook.ts +++ b/src/components/d-flow/DFlow.edges.hook.ts @@ -1,9 +1,9 @@ -import {useService, useStore} from "../../../utils/contextStore"; -import {DFlowReactiveService} from "../DFlow.service"; +import {useService, useStore} from "../../utils/contextStore"; +import {DFlowReactiveService} from "./DFlow.service"; import {Edge} from "@xyflow/react"; -import {NodeFunctionView} from "../DFlow.view"; -import {DFlowFunctionReactiveService} from "../function/DFlowFunction.service"; -import {DFlowDataTypeReactiveService} from "../data-type/DFlowDataType.service"; +import {NodeFunctionView} from "./DFlow.view"; +import {DFlowFunctionReactiveService} from "./function/DFlowFunction.service"; +import {DFlowDataTypeReactiveService} from "./data-type/DFlowDataType.service"; import React from "react"; import {DataTypeIdentifier, DataTypeVariant, Scalars} from "@code0-tech/sagittarius-graphql-types"; @@ -19,7 +19,7 @@ export const FLOW_EDGE_RAINBOW: string[] = [ '#fff170', // 7 – Gelb ]; -export const useFlowViewportEdges = (flowId: string): Edge[] => { +export const useFlowEdges = (flowId: string): Edge[] => { const flowService = useService(DFlowReactiveService); const functionService = useService(DFlowFunctionReactiveService); const dataTypeService = useService(DFlowDataTypeReactiveService); diff --git a/src/components/d-flow/viewport/DFlowViewport.nodes.hook.ts b/src/components/d-flow/DFlow.nodes.hook.ts similarity index 95% rename from src/components/d-flow/viewport/DFlowViewport.nodes.hook.ts rename to src/components/d-flow/DFlow.nodes.hook.ts index 1a4d44e1..4223ef34 100644 --- a/src/components/d-flow/viewport/DFlowViewport.nodes.hook.ts +++ b/src/components/d-flow/DFlow.nodes.hook.ts @@ -1,9 +1,9 @@ -import {useService} from "../../../utils/contextStore"; -import {DFlowReactiveService} from "../DFlow.service"; -import {NodeFunctionView} from "../DFlow.view"; +import {useService} from "../../utils/contextStore"; +import {DFlowReactiveService} from "./DFlow.service"; +import {NodeFunctionView} from "./DFlow.view"; import {Node} from "@xyflow/react"; -import {DFlowFunctionReactiveService} from "../function/DFlowFunction.service"; -import {DFlowDataTypeReactiveService} from "../data-type/DFlowDataType.service"; +import {DFlowFunctionReactiveService} from "./function/DFlowFunction.service"; +import {DFlowDataTypeReactiveService} from "./data-type/DFlowDataType.service"; import {DataTypeIdentifier, DataTypeVariant, Scalars} from "@code0-tech/sagittarius-graphql-types"; const packageNodes = new Map([ @@ -90,7 +90,7 @@ const bestMatchValue = (map: Map, input: string): string => { return bestKey !== null ? map.get(bestKey)! : ""; }; -export const useFlowViewportNodes = (flowId: string): Node[] => { +export const useFlowNodes = (flowId: string): Node[] => { const flowService = useService(DFlowReactiveService); const functionService = useService(DFlowFunctionReactiveService); const dataTypeService = useService(DFlowDataTypeReactiveService); diff --git a/src/components/d-flow/DFlow.tsx b/src/components/d-flow/DFlow.tsx index 2d90a161..242024f8 100644 --- a/src/components/d-flow/DFlow.tsx +++ b/src/components/d-flow/DFlow.tsx @@ -13,11 +13,11 @@ import React from "react"; import {mergeCode0Props} from "../../utils/utils"; import '@xyflow/react/dist/style.css'; import "./DFlow.style.scss" -import {DFlowViewportDefaultCard} from "./viewport/cards/DFlowViewportDefaultCard"; -import {DFlowViewportGroupCard} from "./viewport/cards/DFlowViewportGroupCard"; -import {DFlowViewportSuggestionCard} from "./viewport/cards/DFlowViewportSuggestionCard"; -import {DFlowViewportTriggerCard} from "./viewport/cards/DFlowViewportTriggerCard"; -import {DFlowViewportEdge} from "./viewport/DFlowViewportEdge"; +import {DFlowFunctionDefaultCard} from "./function/DFlowFunctionDefaultCard"; +import {DFlowFunctionGroupCard} from "./function/DFlowFunctionGroupCard"; +import {DFlowFunctionSuggestionCard} from "./function/DFlowFunctionSuggestionCard"; +import {DFlowFunctionTriggerCard} from "./function/DFlowFunctionTriggerCard"; +import {DFlowEdge} from "./DFlowEdge"; /** * Dynamically layouts a tree of nodes and their parameter nodes for a flow-based editor. @@ -523,15 +523,15 @@ const InternalDFlow: React.FC = (props) => { }, [updateNodeInternals]) const nodeTypes = { - default: DFlowViewportDefaultCard, - group: DFlowViewportGroupCard, - suggestion: DFlowViewportSuggestionCard, - trigger: DFlowViewportTriggerCard, + default: DFlowFunctionDefaultCard, + group: DFlowFunctionGroupCard, + suggestion: DFlowFunctionSuggestionCard, + trigger: DFlowFunctionTriggerCard, ...props.nodeTypes } const edgeTypes = { - default: DFlowViewportEdge, + default: DFlowEdge, ...props.edgeTypes } diff --git a/src/components/d-flow/DFlow.view.ts b/src/components/d-flow/DFlow.view.ts index df7fefd7..3c4190b8 100644 --- a/src/components/d-flow/DFlow.view.ts +++ b/src/components/d-flow/DFlow.view.ts @@ -38,6 +38,8 @@ export class FlowView { /** Time when this Flow was last updated */ private readonly _updatedAt?: Maybe; + private _name?: Maybe; + constructor(flow: Flow) { this._createdAt = flow.createdAt @@ -49,6 +51,7 @@ export class FlowView { this._startingNodeId = flow.startingNodeId this._type = flow.type this._updatedAt = flow.updatedAt + this._name = flow.name } @@ -88,6 +91,10 @@ export class FlowView { return this._updatedAt; } + get name(): Maybe | undefined { + return this._name; + } + set inputType(value: Maybe) { this._inputType = value; } @@ -96,6 +103,10 @@ export class FlowView { this._startingNodeId = value; } + set name(value: Maybe) { + this._name = value; + } + addNode(node: NodeFunctionView): void { if (!this._nodes) { this._nodes = []; diff --git a/src/components/d-flow/viewport/DFlowViewportControls.tsx b/src/components/d-flow/DFlowControls.tsx similarity index 80% rename from src/components/d-flow/viewport/DFlowViewportControls.tsx rename to src/components/d-flow/DFlowControls.tsx index c8c91851..725a6f94 100644 --- a/src/components/d-flow/viewport/DFlowViewportControls.tsx +++ b/src/components/d-flow/DFlowControls.tsx @@ -1,13 +1,13 @@ import React from "react"; import {Panel, useReactFlow, useViewport} from "@xyflow/react"; -import ButtonGroup from "../../button-group/ButtonGroup"; -import Button from "../../button/Button"; +import ButtonGroup from "../button-group/ButtonGroup"; +import Button from "../button/Button"; import {IconFocusCentered, IconMinus, IconPlus} from "@tabler/icons-react"; -import Badge from "../../badge/Badge"; -import Flex from "../../flex/Flex"; -import {DFlowViewportMiniMap} from "./DFlowViewportMiniMap"; +import Badge from "../badge/Badge"; +import Flex from "../flex/Flex"; +import {DFlowMiniMap} from "./DFlowMiniMap"; -export const DFlowViewportControls: React.FC = () => { +export const DFlowControls: React.FC = () => { const viewport = useViewport(); const reactFlow = useReactFlow(); diff --git a/src/components/d-flow/viewport/DFlowViewportEdge.tsx b/src/components/d-flow/DFlowEdge.tsx similarity index 79% rename from src/components/d-flow/viewport/DFlowViewportEdge.tsx rename to src/components/d-flow/DFlowEdge.tsx index 5f85659b..737b587b 100644 --- a/src/components/d-flow/viewport/DFlowViewportEdge.tsx +++ b/src/components/d-flow/DFlowEdge.tsx @@ -1,9 +1,9 @@ -import {Code0Component} from "../../../utils/types"; +import {Code0Component} from "../../utils/types"; import {BaseEdge, Edge, EdgeLabelRenderer, EdgeProps, getSmoothStepPath, Position} from "@xyflow/react"; import React, {memo} from "react"; -import Badge from "../../badge/Badge"; +import Badge from "../badge/Badge"; -export interface DFlowViewportEdgeDataProps extends Code0Component { +export interface DFlowEdgeDataProps extends Code0Component { //some data we will use color?: string isParameter?: boolean @@ -11,9 +11,9 @@ export interface DFlowViewportEdgeDataProps extends Code0Component> +export type DFlowEdgeProps = EdgeProps> -export const DFlowViewportEdge: React.FC = memo((props) => { +export const DFlowEdge: React.FC = memo((props) => { const {sourceX, sourceY, targetX, targetY, id, data, ...rest} = props diff --git a/src/components/d-flow/viewport/DFlowViewportMiniMap.style.scss b/src/components/d-flow/DFlowMiniMap.style.scss similarity index 75% rename from src/components/d-flow/viewport/DFlowViewportMiniMap.style.scss rename to src/components/d-flow/DFlowMiniMap.style.scss index 329c940e..dbc5c57a 100644 --- a/src/components/d-flow/viewport/DFlowViewportMiniMap.style.scss +++ b/src/components/d-flow/DFlowMiniMap.style.scss @@ -1,6 +1,6 @@ -@use "../../../styles/helpers"; -@use "../../../styles/box"; -@use "../../../styles/variables"; +@use "../../styles/helpers"; +@use "../../styles/box"; +@use "../../styles/variables"; .d-flow-viewport-mini-map { diff --git a/src/components/d-flow/viewport/DFlowViewportMiniMap.tsx b/src/components/d-flow/DFlowMiniMap.tsx similarity index 89% rename from src/components/d-flow/viewport/DFlowViewportMiniMap.tsx rename to src/components/d-flow/DFlowMiniMap.tsx index 7c1f2119..3733d01f 100644 --- a/src/components/d-flow/viewport/DFlowViewportMiniMap.tsx +++ b/src/components/d-flow/DFlowMiniMap.tsx @@ -1,9 +1,9 @@ import React from "react"; import {MiniMap, useNodes} from "@xyflow/react"; -import {FLOW_EDGE_RAINBOW} from "./DFlowViewport.edges.hook"; -import "./DFlowViewportMiniMap.style.scss" +import {FLOW_EDGE_RAINBOW} from "./DFlow.edges.hook"; +import "./DFlowMiniMap.style.scss" -export const DFlowViewportMiniMap: React.FC = (props) => { +export const DFlowMiniMap: React.FC = (props) => { const nodes = useNodes(); diff --git a/src/components/d-flow/viewport/DFlowViewportValidations.style.scss b/src/components/d-flow/DFlowValidation.style.scss similarity index 61% rename from src/components/d-flow/viewport/DFlowViewportValidations.style.scss rename to src/components/d-flow/DFlowValidation.style.scss index 57750114..6fdc2bdd 100644 --- a/src/components/d-flow/viewport/DFlowViewportValidations.style.scss +++ b/src/components/d-flow/DFlowValidation.style.scss @@ -1,6 +1,6 @@ -@use "../../../styles/variables"; -@use "../../../styles/helpers"; -@use "../../../styles/box"; +@use "../../styles/variables"; +@use "../../styles/helpers"; +@use "../../styles/box"; .d-flow-viewport-validations { padding: variables.$xxs; diff --git a/src/components/d-flow/viewport/DFlowViewportValidations.tsx b/src/components/d-flow/DFlowValidation.tsx similarity index 84% rename from src/components/d-flow/viewport/DFlowViewportValidations.tsx rename to src/components/d-flow/DFlowValidation.tsx index 55101ebb..e3602921 100644 --- a/src/components/d-flow/viewport/DFlowViewportValidations.tsx +++ b/src/components/d-flow/DFlowValidation.tsx @@ -1,18 +1,18 @@ import {Panel} from "@xyflow/react"; import React from "react"; -import {useDFlowValidations} from "../DFlow.validation.hook"; +import {useDFlowValidations} from "./DFlow.validation.hook"; import {Scalars} from "@code0-tech/sagittarius-graphql-types"; -import Flex from "../../flex/Flex"; -import {InspectionSeverity} from "../../../utils/inspection"; -import Badge from "../../badge/Badge"; +import Flex from "../flex/Flex"; +import {InspectionSeverity} from "../../utils/inspection"; +import Badge from "../badge/Badge"; import {IconAlertTriangle, IconExclamationCircle, IconMessageExclamation} from "@tabler/icons-react"; -import "./DFlowViewportValidations.style.scss" +import "./DFlowValidation.style.scss" -export interface DFlowViewportValidationsProps { +export interface DFlowValidationProps { flowId: Scalars['FlowID']['output'] } -export const DFlowViewportValidations: React.FC = (props) => { +export const DFlowValidation: React.FC = (props) => { const {flowId} = props const validations = useDFlowValidations(flowId) diff --git a/src/components/d-folder/DFolder.style.scss b/src/components/d-flow/folder/DFlowFolder.style.scss similarity index 84% rename from src/components/d-folder/DFolder.style.scss rename to src/components/d-flow/folder/DFlowFolder.style.scss index 99cce972..423efb28 100644 --- a/src/components/d-folder/DFolder.style.scss +++ b/src/components/d-flow/folder/DFlowFolder.style.scss @@ -1,6 +1,6 @@ -@use "../../styles/helpers"; -@use "../../styles/box"; -@use "../../styles/variables"; +@use "../../../styles/helpers"; +@use "../../../styles/box"; +@use "../../../styles/variables"; .d-folder { padding: variables.$xxs variables.$xs; @@ -40,13 +40,15 @@ } &__content { + $spacing: variables.$xxs; + margin-left: variables.$xs; position: relative; + padding-left: calc(5px + $spacing); &:before { - z-index: 10; height: 100%; - width: 2px; + width: 1px; background: helpers.backgroundColor(variables.$secondary); position: absolute; content: ""; @@ -64,14 +66,15 @@ align-items: center; cursor: pointer; font-size: variables.$sm; + position: relative; & { @include helpers.borderRadius(); @include box.box(variables.$primary); @include box.boxHover(variables.$secondary); + @include box.boxActive(variables.$secondary); @include helpers.fontStyle(); box-shadow: none; - background: transparent; } } } \ No newline at end of file diff --git a/src/components/d-flow/folder/DFlowFolder.tsx b/src/components/d-flow/folder/DFlowFolder.tsx new file mode 100644 index 00000000..5bf54e2a --- /dev/null +++ b/src/components/d-flow/folder/DFlowFolder.tsx @@ -0,0 +1,184 @@ +"use client" + +import "./DFlowFolder.style.scss" +import React from "react"; +import {Code0Component} from "../../../utils/types"; +import {mergeCode0Props} from "../../../utils/utils"; +import {IconChevronDown, IconChevronRight, IconFolder} from "@tabler/icons-react"; +import {Scalars} from "@code0-tech/sagittarius-graphql-types"; +import {useService, useStore} from "../../../utils/contextStore"; +import {DFlowReactiveService} from "../DFlow.service"; +import {ScrollArea, ScrollAreaScrollbar, ScrollAreaThumb, ScrollAreaViewport} from "../../scroll-area/ScrollArea"; +import {FlowView} from "../DFlow.view"; + + +export interface DFlowFolderProps { + flowId: Scalars["FlowID"]["output"] +} + +export interface DFlowFolderGroupProps extends Omit, "controls"> { + name: string + children: React.ReactElement | React.ReactElement[] | React.ReactElement | React.ReactElement[] + //defaults to false + defaultOpen?: boolean +} + +export interface DFlowFolderItemProps extends Code0Component { + name: string + icon?: React.ReactNode + //defaults to false + active?: boolean +} + +export const DFlowFolder: React.FC = (props) => { + + const { flowId } = props; + + const flowService = useService(DFlowReactiveService); + const flowStore = useStore(DFlowReactiveService) + + type TreeNode = { + name: string; + path: string; + children: Record; + flow?: FlowView; + }; + + const normalizePath = (p: string) => + p.replace(/^\/+|\/+$/g, "").split("/").filter(Boolean); + + const flows = React.useMemo(() => { + const raw = (flowService.values?.() ?? []) as FlowView[]; + return raw.filter(f => !!f?.name); + }, [flowStore]); + + const activePathSegments = React.useMemo(() => { + const active = flows.find(f => f.id === flowId); + if (!active?.name) return []; + return normalizePath(active.name); + }, [flows, flowId]); + + const tree = React.useMemo(() => { + const root: TreeNode = { name: "", path: "", children: {} }; + for (const flow of flows) { + const segs = normalizePath(flow.name as string); + if (segs.length === 0) continue; + + let cur = root; + let acc = ""; + for (let i = 0; i < segs.length; i++) { + const seg = segs[i]; + acc = acc ? `${acc}/${seg}` : seg; + + if (i === segs.length - 1) { + // leaf (Flow) + if (!cur.children[seg]) { + cur.children[seg] = { + name: seg, + path: acc, + children: {}, + flow + }; + } else { + // falls es bereits einen Knoten gibt, hänge Flow an + cur.children[seg].flow = flow; + } + } else { + // folder + if (!cur.children[seg]) { + cur.children[seg] = { + name: seg, + path: acc, + children: {} + }; + } + cur = cur.children[seg]; + } + } + } + return root; + }, [flows]); + + const isPrefixOfActive = React.useCallback((nodePath: string) => { + if (!nodePath) return false; + const segs = nodePath.split("/").filter(Boolean); + return segs.every((s, i) => activePathSegments[i] === s); + }, [activePathSegments]); + + const renderChildren = React.useCallback((childrenMap: Record) => { + const nodes = Object.values(childrenMap); + + const folders = nodes.filter(n => !n.flow); + const items = nodes.filter(n => !!n.flow); + + folders.sort((a, b) => a.name.localeCompare(b.name)); + items.sort((a, b) => a.name.localeCompare(b.name)); + + return ( + <> + {folders.map(folder => ( + + {renderChildren(folder.children)} + + ))} + {items.map(item => ( + + ))} + + ); + }, [flowId, isPrefixOfActive]); + + return ( + + +
+ {renderChildren(tree.children)} +
+
+ + + +
+ ) + +} + +export const DFlowFolderGroup: React.FC = (props) => { + + const {name, defaultOpen = false, children, ...rest} = props + const [open, setOpen] = React.useState(defaultOpen); + + return
+
setOpen(prevState => !prevState)} {...mergeCode0Props(`d-folder`, rest)}> + setOpen(prevState => !prevState)} className={"d-folder__status"}> + {open ? : } + + + {name} +
+
+ {open ? children : null} +
+
+} + +export const DFlowFolderItem: React.FC = (props) => { + + const {name, icon, active, ...rest} = props + + return
+ {icon? {icon} : null} + {name} +
+} + diff --git a/src/components/d-flow/viewport/cards/DFlowViewportDefaultCard.style.scss b/src/components/d-flow/function/DFlowFunctionDefaultCard.style.scss similarity index 82% rename from src/components/d-flow/viewport/cards/DFlowViewportDefaultCard.style.scss rename to src/components/d-flow/function/DFlowFunctionDefaultCard.style.scss index 63c55e1e..e33f0e55 100644 --- a/src/components/d-flow/viewport/cards/DFlowViewportDefaultCard.style.scss +++ b/src/components/d-flow/function/DFlowFunctionDefaultCard.style.scss @@ -1,6 +1,6 @@ -@use "../../../../styles/variables"; -@use "../../../../styles/helpers"; -@use "../../../../styles/box"; +@use "../../../styles/variables"; +@use "../../../styles/helpers"; +@use "../../../styles/box"; .d-flow-viewport-default-card { &__handle { diff --git a/src/components/d-flow/viewport/cards/DFlowViewportDefaultCard.tsx b/src/components/d-flow/function/DFlowFunctionDefaultCard.tsx similarity index 87% rename from src/components/d-flow/viewport/cards/DFlowViewportDefaultCard.tsx rename to src/components/d-flow/function/DFlowFunctionDefaultCard.tsx index 4bd95121..3d906299 100644 --- a/src/components/d-flow/viewport/cards/DFlowViewportDefaultCard.tsx +++ b/src/components/d-flow/function/DFlowFunctionDefaultCard.tsx @@ -1,11 +1,11 @@ -import {Code0Component} from "../../../../utils/types"; +import {Code0Component} from "../../../utils/types"; import {Handle, Node, NodeProps, Position, useReactFlow, useStore, useStoreApi} from "@xyflow/react"; -import {NodeFunctionView, NodeParameterView} from "../../DFlow.view"; +import {NodeFunctionView, NodeParameterView} from "../DFlow.view"; import React, {memo} from "react"; -import Card from "../../../card/Card"; -import "./DFlowViewportDefaultCard.style.scss"; -import CardSection from "../../../card/CardSection"; -import Flex from "../../../flex/Flex"; +import Card from "../../card/Card"; +import "./DFlowFunctionDefaultCard.style.scss"; +import CardSection from "../../card/CardSection"; +import Flex from "../../flex/Flex"; import { IconAlertTriangle, IconArrowRightCircle, IconCopy, @@ -16,23 +16,23 @@ import { IconMessageExclamation, IconTrash } from "@tabler/icons-react"; -import Text from "../../../text/Text"; -import Button from "../../../button/Button"; -import {Menu, MenuContent, MenuItem, MenuLabel, MenuPortal, MenuTrigger} from "../../../menu/Menu"; -import Badge from "../../../badge/Badge"; -import {useService} from "../../../../utils/contextStore"; -import {DFlowFunctionReactiveService} from "../../function/DFlowFunction.service"; -import {useFunctionValidation} from "../../function/DFlowFunction.vaildation.hook"; -import {DFlowDataTypeReactiveService} from "../../data-type/DFlowDataType.service"; -import {InspectionSeverity} from "../../../../utils/inspection"; -import {DFlowReactiveService} from "../../DFlow.service"; -import {DFlowSuggestionMenu} from "../../suggestions/DFlowSuggestionMenu"; -import {useSuggestions} from "../../suggestions/DFlowSuggestion.hook"; -import {FileTabsService} from "../../../file-tabs/FileTabs.service"; -import {DFlowViewportDefaultTabContent} from "../file-tabs/DFlowViewportDefaultTabContent"; +import Text from "../../text/Text"; +import Button from "../../button/Button"; +import {Menu, MenuContent, MenuItem, MenuLabel, MenuPortal, MenuTrigger} from "../../menu/Menu"; +import Badge from "../../badge/Badge"; +import {useService} from "../../../utils/contextStore"; +import {DFlowFunctionReactiveService} from "./DFlowFunction.service"; +import {useFunctionValidation} from "./DFlowFunction.vaildation.hook"; +import {DFlowDataTypeReactiveService} from "../data-type/DFlowDataType.service"; +import {InspectionSeverity} from "../../../utils/inspection"; +import {DFlowReactiveService} from "../DFlow.service"; +import {DFlowSuggestionMenu} from "../suggestion/DFlowSuggestionMenu"; +import {useSuggestions} from "../suggestion/DFlowSuggestion.hook"; +import {FileTabsService} from "../../file-tabs/FileTabs.service"; +import {DFlowTabDefault} from "../tab/DFlowTabDefault"; import {DataTypeVariant, Maybe, Scalars} from "@code0-tech/sagittarius-graphql-types"; -export interface DFlowViewportDefaultCardDataProps extends Omit, "scope"> { +export interface DFlowFunctionDefaultCardDataProps extends Omit, "scope"> { instance: NodeFunctionView flowId: Scalars["FlowID"]["output"] isParameter: boolean @@ -42,9 +42,9 @@ export interface DFlowViewportDefaultCardDataProps extends Omit> +export type DFlowFunctionDefaultCardProps = NodeProps> -export const DFlowViewportDefaultCard: React.FC = memo((props) => { +export const DFlowFunctionDefaultCard: React.FC = memo((props) => { const {data, id} = props; const viewportWidth = useStore(s => s.width); const viewportHeight = useStore(s => s.height); @@ -106,8 +106,8 @@ export const DFlowViewportDefaultCard: React.FC = active: true, closeable: true, children: {definition?.names?.nodes!![0]?.content}, - content: + content: }) }} style={{position: "relative"}}> diff --git a/src/components/d-flow/viewport/cards/DFlowViewportGroupCard.tsx b/src/components/d-flow/function/DFlowFunctionGroupCard.tsx similarity index 90% rename from src/components/d-flow/viewport/cards/DFlowViewportGroupCard.tsx rename to src/components/d-flow/function/DFlowFunctionGroupCard.tsx index b36c2e71..20964830 100644 --- a/src/components/d-flow/viewport/cards/DFlowViewportGroupCard.tsx +++ b/src/components/d-flow/function/DFlowFunctionGroupCard.tsx @@ -1,12 +1,12 @@ import React, {memo} from "react"; import {Handle, NodeProps, Position, useStore} from "@xyflow/react"; -import {FLOW_EDGE_RAINBOW} from "../DFlowViewport.edges.hook"; -import Card from "../../../card/Card"; +import {FLOW_EDGE_RAINBOW} from "../DFlow.edges.hook"; +import Card from "../../card/Card"; -export interface DFlowViewportGroupCardProps extends NodeProps { +export interface DFlowFunctionGroupCardProps extends NodeProps { } -export const DFlowViewportGroupCard: React.FC = memo((props) => { +export const DFlowFunctionGroupCard: React.FC = memo((props) => { const {data, id} = props const depth = (data as any)?.depth ?? 0; const color = FLOW_EDGE_RAINBOW[depth % FLOW_EDGE_RAINBOW.length]; diff --git a/src/components/d-flow/viewport/cards/DFlowViewportSuggestionCard.tsx b/src/components/d-flow/function/DFlowFunctionSuggestionCard.tsx similarity index 69% rename from src/components/d-flow/viewport/cards/DFlowViewportSuggestionCard.tsx rename to src/components/d-flow/function/DFlowFunctionSuggestionCard.tsx index 953c897c..6c6de713 100644 --- a/src/components/d-flow/viewport/cards/DFlowViewportSuggestionCard.tsx +++ b/src/components/d-flow/function/DFlowFunctionSuggestionCard.tsx @@ -1,24 +1,24 @@ -import {Code0Component} from "../../../../utils/types"; +import {Code0Component} from "../../../utils/types"; import {Handle, Node, NodeProps, Position} from "@xyflow/react"; import React, {memo} from "react"; -import Button from "../../../button/Button"; +import Button from "../../button/Button"; import {IconPlus} from "@tabler/icons-react"; -import {useSuggestions} from "../../suggestions/DFlowSuggestion.hook"; -import {NodeFunctionView} from "../../DFlow.view"; -import {useService} from "../../../../utils/contextStore"; -import {DFlowReactiveService} from "../../DFlow.service"; -import {DFlowSuggestionMenu} from "../../suggestions/DFlowSuggestionMenu"; +import {useSuggestions} from "../suggestion/DFlowSuggestion.hook"; +import {NodeFunctionView} from "../DFlow.view"; +import {useService} from "../../../utils/contextStore"; +import {DFlowReactiveService} from "../DFlow.service"; +import {DFlowSuggestionMenu} from "../suggestion/DFlowSuggestionMenu"; import {NodeFunction} from "@code0-tech/sagittarius-graphql-types"; -export interface DFlowViewportSuggestionCardDataProps extends Code0Component { +export interface DFlowFunctionSuggestionCardDataProps extends Code0Component { flowId: string parentFunction?: NodeFunctionView } // @ts-ignore -export type DFlowViewportSuggestionCardProps = NodeProps> +export type DFlowFunctionSuggestionCardProps = NodeProps> -export const DFlowViewportSuggestionCard: React.FC = memo((props) => { +export const DFlowFunctionSuggestionCard: React.FC = memo((props) => { const result = useSuggestions(undefined, [], props.data.flowId, 0, [0], 0) const flowService = useService(DFlowReactiveService) diff --git a/src/components/d-flow/viewport/cards/DFlowViewportTriggerCard.tsx b/src/components/d-flow/function/DFlowFunctionTriggerCard.tsx similarity index 75% rename from src/components/d-flow/viewport/cards/DFlowViewportTriggerCard.tsx rename to src/components/d-flow/function/DFlowFunctionTriggerCard.tsx index 52102a16..1e1c2d8c 100644 --- a/src/components/d-flow/viewport/cards/DFlowViewportTriggerCard.tsx +++ b/src/components/d-flow/function/DFlowFunctionTriggerCard.tsx @@ -1,27 +1,27 @@ import React, {memo} from "react"; -import {Code0Component} from "../../../../utils/types"; -import {FlowView} from "../../DFlow.view"; +import {Code0Component} from "../../../utils/types"; +import {FlowView} from "../DFlow.view"; import {Handle, Node, NodeProps, Position, useReactFlow, useStore} from "@xyflow/react"; -import Text from "../../../text/Text"; -import {useService} from "../../../../utils/contextStore"; -import {FileTabsService} from "../../../file-tabs/FileTabs.service"; -import Card from "../../../card/Card"; -import CardSection from "../../../card/CardSection"; -import Flex from "../../../flex/Flex"; +import Text from "../../text/Text"; +import {useService} from "../../../utils/contextStore"; +import {FileTabsService} from "../../file-tabs/FileTabs.service"; +import Card from "../../card/Card"; +import CardSection from "../../card/CardSection"; +import Flex from "../../flex/Flex"; import {IconBolt, IconLayoutNavbarCollapseFilled} from "@tabler/icons-react"; -import Button from "../../../button/Button"; -import Badge from "../../../badge/Badge"; -import {DFlowViewportTriggerTabContent} from "../file-tabs/DFlowViewportTriggerTabContent"; -import {DFlowTypeReactiveService} from "../../type/DFlowType.service"; +import Button from "../../button/Button"; +import Badge from "../../badge/Badge"; +import {DFlowTabTrigger} from "../tab/DFlowTabTrigger"; +import {DFlowTypeReactiveService} from "../type/DFlowType.service"; -export interface DFlowViewportTriggerCardDataProps extends Omit, "scope"> { +export interface DFlowFunctionTriggerCardDataProps extends Omit, "scope"> { instance: FlowView } // @ts-ignore -export type DFlowViewportTriggerCardProps = NodeProps> +export type DFlowFunctionTriggerCardProps = NodeProps> -export const DFlowViewportTriggerCard: React.FC = memo((props) => { +export const DFlowFunctionTriggerCard: React.FC = memo((props) => { const {data, id} = props const fileTabsService = useService(FileTabsService) @@ -49,7 +49,7 @@ export const DFlowViewportTriggerCard: React.FC = active: true, closeable: true, children: {definition?.names?.nodes!![0]?.content}, - content: + content: }) }}> diff --git a/src/components/d-flow/viewport/inputs/DFlowViewportDataTypeInput.style.scss b/src/components/d-flow/input/DFlowInputDataType.style.scss similarity index 79% rename from src/components/d-flow/viewport/inputs/DFlowViewportDataTypeInput.style.scss rename to src/components/d-flow/input/DFlowInputDataType.style.scss index 15084084..b730e58a 100644 --- a/src/components/d-flow/viewport/inputs/DFlowViewportDataTypeInput.style.scss +++ b/src/components/d-flow/input/DFlowInputDataType.style.scss @@ -1,6 +1,6 @@ -@use "../../../../styles/helpers"; -@use "../../../../styles/variables"; -@use "../../../../styles/box"; +@use "../../../styles/helpers"; +@use "../../../styles/variables"; +@use "../../../styles/box"; .d-flow-viewport-data-type-input { padding: variables.$md; diff --git a/src/components/d-flow/viewport/inputs/DFlowViewportDataTypeInput.tsx b/src/components/d-flow/input/DFlowInputDataType.tsx similarity index 96% rename from src/components/d-flow/viewport/inputs/DFlowViewportDataTypeInput.tsx rename to src/components/d-flow/input/DFlowInputDataType.tsx index bc67c2ca..1a7bbdbc 100644 --- a/src/components/d-flow/viewport/inputs/DFlowViewportDataTypeInput.tsx +++ b/src/components/d-flow/input/DFlowInputDataType.tsx @@ -1,5 +1,5 @@ import React from "react"; -import {ValidationProps} from "../../../form/useForm"; +import {ValidationProps} from "../../form/useForm"; import { DataType, DataTypeIdentifier, @@ -13,25 +13,25 @@ import { GenericMapper, GenericType } from "@code0-tech/sagittarius-graphql-types"; -import InputMessage from "../../../form/InputMessage"; -import "./DFlowViewportDataTypeInput.style.scss"; -import TextInput from "../../../form/TextInput"; -import Button from "../../../button/Button"; +import InputMessage from "../../form/InputMessage"; +import "./DFlowInputDataType.style.scss"; +import TextInput from "../../form/TextInput"; +import Button from "../../button/Button"; import {IconSettings, IconTrash} from "@tabler/icons-react"; -import Text from "../../../text/Text"; -import Flex from "../../../flex/Flex"; -import Badge from "../../../badge/Badge"; -import InputLabel from "../../../form/InputLabel"; -import {useSuggestions} from "../../suggestions/DFlowSuggestion.hook"; -import {DFlowSuggestionMenuFooter} from "../../suggestions/DFlowSuggestionMenuFooter"; -import {toInputSuggestions} from "../../suggestions/DFlowSuggestionMenu.util"; -import {DFlowSuggestionType} from "../../suggestions/DFlowSuggestion.view"; -import {Menu, MenuPortal, MenuTrigger} from "../../../menu/Menu"; +import Text from "../../text/Text"; +import Flex from "../../flex/Flex"; +import Badge from "../../badge/Badge"; +import InputLabel from "../../form/InputLabel"; +import {useSuggestions} from "../suggestion/DFlowSuggestion.hook"; +import {DFlowSuggestionMenuFooter} from "../suggestion/DFlowSuggestionMenuFooter"; +import {toInputSuggestions} from "../suggestion/DFlowSuggestionMenu.util"; +import {DFlowSuggestionType} from "../suggestion/DFlowSuggestion.view"; +import {Menu, MenuPortal, MenuTrigger} from "../../menu/Menu"; import { InputSuggestion, InputSuggestionMenuContent, InputSuggestionMenuContentItems -} from "../../../form/InputSuggestion"; +} from "../../form/InputSuggestion"; const NON_TYPE_RULE_VARIANTS = new Set([ DataTypeRulesVariant.ItemOfCollection, @@ -46,12 +46,12 @@ const DATA_TYPE_RULES_VARIANTS = [ DataTypeRulesVariant.NumberRange, DataTypeRulesVariant.Regex, ] -export interface DFlowViewportDataTypeInputProps extends ValidationProps { +export interface DFlowInputDataTypeProps extends ValidationProps { onDataTypeChange?: (value: DataType | GenericType) => void blockingDataType?: DataType | GenericType } -export const DFlowViewportDataTypeInput: React.FC = (props) => { +export const DFlowInputDataType: React.FC = (props) => { const { formValidation, @@ -388,7 +388,7 @@ const RuleItem: React.FC<{ <> {header} {isOpen ? ( - = (props) => { +export const DFlowTabDefault: React.FC = (props) => { const {functionInstance, flowId, depthLevel, scopeLevel, nodeLevel} = props const functionService = useService(DFlowFunctionReactiveService) diff --git a/src/components/d-flow/viewport/file-tabs/DFlowViewportTriggerTabContent.tsx b/src/components/d-flow/tab/DFlowTabTrigger.tsx similarity index 76% rename from src/components/d-flow/viewport/file-tabs/DFlowViewportTriggerTabContent.tsx rename to src/components/d-flow/tab/DFlowTabTrigger.tsx index 11bfa46f..b449465b 100644 --- a/src/components/d-flow/viewport/file-tabs/DFlowViewportTriggerTabContent.tsx +++ b/src/components/d-flow/tab/DFlowTabTrigger.tsx @@ -1,22 +1,22 @@ import React from "react"; -import {FlowView} from "../../DFlow.view"; -import {useService} from "../../../../utils/contextStore"; -import {DFlowReactiveService} from "../../DFlow.service"; -import TextInput from "../../../form/TextInput"; -import Flex from "../../../flex/Flex"; -import {DFlowTypeReactiveService} from "../../type/DFlowType.service"; -import {DFlowSuggestion} from "../../suggestions/DFlowSuggestion.view"; -import {useSuggestions} from "../../suggestions/DFlowSuggestion.hook"; -import {DFlowSuggestionMenuFooter} from "../../suggestions/DFlowSuggestionMenuFooter"; -import {toInputSuggestions} from "../../suggestions/DFlowSuggestionMenu.util"; +import {FlowView} from "../DFlow.view"; +import {useService} from "../../../utils/contextStore"; +import {DFlowReactiveService} from "../DFlow.service"; +import TextInput from "../../form/TextInput"; +import Flex from "../../flex/Flex"; +import {DFlowTypeReactiveService} from "../type/DFlowType.service"; +import {DFlowSuggestion} from "../suggestion/DFlowSuggestion.view"; +import {useSuggestions} from "../suggestion/DFlowSuggestion.hook"; +import {DFlowSuggestionMenuFooter} from "../suggestion/DFlowSuggestionMenuFooter"; +import {toInputSuggestions} from "../suggestion/DFlowSuggestionMenu.util"; import {DataType, NodeParameterValue, Scalars} from "@code0-tech/sagittarius-graphql-types"; -import {DFlowViewportDataTypeInput} from "../inputs/DFlowViewportDataTypeInput"; +import {DFlowInputDataType} from "../input/DFlowInputDataType"; -export interface DFlowViewportTriggerTabContentProps { +export interface DFlowTabTriggerProps { instance: FlowView } -export const DFlowViewportTriggerTabContent: React.FC = (props) => { +export const DFlowTabTrigger: React.FC = (props) => { const {instance} = props const flowTypeService = useService(DFlowTypeReactiveService) @@ -30,7 +30,7 @@ export const DFlowViewportTriggerTabContent: React.FC - {definition?.inputType ? { + {definition?.inputType ? { instance.inputType = value as DataType flowService.update() }} initialValue={instance.inputType || definition.inputType} blockingDataType={definition.inputType}/> : null} diff --git a/src/components/d-flow/viewport/file-tabs/DFlowViewportTabs.tsx b/src/components/d-flow/tab/DFlowTabs.tsx similarity index 92% rename from src/components/d-flow/viewport/file-tabs/DFlowViewportTabs.tsx rename to src/components/d-flow/tab/DFlowTabs.tsx index ad2b81b4..217b27de 100644 --- a/src/components/d-flow/viewport/file-tabs/DFlowViewportTabs.tsx +++ b/src/components/d-flow/tab/DFlowTabs.tsx @@ -1,13 +1,13 @@ -import {useService, useStore} from "../../../../utils/contextStore"; -import {FileTabsService} from "../../../file-tabs/FileTabs.service"; -import {FileTabs, FileTabsContent, FileTabsList, FileTabsTrigger} from "../../../file-tabs/FileTabs"; +import {useService, useStore} from "../../../utils/contextStore"; +import {FileTabsService} from "../../file-tabs/FileTabs.service"; +import {FileTabs, FileTabsContent, FileTabsList, FileTabsTrigger} from "../../file-tabs/FileTabs"; import React from "react"; -import {Menu, MenuContent, MenuItem, MenuPortal, MenuSeparator, MenuTrigger} from "../../../menu/Menu"; -import Button from "../../../button/Button"; +import {Menu, MenuContent, MenuItem, MenuPortal, MenuSeparator, MenuTrigger} from "../../menu/Menu"; +import Button from "../../button/Button"; import {IconChevronDown, IconDotsVertical} from "@tabler/icons-react"; -import {FileTabsView} from "../../../file-tabs/FileTabs.view"; +import {FileTabsView} from "../../file-tabs/FileTabs.view"; -export const DFlowViewportTabs = () => { +export const DFlowTabs = () => { const fileTabsService = useService(FileTabsService) const fileTabsStore = useStore(FileTabsService) diff --git a/src/components/d-folder/DFolder.tsx b/src/components/d-folder/DFolder.tsx deleted file mode 100644 index e37b1a3e..00000000 --- a/src/components/d-folder/DFolder.tsx +++ /dev/null @@ -1,75 +0,0 @@ -"use client" - -import "./DFolder.style.scss" -import React, {useEffect} from "react"; -import {Code0Component} from "../../utils/types"; -import {mergeCode0Props} from "../../utils/utils"; -import {IconChevronDown, IconChevronRight, IconFolder} from "@tabler/icons-react"; - -// -1 && -3 means open all folders -// -2 && -4 means close all folders -export type DFolderControls = -1 | -2 | -3 | -4 | undefined - -export interface DFolderProps extends Omit, "controls"> { - name: string - children: React.ReactElement | React.ReactElement[] | React.ReactElement | React.ReactElement[] - //defaults to false - defaultOpen?: boolean - controls?: DFolderControls -} - -export interface DFolderItemProps extends Code0Component { - name: string - icon?: React.ReactNode - //defaults to false - active?: boolean -} - -export const useFolderControls = (): [DFolderControls, () => void, () => void] => { - - const [folderControlState, setFolderControlState] = React.useState(undefined) - const openAll = () => setFolderControlState(prevState => prevState === -1 ? -3 : -1) - const closeAll = () => setFolderControlState(prevState => prevState === -2 ? -4 : -2) - - return [folderControlState, openAll, closeAll] -} - -const DFolder: React.FC = (props) => { - - const {name, defaultOpen = false, controls, children, ...rest} = props - const [open, setOpen] = React.useState(defaultOpen); - - useEffect(() => { - if (!controls) return - if (controls === -1 || controls === -3) setOpen(true) - else if (controls === -2 || controls === -4) setOpen(false) - }, [controls]); - - return
-
setOpen(prevState => !prevState)} {...mergeCode0Props(`d-folder`, rest)}> - setOpen(prevState => !prevState)} className={"d-folder__status"}> - {open ? : } - - - {name} -
-
- {open ? children : null} -
-
-} - -const DFolderItem: React.FC = (props) => { - - const {name, icon, active, ...rest} = props - - return
- {icon? {icon} : null} - {name} -
-} - -export default Object.assign(DFolder, { - Item: DFolderItem -}) - diff --git a/src/components/d-resizable/DResizable.stories.tsx b/src/components/d-resizable/DResizable.stories.tsx index 1bc2140e..2cbfe8e7 100644 --- a/src/components/d-resizable/DResizable.stories.tsx +++ b/src/components/d-resizable/DResizable.stories.tsx @@ -2,11 +2,9 @@ import {Meta} from "@storybook/react"; import {DResizableHandle, DResizablePanel, DResizablePanelGroup} from "./DResizable"; import React from "react"; import DFullScreen from "../d-fullscreen/DFullScreen"; -import DFolder from "../d-folder/DFolder"; import Button from "../button/Button"; -import {IconDatabase, IconFileFilled, IconHierarchy3, IconSettings, IconTicket} from "@tabler/icons-react"; +import {IconDatabase, IconHierarchy3, IconSettings, IconTicket} from "@tabler/icons-react"; import Flex from "../flex/Flex"; -import {ScrollArea, ScrollAreaScrollbar, ScrollAreaThumb, ScrollAreaViewport} from "../scroll-area/ScrollArea"; import {Tooltip, TooltipContent, TooltipPortal, TooltipTrigger} from "../tooltip/Tooltip"; import {FunctionDefinitionView} from "../d-flow/function/DFlowFunction.view"; import {useReactiveArrayService} from "../../utils/reactiveArrayService"; @@ -16,23 +14,24 @@ import {DataTypeView} from "../d-flow/data-type/DFlowDataType.view"; import {DFlowDataTypeReactiveService} from "../d-flow/data-type/DFlowDataType.service"; import {DFlowFunctionReactiveService} from "../d-flow/function/DFlowFunction.service"; import {DFlowReactiveService} from "../d-flow/DFlow.service"; -import {DFlowSuggestion} from "../d-flow/suggestions/DFlowSuggestion.view"; -import {DFlowReactiveSuggestionService} from "../d-flow/suggestions/DFlowSuggestion.service"; +import {DFlowSuggestion} from "../d-flow/suggestion/DFlowSuggestion.view"; +import {DFlowReactiveSuggestionService} from "../d-flow/suggestion/DFlowSuggestion.service"; import {FlowView} from "../d-flow/DFlow.view"; import {ContextStoreProvider} from "../../utils/contextStore"; -import {DFlowViewportTabs} from "../d-flow/viewport/file-tabs/DFlowViewportTabs"; +import {DFlowTabs} from "../d-flow/tab/DFlowTabs"; import {DFlowTypeReactiveService} from "../d-flow/type/DFlowType.service"; import {FlowTypeView} from "../d-flow/type/DFlowType.view"; import DataTypesData from "./data_types.json"; import FunctionsData from "./runtime_functions.json"; import FlowTypeData from "./flow_types.json"; -import {useFlowViewportNodes} from "../d-flow/viewport/DFlowViewport.nodes.hook"; -import {useFlowViewportEdges} from "../d-flow/viewport/DFlowViewport.edges.hook"; +import {useFlowNodes} from "../d-flow/DFlow.nodes.hook"; +import {useFlowEdges} from "../d-flow/DFlow.edges.hook"; import {DFlow} from "../d-flow/DFlow"; import {Background, BackgroundVariant} from "@xyflow/react"; -import {DFlowViewportControls} from "../d-flow/viewport/DFlowViewportControls"; -import {DFlowViewportValidations} from "../d-flow/viewport/DFlowViewportValidations"; +import {DFlowControls} from "../d-flow/DFlowControls"; +import {DFlowValidation} from "../d-flow/DFlowValidation"; import {DLayout} from "../d-layout/DLayout"; +import {DFlowFolder} from "../d-flow/folder/DFlowFolder"; const meta: Meta = { title: "Dashboard Resizable", @@ -59,6 +58,7 @@ export const Dashboard = () => { type: { id: "gid://sagittarius/TypesFlowType/842", }, + name: "de/codezero/examples/REST Flow", settings: { nodes: [{ flowSettingIdentifier: "HTTP_URL", @@ -74,101 +74,86 @@ export const Dashboard = () => { const [flowTypeStore, flowTypeService] = useReactiveArrayService(DFlowTypeReactiveService, [...FlowTypeData.map(data => new FlowTypeView(data))]); return - - - - - - - - - All Flows - - - - - - - - - - Issue Management - - - - - - - - - - Database - - - - -
- - - - - - - Settings - - - -
-
}> - - - {[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1].map((_, index) => { - return - - } - name={"Google Cloud Flows"}/> - - - - })} - - - - - }> - - + + + + + + + + + + All Flows + + + + + + + + + + Issue Management + + + + + + + + + + Database + + + + +
+ + + + + + + Settings + + + +
+ }> + }> + - + -
-
+ +
- + } const FlowExample = () => { - const initialNodes = useFlowViewportNodes("gid://sagittarius/Flow/1") - const initialEdges = useFlowViewportEdges("gid://sagittarius/Flow/1") + const initialNodes = useFlowNodes("gid://sagittarius/Flow/1") + const initialEdges = useFlowEdges("gid://sagittarius/Flow/1") return { fitView > - - + + {/**/} } \ No newline at end of file diff --git a/src/components/d-zoom-pan-pinch/DZoomPanPinch.style.scss b/src/components/d-zoom-pan-pinch/DZoomPanPinch.style.scss deleted file mode 100644 index 68a43378..00000000 --- a/src/components/d-zoom-pan-pinch/DZoomPanPinch.style.scss +++ /dev/null @@ -1,7 +0,0 @@ -.d-zoom-pan-pinch { - width: 100% !important; - height: 100% !important; - background-image: radial-gradient(rgba(white, .25) 1px, transparent 0); - background-size: 1rem 1rem; - background-position: -19px -19px; -} \ No newline at end of file diff --git a/src/components/d-zoom-pan-pinch/DZoomPanPinch.tsx b/src/components/d-zoom-pan-pinch/DZoomPanPinch.tsx deleted file mode 100644 index 157ad595..00000000 --- a/src/components/d-zoom-pan-pinch/DZoomPanPinch.tsx +++ /dev/null @@ -1,52 +0,0 @@ -"use client" - -import React from "react"; -import {TransformComponent, TransformWrapper} from "react-zoom-pan-pinch"; -import ButtonGroup from "../button-group/ButtonGroup"; -import Button from "../button/Button"; -import {IconFocusCentered, IconMinus, IconPlus} from "@tabler/icons-react"; -import "./DZoomPanPinch.style.scss" -import Flex from "../flex/Flex"; -import Badge from "../badge/Badge"; - -export interface DZoomPanPinchProps { - - children: React.ReactNode - -} - - -const DZoomPanPinch: React.FC = (props) => { - - const {children} = props - const [scale, setScale] = React.useState(100) - - const memorizedChildren = React.useMemo(() => children, []) - const memorizedScale = React.useMemo(() => { - return <>{scale}% - }, [scale]) - - return { - setScale(() => Math.trunc(state.scale * 100)) - }}> - {({zoomIn, zoomOut, resetTransform}) => ( - <> -
- - - - - - - {memorizedScale} - -
- - {memorizedChildren} - - - )} -
-} - -export default DZoomPanPinch \ No newline at end of file diff --git a/src/components/flow-line/FlowLines.stories.tsx b/src/components/flow-line/FlowLines.stories.tsx deleted file mode 100644 index 6d6166d2..00000000 --- a/src/components/flow-line/FlowLines.stories.tsx +++ /dev/null @@ -1,99 +0,0 @@ -"use client"; - -import React from "react"; -import {Meta} from "@storybook/react"; -import FlowLinesProvider, {useFlowLines} from "./FlowLinesProvider" -import Quote from "../quote/Quote"; -import Flex from "../flex/Flex"; -import DZoomPanPinch from "../d-zoom-pan-pinch/DZoomPanPinch"; - -const meta: Meta = { - title: "FlowLine", - parameters: { - visualTest: { - selector: 'body' - }, - layout: "fullscreen" - }, - component: FlowLinesProvider -} - -export default meta - -export const ExampleFlowLine = () => { - - return - - - - -} - -const FlowLineExample = () => { - - const {addFlowLine, removeFlowLine} = useFlowLines() - const firstRef = React.useRef(null) - const secondRef = React.useRef(null) - const thirdRef = React.useRef(null) - - React.useEffect(() => { - if (!(firstRef.current && secondRef.current)) return - - const id1 = addFlowLine({ - align: "vertical", - startElement: firstRef.current, - endElement: secondRef.current, - }) - - const id2 = addFlowLine({ - align: "vertical", - startElement: secondRef.current, - endElement: thirdRef.current!!, - }) - - return () => { - removeFlowLine(id1) - removeFlowLine(id2) - } - - }, [firstRef, secondRef]); - - return -
- - My favorite UX feedback from customers is: - "How is the app so fast?" - Because we’ve built on Next.js and Vercel since day one, our pages load in an instant, - which is important when it comes to mission-critical software. - -
-
- - My favorite UX feedback from customers is: - "How is the app so fast?" - Because we’ve built on Next.js and Vercel since day one, our pages load in an instant, - which is important when it comes to mission-critical software. - -
-
- - My favorite UX feedback from customers is: - "How is the app so fast?" - Because we’ve built on Next.js and Vercel since day one, our pages load in an instant, - which is important when it comes to mission-critical software. - -
-
-} \ No newline at end of file diff --git a/src/components/flow-line/FlowLines.style.scss b/src/components/flow-line/FlowLines.style.scss deleted file mode 100644 index 10f69a5a..00000000 --- a/src/components/flow-line/FlowLines.style.scss +++ /dev/null @@ -1,12 +0,0 @@ -.flow-lines { - - display: block; - position: absolute; - content: ""; - top: 0; - left: 0; - width: 100%; - height: 100%; - - -} \ No newline at end of file diff --git a/src/components/flow-line/FlowLinesProvider.tsx b/src/components/flow-line/FlowLinesProvider.tsx deleted file mode 100644 index ec1a1990..00000000 --- a/src/components/flow-line/FlowLinesProvider.tsx +++ /dev/null @@ -1,246 +0,0 @@ -"use client" - -import React from "react"; -import "./FlowLines.style.scss" - -interface Coordinates { - x: number - y: number -} - - -interface FlowLineStore { - startPoint: Coordinates - endPoint: Coordinates - align?: FlowLineAlignment - color?: string -} - -export type FlowLineAlignment = 'vertical' | 'horizontal' - -export interface FlowLine extends Partial { - startElement: HTMLDivElement - endElement: HTMLDivElement -} - -export interface FlowLinesContext { - addFlowLine: (flowLine: FlowLine) => number - removeFlowLine: (id: number) => void -} - -export interface FlowLinesProvider { - children?: React.ReactNode -} - -/** - * React context for storing flow-lines and making the functions accessible to - * child components - */ -const FlowLinesContext = React.createContext(null) - -/** - * React hook to get the stored functions to add and remove flow-lines - */ -export const useFlowLines = () => React.useContext(FlowLinesContext) as FlowLinesContext - -/** - * The React component which renders the svg paths behind the connected elements. - * - * @todo rendering the labels for the connected lines as absolute elements between lines and childrens - * - * @param props - * @constructor - */ -const FlowLinesProvider: React.FC = (props) => { - - const {children} = props - const [flowLines, setFlowLines] = React.useState([]) - const svgRef = React.useRef(null) - - /** - * This function calculates the linking coordinates within the starting element - * in relation to the ending element. - * For vertical alignment its only possible to connect from TOP to BOTTOM. - * For horizontal alignment its only possible to connect from RIGHT to LEFT. - * Also, the opposite is possible for both. - * - * Currently, the default behaviour is the RIGHT connection coordinates. - * - * This function is also memorized with no dependencies to increase performance. - */ - const calculateCoordinates = React.useCallback((startElement: HTMLElement, endElement: HTMLElement, alignment: FlowLineAlignment = "vertical"): Coordinates => { - - const bBStartElement = startElement.getBoundingClientRect() - const bBEndElement = endElement.getBoundingClientRect() - - if (alignment === 'vertical' && bBEndElement.y <= bBStartElement.y) { - return { - x: (bBStartElement.x + (bBStartElement.width / 2)) - svgRef.current?.getBoundingClientRect().x!!, - y: (bBStartElement.y) - svgRef.current?.getBoundingClientRect().y!! - } - } else if (alignment === 'vertical' && bBStartElement.y <= bBEndElement.y) { - return { - x: (bBStartElement.x + (bBStartElement.width / 2)) - svgRef.current?.getBoundingClientRect().x!!, - y: (bBStartElement.bottom) - svgRef.current?.getBoundingClientRect().y!! - } - } else if (alignment === 'horizontal' && bBEndElement.x >= bBStartElement.x) { - return { - x: (bBStartElement.x) - svgRef.current?.getBoundingClientRect().x!!, - y: (bBStartElement.y + (bBStartElement.height / 2)) - svgRef.current?.getBoundingClientRect().y!! - } - } - - return { - x: (bBStartElement.right) - svgRef.current?.getBoundingClientRect().x!!, - y: (bBStartElement.y + (bBStartElement.height / 2)) - svgRef.current?.getBoundingClientRect().y!! - } - - }, []) - - /** - * Adds a line between to HTMLElements to the flow-line-store. - * It also transforms the elements to real calculated coordinates. - */ - const addFlowLine = React.useCallback((flowLine: FlowLine): number => { - setFlowLines(prevState => { - - const flowLineStore: FlowLineStore = { - startPoint: calculateCoordinates(flowLine.startElement, flowLine.endElement, flowLine.align), - endPoint: calculateCoordinates(flowLine.endElement, flowLine.startElement, flowLine.align), - align: flowLine.align, - color: flowLine.color - } - - return [ - ...prevState, - flowLineStore - ] - }) - return flowLines.length - }, []) - - /** - * Removes a generated line from store based upon the line id. - * - * @todo check if flowLines are needed as dependency to increase performance - */ - const removeFlowLine = React.useCallback((id: number) => { - setFlowLines(prevState => { - prevState.splice(id, 1) - return prevState - }) - }, [flowLines]) - - /** - * Rendered svg paths based on calculated start / end points. - * This function is memorized by flowLines to minimize the rendering. - * - * @todo minimize mapping function to reduce overall complexity - */ - const svgElement = React.useMemo(() => { - return - { - flowLines.map((line, index) => { - - const { - color = '#70ffb2', - align = 'vertical', - startPoint = {x: 0, y: 0}, - endPoint = {x: 0, y: 0} - } = line - - const isBottom = startPoint.y < endPoint.y - const isTop = startPoint.y > endPoint.y - const isRight = startPoint.x < endPoint.x - const isLeft = startPoint.x > endPoint.x - - const height = align == 'vertical' ? - ((isBottom ? endPoint.y - startPoint.y : startPoint.y - endPoint.y) - 20 - 1) / 2 : - (isBottom ? endPoint.y - startPoint.y : startPoint.y - endPoint.y) - 20 - 2 - const width = align == 'vertical' ? - (isRight ? endPoint.x - startPoint.x : startPoint.x - endPoint.x) - 20 - 2 : - ((isRight ? endPoint.x - startPoint.x : startPoint.x - endPoint.x) - 20 - 1) / 2 - - let pathData = `M ${startPoint.x},${startPoint.y}` - - if (isBottom && isRight) { - pathData += align == 'vertical' ? ` - v${isBottom ? height : -1 * height} - a10,10 0 0 0 10,10 - h${isRight ? width : -1 * width} - a10,10 0 0 1 10,10 - v${isBottom ? height : -1 * height} - ` : ` - h${isRight ? width : -1 * width} - a10,10 0 0 1 10,10 - v${isBottom ? height : -1 * height} - a10,10 0 0 0 10,10 - h${isRight ? width : -1 * width} - ` - } else if (isBottom && isLeft) { - pathData += align == 'vertical' ? ` - v${isBottom ? height : -1 * height} - a10,10 0 0 1 -10,10 - h${isRight ? width : -1 * width} - a10,10 0 0 0 -10,10 - v${isBottom ? height : -1 * height} - ` : ` - h${isRight ? width : -1 * width} - a10,10 0 0 0 -10,10 - v${isBottom ? height : -1 * height} - a10,10 0 0 1 -10,10 - h${isRight ? width : -1 * width} - ` - } else if (isTop && isRight) { - pathData += align == 'vertical' ? ` - v${isBottom ? height : -1 * height} - a10,10 0 0 1 10,-10 - h${isRight ? width : -1 * width} - a10,10 0 0 0 10,-10 - v${isBottom ? height : -1 * height} - ` : ` - h${isRight ? width : -1 * width} - a10,10 0 0 0 10,-10 - v${isBottom ? height : -1 * height} - a10,10 0 0 1 10,-10 - h${isRight ? width : -1 * width} - ` - } else if (isTop && isLeft) { - pathData += align == 'vertical' ? ` - v${isBottom ? height : -1 * height} - a10,10 0 0 0 -10,-10 - h${isRight ? width : -1 * width} - a10,10 0 0 1 -10,-10 - v${isBottom ? height : -1 * height} - ` : ` - h${isRight ? width : -1 * width} - a10,10 0 0 1 -10,-10 - v${isBottom ? height : -1 * height} - a10,10 0 0 0 -10,-10 - h${isRight ? width : -1 * width} - ` - } else if (isRight) { - pathData += `h${width + 20 + 2}` - } else if (isLeft) { - pathData += `h${-1 * (width + 22)}` - } else if (isBottom) { - pathData += `v${(height * 2) + 21}` - } else if (isTop) { - pathData += `v${-1 * ((height * 2) + 21)}` - } - - return - }) - } - - }, [flowLines]) - - return - {svgElement} - {React.useMemo(() => children, [])} - - -} - -export default FlowLinesProvider diff --git a/src/index.ts b/src/index.ts index 2bf1b721..79b4266b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,9 +5,7 @@ export { default as Card} from "./components/card/Card" export { default as Col} from "./components/col/Col" export { default as Container} from "./components/container/Container" -export {default as DFolder} from "./components/d-folder/DFolder" export {default as DFullScreen} from "./components/d-fullscreen/DFullScreen" -export {default as DZoomPanPinch} from "./components/d-zoom-pan-pinch/DZoomPanPinch" export { default as Flex} from "./components/flex/Flex" export { default as Quote} from "./components/quote/Quote"