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
commit 0070dafba9db17f40ff03db3a1b283b5e0f24b5b Author: Marat Gubaidullin <marat.gubaidul...@gmail.com> AuthorDate: Sun Nov 13 14:57:45 2022 -0500 Standalone Designer --- karavan-designer/src/App.tsx | 253 ++++++++++++++------- karavan-designer/src/designer/DesignerPage.tsx | 112 +++++++++ karavan-designer/src/designer/KaravanDesigner.tsx | 18 +- karavan-designer/src/designer/karavan.css | 31 ++- .../src/designer/utils/KaravanComponents.tsx | 12 +- .../src/designer/utils/KaravanIcons.tsx | 164 +++++++++++++ karavan-designer/src/index.css | 48 ++++ karavan-designer/src/index.tsx | 26 +-- 8 files changed, 535 insertions(+), 129 deletions(-) diff --git a/karavan-designer/src/App.tsx b/karavan-designer/src/App.tsx index 5d7700f..dc88624 100644 --- a/karavan-designer/src/App.tsx +++ b/karavan-designer/src/App.tsx @@ -16,122 +16,205 @@ */ import * as React from "react"; import { - Page, + Alert, + AlertActionCloseButton, AlertGroup, Badge, + Bullseye, Button, Divider, Flex, FlexItem, + Page, PageSection, PageSectionVariants, Spinner, Text, TextContent, TextInput, Toolbar, ToolbarContent, ToolbarItem, Tooltip, } from "@patternfly/react-core"; import {KameletApi} from "karavan-core/lib/api/KameletApi"; import {ComponentApi} from "karavan-core/lib/api/ComponentApi"; -import {KaravanDesigner} from "./designer/KaravanDesigner"; import {KameletsPage} from "./kamelets/KameletsPage"; import {ComponentsPage} from "./components/ComponentsPage"; import {EipPage} from "./eip/EipPage"; -import {CamelDefinitionYaml} from "karavan-core/lib/api/CamelDefinitionYaml"; -import {CamelDisplayUtil} from "karavan-core/lib/api/CamelDisplayUtil"; +import {BlueprintIcon} from "@patternfly/react-icons"; +import KameletsIcon from "@patternfly/react-icons/dist/js/icons/registry-icon"; +import EipIcon from "@patternfly/react-icons/dist/js/icons/topology-icon"; +import ComponentsIcon from "@patternfly/react-icons/dist/js/icons/module-icon"; +import {KaravanIcon} from "./designer/utils/KaravanIcons"; +import './designer/karavan.css'; +import {DesignerPage} from "./designer/DesignerPage"; + +class ToastMessage { + id: string = '' + text: string = '' + title: string = '' + variant?: 'success' | 'danger' | 'warning' | 'info' | 'default'; + + constructor(title: string, text: string, variant: 'success' | 'danger' | 'warning' | 'info' | 'default') { + this.id = Date.now().toString().concat(Math.random().toString()); + this.title = title; + this.text = text; + this.variant = variant; + } +} + +class MenuItem { + pageId: string = ''; + tooltip: string = ''; + icon: any; + + constructor(pageId: string, tooltip: string, icon: any) { + this.pageId = pageId; + this.tooltip = tooltip; + this.icon = icon; + } +} interface Props { - page: "designer" | "kamelets" | "components" | "eip" | "builder"; } interface State { name: string yaml: string key: string + loaded?: boolean, + pageId: string, + alerts: ToastMessage[], } class App extends React.Component<Props, State> { public state: State = { - name: 'demo.yaml', + pageId: "designer", + alerts: [], + name: 'example.yaml', key: '', - yaml: '- route:\n' + - ' from:\n' + - ' uri: direct:direct1\n' + - ' steps:\n' + - ' - circuitBreaker:\n' + - ' steps:\n' + - ' - log:\n' + - ' message: hello11\n' + - ' logName: log11\n' + - ' resilience4jConfiguration:\n' + - ' minimumNumberOfCalls: 5\n' + - ' failureRateThreshold: 50\n' - // 'apiVersion: camel.apache.org/v1\n' + - // 'kind: Integration\n' + - // 'metadata:\n' + - // ' name: postman.yaml\n' + - // 'spec:\n' + - // ' flows:\n' + - // ' - route:\n' + - // ' from:\n' + - // ' uri: kamelet:timer-source\n' + - // ' steps:\n' + - // ' - marshal: {}\n' + - // ' parameters:\n' + - // ' period: 2000\n' + - // ' message: Hello World\n' - }; + yaml: '' + } + + toast = (title: string, text: string, variant: 'success' | 'danger' | 'warning' | 'info' | 'default') => { + const mess = []; + mess.push(...this.state.alerts, new ToastMessage(title, text, variant)); + this.setState({alerts: mess}) + } + + deleteErrorMessage = (id: string) => { + this.setState({alerts: this.state.alerts.filter(a => a.id !== id)}) + } componentDidMount() { - ["aws-eventbridge-sink.kamelet.yaml", - "chuck-norris-source.kamelet.yaml", - "http-secured-sink.kamelet.yaml", - "timer-source.kamelet.yaml", - "http-secured-source.kamelet.yaml", - "http-sink.kamelet.yaml", - "http-source.kamelet.yaml", - "mqtt-source.kamelet.yaml", - "insert-header-action.kamelet.yaml", - "kafka-not-secured-sink.kamelet.yaml", - "kafka-not-secured-source.kamelet.yaml", - "kafka-sink.kamelet.yaml", - "kafka-source.kamelet.yaml", - "postgresql-sink.kamelet.yaml", - "postgresql-source.kamelet.yaml" - ].forEach(name => - fetch("kamelets/" + name) - .then((r) => r.text()) - .then(value => KameletApi.saveKamelet(value))); - - ["bonita.json", - "activemq.json", - "direct.json", - "seda.json", - "docker.json", - "netty-http.json", - "jms.json", - "sql.json", - "cxf.json", - "file.json", - "log.json", - "kafka.json", - "coap+tcp.json", - "pg-replication-slot.json", - "rest-api.json", - "rest-openapi.json", - "salesforce.json", - "kubernetes-service-accounts.json", - "mvel.json"].forEach(name => - fetch("components/" + name) - .then((r) => r.text()) - .then(value => ComponentApi.saveComponent(value))); + Promise.all([ + fetch("kamelets/kamelets.yaml"), + fetch("components/components.json") + ]).then(responses => + Promise.all(responses.map(response => response.text())) + ).then(data => { + const kamelets: string[] = []; + data[0].split("\n---\n").map(c => c.trim()).forEach(z => kamelets.push(z)); + KameletApi.saveKamelets(kamelets, true); + this.toast("Success", "Loaded " + kamelets.length + " kamelets", 'success'); + + const components: [] = JSON.parse(data[1]); + const jsons: string[] = []; + components.forEach(c => jsons.push(JSON.stringify(c))); + ComponentApi.saveComponents(jsons, true); + + this.toast("Success", "Loaded " + jsons.length + " components", 'success'); + this.setState({loaded: true}); + }).catch(err => + this.toast("Error", err.text, 'danger') + ); } save(filename: string, yaml: string, propertyOnly: boolean) { - // console.log(filename); - console.log(yaml); - // console.log(propertyOnly); + this.setState({name: filename, yaml: yaml}); + // console.log(yaml); + } + + getSpinner() { + return ( + <Bullseye className="loading-page"> + <Spinner className="progress-stepper" isSVG diameter="80px" aria-label="Loading..."/> + </Bullseye> + ) + } + + pageNav = () => { + const {pageId} = this.state; + const pages: MenuItem[] = [ + new MenuItem("designer", "Designer", <BlueprintIcon/>), + new MenuItem("eip", "Enterprise Integration Patterns", <EipIcon/>), + new MenuItem("kamelets", "Kamelets", <KameletsIcon/>), + new MenuItem("components", "Components", <ComponentsIcon/>), + ] + return (<Flex className="nav-buttons" direction={{default: "column"}} style={{height: "100%"}} + spaceItems={{default: "spaceItemsNone"}}> + <FlexItem alignSelf={{default: "alignSelfCenter"}}> + <Tooltip className="logo-tooltip" content={"Apache Camel Karavan"} + position={"right"}> + {KaravanIcon()} + </Tooltip> + </FlexItem> + {pages.map(page => + <FlexItem key={page.pageId} className={pageId === page.pageId ? "nav-button-selected" : ""}> + <Tooltip content={page.tooltip} position={"right"}> + <Button id={page.pageId} icon={page.icon} variant={"plain"} + className={pageId === page.pageId ? "nav-button-selected" : ""} + onClick={event => this.setState({pageId: page.pageId})} + /> + </Tooltip> + </FlexItem> + )} + <FlexItem flex={{default: "flex_2"}} alignSelf={{default: "alignSelfCenter"}}> + <Divider/> + </FlexItem> + </Flex>) + } + + getDesigner() { + const {key, name, yaml, pageId} = this.state; + const dark = document.body.className.includes('vscode-dark'); + switch (pageId) { + case "designer": + return ( + <DesignerPage + name={name} + yaml={yaml} + onSave={(filename, yaml1, propertyOnly) => this.save(filename, yaml1, propertyOnly)} + dark={dark}/> + ) + case "kamelets": + return ( + <KameletsPage dark={dark}/> + ) + case "components": + return ( + <ComponentsPage dark={dark}/> + ) + case "eip": + return ( + <EipPage dark={dark}/> + ) + } } public render() { + const {loaded} = this.state; return ( <Page className="karavan"> - {this.props.page === "designer" && <KaravanDesigner key={this.state.key} filename={this.state.name} yaml={this.state.yaml} - onSave={(filename, yaml, propertyOnly) => this.save(filename, yaml, propertyOnly)} - dark={document.body.className.includes('vscode-dark')}/>} - {this.props.page === "kamelets" && <KameletsPage dark={document.body.className.includes('vscode-dark')} />} - {this.props.page === "components" && <ComponentsPage dark={document.body.className.includes('vscode-dark')} />} - {this.props.page === "eip" && <EipPage dark={document.body.className.includes('vscode-dark')} />} + <AlertGroup isToast isLiveRegion> + {this.state.alerts.map((e: ToastMessage) => ( + <Alert key={e.id} className="main-alert" variant={e.variant} title={e.title} + timeout={e.variant === "success" ? 2000 : 10000} + actionClose={<AlertActionCloseButton onClose={() => this.deleteErrorMessage(e.id)}/>}> + {e.text} + </Alert> + ))} + </AlertGroup> + <> + <Flex direction={{default: "row"}} style={{width: "100%", height: "100%"}} + alignItems={{default: "alignItemsStretch"}} spaceItems={{default: 'spaceItemsNone'}}> + <FlexItem> + {this.pageNav()} + </FlexItem> + <FlexItem flex={{default: "flex_2"}} style={{height: "100%"}}> + {loaded !== true && this.getSpinner()} + {loaded === true && this.getDesigner()} + </FlexItem> + </Flex> + </> </Page> - ); + ) } } diff --git a/karavan-designer/src/designer/DesignerPage.tsx b/karavan-designer/src/designer/DesignerPage.tsx new file mode 100644 index 0000000..4fb5662 --- /dev/null +++ b/karavan-designer/src/designer/DesignerPage.tsx @@ -0,0 +1,112 @@ +/* + * 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: 'padding'}} style={{backgroundColor:"transparent"}}> + <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-designer/src/designer/KaravanDesigner.tsx b/karavan-designer/src/designer/KaravanDesigner.tsx index a5a9f22..6333b37 100644 --- a/karavan-designer/src/designer/KaravanDesigner.tsx +++ b/karavan-designer/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-designer/src/designer/karavan.css b/karavan-designer/src/designer/karavan.css index 6d8c687..38e2973 100644 --- a/karavan-designer/src/designer/karavan.css +++ b/karavan-designer/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-designer/src/designer/utils/KaravanComponents.tsx b/karavan-designer/src/designer/utils/KaravanComponents.tsx index be32ff7..fa8c3bd 100644 --- a/karavan-designer/src/designer/utils/KaravanComponents.tsx +++ b/karavan-designer/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-designer/src/designer/utils/KaravanIcons.tsx b/karavan-designer/src/designer/utils/KaravanIcons.tsx index a215143..37a3182 100644 --- a/karavan-designer/src/designer/utils/KaravanIcons.tsx +++ b/karavan-designer/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"> diff --git a/karavan-designer/src/index.css b/karavan-designer/src/index.css index 379741d..e6a61da 100644 --- a/karavan-designer/src/index.css +++ b/karavan-designer/src/index.css @@ -15,6 +15,10 @@ body, flex-direction: column; } +.karavan .pf-c-page__main { + overflow: hidden; +} + .logo { display: flex; } @@ -23,3 +27,47 @@ body, height: 30px; margin-right: 10px; } + +.karavan .nav-buttons { + background: var(--pf-c-page__header--BackgroundColor); +} + +.karavan .nav-buttons .logo { + margin-top: 16px; + margin-bottom: 10px; + width: 32px; + height: 32px; +} + +.karavan .nav-buttons .pf-c-button { + padding: 0; + width: 64px; + height: 64px; + color: var(--pf-global--Color--light-100); +} + +.karavan .nav-buttons .pf-c-button svg { + width: 24px; +} + +.karavan .nav-buttons .avatar { + width: 32px; + height: 32px; + margin-bottom: 6px; + border: solid var(--pf-global--Color--light-100) 1px; + background-color: var(--pf-global--Color--light-100); + border-radius: 32px; + padding: 6px; +} + +.karavan .nav-buttons .pf-c-button.pf-m-plain { + border-left-width: 3px; + border-left-style: solid; + border-left-color: transparent; + border-radius: 0; +} + +.karavan .nav-button-selected .pf-c-button.pf-m-plain { + border-left-color: var(--pf-global--active-color--400); + background-color: var(--pf-global--BackgroundColor--dark-400); +} diff --git a/karavan-designer/src/index.tsx b/karavan-designer/src/index.tsx index b8d7e70..98fd060 100644 --- a/karavan-designer/src/index.tsx +++ b/karavan-designer/src/index.tsx @@ -14,27 +14,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import * as React from "react"; +import React from 'react'; +import ReactDOM from 'react-dom'; import "./index.css"; import "@patternfly/patternfly/patternfly.css"; import App from "./App"; -import {render} from "react-dom"; -import { - BrowserRouter, - Routes, - Route, -} from "react-router-dom"; -const rootElement = document.getElementById("root"); -render( - <BrowserRouter> - <Routes> - <Route path="/" element={<App page="designer"/>} /> - <Route path="kamelets-page" element={<App page="kamelets"/>} /> - <Route path="components-page" element={<App page="components"/>} /> - <Route path="eip-page" element={<App page="eip"/>} /> - <Route path="builder" element={<App page="builder"/>} /> - </Routes> - </BrowserRouter>, - rootElement -); +ReactDOM.render( + <App/>, + document.getElementById('root') +); \ No newline at end of file