karavan-designer/src/designer/route/RouteDesigner.tsx (198 lines of code) (raw):

/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import React from 'react'; import { Drawer, DrawerPanelContent, DrawerContent, DrawerContentBody, Button, Modal, PageSection, } from '@patternfly/react-core'; import '../karavan.css'; import {DslSelector} from "./DslSelector"; import {DslProperties} from "./DslProperties"; import {CamelElement, Integration} from "karavan-core/lib/model/IntegrationDefinition"; import {DslConnections} from "./DslConnections"; import PlusIcon from "@patternfly/react-icons/dist/esm/icons/plus-icon"; import {DslElement} from "./DslElement"; import {CamelUi} from "../utils/CamelUi"; import {CamelDisplayUtil} from "karavan-core/lib/api/CamelDisplayUtil"; import {RouteDesignerLogic} from "./RouteDesignerLogic"; interface Props { onSave?: (integration: Integration, propertyOnly: boolean) => void integration: Integration dark: boolean } export interface RouteDesignerState { logic: RouteDesignerLogic integration: Integration selectedStep?: CamelElement showSelector: boolean showDeleteConfirmation: boolean deleteMessage: string parentId: string parentDsl?: string selectedPosition?: number showSteps: boolean selectedUuids: string [] key: string width: number height: number top: number left: number clipboardSteps: CamelElement[] shiftKeyPressed?: boolean ref?: any printerRef?: any propertyOnly: boolean selectorTabIndex?: string | number } export class RouteDesigner extends React.Component<Props, RouteDesignerState> { public state: RouteDesignerState = { logic: new RouteDesignerLogic(this), integration: CamelDisplayUtil.setIntegrationVisibility(this.props.integration, undefined), showSelector: false, showDeleteConfirmation: false, deleteMessage: '', parentId: '', showSteps: true, selectedUuids: [], clipboardSteps: [], key: "", width: 1000, height: 1000, top: 0, left: 0, ref: React.createRef(), printerRef: React.createRef(), propertyOnly: false, }; componentDidMount() { this.state.logic.componentDidMount(); } componentWillUnmount() { this.state.logic.componentWillUnmount(); } handleResize = (event: any) => { return this.state.logic.handleResize(event); } handleKeyDown = (event: KeyboardEvent) => { return this.state.logic.handleKeyDown(event); } handleKeyUp = (event: KeyboardEvent) => { return this.state.logic.handleKeyUp(event); } componentDidUpdate = (prevProps: Readonly<Props>, prevState: Readonly<RouteDesignerState>, snapshot?: any) => { return this.state.logic.componentDidUpdate(prevState, snapshot); } getSelectorModal() { return ( <DslSelector isOpen={this.state.showSelector} onClose={() => this.state.logic.closeDslSelector()} dark={this.props.dark} parentId={this.state.parentId} parentDsl={this.state.parentDsl} showSteps={this.state.showSteps} position={this.state.selectedPosition} tabIndex={this.state.selectorTabIndex} onDslSelect={this.state.logic.onDslSelect}/>) } getDeleteConfirmation() { let htmlContent: string = this.state.deleteMessage; return (<Modal className="modal-delete" title="Confirmation" isOpen={this.state.showDeleteConfirmation} onClose={() => this.setState({showDeleteConfirmation: false})} actions={[ <Button key="confirm" variant="primary" onClick={e => this.state.logic.deleteElement()}>Delete</Button>, <Button key="cancel" variant="link" onClick={e => this.setState({showDeleteConfirmation: false})}>Cancel</Button> ]} onEscapePress={e => this.setState({showDeleteConfirmation: false})}> <div> {htmlContent} </div> </Modal>) } getPropertiesPanel() { return ( <DrawerPanelContent onResize={width => this.setState({key: Math.random().toString()})} style={{transform: "initial"}} isResizable hasNoBorder defaultSize={'400px'} maxSize={'800px'} minSize={'300px'}> <DslProperties ref={this.state.ref} integration={this.state.integration} step={this.state.selectedStep} onIntegrationUpdate={this.state.logic.onIntegrationUpdate} onPropertyUpdate={this.state.logic.onPropertyUpdate} isRouteDesigner={true} dark={this.props.dark}/> </DrawerPanelContent> ) } getGraph() { const {selectedUuids, integration, key, width, height, top, left} = this.state; const routes = CamelUi.getRoutes(integration); const routeConfigurations = CamelUi.getRouteConfigurations(integration); return ( <div ref={this.state.printerRef} className="graph"> <DslConnections height={height} width={width} top={top} left={left} integration={integration}/> <div className="flows" data-click="FLOWS" onClick={event => this.state.logic.unselectElement(event)} ref={el => this.state.logic.onResizePage(el)}> {routeConfigurations?.map((routeConfiguration, index: number) => ( <DslElement key={routeConfiguration.uuid + key} integration={integration} openSelector={this.state.logic.openSelector} deleteElement={this.state.logic.showDeleteConfirmation} selectElement={this.state.logic.selectElement} moveElement={this.state.logic.moveElement} selectedUuid={selectedUuids} inSteps={false} position={index} step={routeConfiguration} parent={undefined}/> ))} {routes?.map((route: any, index: number) => ( <DslElement key={route.uuid + key} integration={integration} openSelector={this.state.logic.openSelector} deleteElement={this.state.logic.showDeleteConfirmation} selectElement={this.state.logic.selectElement} moveElement={this.state.logic.moveElement} selectedUuid={selectedUuids} inSteps={false} position={index} step={route} parent={undefined}/> ))} <div className="add-flow"> <Button variant={routes.length === 0 ? "primary" : "secondary"} icon={<PlusIcon/>} onClick={e => this.state.logic.openSelector(undefined, undefined)}>Create route </Button> <Button variant="secondary" icon={<PlusIcon/>} onClick={e => this.state.logic.createRouteConfiguration()}>Create configuration </Button> </div> </div> </div>) } render() { return ( <PageSection className="dsl-page" isFilled padding={{default: 'noPadding'}}> <div className="dsl-page-columns"> <Drawer isExpanded isInline> <DrawerContent panelContent={this.getPropertiesPanel()}> <DrawerContentBody>{this.getGraph()}</DrawerContentBody> </DrawerContent> </Drawer> </div> {this.state.showSelector === true && this.getSelectorModal()} {this.getDeleteConfirmation()} </PageSection> ); } }