This is an automated email from the ASF dual-hosted git repository. marat pushed a commit to branch feature-836 in repository https://gitbox.apache.org/repos/asf/camel-karavan.git
commit 632230716b514c96454cbde2b613d580d6da0a3b Author: Marat Gubaidullin <marat@Marats-MacBook-Pro.local> AuthorDate: Wed Aug 23 17:24:16 2023 -0400 Download YAML and PNG #836 --- karavan-designer/public/example/demo.camel.yaml | 972 +++++++++++++++++++-- karavan-designer/src/designer/KaravanDesigner.tsx | 7 +- karavan-designer/src/designer/KaravanStore.ts | 16 +- karavan-designer/src/designer/route/DslElement.tsx | 21 +- .../src/designer/route/DslSelector.tsx | 10 +- .../src/designer/route/RouteDesigner.tsx | 70 +- .../src/designer/route/useRouteDesignerHook.tsx | 206 ++--- 7 files changed, 1065 insertions(+), 237 deletions(-) diff --git a/karavan-designer/public/example/demo.camel.yaml b/karavan-designer/public/example/demo.camel.yaml index 4aed6c49..f7df5980 100644 --- a/karavan-designer/public/example/demo.camel.yaml +++ b/karavan-designer/public/example/demo.camel.yaml @@ -1,44 +1,186 @@ -#- route: -# id: route-f435 -# from: -# uri: kamelet:timer-source -# id: from-e52c -# steps: -# - choice: -# when: -# - expression: {} -# id: when-064f -# steps: -# - multicast: -# id: multicast-38ce -# steps: -# - bean: -# id: bean-3b8e -# - log: -# message: ${body} -# id: log-546f -# - loop: -# expression: {} -# id: loop-4635 -# steps: -# - convertBodyTo: -# id: convertBodyTo-1cae -# otherwise: -# id: otherwise-0b09 -# steps: -# - filter: -# expression: {} -# id: filter-a02b -# id: choice-c53c -# - doTry: -# id: doTry-8fd5 -# doCatch: -# - id: doCatch-1071 -# - id: doCatch-c38e -# steps: -# - routingSlip: -# expression: {} -# id: routingSlip-a85a +- route: + id: route-f435 + from: + uri: kamelet:timer-source + id: from-e52c + steps: + - choice: + when: + - expression: {} + id: when-064f + steps: + - multicast: + id: multicast-38ce + steps: + - bean: + id: bean-3b8e + - log: + message: ${body} + id: log-546f + - loop: + expression: {} + id: loop-4635 + steps: + - convertBodyTo: + id: convertBodyTo-1cae + otherwise: + id: otherwise-0b09 + steps: + - filter: + expression: {} + id: filter-a02b + id: choice-c53c + - doTry: + id: doTry-8fd5 + doCatch: + - id: doCatch-1071 + - id: doCatch-c38e + steps: + - routingSlip: + expression: {} + id: routingSlip-a85a +- route: + id: route-178a + from: + uri: kamelet:aws-cloudtrail-source + id: from-3e7d + steps: + - multicast: + id: multicast-eef7 + steps: + - bean: + id: bean-a5ef + - aggregate: + id: aggregate-f5d8 + - aggregate: + id: aggregate-b9e7 + - aggregate: + id: aggregate-5eb8 + - aggregate: + id: aggregate-c57e + - aggregate: + id: aggregate-1cd4 + - bean: + id: bean-72a1 + - choice: + when: + - expression: {} + id: when-a56b + otherwise: + id: otherwise-9f31 + id: choice-1905 +- route: + id: route-f435 + from: + uri: kamelet:timer-source + id: from-e52c + steps: + - choice: + when: + - expression: {} + id: when-064f + steps: + - multicast: + id: multicast-38ce + steps: + - bean: + id: bean-3b8e + - log: + message: ${body} + id: log-546f + - loop: + expression: {} + id: loop-4635 + steps: + - convertBodyTo: + id: convertBodyTo-1cae + otherwise: + id: otherwise-0b09 + steps: + - filter: + expression: {} + id: filter-a02b + id: choice-c53c + - doTry: + id: doTry-8fd5 + doCatch: + - id: doCatch-1071 + - id: doCatch-c38e + steps: + - routingSlip: + expression: {} + id: routingSlip-a85a +- route: + id: route-178a + from: + uri: kamelet:aws-cloudtrail-source + id: from-3e7d + steps: + - multicast: + id: multicast-eef7 + steps: + - bean: + id: bean-a5ef + - aggregate: + id: aggregate-f5d8 + - aggregate: + id: aggregate-b9e7 + - aggregate: + id: aggregate-5eb8 + - aggregate: + id: aggregate-c57e + - aggregate: + id: aggregate-1cd4 + - bean: + id: bean-72a1 + - choice: + when: + - expression: {} + id: when-a56b + otherwise: + id: otherwise-9f31 + id: choice-1905 +- route: + id: route-f435 + from: + uri: kamelet:timer-source + id: from-e52c + steps: + - choice: + when: + - expression: {} + id: when-064f + steps: + - multicast: + id: multicast-38ce + steps: + - bean: + id: bean-3b8e + - log: + message: ${body} + id: log-546f + - loop: + expression: {} + id: loop-4635 + steps: + - convertBodyTo: + id: convertBodyTo-1cae + otherwise: + id: otherwise-0b09 + steps: + - filter: + expression: {} + id: filter-a02b + id: choice-c53c + - doTry: + id: doTry-8fd5 + doCatch: + - id: doCatch-1071 + - id: doCatch-c38e + steps: + - routingSlip: + expression: {} + id: routingSlip-a85a - route: id: route-178a from: @@ -50,22 +192,732 @@ steps: - bean: id: bean-a5ef -# - aggregate: -# id: aggregate-f5d8 -# - aggregate: -# id: aggregate-b9e7 -# - aggregate: -# id: aggregate-5eb8 -# - aggregate: -# id: aggregate-c57e -# - aggregate: -# id: aggregate-1cd4 -# - bean: -# id: bean-72a1 -# - choice: -# when: -# - expression: {} -# id: when-a56b -# otherwise: -# id: otherwise-9f31 -# id: choice-1905 + - aggregate: + id: aggregate-f5d8 + - aggregate: + id: aggregate-b9e7 + - aggregate: + id: aggregate-5eb8 + - aggregate: + id: aggregate-c57e + - aggregate: + id: aggregate-1cd4 + - bean: + id: bean-72a1 + - choice: + when: + - expression: {} + id: when-a56b + otherwise: + id: otherwise-9f31 + id: choice-1905 +- route: + id: route-f435 + from: + uri: kamelet:timer-source + id: from-e52c + steps: + - choice: + when: + - expression: {} + id: when-064f + steps: + - multicast: + id: multicast-38ce + steps: + - bean: + id: bean-3b8e + - log: + message: ${body} + id: log-546f + - loop: + expression: {} + id: loop-4635 + steps: + - convertBodyTo: + id: convertBodyTo-1cae + otherwise: + id: otherwise-0b09 + steps: + - filter: + expression: {} + id: filter-a02b + id: choice-c53c + - doTry: + id: doTry-8fd5 + doCatch: + - id: doCatch-1071 + - id: doCatch-c38e + steps: + - routingSlip: + expression: {} + id: routingSlip-a85a +- route: + id: route-178a + from: + uri: kamelet:aws-cloudtrail-source + id: from-3e7d + steps: + - multicast: + id: multicast-eef7 + steps: + - bean: + id: bean-a5ef + - aggregate: + id: aggregate-f5d8 + - aggregate: + id: aggregate-b9e7 + - aggregate: + id: aggregate-5eb8 + - aggregate: + id: aggregate-c57e + - aggregate: + id: aggregate-1cd4 + - bean: + id: bean-72a1 + - choice: + when: + - expression: {} + id: when-a56b + otherwise: + id: otherwise-9f31 + id: choice-1905 +- route: + id: route-f435 + from: + uri: kamelet:timer-source + id: from-e52c + steps: + - choice: + when: + - expression: {} + id: when-064f + steps: + - multicast: + id: multicast-38ce + steps: + - bean: + id: bean-3b8e + - log: + message: ${body} + id: log-546f + - loop: + expression: {} + id: loop-4635 + steps: + - convertBodyTo: + id: convertBodyTo-1cae + otherwise: + id: otherwise-0b09 + steps: + - filter: + expression: {} + id: filter-a02b + id: choice-c53c + - doTry: + id: doTry-8fd5 + doCatch: + - id: doCatch-1071 + - id: doCatch-c38e + steps: + - routingSlip: + expression: {} + id: routingSlip-a85a +- route: + id: route-178a + from: + uri: kamelet:aws-cloudtrail-source + id: from-3e7d + steps: + - multicast: + id: multicast-eef7 + steps: + - bean: + id: bean-a5ef + - aggregate: + id: aggregate-f5d8 + - aggregate: + id: aggregate-b9e7 + - aggregate: + id: aggregate-5eb8 + - aggregate: + id: aggregate-c57e + - aggregate: + id: aggregate-1cd4 + - bean: + id: bean-72a1 + - choice: + when: + - expression: {} + id: when-a56b + otherwise: + id: otherwise-9f31 + id: choice-1905 +- route: + id: route-f435 + from: + uri: kamelet:timer-source + id: from-e52c + steps: + - choice: + when: + - expression: {} + id: when-064f + steps: + - multicast: + id: multicast-38ce + steps: + - bean: + id: bean-3b8e + - log: + message: ${body} + id: log-546f + - loop: + expression: {} + id: loop-4635 + steps: + - convertBodyTo: + id: convertBodyTo-1cae + otherwise: + id: otherwise-0b09 + steps: + - filter: + expression: {} + id: filter-a02b + id: choice-c53c + - doTry: + id: doTry-8fd5 + doCatch: + - id: doCatch-1071 + - id: doCatch-c38e + steps: + - routingSlip: + expression: {} + id: routingSlip-a85a +- route: + id: route-178a + from: + uri: kamelet:aws-cloudtrail-source + id: from-3e7d + steps: + - multicast: + id: multicast-eef7 + steps: + - bean: + id: bean-a5ef + - aggregate: + id: aggregate-f5d8 + - aggregate: + id: aggregate-b9e7 + - aggregate: + id: aggregate-5eb8 + - aggregate: + id: aggregate-c57e + - aggregate: + id: aggregate-1cd4 + - bean: + id: bean-72a1 + - choice: + when: + - expression: {} + id: when-a56b + otherwise: + id: otherwise-9f31 + id: choice-1905 +- route: + id: route-f435 + from: + uri: kamelet:timer-source + id: from-e52c + steps: + - choice: + when: + - expression: {} + id: when-064f + steps: + - multicast: + id: multicast-38ce + steps: + - bean: + id: bean-3b8e + - log: + message: ${body} + id: log-546f + - loop: + expression: {} + id: loop-4635 + steps: + - convertBodyTo: + id: convertBodyTo-1cae + otherwise: + id: otherwise-0b09 + steps: + - filter: + expression: {} + id: filter-a02b + id: choice-c53c + - doTry: + id: doTry-8fd5 + doCatch: + - id: doCatch-1071 + - id: doCatch-c38e + steps: + - routingSlip: + expression: {} + id: routingSlip-a85a +- route: + id: route-178a + from: + uri: kamelet:aws-cloudtrail-source + id: from-3e7d + steps: + - multicast: + id: multicast-eef7 + steps: + - bean: + id: bean-a5ef + - aggregate: + id: aggregate-f5d8 + - aggregate: + id: aggregate-b9e7 + - aggregate: + id: aggregate-5eb8 + - aggregate: + id: aggregate-c57e + - aggregate: + id: aggregate-1cd4 + - bean: + id: bean-72a1 + - choice: + when: + - expression: {} + id: when-a56b + otherwise: + id: otherwise-9f31 + id: choice-1905 +- route: + id: route-f435 + from: + uri: kamelet:timer-source + id: from-e52c + steps: + - choice: + when: + - expression: {} + id: when-064f + steps: + - multicast: + id: multicast-38ce + steps: + - bean: + id: bean-3b8e + - log: + message: ${body} + id: log-546f + - loop: + expression: {} + id: loop-4635 + steps: + - convertBodyTo: + id: convertBodyTo-1cae + otherwise: + id: otherwise-0b09 + steps: + - filter: + expression: {} + id: filter-a02b + id: choice-c53c + - doTry: + id: doTry-8fd5 + doCatch: + - id: doCatch-1071 + - id: doCatch-c38e + steps: + - routingSlip: + expression: {} + id: routingSlip-a85a +- route: + id: route-178a + from: + uri: kamelet:aws-cloudtrail-source + id: from-3e7d + steps: + - multicast: + id: multicast-eef7 + steps: + - bean: + id: bean-a5ef + - aggregate: + id: aggregate-f5d8 + - aggregate: + id: aggregate-b9e7 + - aggregate: + id: aggregate-5eb8 + - aggregate: + id: aggregate-c57e + - aggregate: + id: aggregate-1cd4 + - bean: + id: bean-72a1 + - choice: + when: + - expression: {} + id: when-a56b + otherwise: + id: otherwise-9f31 + id: choice-1905 +- route: + id: route-f435 + from: + uri: kamelet:timer-source + id: from-e52c + steps: + - choice: + when: + - expression: {} + id: when-064f + steps: + - multicast: + id: multicast-38ce + steps: + - bean: + id: bean-3b8e + - log: + message: ${body} + id: log-546f + - loop: + expression: {} + id: loop-4635 + steps: + - convertBodyTo: + id: convertBodyTo-1cae + otherwise: + id: otherwise-0b09 + steps: + - filter: + expression: {} + id: filter-a02b + id: choice-c53c + - doTry: + id: doTry-8fd5 + doCatch: + - id: doCatch-1071 + - id: doCatch-c38e + steps: + - routingSlip: + expression: {} + id: routingSlip-a85a +- route: + id: route-178a + from: + uri: kamelet:aws-cloudtrail-source + id: from-3e7d + steps: + - multicast: + id: multicast-eef7 + steps: + - bean: + id: bean-a5ef + - aggregate: + id: aggregate-f5d8 + - aggregate: + id: aggregate-b9e7 + - aggregate: + id: aggregate-5eb8 + - aggregate: + id: aggregate-c57e + - aggregate: + id: aggregate-1cd4 + - bean: + id: bean-72a1 + - choice: + when: + - expression: {} + id: when-a56b + otherwise: + id: otherwise-9f31 + id: choice-1905 +- route: + id: route-f435 + from: + uri: kamelet:timer-source + id: from-e52c + steps: + - choice: + when: + - expression: {} + id: when-064f + steps: + - multicast: + id: multicast-38ce + steps: + - bean: + id: bean-3b8e + - log: + message: ${body} + id: log-546f + - loop: + expression: {} + id: loop-4635 + steps: + - convertBodyTo: + id: convertBodyTo-1cae + otherwise: + id: otherwise-0b09 + steps: + - filter: + expression: {} + id: filter-a02b + id: choice-c53c + - doTry: + id: doTry-8fd5 + doCatch: + - id: doCatch-1071 + - id: doCatch-c38e + steps: + - routingSlip: + expression: {} + id: routingSlip-a85a +- route: + id: route-178a + from: + uri: kamelet:aws-cloudtrail-source + id: from-3e7d + steps: + - multicast: + id: multicast-eef7 + steps: + - bean: + id: bean-a5ef + - aggregate: + id: aggregate-f5d8 + - aggregate: + id: aggregate-b9e7 + - aggregate: + id: aggregate-5eb8 + - aggregate: + id: aggregate-c57e + - aggregate: + id: aggregate-1cd4 + - bean: + id: bean-72a1 + - choice: + when: + - expression: {} + id: when-a56b + otherwise: + id: otherwise-9f31 + id: choice-1905 +- route: + id: route-f435 + from: + uri: kamelet:timer-source + id: from-e52c + steps: + - choice: + when: + - expression: {} + id: when-064f + steps: + - multicast: + id: multicast-38ce + steps: + - bean: + id: bean-3b8e + - log: + message: ${body} + id: log-546f + - loop: + expression: {} + id: loop-4635 + steps: + - convertBodyTo: + id: convertBodyTo-1cae + otherwise: + id: otherwise-0b09 + steps: + - filter: + expression: {} + id: filter-a02b + id: choice-c53c + - doTry: + id: doTry-8fd5 + doCatch: + - id: doCatch-1071 + - id: doCatch-c38e + steps: + - routingSlip: + expression: {} + id: routingSlip-a85a +- route: + id: route-178a + from: + uri: kamelet:aws-cloudtrail-source + id: from-3e7d + steps: + - multicast: + id: multicast-eef7 + steps: + - bean: + id: bean-a5ef + - aggregate: + id: aggregate-f5d8 + - aggregate: + id: aggregate-b9e7 + - aggregate: + id: aggregate-5eb8 + - aggregate: + id: aggregate-c57e + - aggregate: + id: aggregate-1cd4 + - bean: + id: bean-72a1 + - choice: + when: + - expression: {} + id: when-a56b + otherwise: + id: otherwise-9f31 + id: choice-1905 +- route: + id: route-f435 + from: + uri: kamelet:timer-source + id: from-e52c + steps: + - choice: + when: + - expression: {} + id: when-064f + steps: + - multicast: + id: multicast-38ce + steps: + - bean: + id: bean-3b8e + - log: + message: ${body} + id: log-546f + - loop: + expression: {} + id: loop-4635 + steps: + - convertBodyTo: + id: convertBodyTo-1cae + otherwise: + id: otherwise-0b09 + steps: + - filter: + expression: {} + id: filter-a02b + id: choice-c53c + - doTry: + id: doTry-8fd5 + doCatch: + - id: doCatch-1071 + - id: doCatch-c38e + steps: + - routingSlip: + expression: {} + id: routingSlip-a85a +- route: + id: route-178a + from: + uri: kamelet:aws-cloudtrail-source + id: from-3e7d + steps: + - multicast: + id: multicast-eef7 + steps: + - bean: + id: bean-a5ef + - aggregate: + id: aggregate-f5d8 + - aggregate: + id: aggregate-b9e7 + - aggregate: + id: aggregate-5eb8 + - aggregate: + id: aggregate-c57e + - aggregate: + id: aggregate-1cd4 + - bean: + id: bean-72a1 + - choice: + when: + - expression: {} + id: when-a56b + otherwise: + id: otherwise-9f31 + id: choice-1905 +- route: + id: route-f435 + from: + uri: kamelet:timer-source + id: from-e52c + steps: + - choice: + when: + - expression: {} + id: when-064f + steps: + - multicast: + id: multicast-38ce + steps: + - bean: + id: bean-3b8e + - log: + message: ${body} + id: log-546f + - loop: + expression: {} + id: loop-4635 + steps: + - convertBodyTo: + id: convertBodyTo-1cae + otherwise: + id: otherwise-0b09 + steps: + - filter: + expression: {} + id: filter-a02b + id: choice-c53c + - doTry: + id: doTry-8fd5 + doCatch: + - id: doCatch-1071 + - id: doCatch-c38e + steps: + - routingSlip: + expression: {} + id: routingSlip-a85a +- route: + id: route-178a + from: + uri: kamelet:aws-cloudtrail-source + id: from-3e7d + steps: + - multicast: + id: multicast-eef7 + steps: + - bean: + id: bean-a5ef + - aggregate: + id: aggregate-f5d8 + - aggregate: + id: aggregate-b9e7 + - aggregate: + id: aggregate-5eb8 + - aggregate: + id: aggregate-c57e + - aggregate: + id: aggregate-1cd4 + - bean: + id: bean-72a1 + - choice: + when: + - expression: {} + id: when-a56b + otherwise: + id: otherwise-9f31 + id: choice-1905 diff --git a/karavan-designer/src/designer/KaravanDesigner.tsx b/karavan-designer/src/designer/KaravanDesigner.tsx index 5f25fe91..940df7e2 100644 --- a/karavan-designer/src/designer/KaravanDesigner.tsx +++ b/karavan-designer/src/designer/KaravanDesigner.tsx @@ -66,13 +66,14 @@ export class KaravanInstance { export const KaravanDesigner = (props: Props) => { const [tab, setTab] = useState<string>('routes'); - const [propertyOnly, setPropertyOnly] = useDesignerStore((state) => - [state.propertyOnly, state.setPropertyOnly], shallow ) + const [propertyOnly, setPropertyOnly, setDark] = useDesignerStore((state) => + [state.propertyOnly, state.setPropertyOnly, state.setDark], shallow ) const [integration, setIntegration] = useIntegrationStore((state) => [state.integration, state.setIntegration], shallow ) useEffect(() => { setIntegration(makeIntegration(props.yaml, props.filename)); + setDark(props.dark); }, []); function makeIntegration (yaml: string, filename: string): Integration { @@ -131,7 +132,7 @@ export const KaravanDesigner = (props: Props) => { {tab === 'routes' && <RouteDesigner // integration={integration} // onSave={(integration, propertyOnly) => save(integration, propertyOnly)} - dark={props.dark}/>} + />} {/*{tab === 'rest' && <RestDesigner integration={integration}*/} {/* onSave={(integration, propertyOnly) => save(integration, propertyOnly)}*/} {/* dark={props.dark}/>}*/} diff --git a/karavan-designer/src/designer/KaravanStore.ts b/karavan-designer/src/designer/KaravanStore.ts index 4dc570ed..3bd2ed91 100644 --- a/karavan-designer/src/designer/KaravanStore.ts +++ b/karavan-designer/src/designer/KaravanStore.ts @@ -136,7 +136,10 @@ export const useConnectionsStore = createWithEqualityFn<ConnectionsState>((set) }), shallow) interface DesignerState { + dark: boolean; + setDark: (dark: boolean) => void; shiftKeyPressed: boolean; + setShiftKeyPressed: (shiftKeyPressed: boolean) => void; showDeleteConfirmation: boolean; setShowDeleteConfirmation: (showDeleteConfirmation: boolean) => void; showMoveConfirmation: boolean; @@ -149,8 +152,8 @@ interface DesignerState { setSelectedStep: (selectedStep?: CamelElement) => void; selectedUuids: string[]; setSelectedUuids: (selectedUuids: string[]) => void; - clipboardSteps: string[]; - setClipboardSteps: (clipboardSteps: string[]) => void; + clipboardSteps: CamelElement[]; + setClipboardSteps: (clipboardSteps: CamelElement[]) => void; width: number, height: number, top: number, @@ -159,6 +162,7 @@ interface DesignerState { } export const useDesignerStore = createWithEqualityFn<DesignerState>((set) => ({ + dark: false, shiftKeyPressed: false, showDeleteConfirmation: false, showMoveConfirmation: false, @@ -166,6 +170,12 @@ export const useDesignerStore = createWithEqualityFn<DesignerState>((set) => ({ selectedUuids: [], clipboardSteps: [], propertyOnly: false, + setDark: (dark: boolean) => { + set({dark: dark}) + }, + setShiftKeyPressed: (shiftKeyPressed: boolean) => { + set({shiftKeyPressed: shiftKeyPressed}) + }, setSelectedStep: (selectedStep?: CamelElement) => { set({selectedStep: selectedStep}) }, @@ -184,7 +194,7 @@ export const useDesignerStore = createWithEqualityFn<DesignerState>((set) => ({ setSelectedUuids: (selectedUuids: string[]) => { set({selectedUuids: selectedUuids}) }, - setClipboardSteps: (clipboardSteps: string[]) => { + setClipboardSteps: (clipboardSteps: CamelElement[]) => { set({clipboardSteps: clipboardSteps}) }, width: 100, diff --git a/karavan-designer/src/designer/route/DslElement.tsx b/karavan-designer/src/designer/route/DslElement.tsx index bf246051..19554e03 100644 --- a/karavan-designer/src/designer/route/DslElement.tsx +++ b/karavan-designer/src/designer/route/DslElement.tsx @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React, {CSSProperties, useEffect, useRef, useState} from 'react'; +import React, {CSSProperties, useEffect, useMemo, useRef, useState} from 'react'; import { Button, Flex, @@ -60,11 +60,6 @@ export const DslElement = (props: Props) => { const [isDraggedOver, setIsDraggedOver] = useState<boolean>(false); const [moveElements, setMoveElements] = useState<[string | undefined, string | undefined]>([undefined, undefined]); - // const elementRef = useRef(null); - - // useEffect(() => { - // }, [elementRef]); - function onOpenSelector (evt: React.MouseEvent, showSteps: boolean = true, isInsert: boolean = false) { evt.stopPropagation(); if (isInsert && props.parent) { @@ -76,7 +71,6 @@ export const DslElement = (props: Props) => { function onDeleteElement (evt: React.MouseEvent) { evt.stopPropagation(); - console.log("!!!!!") onShowDeleteConfirmation(props.step.uuid); } @@ -200,7 +194,6 @@ export const DslElement = (props: Props) => { } function sendPosition (el: HTMLDivElement | null, isSelected: boolean) { - // console.log("sendPosition", props.step) const node = el; if (node && el) { const header = Array.from(node.childNodes.values()).filter((n: any) => n.classList.contains("header"))[0]; @@ -218,11 +211,21 @@ export const DslElement = (props: Props) => { } } + function getAvailableModels () { // TODO: make static list-of-values instead + const step: CamelElement = props.step + return CamelUi.getSelectorModelsForParent(step.dslName, false); + } + + const availableModels = useMemo( + () => getAvailableModels(), + [props.step.dslName] + ); + + function getHeader () { const step: CamelElement = props.step; const parent = props.parent; const inRouteConfiguration = parent !== undefined && parent.dslName === 'RouteConfigurationDefinition'; - const availableModels = CamelUi.getSelectorModelsForParent(step.dslName, false); const showAddButton = !['CatchDefinition', 'RouteDefinition'].includes(step.dslName) && availableModels.length > 0; const showInsertButton = !['FromDefinition', 'RouteConfigurationDefinition', 'RouteDefinition', 'CatchDefinition', 'FinallyDefinition', 'WhenDefinition', 'OtherwiseDefinition'].includes(step.dslName) diff --git a/karavan-designer/src/designer/route/DslSelector.tsx b/karavan-designer/src/designer/route/DslSelector.tsx index 798a6ed6..af0668e2 100644 --- a/karavan-designer/src/designer/route/DslSelector.tsx +++ b/karavan-designer/src/designer/route/DslSelector.tsx @@ -29,7 +29,6 @@ import {shallow} from "zustand/shallow"; import {useRouteDesignerHook} from "./useRouteDesignerHook"; interface Props { - dark: boolean, tabIndex?: string | number } @@ -41,11 +40,8 @@ export const DslSelector = (props: Props) => { [s.showSelector, s.showSteps, s.parentId, s.parentDsl, s.selectorTabIndex, s.setShowSelector, s.setSelectorTabIndex, s.selectedPosition, s.selectedLabels, s.setSelectedLabels, s.addSelectedLabel, s.deleteSelectedLabel], shallow) - // - // const [showSelector, showDeleteConfirmation, showSteps, deleteMessage, parentId, parentDsl, selectedPosition, selectorTabIndex, - // setShowSelector, setShowDeleteConfirmation, setPosition, setSelectorTabIndex, width, height, top, left] = useDesignerStore((s) => - // [s.showSelector, s.showDeleteConfirmation, s.showSteps, s.deleteMessage, s.parentId, s.parentDsl, s.selectedPosition, s.selectorTabIndex, - // s.setShowSelector, s.setShowDeleteConfirmation, s.setPosition, s.setSelectorTabIndex, s.width, s.height, s.top, s.left], shallow) + + const [dark] = useDesignerStore((s) => [s.dark], shallow) const {deleteElement, selectElement, moveElement, onShowDeleteConfirmation, onDslSelect, openSelector, createRouteConfiguration} = useRouteDesignerHook(); @@ -174,7 +170,7 @@ export const DslSelector = (props: Props) => { </Flex> } actions={{}}> - <PageSection padding={{default: "noPadding"}} variant={props.dark ? "darker" : "light"}> + <PageSection padding={{default: "noPadding"}} variant={dark ? "darker" : "light"}> {isEip && <ToggleGroup aria-label="Labels" isCompact> {eipLabels.map(eipLabel => <ToggleGroupItem key={eipLabel} diff --git a/karavan-designer/src/designer/route/RouteDesigner.tsx b/karavan-designer/src/designer/route/RouteDesigner.tsx index 878d806c..d605044a 100644 --- a/karavan-designer/src/designer/route/RouteDesigner.tsx +++ b/karavan-designer/src/designer/route/RouteDesigner.tsx @@ -39,22 +39,14 @@ import {CamelUtil} from "karavan-core/lib/api/CamelUtil"; import {RouteConfigurationDefinition} from "karavan-core/lib/model/CamelDefinition"; import {CamelDefinitionApiExt} from "karavan-core/lib/api/CamelDefinitionApiExt"; import useResizeObserver from "./useResizeObserver"; -import {DslPosition} from "../utils/EventBus"; +import {Command, DslPosition, EventBus} from "../utils/EventBus"; import useMutationsObserver from "./useDrawerMutationsObserver"; import {DeleteConfirmation} from "./DeleteConfirmation"; -interface Props { - // onSave?: (integration: Integration, propertyOnly: boolean) => void - // integration: Integration - dark: boolean -} +export const RouteDesigner = () => { -export const RouteDesigner = (props: Props) => { - const printerRef = React.createRef(); - const contentRef: React.RefObject<HTMLDivElement> = useRef(null); - - const {deleteElement, selectElement, moveElement, onShowDeleteConfirmation, onDslSelect, openSelector, createRouteConfiguration} = useRouteDesignerHook(); + const {deleteElement, selectElement, moveElement, onShowDeleteConfirmation, onDslSelect, openSelector, createRouteConfiguration, handleKeyDown, handleKeyUp, onCommand} = useRouteDesignerHook(); const [integration] = useIntegrationStore((state) => [state.integration], shallow) const [showDeleteConfirmation, deleteMessage , setShowDeleteConfirmation, setPosition, width, height, top, left] = @@ -67,14 +59,6 @@ export const RouteDesigner = (props: Props) => { const [clearSteps] = useConnectionsStore((s) => [s.clearSteps]) - useEffect(() => { - if (flowRef.current === null) { - clearSteps(); - } else { - changeGraphSize(); - } - }, [showSelector]); - const onChangeGraphSize = useCallback((target: HTMLDivElement) => { changeGraphSize(); }, []) @@ -90,32 +74,27 @@ export const RouteDesigner = (props: Props) => { const firstRef = useResizeObserver(onChangeGraphSize); const secondRef = useMutationsObserver(onChangeGraphSize); + const printerRef = useRef<HTMLDivElement | null>(null); const flowRef = useRef<HTMLDivElement | null>(null); + const contentRef: React.RefObject<HTMLDivElement> = useRef(null); - // function componentDidMount() { - // logic.componentDidMount(); - // } - // - // function componentWillUnmount() { - // logic.componentWillUnmount(); - // } - // - // function handleResize = (event: any) => { - // return logic.handleResize(event); - // } - // - // function handleKeyDown = (event: KeyboardEvent) => { - // return logic.handleKeyDown(event); - // } - // - // function handleKeyUp = (event: KeyboardEvent) => { - // return logic.handleKeyUp(event); - // } - // - // function componentDidUpdate = (prevProps: Readonly<Props>, prevState: Readonly<RouteDesignerState>, snapshot?: any) => { - // return logic.componentDidUpdate(prevState, snapshot); - // } - + useEffect(()=>{ + window.addEventListener('resize', changeGraphSize); + window.addEventListener('keydown', handleKeyDown); + window.addEventListener('keyup', handleKeyUp); + const commandSub = EventBus.onCommand()?.subscribe((command: Command) => onCommand(command, printerRef)); + if (flowRef.current === null) { + clearSteps(); + } else { + changeGraphSize(); + } + return ()=> { + window.removeEventListener('resize', changeGraphSize); + window.removeEventListener('keydown', handleKeyDown); + window.removeEventListener('keyup', handleKeyUp); + commandSub?.unsubscribe(); + } + }, [showSelector]) function getDeleteConfirmation() { let htmlContent: string = deleteMessage; @@ -158,12 +137,11 @@ export const RouteDesigner = (props: Props) => { const routes = CamelUi.getRoutes(integration); const routeConfigurations = CamelUi.getRouteConfigurations(integration); return ( - <div className="graph"> + <div className="graph" ref={printerRef}> <DslConnections/> <div id="flows" className="flows" data-click="FLOWS" onClick={event => { // logic.unselectElement(event) }} - ref={flowRef} > {routeConfigurations?.map((routeConfiguration, index: number) => ( @@ -212,7 +190,7 @@ export const RouteDesigner = (props: Props) => { </DrawerContent> </Drawer> </div> - {showSelector && <DslSelector dark={props.dark}/>} + {showSelector && <DslSelector/>} {showDeleteConfirmation && <DeleteConfirmation/>} </div> ) diff --git a/karavan-designer/src/designer/route/useRouteDesignerHook.tsx b/karavan-designer/src/designer/route/useRouteDesignerHook.tsx index f2c995da..4a69a10d 100644 --- a/karavan-designer/src/designer/route/useRouteDesignerHook.tsx +++ b/karavan-designer/src/designer/route/useRouteDesignerHook.tsx @@ -34,15 +34,16 @@ import {useDesignerStore, useIntegrationStore, useSelectorStore} from "../Karava import {shallow} from "zustand/shallow"; import {setTabIndex} from "@patternfly/react-core"; + export const useRouteDesignerHook = () => { const [integration, setIntegration] = useIntegrationStore((state) => [state.integration, state.setIntegration], shallow) const [ showDeleteConfirmation, propertyOnly,deleteMessage, selectedUuids,clipboardSteps,selectedStep,shiftKeyPressed, - setShowDeleteConfirmation,setPropertyOnly, setDeleteMessage, setSelectedStep, setSelectedUuids, setClipboardSteps, setPosition, - width, height, top, left] = useDesignerStore((s) => + setShowDeleteConfirmation,setPropertyOnly, setDeleteMessage, setSelectedStep, setSelectedUuids, setClipboardSteps, setPosition, setShiftKeyPressed, + width, height, top, left, dark] = useDesignerStore((s) => [s.showDeleteConfirmation, s.propertyOnly,s.deleteMessage, s.selectedUuids,s.clipboardSteps, s.selectedStep, s.shiftKeyPressed, - s.setShowDeleteConfirmation,s.setPropertyOnly,s.setDeleteMessage, s.setSelectedStep, s.setSelectedUuids, s.setClipboardSteps, s.setPosition, - s.width, s.height, s.top, s.left], shallow) + s.setShowDeleteConfirmation,s.setPropertyOnly,s.setDeleteMessage, s.setSelectedStep, s.setSelectedUuids, s.setClipboardSteps, s.setPosition, s.setShiftKeyPressed, + s.width, s.height, s.top, s.left, s.dark], shallow) const [setParentId, setShowSelector, setSelectorTabIndex, setParentDsl, setShowSteps, setSelectedPosition] = useSelectorStore((s) => [s.setParentId, s.setShowSelector, s.setSelectorTabIndex, s.setParentDsl, s.setShowSteps, s.setSelectedPosition], shallow) @@ -78,80 +79,69 @@ export const useRouteDesignerHook = () => { // this.routeDesigner.setState({key: Math.random().toString()}); // } // - // function handleKeyDown = (event: KeyboardEvent) => { - // if ((event.shiftKey)) { - // this.routeDesigner.setState({shiftKeyPressed: true}); - // } - // if (window.document.hasFocus() && window.document.activeElement) { - // if (['BODY', 'MAIN'].includes(window.document.activeElement.tagName)) { - // let charCode = String.fromCharCode(event.which).toLowerCase(); - // if ((event.ctrlKey || event.metaKey) && charCode === 'c') { - // this.copyToClipboard(); - // } else if ((event.ctrlKey || event.metaKey) && charCode === 'v') { - // this.pasteFromClipboard(); - // } - // } - // } else { - // if (event.repeat) { - // window.dispatchEvent(event); - // } - // } - // } - // - // function handleKeyUp = (event: KeyboardEvent) => { - // this.routeDesigner.setState({shiftKeyPressed: false}); - // if (event.repeat) { - // window.dispatchEvent(event); - // } - // } - // - // function componentDidUpdate = (prevState: Readonly<RouteDesignerState>, snapshot?: any) => { - // if (prevState.key !== this.routeDesigner.state.key) { - // this.routeDesigner.props.onSave?.call(this, this.routeDesigner.state.integration, this.routeDesigner.state.propertyOnly); - // } - // } - // - // copyToClipboard = (): void => { - // const {integration, selectedUuids} = this.routeDesigner.state; - // const steps: CamelElement[] = [] - // selectedUuids.forEach(selectedUuid => { - // const selectedElement = CamelDefinitionApiExt.findElementInIntegration(integration, selectedUuid); - // if (selectedElement) { - // steps.push(selectedElement); - // } - // }) - // if (steps.length >0) { - // this.routeDesigner.setState(prevState => ({ - // key: Math.random().toString(), - // clipboardSteps: [...steps] - // })); - // } - // } - // function pasteFromClipboard = (): void => { - // const {integration, selectedUuids, clipboardSteps} = this.routeDesigner.state; - // if (clipboardSteps.length === 1 && clipboardSteps[0]?.dslName === 'FromDefinition') { - // const clone = CamelUtil.cloneStep(clipboardSteps[0], true); - // const route = CamelDefinitionApi.createRouteDefinition({from: clone}); - // this.addStep(route, '', 0) - // } else if (clipboardSteps.length === 1 && clipboardSteps[0]?.dslName === 'RouteDefinition') { - // const clone = CamelUtil.cloneStep(clipboardSteps[0], true); - // this.addStep(clone, '', 0) - // } else if (selectedUuids.length === 1) { - // const targetMeta = CamelDefinitionApiExt.findElementMetaInIntegration(integration, selectedUuids[0]); - // clipboardSteps.reverse().forEach(clipboardStep => { - // if (clipboardStep && targetMeta.parentUuid) { - // const clone = CamelUtil.cloneStep(clipboardStep, true); - // this.addStep(clone, targetMeta.parentUuid, targetMeta.position); - // } - // }) - // } - // } + function handleKeyDown (event: KeyboardEvent) { + if ((event.shiftKey)) { + setShiftKeyPressed(true); + } + if (window.document.hasFocus() && window.document.activeElement) { + if (['BODY', 'MAIN'].includes(window.document.activeElement.tagName)) { + let charCode = String.fromCharCode(event.which).toLowerCase(); + if ((event.ctrlKey || event.metaKey) && charCode === 'c') { + copyToClipboard(); + } else if ((event.ctrlKey || event.metaKey) && charCode === 'v') { + pasteFromClipboard(); + } + } + } else { + if (event.repeat) { + window.dispatchEvent(event); + } + } + } + + function handleKeyUp (event: KeyboardEvent) { + setShiftKeyPressed(false); + if (event.repeat) { + window.dispatchEvent(event); + } + } + + function copyToClipboard (): void { + const steps: CamelElement[] = [] + selectedUuids.forEach(selectedUuid => { + const selectedElement = CamelDefinitionApiExt.findElementInIntegration(integration, selectedUuid); + if (selectedElement) { + steps.push(selectedElement); + } + }) + if (steps.length > 0) { + setClipboardSteps(steps); + } + } + function pasteFromClipboard (): void { + if (clipboardSteps.length === 1 && clipboardSteps[0]?.dslName === 'FromDefinition') { + const clone = CamelUtil.cloneStep(clipboardSteps[0], true); + const route = CamelDefinitionApi.createRouteDefinition({from: clone}); + addStep(route, '', 0) + } else if (clipboardSteps.length === 1 && clipboardSteps[0]?.dslName === 'RouteDefinition') { + const clone = CamelUtil.cloneStep(clipboardSteps[0], true); + addStep(clone, '', 0) + } else if (selectedUuids.length === 1) { + const targetMeta = CamelDefinitionApiExt.findElementMetaInIntegration(integration, selectedUuids[0]); + clipboardSteps.reverse().forEach(clipboardStep => { + if (clipboardStep && targetMeta.parentUuid) { + const clone = CamelUtil.cloneStep(clipboardStep, true); + addStep(clone, targetMeta.parentUuid, targetMeta.position); + } + }) + } + } // - // function onCommand = (command: Command) => { - // switch (command.command){ - // case "downloadImage": this.integrationImageDownload() - // } - // } + function onCommand (command: Command, printerRef: React.MutableRefObject<HTMLDivElement | null>) { + switch (command.command){ + case "downloadImage": integrationImageDownload(printerRef); + } + } // // function onPropertyUpdate = debounce((element: CamelElement, newRoute?: RouteToCreate) => { // if (newRoute) { @@ -230,6 +220,7 @@ export const useRouteDesignerHook = () => { } const add = shiftKeyPressed && !selectedUuids.includes(element.uuid); const remove = shiftKeyPressed && selectedUuids.includes(element.uuid); + // TODO: do we need to change Intgration just for select???? const i = CamelDisplayUtil.setIntegrationVisibility(integration, element.uuid); if (remove) { @@ -243,7 +234,6 @@ export const useRouteDesignerHook = () => { setIntegration(i); setSelectedStep(selectedElement); - setShowSelector(false); setSelectedUuids(shiftKeyPressed ? [...selectedUuids] : [element.uuid]) } // @@ -349,37 +339,35 @@ export const useRouteDesignerHook = () => { setPropertyOnly(false); setSelectedUuids([source]); } - // - // - // function downloadIntegrationImage(dataUrl: string) { - // const a = document.createElement('a'); - // a.setAttribute('download', 'karavan-routes.png'); - // a.setAttribute('href', dataUrl); - // a.click(); - // } - // - // function integrationImageDownloadFilter = (node: HTMLElement) => { - // const exclusionClasses = ['add-flow']; - // return !exclusionClasses.some(classname => { - // return node.classList === undefined ? false : node.classList.contains(classname); - // }); - // } - // - // function integrationImageDownload() { - // if (this.routeDesigner.state.printerRef.current === null) { - // return - // } - // toPng(this.routeDesigner.state.printerRef.current, { - // style: {overflow: 'hidden'}, cacheBust: true, filter: this.integrationImageDownloadFilter, - // height: this.routeDesigner.state.height, width: this.routeDesigner.state.width, backgroundColor: this.routeDesigner.props.dark ? "black" : "white" - // }).then(v => { - // toPng(this.routeDesigner.state.printerRef.current, { - // style: {overflow: 'hidden'}, cacheBust: true, filter: this.integrationImageDownloadFilter, - // height: this.routeDesigner.state.height, width: this.routeDesigner.state.width, backgroundColor: this.routeDesigner.props.dark ? "black" : "white" - // }).then(this.downloadIntegrationImage); - // }) - // } + function downloadIntegrationImage(dataUrl: string) { + const a = document.createElement('a'); + a.setAttribute('download', 'karavan-routes.png'); + a.setAttribute('href', dataUrl); + a.click(); + } + + function integrationImageDownloadFilter (node: HTMLElement) { + const exclusionClasses = ['add-flow']; + return !exclusionClasses.some(classname => { + return node.classList === undefined ? false : node.classList.contains(classname); + }); + } + + function integrationImageDownload(printerRef: React.MutableRefObject<HTMLDivElement | null>) { + const ref = printerRef.current; + if (ref !== null) { + toPng(ref, { + style: {overflow: 'hidden'}, cacheBust: true, filter: integrationImageDownloadFilter, + height: height, width: width, backgroundColor: dark ? "black" : "white" + }).then(v => { + toPng(ref, { + style: {overflow: 'hidden'}, cacheBust: true, filter: integrationImageDownloadFilter, + height: height, width: width, backgroundColor: dark ? "black" : "white" + }).then(downloadIntegrationImage); + }) + } + } - return { deleteElement, selectElement, moveElement, onShowDeleteConfirmation, onDslSelect, openSelector, createRouteConfiguration} + return { deleteElement, selectElement, moveElement, onShowDeleteConfirmation, onDslSelect, openSelector, createRouteConfiguration, handleKeyDown, handleKeyUp, onCommand} } \ No newline at end of file