karavan-space/src/App.tsx (179 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 * as React from "react";
import {
Bullseye, Button, Divider, Flex, FlexItem,
Page, Spinner, Tooltip,
} from "@patternfly/react-core";
import {KameletApi} from "karavan-core/lib/api/KameletApi";
import {ComponentApi} from "karavan-core/lib/api/ComponentApi";
import {BlueprintIcon} from "@patternfly/react-icons";
import KnowledgebaseIcon from "@patternfly/react-icons/dist/js/icons/book-open-icon";
import TopologyIcon from "@patternfly/react-icons/dist/js/icons/topology-icon";
import './designer/karavan.css';
import {SpacePage} from "./space/SpacePage";
import {GithubModal} from "./space/GithubModal";
import {TemplateApi} from "karavan-core/lib/api/TemplateApi";
import {KnowledgebasePage} from "./knowledgebase/KnowledgebasePage";
import {EventBus} from "./designer/utils/EventBus";
import {Notification} from "./designer/utils/Notification";
import {TopologyTab} from "./topology/TopologyTab";
import {IntegrationFile} from "karavan-core/lib/model/IntegrationDefinition";
import {KaravanIcon} from "./designer/icons/KaravanIcons";
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 {
}
interface State {
name: string
yaml: string
key: string
loaded?: boolean,
githubModalIsOpen: boolean,
pageId: string,
}
class App extends React.Component<Props, State> {
public state: State = {
pageId: "designer",
name: 'example.camel.yaml',
key: '',
yaml: '',
githubModalIsOpen: false
}
componentDidMount() {
Promise.all([
fetch("metadata/kamelets.yaml"),
fetch("metadata/components.json"),
fetch("snippets/org.apache.camel.AggregationStrategy"),
fetch("snippets/org.apache.camel.Processor"),
]).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);
const components: [] = JSON.parse(data[1]);
const jsons: string[] = [];
components.forEach(c => jsons.push(JSON.stringify(c)));
ComponentApi.saveComponents(jsons, true);
this.setState({loaded: true, key: Math.random().toString()});
TemplateApi.saveTemplate("org.apache.camel.AggregationStrategy", data[2]);
TemplateApi.saveTemplate("org.apache.camel.Processor", data[3]);
}).catch(err =>
EventBus.sendAlert("Error", err.text, 'danger')
);
}
save(filename: string, yaml: string, propertyOnly: boolean) {
this.setState({name: filename, yaml: yaml});
// console.log(yaml);
}
onchangeBlockedList(type: string, name: string, checked: boolean){
if (type === 'kamelet') {
const blockedKamelet = KameletApi.saveBlockedKameletName(name, checked);
}
else if (type === 'component') {
const blockedComponent = ComponentApi.saveBlockedComponentName(name, checked);
}
}
closeGithubModal() {
this.setState({githubModalIsOpen: false})
}
openGithubModal() {
this.setState({githubModalIsOpen: true, key: Math.random().toString()});
}
getSpinner() {
return (
<Bullseye className="loading-page">
<Spinner className="progress-stepper" diameter="80px" aria-label="Loading..."/>
</Bullseye>
)
}
pageNav = () => {
const {pageId} = this.state;
const pages: MenuItem[] = [
new MenuItem("designer", "Designer", <BlueprintIcon/>),
new MenuItem("topology", "Topology", <TopologyIcon/>),
new MenuItem("knowledgebase", "Knowledgebase", <KnowledgebaseIcon/>),
]
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 4.10.2"}
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>)
}
getIntegrationFiles(): IntegrationFile[]{
return [new IntegrationFile("example.camel.yaml", this.state.yaml)];
}
getDesigner() {
const {name, yaml, pageId} = this.state;
const dark = document.body.className.includes('vscode-dark');
switch (pageId) {
case "designer":
return (
<SpacePage
name={name}
yaml={yaml}
onSave={(filename, yaml1, propertyOnly) => this.save(filename, yaml1, propertyOnly)}
onPush={type => this.openGithubModal()}
dark={dark}/>
)
case "knowledgebase":
return (
<KnowledgebasePage dark={dark} changeBlockList={(type: string, name: string, checked: boolean) => this.onchangeBlockedList(type, name, checked)}/>
)
case "topology":
return (
<TopologyTab
files={this.getIntegrationFiles()}
onSetFile={fileName => this.setState({pageId: 'designer'})}
onClickAddRoute={() => {}}
onClickAddREST={() => {}}
onClickAddBean={() => {}}
onClickAddKamelet={() => {}}
hideToolbar={true}
/>
)
}
}
render() {
const {loaded, githubModalIsOpen, yaml, name} = this.state;
return (
<Page className="karavan">
<Notification/>
<>
<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()}
{loaded === true && githubModalIsOpen &&
<GithubModal yaml={yaml} filename={name} isOpen={githubModalIsOpen} onClose={this.closeGithubModal}/>}
</FlexItem>
</Flex>
</>
</Page>
)
}
}
export default App;