blob: 4ed08500c3303c599df0a53e03ff085f2aa7136c [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 {
Badge,
Card, CardBody, CardFooter, CardHeader, Flex, FlexItem, Form, FormGroup, Gallery, Label, Modal, PageSection,
Tab, Tabs, TabTitleText,
Text, TextInput, ToggleGroup, ToggleGroupItem,
} from '@patternfly/react-core';
import '../karavan.css';
import {CamelUi} from "../utils/CamelUi";
import {DslMetaModel} from "../utils/DslMetaModel";
interface Props {
onDslSelect: (dsl: DslMetaModel, parentId: string, position?: number | undefined) => void,
onClose?: () => void,
parentId: string,
parentDsl?: string,
showSteps: boolean,
dark: boolean,
isOpen: boolean,
position?: number
tabIndex?: string | number
}
interface State {
tabIndex: string | number
filter: string;
selectedLabels: string []
}
export class DslSelector extends React.Component<Props, State> {
public state: State = {
tabIndex: this.props.tabIndex ? this.props.tabIndex : (this.props.parentDsl ? 'eip' : 'kamelet'),
filter: '',
selectedLabels: []
}
selectTab = (evt: React.MouseEvent<HTMLElement, MouseEvent>, eventKey: string | number) => {
this.setState({tabIndex: eventKey});
}
componentDidUpdate = (prevProps: Readonly<Props>, prevState: Readonly<State>, snapshot?: any) => {
if (prevProps.parentDsl !== this.props.parentDsl) {
this.setState({tabIndex: CamelUi.getSelectorModelTypes(this.props.parentDsl, this.props.showSteps)[0][0]});
}
}
selectDsl = (evt: React.MouseEvent, dsl: any) => {
evt.stopPropagation();
this.setState({filter: ""});
this.props.onDslSelect.call(this, dsl, this.props.parentId, this.props.position);
}
searchInput = () => {
return (
<Form isHorizontal className="search" autoComplete="off">
<FormGroup fieldId="search">
<TextInput className="text-field" type="text" id="search" name="search"
value={this.state.filter}
onChange={(_, value) => this.setState({filter: value})}/>
</FormGroup>
</Form>
)
}
getCard(dsl: DslMetaModel, index: number) {
const labels = dsl.labels !== undefined ? dsl.labels.split(",").filter(label => label !== 'eip') : [];
return (
<Card key={dsl.dsl + index} isCompact className="dsl-card"
onClick={event => this.selectDsl(event, dsl)}>
<CardHeader className="header-labels">
<Badge isRead className="support-level labels">{dsl.supportLevel}</Badge>
{['kamelet', 'component'].includes(dsl.navigation.toLowerCase()) &&
<Badge isRead className="version labels">{dsl.version}</Badge>
}
</CardHeader>
<CardHeader>
{CamelUi.getIconForDsl(dsl)}
<Text>{dsl.title}</Text>
</CardHeader>
<CardBody>
<Text>{dsl.description}</Text>
</CardBody>
<CardFooter className="footer-labels">
<div style={{display: "flex", flexDirection: "row", justifyContent: "start"}}>
{labels.map(label => <Badge key={label} isRead className="labels">{label}</Badge>)}
</div>
</CardFooter>
</Card>
)
}
close = () => {
this.setState({filter: ""});
this.props.onClose?.call(this);
}
selectLabel = (eipLabel: string) => {
if (!this.state.selectedLabels.includes(eipLabel)) {
this.setState((state) => {
state.selectedLabels.push(eipLabel);
return state
})
} else {
this.setState((state) => {
const index = state.selectedLabels.findIndex((label) => label === eipLabel);
state.selectedLabels.splice(index, 1);
return state;
})
}
}
render() {
const isEip = this.state.tabIndex === 'eip';
const {parentDsl, isOpen} = this.props;
const title = parentDsl === undefined ? "Select source" : "Select step";
const navigation: string = this.state.tabIndex ? this.state.tabIndex.toString() : "";
const elements = CamelUi.getSelectorModelsForParentFiltered(parentDsl, navigation, this.props.showSteps);
const eipLabels = [...new Set(elements.map(e => e.labels).join(",").split(",").filter(e => e !== 'eip'))];
const filteredElement = elements
.filter((dsl: DslMetaModel) => CamelUi.checkFilter(dsl, this.state.filter))
.filter((dsl: DslMetaModel) => {
if (!isEip || this.state.selectedLabels.length === 0) {
return true;
} else {
return dsl.labels.split(",").some(r => this.state.selectedLabels.includes(r));
}
});
return (
<Modal
aria-label={title}
width={'90%'}
className='dsl-modal'
isOpen={this.props.isOpen}
onClose={() => this.close()}
header={
<Flex direction={{default: "column"}}>
<FlexItem>
<h3>{title}</h3>
{this.searchInput()}
</FlexItem>
<FlexItem>
<Tabs style={{overflow: 'hidden'}} activeKey={this.state.tabIndex}
onSelect={this.selectTab}>
{parentDsl !== undefined &&
<Tab eventKey={"eip"} key={"tab-eip"}
title={<TabTitleText>Integration Patterns</TabTitleText>}>
</Tab>
}
<Tab eventKey={'kamelet'} key={"tab-kamelet"}
title={<TabTitleText>Kamelets</TabTitleText>}>
</Tab>
<Tab eventKey={'component'} key={'tab-component'}
title={<TabTitleText>Components</TabTitleText>}>
</Tab>
</Tabs>
</FlexItem>
</Flex>
}
actions={{}}>
<PageSection padding={{default:"noPadding"}} variant={this.props.dark ? "darker" : "light"}>
{isEip && <ToggleGroup aria-label="Labels" isCompact>
{eipLabels.map(eipLabel => <ToggleGroupItem
key={eipLabel}
text={eipLabel}
buttonId={eipLabel}
isSelected={this.state.selectedLabels.includes(eipLabel)}
onChange={selected => this.selectLabel(eipLabel)}
/>)}
</ToggleGroup>}
<Gallery key={"gallery-" + navigation} hasGutter className="dsl-gallery">
{isOpen && filteredElement.map((dsl: DslMetaModel, index: number) => this.getCard(dsl, index))}
</Gallery>
</PageSection>
</Modal>
)
}
}