This is an automated email from the ASF dual-hosted git repository.
marat pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-karavan.git
The following commit(s) were added to refs/heads/main by this push:
new ee454172 Implement #622
ee454172 is described below
commit ee454172d18c94a85e96638c4a0cac8dccf19921
Author: Marat Gubaidullin <[email protected]>
AuthorDate: Fri Jan 20 16:40:41 2023 -0500
Implement #622
---
karavan-core/src/core/api/CamelUtil.ts | 11 ++++-
.../src/designer/rest/RestDesigner.tsx | 1 -
.../src/designer/route/DslConnections.tsx | 8 +++-
karavan-designer/src/designer/route/DslElement.tsx | 17 ++++++-
.../src/designer/route/DslProperties.tsx | 19 --------
.../src/designer/route/RouteDesigner.tsx | 56 +++++++++++++++++-----
karavan-designer/src/designer/utils/EventBus.ts | 6 +--
7 files changed, 80 insertions(+), 38 deletions(-)
diff --git a/karavan-core/src/core/api/CamelUtil.ts
b/karavan-core/src/core/api/CamelUtil.ts
index dca89363..170d267a 100644
--- a/karavan-core/src/core/api/CamelUtil.ts
+++ b/karavan-core/src/core/api/CamelUtil.ts
@@ -26,6 +26,7 @@ import {ComponentProperty} from "../model/ComponentModels";
import {ComponentApi} from "./ComponentApi";
import {CamelMetadataApi} from "../model/CamelMetadata";
import {CamelDefinitionApiExt} from "./CamelDefinitionApiExt";
+import {v4 as uuidv4} from 'uuid';
export class CamelUtil {
@@ -50,8 +51,14 @@ export class CamelUtil {
return int;
}
- static cloneStep = (step: CamelElement): CamelElement => {
- const clone = JSON.parse(JSON.stringify(step));
+ static cloneStep = (step: CamelElement, generateUuids: boolean = false):
CamelElement => {
+ const clone = JSON.parse(JSON.stringify(step, (key, value) => {
+ if (generateUuids && key === 'uuid'){
+ return uuidv4();
+ } else {
+ return value;
+ }
+ }));
return CamelDefinitionApi.createStep(step.dslName, clone, true);
}
diff --git a/karavan-designer/src/designer/rest/RestDesigner.tsx
b/karavan-designer/src/designer/rest/RestDesigner.tsx
index f91c5129..d13d07e6 100644
--- a/karavan-designer/src/designer/rest/RestDesigner.tsx
+++ b/karavan-designer/src/designer/rest/RestDesigner.tsx
@@ -240,7 +240,6 @@ export class RestDesigner extends React.Component<Props,
State> {
step={this.state.selectedStep}
onIntegrationUpdate={this.onIntegrationUpdate}
onPropertyUpdate={this.onPropertyUpdate}
- clipboardStep={undefined}
isRouteDesigner={false}
onClone={this.cloneRest}
dark={this.props.dark}/>
diff --git a/karavan-designer/src/designer/route/DslConnections.tsx
b/karavan-designer/src/designer/route/DslConnections.tsx
index 0806761e..6dc1ced3 100644
--- a/karavan-designer/src/designer/route/DslConnections.tsx
+++ b/karavan-designer/src/designer/route/DslConnections.tsx
@@ -57,12 +57,18 @@ export class DslConnections extends React.Component<Props,
State> {
}
setPosition(evt: DslPosition) {
- if (evt.command === "add") this.setState(prevState => ({steps:
prevState.steps.set(evt.step.uuid, evt)}));
+ if (evt.command === "add") {
+ this.setState(prevState => ({steps:
prevState.steps.set(evt.step.uuid, evt)}));
+ }
else if (evt.command === "delete") this.setState(prevState => {
// prevState.steps.clear();
prevState.steps.delete(evt.step.uuid);
return {steps: prevState.steps};
});
+ else if (evt.command === "clean") this.setState(prevState => {
+ prevState.steps.clear();
+ return {steps: prevState.steps};
+ });
}
getIncomings() {
diff --git a/karavan-designer/src/designer/route/DslElement.tsx
b/karavan-designer/src/designer/route/DslElement.tsx
index 868f3e2c..07222d84 100644
--- a/karavan-designer/src/designer/route/DslElement.tsx
+++ b/karavan-designer/src/designer/route/DslElement.tsx
@@ -65,9 +65,22 @@ export class DslElement extends React.Component<Props,
State> {
tabIndex: 0,
selectedUuid: this.props.selectedUuid,
isDragging: false,
- isDraggedOver: false
+ isDraggedOver: false,
};
+ handleKeyDown = (event: React.KeyboardEvent) =>{
+ // event.preventDefault();
+ // console.log(event);
+ // let charCode = String.fromCharCode(event.which).toLowerCase();
+ // if((event.ctrlKey || event.metaKey) && charCode === 's') {
+ // alert("CTRL+S Pressed");
+ // }else if((event.ctrlKey || event.metaKey) && charCode === 'c') {
+ // alert("CTRL+C Pressed");
+ // }else if((event.ctrlKey || event.metaKey) && charCode === 'v') {
+ // alert("CTRL+V Pressed");
+ // }
+ }
+
componentDidUpdate = (prevProps: Readonly<Props>, prevState:
Readonly<State>, snapshot?: any) => {
if (prevState.selectedUuid !== this.props.selectedUuid) {
this.setState({selectedUuid: this.props.selectedUuid});
@@ -484,6 +497,8 @@ export class DslElement extends React.Component<Props,
State> {
}}
onDrop={event => this.dragElement(event, element)}
draggable={!this.isNotDraggable()}
+ // tabIndex={0}
+ onKeyDown={this.handleKeyDown}
>
{this.getElementHeader()}
{this.getChildElements()}
diff --git a/karavan-designer/src/designer/route/DslProperties.tsx
b/karavan-designer/src/designer/route/DslProperties.tsx
index 0359bb36..f0000bc1 100644
--- a/karavan-designer/src/designer/route/DslProperties.tsx
+++ b/karavan-designer/src/designer/route/DslProperties.tsx
@@ -36,8 +36,6 @@ import {CamelUtil} from "karavan-core/lib/api/CamelUtil";
import {CamelUi, RouteToCreate} from "../utils/CamelUi";
import {CamelMetadataApi, PropertyMeta} from
"karavan-core/lib/model/CamelMetadata";
import {IntegrationHeader} from "../utils/KaravanComponents";
-import CopyIcon from '@patternfly/react-icons/dist/esm/icons/copy-icon'
-import PasteIcon from '@patternfly/react-icons/dist/esm/icons/paste-icon'
import CloneIcon from "@patternfly/react-icons/dist/esm/icons/clone-icon";
interface Props {
@@ -45,8 +43,6 @@ interface Props {
step?: CamelElement,
onIntegrationUpdate?: any,
onPropertyUpdate?: (element: CamelElement, newRoute?: RouteToCreate) =>
void
- clipboardStep?: CamelElement
- onSaveClipboardStep?: (element?: CamelElement) => void
onClone?: (element: CamelElement) => void
isRouteDesigner: boolean
dark: boolean
@@ -76,15 +72,6 @@ export class DslProperties extends React.Component<Props,
State> {
}
}
- pasteClipboardStep = () => {
- if (this.props.clipboardStep && this.state.step) {
- const clone = CamelUtil.cloneStep(this.props.clipboardStep);
- clone.uuid = this.state.step.uuid;
- this.setStep(clone)
- this.props.onPropertyUpdate?.call(this, clone);
- }
- }
-
dataFormatChanged = (value: DataFormatDefinition) => {
value.uuid = this.state.step?.uuid ? this.state.step?.uuid :
value.uuid;
this.setStep(value);
@@ -144,12 +131,6 @@ export class DslProperties extends React.Component<Props,
State> {
<div className="headers">
<div className="top">
<Title headingLevel="h1" size="md">{title}</Title>
- <Tooltip content="Copy step" position="bottom">
- <Button variant="link" onClick={() =>
this.props.onSaveClipboardStep?.call(this, this.state.step)}
icon={<CopyIcon/>}/>
- </Tooltip>
- <Tooltip content="Paste step" position="bottom">
- <Button variant="link" onClick={() =>
this.pasteClipboardStep()} icon={<PasteIcon/>}/>
- </Tooltip>
</div>
<Text
component={TextVariants.p}>{descriptionLines.at(0)}</Text>
{descriptionLines.length > 1 && <ExpandableSection
toggleText={isDescriptionExpanded ? 'Show less' : 'Show more'}
diff --git a/karavan-designer/src/designer/route/RouteDesigner.tsx
b/karavan-designer/src/designer/route/RouteDesigner.tsx
index 949295ea..10a44ca6 100644
--- a/karavan-designer/src/designer/route/RouteDesigner.tsx
+++ b/karavan-designer/src/designer/route/RouteDesigner.tsx
@@ -92,6 +92,7 @@ export class RouteDesigner extends React.Component<Props,
State> {
componentDidMount() {
window.addEventListener('resize', this.handleResize);
+ window.addEventListener('keydown', this.handleKeyDown);
const element =
findDOMNode(this.state.ref.current)?.parentElement?.parentElement;
const checkResize = (mutations: any) => {
const el = mutations[0].target;
@@ -107,12 +108,42 @@ export class RouteDesigner extends React.Component<Props,
State> {
componentWillUnmount() {
window.removeEventListener('resize', this.handleResize);
+ window.removeEventListener('keydown', this.handleKeyDown);
}
handleResize = (event: any) => {
this.setState({key: Math.random().toString()});
}
+ handleKeyDown = (event: KeyboardEvent) => {
+ const {integration, selectedUuid, clipboardStep} = this.state;
+ if (window.document.hasFocus() && window.document.activeElement &&
selectedUuid && selectedUuid !== '') {
+ if (['BODY',
'MAIN'].includes(window.document.activeElement.tagName)) {
+ let charCode = String.fromCharCode(event.which).toLowerCase();
+ if ((event.ctrlKey || event.metaKey) && charCode === 'c') {
+ const selectedElement =
CamelDefinitionApiExt.findElementInIntegration(integration, selectedUuid);
+ this.saveToClipboard(selectedElement);
+ } else if ((event.ctrlKey || event.metaKey) && charCode ===
'v') {
+ if (clipboardStep?.dslName === 'FromDefinition') {
+ const clone = CamelUtil.cloneStep(clipboardStep, true);
+ const route =
CamelDefinitionApi.createRouteDefinition({from: clone});
+ this.addStep(route, '', 0)
+ } else {
+ const meta =
CamelDefinitionApiExt.findElementMetaInIntegration(integration, selectedUuid);
+ if (clipboardStep && meta.parentUuid) {
+ const clone = CamelUtil.cloneStep(clipboardStep,
true);
+ this.addStep(clone, meta.parentUuid,
meta.position);
+ }
+ }
+ }
+ }
+ } else {
+ if (event.repeat) {
+ window.dispatchEvent(event);
+ }
+ }
+ }
+
componentDidUpdate = (prevProps: Readonly<Props>, prevState:
Readonly<State>, snapshot?: any) => {
if (prevState.key !== this.state.key) {
this.props.onSave?.call(this, this.state.integration,
this.state.propertyOnly);
@@ -222,8 +253,8 @@ export class RouteDesigner extends React.Component<Props,
State> {
onDslSelect = (dsl: DslMetaModel, parentId: string, position?: number |
undefined) => {
switch (dsl.dsl) {
case 'FromDefinition' :
- const from = CamelDefinitionApi.createRouteDefinition({from:
new FromDefinition({uri: dsl.uri})});
- this.addStep(from, parentId, position)
+ const route = CamelDefinitionApi.createRouteDefinition({from:
new FromDefinition({uri: dsl.uri})});
+ this.addStep(route, parentId, position)
break;
case 'ToDefinition' :
const to = CamelDefinitionApi.createStep(dsl.dsl, {uri:
dsl.uri});
@@ -260,6 +291,7 @@ export class RouteDesigner extends React.Component<Props,
State> {
addStep = (step: CamelElement, parentId: string, position?: number |
undefined) => {
const i =
CamelDefinitionApiExt.addStepToIntegration(this.state.integration, step,
parentId, position);
const clone = CamelUtil.cloneIntegration(i);
+ EventBus.sendPosition("clean", step, undefined, new DOMRect(), new
DOMRect(), 0);
this.setState({
integration: clone,
key: Math.random().toString(),
@@ -338,9 +370,7 @@ export class RouteDesigner extends React.Component<Props,
State> {
step={this.state.selectedStep}
onIntegrationUpdate={this.onIntegrationUpdate}
onPropertyUpdate={this.onPropertyUpdate}
- clipboardStep={this.state.clipboardStep}
isRouteDesigner={true}
- onSaveClipboardStep={this.saveToClipboard}
dark={this.props.dark}/>
</DrawerPanelContent>
)
@@ -356,7 +386,7 @@ export class RouteDesigner extends React.Component<Props,
State> {
integrationImageDownloadFilter = (node: HTMLElement) => {
const exclusionClasses = ['add-flow'];
return !exclusionClasses.some(classname => {
- return node.classList === undefined ? false:
node.classList.contains(classname);
+ return node.classList === undefined ? false :
node.classList.contains(classname);
});
}
@@ -364,11 +394,15 @@ export class RouteDesigner extends React.Component<Props,
State> {
if (this.state.printerRef.current === null) {
return
}
- toPng(this.state.printerRef.current, { style:{overflow:'hidden'},
cacheBust: true, filter: this.integrationImageDownloadFilter,
- height:this.state.height,width:this.state.width,
backgroundColor: this.props.dark?"black":"white" }).then(v => {
- toPng(this.state.printerRef.current, {
style:{overflow:'hidden'}, cacheBust: true, filter:
this.integrationImageDownloadFilter,
- height:this.state.height,width:this.state.width,
backgroundColor: this.props.dark?"black":"white"
}).then(this.downloadIntegrationImage);
- })
+ toPng(this.state.printerRef.current, {
+ style: {overflow: 'hidden'}, cacheBust: true, filter:
this.integrationImageDownloadFilter,
+ height: this.state.height, width: this.state.width,
backgroundColor: this.props.dark ? "black" : "white"
+ }).then(v => {
+ toPng(this.state.printerRef.current, {
+ style: {overflow: 'hidden'}, cacheBust: true, filter:
this.integrationImageDownloadFilter,
+ height: this.state.height, width: this.state.width,
backgroundColor: this.props.dark ? "black" : "white"
+ }).then(this.downloadIntegrationImage);
+ })
}
getGraph() {
@@ -380,7 +414,7 @@ export class RouteDesigner extends React.Component<Props,
State> {
<DslConnections height={height} width={width} top={top}
left={left} integration={integration}/>
<div className="flows" data-click="FLOWS" onClick={event =>
this.unselectElement(event)}
ref={el => this.onResizePage(el)}>
- {routeConfigurations?.map((routeConfiguration , index:
number) => (
+ {routeConfigurations?.map((routeConfiguration, index:
number) => (
<DslElement key={routeConfiguration.uuid + key}
integration={integration}
openSelector={this.openSelector}
diff --git a/karavan-designer/src/designer/utils/EventBus.ts
b/karavan-designer/src/designer/utils/EventBus.ts
index 98e573d7..2df867f4 100644
--- a/karavan-designer/src/designer/utils/EventBus.ts
+++ b/karavan-designer/src/designer/utils/EventBus.ts
@@ -27,9 +27,9 @@ export class DslPosition {
position: number = 0;
rect: DOMRect = new DOMRect();
headerRect: DOMRect = new DOMRect();
- command: "add" | "delete" = "add";
+ command: "add" | "delete" | "clean" = "add";
- constructor(command: "add" | "delete",
+ constructor(command: "add" | "delete" | "clean",
step: CamelElement,
parent:CamelElement | undefined,
rect: DOMRect,
@@ -49,7 +49,7 @@ export class DslPosition {
}
export const EventBus = {
- sendPosition: (command: "add" | "delete",
+ sendPosition: (command: "add" | "delete" | "clean",
step: CamelElement,
parent: CamelElement | undefined,
rect: DOMRect,