blob: 499819a8d03d10f219fa2e02c5f5a0209e4c2102 [file] [log] [blame]
/*
* 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 Tour from "@reactour/tour";
import {EventBus} from "./utils/EventBus";
import {TextContent, TextVariants, Title, Text} from "@patternfly/react-core";
import ArrowIcon from "@patternfly/react-icons/dist/js/icons/arrow-right-icon";
import CloseIcon from "@patternfly/react-icons/dist/js/icons/times-icon";
import {Integration} from "karavan-core/lib/model/IntegrationDefinition";
import {CamelDefinitionApi} from "karavan-core/lib/api/CamelDefinitionApi";
import {CamelDefinitionApiExt} from "karavan-core/lib/api/CamelDefinitionApiExt";
import {CamelUtil} from "karavan-core/lib/api/CamelUtil";
import {FromDefinition} from "karavan-core/lib/model/CamelDefinition";
function getContent(text: string, title?: string){
return (
<div>
{title && <Title headingLevel="h3">{title}</Title>}
<TextContent>
<Text component={TextVariants.p}>
{text}
</Text>
<Text component={TextVariants.blockquote}>
<div style={{display: "flex", flexDirection: "row", justifyContent: "space-between"}}>
<div>Follow the tour by clicking</div>
<ArrowIcon style={{margin: "auto"}}/>
<div>button</div>
</div>
</Text>
</TextContent>
</div>
)
}
const STEPS: Map<string, any[]> = new Map([
['routes', [
{selector: '[data-tour="routes"]', content: getContent("Create a route from MQTT to Kafka for messages with header 'approved' equals to 'true'", "Tour use case")},
{selector: '[data-tour="add-route"]', content: getContent("Click button to add new route")},
{selector: '[data-tour="selector-tabs"]', content: getContent("Select Source Kamelet")},
{selector: '[data-tour="mqtt-source"]', content: getContent("Click on MQTT Source")},
{selector: '[data-tour="route-created"]', content: getContent("Route created")},
{selector: '[data-tour="FromDefinition-icon"]', content: getContent("Click on MQTT Source icon to select")},
{selector: '[data-tour="properties"]', content: getContent("Set MQTT Source broker and topic")},
{highlightedSelectors: ['[data-tour="topic"]', '[data-tour="brokerUrl"]'], content: getContent("MQTT Source broker and topic are set")},
{selector: '[data-tour="add-step"]', content: getContent("Click button to add step")},
{selector: '[data-tour="selector-tabs"]', content: getContent("Select Integration Pattern")},
{selector: '[data-tour="filter"]', content: getContent("Click on Filter")},
{selector: '[data-tour="FilterDefinition"]', content: getContent("Filter added")},
{selector: '[data-tour="properties"]', content: getContent("Set Filter expression")},
{selector: '[data-tour="expression"]', content: getContent("Filter expression is set")},
{selector: '[data-tour="add-step"]', content: getContent("Click button to add step")},
{selector: '[data-tour="selector-tabs"]', content: getContent("Select source Kamelet")},
{selector: '[data-tour="kafka-not-secured-sink"]', content: getContent("Click on Kafka Sink")},
{selector: '[data-tour="ToDefinition"]', content: getContent("Kafka Sink added")},
{selector: '[data-tour="properties"]', content: getContent("Set Kafka Sink bootstrap servers and topic")},
{highlightedSelectors: ['[data-tour="topic"]', '[data-tour="bootstrapServers"]'], content: getContent("Kafka Sink bootstrap servers and topic are set")},
{selector: '[data-tour="route-created"]', content: getContent("Route filtered messages from MQTT to Kafka is done", "Tour use case")},
{
selector: '[data-tour="route-created"]', content:
<div>
<Title headingLevel="h3">Tour use case:</Title>
<TextContent>
<Text component={TextVariants.p}>
Route from MQTT to Kafka for messages with header 'approved' equals to 'true' created
</Text>
<Text component={TextVariants.blockquote} size={14}>
<div style={{display: "flex", flexDirection: "row", justifyContent: "space-between"}}>
<div>Close the tour by clicking</div>
<CloseIcon style={{margin: "auto"}}/>
<div>button</div>
</div>
</Text>
</TextContent>
</div>
},
]],
['rest', []],
]);
interface Props {
onSave?: (integration: Integration, propertyOnly: boolean) => void
integration: Integration
showTour: boolean
tab: string
onClose: () => void
}
interface State {
showTour: boolean
steps: any[]
currentStep: number
}
export class KaravanTour extends React.Component<Props, State> {
public state: State = {
showTour: this.props.showTour,
currentStep: 0,
steps: STEPS.get(this.props.tab) || []
}
setCurrentStep(step: number) {
if (step > this.state.currentStep) {
switch (this.props.tab) {
case "routes":
this.routeSteps(step);
}
setTimeout(() => { this.setState({ currentStep: step }); }, 0);
}
}
routeSteps(step: number) {
switch (step) {
case 2:
EventBus.sendTourEvent("routes", "openSelector", "kamelet");
break;
case 4:
const route = CamelDefinitionApi.createRouteDefinition({from: new FromDefinition({uri: "kamelet:mqtt-source"})});
const i = CamelDefinitionApiExt.addStepToIntegration(this.props.integration, route, '');
const clone = CamelUtil.cloneIntegration(i);
this.props.onSave?.call(this, clone, true);
EventBus.sendTourEvent("routes", "closeSelector");
break;
case 6:
const from = this.props.integration.spec.flows?.[0].from;
EventBus.sendTourEvent("routes", "selectElement", undefined, from);
break;
case 7:
const mqtt = this.props.integration.spec.flows?.[0].from;
mqtt.parameters.brokerUrl = "tcp://localhost:1883";
mqtt.parameters.topic = "topic1";
const i2 = CamelDefinitionApiExt.updateIntegrationRouteElement(this.props.integration, mqtt);
const clone2 = CamelUtil.cloneIntegration(i2);
this.props.onSave?.call(this, clone2, true);
break;
case 9:
EventBus.sendTourEvent("routes", "openSelector", "routing");
break;
case 11:
const filter = CamelDefinitionApi.createFilterDefinition({});
const from3 = this.props.integration.spec.flows?.[0].from;
const i3 = CamelDefinitionApiExt.addStepToIntegration(this.props.integration, filter, from3.uuid);
const clone3 = CamelUtil.cloneIntegration(i3);
this.props.onSave?.call(this, clone3, true);
EventBus.sendTourEvent("routes", "closeSelector", undefined, filter);
break;
case 12:
const filter0 = this.props.integration.spec.flows?.[0].from.steps[0];
EventBus.sendTourEvent("routes", "selectElement", undefined, filter0);
break;
case 13:
const filter1 = this.props.integration.spec.flows?.[0].from.steps[0];
filter1.expression = CamelDefinitionApi.createExpressionDefinition({simple: CamelDefinitionApi.createSimpleExpression({expression: "${header.approved} != 'true'"})});
const i4 = CamelDefinitionApiExt.updateIntegrationRouteElement(this.props.integration, filter1);
const clone4 = CamelUtil.cloneIntegration(i4);
this.props.onSave?.call(this, clone4, true);
break;
case 15:
EventBus.sendTourEvent("routes", "openSelector", "kamelet");
break;
case 17:
const kafka = CamelDefinitionApi.createToDefinition({uri: "kamelet:kafka-not-secured-sink"});
const filter2 = this.props.integration.spec.flows?.[0].from.steps[0];
const i5 = CamelDefinitionApiExt.addStepToIntegration(this.props.integration, kafka, filter2.uuid);
const clone5 = CamelUtil.cloneIntegration(i5);
this.props.onSave?.call(this, clone5, true);
EventBus.sendTourEvent("routes", "closeSelector", undefined, kafka);
EventBus.sendTourEvent("routes", "selectElement", undefined, kafka);
break;
case 19:
const kafka1 = this.props.integration.spec.flows?.[0].from.steps[0].steps[0];
kafka1.parameters.bootstrapServers = "localhost:9092"
kafka1.parameters.topic = "topic1"
const i6 = CamelDefinitionApiExt.updateIntegrationRouteElement(this.props.integration, kafka1);
const clone6 = CamelUtil.cloneIntegration(i6);
this.props.onSave?.call(this, clone6, true);
EventBus.sendTourEvent("routes", "selectElement", undefined, kafka1);
break;
case 21:
this.props.onSave?.call(this, this.props.integration, true);
this.close();
break;
}
}
close() {
this.props.onClose?.call(this);
}
render() {
return (
<Tour
scrollSmooth={true}
currentStep={this.state.currentStep}
setIsOpen={value => {}}
disabledActions={false}
setCurrentStep={value => this.setCurrentStep(value as number)}
setDisabledActions={value => {}}
setSteps={value => {}}
steps={this.state.steps}
isOpen={this.state.showTour}
badgeContent={b => `${b.currentStep + 1}/${b.totalSteps}`}
onClickHighlighted={e => e.stopPropagation()}
disableInteraction
// disableKeyboardNavigation
// disableDotsNavigation
// disableFocusLock
onClickClose={clickProps => this.close()}
prevButton={props => props.setIsOpen(false)}
>
</Tour>
)
}
}
export default KaravanTour;