You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ma...@apache.org on 2023/08/24 23:26:15 UTC
[camel-karavan] 01/06: Download YAML and PNG #836
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 <ma...@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