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 e559dd3 Fix clous-app with quinoa e559dd3 is described below commit e559dd3d20f83071abefd74d7a1e27feca1fdfc9 Author: Marat Gubaidullin <marat.gubaidul...@gmail.com> AuthorDate: Mon Nov 14 07:46:15 2022 -0500 Fix clous-app with quinoa --- .../src/main/resources/application.properties | 2 +- .../src/main/webui/src/designer/DesignerPage.tsx | 113 ++++++++++++++ .../main/webui/src/designer/KaravanDesigner.tsx | 18 ++- .../src/main/webui/src/designer/karavan.css | 31 ++-- .../webui/src/designer/utils/KaravanComponents.tsx | 12 +- .../main/webui/src/designer/utils/KaravanIcons.tsx | 164 +++++++++++++++++++++ 6 files changed, 315 insertions(+), 25 deletions(-) diff --git a/karavan-app/src/main/resources/application.properties b/karavan-app/src/main/resources/application.properties index 760d34a..74e3637 100644 --- a/karavan-app/src/main/resources/application.properties +++ b/karavan-app/src/main/resources/application.properties @@ -98,5 +98,5 @@ quarkus.kubernetes-client.request-timeout=10000 quarkus.swagger-ui.always-include=false quarkus.quinoa.package-manager-install=true -quarkus.quinoa.package-manager-install.node-version=16.17.0 +quarkus.quinoa.package-manager-install.node-version=18.12.1 quarkus.quinoa.dev-server.port=3000 \ No newline at end of file diff --git a/karavan-app/src/main/webui/src/designer/DesignerPage.tsx b/karavan-app/src/main/webui/src/designer/DesignerPage.tsx new file mode 100644 index 0000000..fb05426 --- /dev/null +++ b/karavan-app/src/main/webui/src/designer/DesignerPage.tsx @@ -0,0 +1,113 @@ +/* + * 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 { + Toolbar, + ToolbarContent, + ToolbarItem, + PageSection, TextContent, Text, PageSectionVariants, Flex, FlexItem, Badge, Button, Tooltip +} from '@patternfly/react-core'; +import '../designer/karavan.css'; +import DownloadIcon from "@patternfly/react-icons/dist/esm/icons/download-icon"; +import DownloadImageIcon from "@patternfly/react-icons/dist/esm/icons/image-icon"; +import {KaravanDesigner} from "./KaravanDesigner"; + +interface Props { + name: string, + yaml: string, + dark: boolean, + onSave?: (filename: string, yaml: string, propertyOnly: boolean) => void +} + +interface State { + karavanDesignerRef: any, +} + +export class DesignerPage extends React.Component<Props, State> { + + public state: State = { + + karavanDesignerRef: React.createRef(), + }; + + componentDidMount() { + } + + save(filename: string, yaml: string, propertyOnly: boolean) { + this.props.onSave?.call(this, filename, yaml, propertyOnly); + } + + download = () => { + const {name, yaml} = this.props; + if (name && yaml) { + const a = document.createElement('a'); + a.setAttribute('download', 'example.yaml'); + a.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(yaml)); + a.click(); + } + } + + downloadImage = () => { + if (this.state.karavanDesignerRef) { + this.state.karavanDesignerRef.current.downloadImage(); + } + } + + render() { + const {name, yaml} = this.props; + return ( + <PageSection className="kamelet-section designer-page" padding={{default: 'noPadding'}}> + <PageSection className="tools-section" padding={{default: 'noPadding'}} + style={{backgroundColor:"transparent", paddingLeft: "var(--pf-c-page__main-section--PaddingLeft)"}}> + <Flex className="tools" justifyContent={{default: 'justifyContentSpaceBetween'}}> + <FlexItem> + <TextContent className="header"> + <Text component="h2">Designer</Text> + </TextContent> + </FlexItem> + <FlexItem> + <Toolbar id="toolbar-group-types"> + <ToolbarContent> + <ToolbarItem> + <Tooltip content="Download source" position={"bottom-end"}> + <Button variant="primary" icon={<DownloadIcon/>} onClick={e => this.download()}> + Download yaml + </Button> + </Tooltip> + </ToolbarItem> + <ToolbarItem> + <Tooltip content="Download image" position={"bottom-end"}> + <Button variant="secondary" icon={<DownloadImageIcon/>} onClick={e => this.downloadImage()}> + Download image + </Button> + </Tooltip> + </ToolbarItem> + </ToolbarContent> + </Toolbar> + </FlexItem> + </Flex> + </PageSection> + <KaravanDesigner + dark={this.props.dark} + ref={this.state.karavanDesignerRef} + filename={name} + yaml={yaml} + onSave={(filename, yaml, propertyOnly) => this.save(filename, yaml, propertyOnly)}/> + </PageSection> + ); + } +}; \ No newline at end of file diff --git a/karavan-app/src/main/webui/src/designer/KaravanDesigner.tsx b/karavan-app/src/main/webui/src/designer/KaravanDesigner.tsx index a5a9f22..6333b37 100644 --- a/karavan-app/src/main/webui/src/designer/KaravanDesigner.tsx +++ b/karavan-app/src/main/webui/src/designer/KaravanDesigner.tsx @@ -50,15 +50,21 @@ interface State { export class KaravanDesigner extends React.Component<Props, State> { + getIntegration = (yaml: string, filename: string): Integration => { + if (yaml && CamelDefinitionYaml.yamlIsIntegration(yaml)) { + return CamelDefinitionYaml.yamlToIntegration(this.props.filename, this.props.yaml) + } else { + return Integration.createNew(filename, 'plain'); + } + } + public state: State = { tab: this.props.tab ? this.props.tab : 'routes', - integration: this.props.yaml && CamelDefinitionYaml.yamlIsIntegration(this.props.yaml) - ? CamelDefinitionYaml.yamlToIntegration(this.props.filename, this.props.yaml) - : Integration.createNew(this.props.filename), + integration: this.getIntegration(this.props.yaml, this.props.filename), key: "", propertyOnly: false, routeDesignerRef: React.createRef(), - }; + } componentDidUpdate = (prevProps: Readonly<Props>, prevState: Readonly<State>, snapshot?: any) => { if (prevState.key !== this.state.key) { @@ -107,7 +113,6 @@ export class KaravanDesigner extends React.Component<Props, State> { <Tab eventKey='rest' title={this.getTab("REST", "REST services", "rest")}></Tab> <Tab eventKey='beans' title={this.getTab("Beans", "Beans Configuration", "beans")}></Tab> <Tab eventKey='error' title={this.getTab("Error", "Error Handler", "error")}></Tab> - <Tab eventKey='exception' title={this.getTab("Exceptions", "Exception Clauses per type", "exception")}></Tab> </Tabs> {tab === 'routes' && <RouteDesigner integration={this.state.integration} onSave={(integration, propertyOnly) => this.save(integration, propertyOnly)} @@ -122,9 +127,6 @@ export class KaravanDesigner extends React.Component<Props, State> { {tab === 'error' && <ErrorDesigner integration={this.state.integration} onSave={(integration, propertyOnly) => this.save(integration, propertyOnly)} dark={this.props.dark}/>} - {tab === 'exception' && <ExceptionDesigner integration={this.state.integration} - onSave={(integration, propertyOnly) => this.save(integration, propertyOnly)} - dark={this.props.dark}/>} </PageSection> ) } diff --git a/karavan-app/src/main/webui/src/designer/karavan.css b/karavan-app/src/main/webui/src/designer/karavan.css index 6d8c687..38e2973 100644 --- a/karavan-app/src/main/webui/src/designer/karavan.css +++ b/karavan-app/src/main/webui/src/designer/karavan.css @@ -54,15 +54,6 @@ padding-right: 16px; } -.karavan .main-alert { - position: fixed; - width: 500px; - height: 90px; - left: 50%; - margin-top: 20px; - margin-left: -250px; -} - .filler { width: 100%; } @@ -1271,4 +1262,24 @@ .root .tooltip-required-field .pf-c-tooltip__content { text-align: start; -} \ No newline at end of file +} + +.karavan .kamelet-section { + display: flex; + flex-direction: column; + height: 100%; +} + +.karavan .kamelets-page { + overflow: auto; + flex-shrink: unset; + flex-grow: 1; +} + +.karavan .designer-page { + background-color: white; +} + +.karavan .designer-page .project-page-section { + background-color: white; +} diff --git a/karavan-app/src/main/webui/src/designer/utils/KaravanComponents.tsx b/karavan-app/src/main/webui/src/designer/utils/KaravanComponents.tsx index be32ff7..fa8c3bd 100644 --- a/karavan-app/src/main/webui/src/designer/utils/KaravanComponents.tsx +++ b/karavan-app/src/main/webui/src/designer/utils/KaravanComponents.tsx @@ -29,12 +29,12 @@ export class IntegrationHeader extends React.Component<Props> { return ( <div className="headers"> <Title headingLevel="h1" size="md">Integration</Title> - <FormGroup label="Title" fieldId="title" isRequired> - <TextInput className="text-field" type="text" id="title" name="title" isReadOnly - value={ - CamelUi.titleFromName(this.props.integration.metadata.name) - }/> - </FormGroup> + {/*<FormGroup label="Title" fieldId="title" isRequired>*/} + {/* <TextInput className="text-field" type="text" id="title" name="title" isReadOnly*/} + {/* value={*/} + {/* CamelUi.titleFromName(this.props.integration.metadata.name)*/} + {/* }/>*/} + {/*</FormGroup>*/} <FormGroup label="Name" fieldId="name" isRequired> <TextInput className="text-field" type="text" id="name" name="name" isReadOnly value={this.props.integration.metadata.name}/> diff --git a/karavan-app/src/main/webui/src/designer/utils/KaravanIcons.tsx b/karavan-app/src/main/webui/src/designer/utils/KaravanIcons.tsx index a215143..37a3182 100644 --- a/karavan-app/src/main/webui/src/designer/utils/KaravanIcons.tsx +++ b/karavan-app/src/main/webui/src/designer/utils/KaravanIcons.tsx @@ -16,6 +16,170 @@ */ import React from 'react'; +export function KaravanIcon(className?: string) { + return ( + <svg + xmlns="http://www.w3.org/2000/svg" + xmlnsXlink="http://www.w3.org/1999/xlink" + id="svg50" + width="256" + height="256" + preserveAspectRatio="xMidYMid" + version="1.1" + viewBox="0 0 256 256" + className={className ? className : "logo"} + > + <defs id="defs31"> + <linearGradient id="linearGradient1351"> + <stop + id="stop1347" + offset="0" + stopColor="#dcffff" + stopOpacity="1" + ></stop> + <stop + id="stop1349" + offset="1" + stopColor="#96d2e6" + stopOpacity="1" + ></stop> + </linearGradient> + <circle id="path-1" cx="128" cy="128" r="128"></circle> + <linearGradient + id="linearGradient-3" + x1="-26.051" + x2="254.316" + y1="271.331" + y2="0.048" + gradientUnits="userSpaceOnUse" + > + <stop + id="stop10" + offset="0%" + stopColor="#4790bb" + stopOpacity="1" + ></stop> + <stop + id="stop12" + offset="10.996%" + stopColor="#64b7db" + stopOpacity="1" + ></stop> + <stop + id="stop14" + offset="94.502%" + stopColor="#326ea0" + stopOpacity="1" + ></stop> + </linearGradient> + <linearGradient + id="linearGradient-4" + x1="-32.163" + x2="259.338" + y1="277.029" + y2="-5.028" + gradientUnits="userSpaceOnUse" + > + <stop id="stop17" offset="0%" stopColor="#F69923"></stop> + <stop id="stop19" offset="8.048%" stopColor="#F79A23"></stop> + <stop id="stop21" offset="41.874%" stopColor="#E97826"></stop> + </linearGradient> + <linearGradient + id="linearGradient-5" + x1="217.945" + x2="99.459" + y1="67.505" + y2="247.005" + gradientTransform="scale(.96442 1.0369)" + gradientUnits="userSpaceOnUse" + xlinkHref="#linearGradient-4" + > + <stop + id="stop24" + offset="0%" + stopColor="#92d6d5" + stopOpacity="1" + ></stop> + <stop + id="stop26" + offset="41.191%" + stopColor="#79b7cc" + stopOpacity="1" + ></stop> + <stop + id="stop28" + offset="73.271%" + stopColor="#5891c5" + stopOpacity="1" + ></stop> + </linearGradient> + <mask id="mask-2" fill="#fff"> + <use id="use33" xlinkHref="#path-1"></use> + </mask> + <mask id="mask-2-7" fill="#fff"> + <use id="use137" xlinkHref="#path-1"></use> + </mask> + <linearGradient + id="linearGradient1345" + x1="233.122" + x2="2.24" + y1="56.015" + y2="242.78" + gradientUnits="userSpaceOnUse" + xlinkHref="#linearGradient1351" + ></linearGradient> + </defs> + <circle + id="circle38" + cx="127.994" + cy="127.994" + r="123.111" + fill="url(#linearGradient-3)" + fillRule="nonzero" + mask="url(#mask-2)" + ></circle> + <g id="g2266"> + <path + id="path42" + fill="url(#linearGradient-5)" + fillOpacity="1" + fillRule="nonzero" + d="M98.044 75.517c-1.751-.002-3.524.01-5.292.061-2.056.06-4.817.713-8 1.785 53.775 40.834 73.108 114.497 39.875 178.514 1.129.03 2.249.123 3.385.123 60.736 0 111.492-42.323 124.609-99.071-38.542-45.178-90.813-81.314-154.578-81.412z" + mask="url(#mask-2)" + opacity="0.75" + ></path> + </g> + <path + id="path44" + fill="#1e4b7b" + fillOpacity="1" + fillRule="nonzero" + d="M84.752 77.368C66.895 83.378 32.83 104.546.079 132.81c2.487 67.334 57.028 121.313 124.548 123.07 33.233-64.016 13.901-137.68-39.875-178.513z" + mask="url(#mask-2)" + opacity="0.75" + ></path> + <path + id="path150" + fill="url(#linearGradient1345)" + fillOpacity="1" + fillRule="nonzero" + d="M128.747 54.005c-10.985 5.495 0 27.466 0 27.466C95.774 108.954 102.78 155.9 64.312 155.9c-20.97 0-42.242-24.077-64.233-38.828-.283 3.479-.785 6.972-.785 10.524 0 48.095 26.263 89.924 65.42 111.897 10.952-1.38 22.838-4.114 31.05-9.592 43.146-28.765 53.857-83.491 71.487-109.925 10.979-16.492 62.434-15.061 65.906-22.01 5.502-10.991-10.99-27.467-16.491-27.467h-43.958c-3.071 0-7.897-5.456-10.974-5.456h-16.492s-7.307-11.085-13.794-11.526c-.93-.066-1.83.053-2.7.488z" + mask="url(#mask-2-7)" + transform="translate(-.769 -.133)" + ></path> + <path + id="path40" + fill="#2d4150" + fillOpacity="1" + fillRule="nonzero" + d="M128 256C57.308 256 0 198.692 0 128 0 57.308 57.308 0 128 0c70.692 0 128 57.308 128 128 0 70.692-57.308 128-128 128zm0-9.768c65.298 0 118.232-52.934 118.232-118.232S193.298 9.768 128 9.768 9.768 62.702 9.768 128 62.702 246.232 128 246.232z" + mask="url(#mask-2)" + transform="translate(-.59) scale(1.00078)" + ></path> + </svg> + ); +} + export function getDesignerIcon(icon: string) { if (icon === 'routes') return ( <svg className="top-icon" width="32px" height="32px" viewBox="0 0 32 32" id="icon">