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 d14e09e Saas feature38 (#435)
d14e09e is described below
commit d14e09e8ffd6f9cf676ba52bb226180b6212f173
Author: Marat Gubaidullin <[email protected]>
AuthorDate: Thu Jul 28 21:45:00 2022 -0400
Saas feature38 (#435)
* Rollback errorrously deleted Project Classes
* Cleanup
---
karavan-app/src/main/webapp/package-lock.json | 6 +-
karavan-app/src/main/webapp/package.json | 2 +-
karavan-designer/src/App.tsx | 16 --
karavan-designer/src/builder/BuilderPage.tsx | 298 ---------------------
karavan-designer/src/builder/FileSelector.tsx | 97 -------
karavan-designer/src/builder/ProfileSelector.tsx | 148 ----------
karavan-designer/src/builder/PropertiesTable.tsx | 148 ----------
karavan-vscode/package.json | 2 +-
karavan-vscode/webview/builder/BuilderPage.tsx | 298 ---------------------
karavan-vscode/webview/builder/FileSelector.tsx | 97 -------
karavan-vscode/webview/builder/ProfileSelector.tsx | 148 ----------
karavan-vscode/webview/builder/PropertiesTable.tsx | 148 ----------
12 files changed, 5 insertions(+), 1403 deletions(-)
diff --git a/karavan-app/src/main/webapp/package-lock.json
b/karavan-app/src/main/webapp/package-lock.json
index f397c3c..ed941bd 100644
--- a/karavan-app/src/main/webapp/package-lock.json
+++ b/karavan-app/src/main/webapp/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "karavan",
- "version": "0.0.16",
+ "version": "3.18.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "karavan",
- "version": "0.0.16",
+ "version": "3.18.0",
"dependencies": {
"@monaco-editor/react": "4.3.1",
"@patternfly/patternfly": "4.194.4",
@@ -40,7 +40,7 @@
}
},
"../../../../karavan-core": {
- "version": "0.0.16",
+ "version": "3.18.0",
"license": "Apache-2.0",
"dependencies": {
"@types/js-yaml": "^4.0.5",
diff --git a/karavan-app/src/main/webapp/package.json
b/karavan-app/src/main/webapp/package.json
index e066815..1e64f4a 100644
--- a/karavan-app/src/main/webapp/package.json
+++ b/karavan-app/src/main/webapp/package.json
@@ -3,7 +3,7 @@
"version": "3.18.0",
"private": true,
"scripts": {
- "copy-designer": "cp -r ../../../../karavan-designer/src/designer src &&
cp -r ../../../../karavan-designer/src/kamelets src && cp -r
../../../../karavan-designer/src/components src && cp -r
../../../../karavan-designer/src/eip src && cp -r
../../../../karavan-designer/src/builder src",
+ "copy-designer": "cp -r ../../../../karavan-designer/src/designer src &&
cp -r ../../../../karavan-designer/src/kamelets src && cp -r
../../../../karavan-designer/src/components src && cp -r
../../../../karavan-designer/src/eip src",
"start": "npm run copy-designer && react-scripts start",
"build": "npm run copy-designer && react-scripts build",
"prod": "npm run copy-designer && react-scripts build --dest && rsync -a
build/* ../resources/META-INF/resources"
diff --git a/karavan-designer/src/App.tsx b/karavan-designer/src/App.tsx
index af4a5a8..35930b4 100644
--- a/karavan-designer/src/App.tsx
+++ b/karavan-designer/src/App.tsx
@@ -24,8 +24,6 @@ import {KaravanDesigner} from "./designer/KaravanDesigner";
import {KameletsPage} from "./kamelets/KameletsPage";
import {ComponentsPage} from "./components/ComponentsPage";
import {EipPage} from "./eip/EipPage";
-import {BuilderPage} from "./builder/BuilderPage";
-import {ProjectModel, StepStatus} from "karavan-core/lib/model/ProjectModel";
interface Props {
page: "designer" | "kamelets" | "components" | "eip" | "builder";
@@ -127,14 +125,6 @@ class App extends React.Component<Props, State> {
}
public render() {
- const project = ProjectModel.createNew({});
- // project.properties.set("message", "Hello Placeholder!")
- // project.properties.set("camel.jbang.classpathFiles",
"application.properties")
- // project.properties.set("camel.main.routesIncludePattern",
"file:demo.yaml")
- // project.properties.set("camel.component.properties.location",
"file:application.properties")
- project.status.active = true;
- project.status.export = new StepStatus({status:"progress"});
- project.status.package = new StepStatus({status:"progress"});
return (
<Page className="karavan">
{this.props.page === "designer" && <KaravanDesigner
key={this.state.key} filename={this.state.name} yaml={this.state.yaml}
@@ -144,12 +134,6 @@ class App extends React.Component<Props, State> {
{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')} />}
- {this.props.page === "builder" && <BuilderPage
dark={document.body.className.includes('vscode-dark')} project={project}
-
onChange={project => {
- //
console.log("routesIncludePattern", project.routesIncludePattern);
- //
console.log("classpathFiles", project.classpathFiles);
- }}
-
files={'demo.yaml,CustomProcessor.java,script.groovy,docker-compose.yaml,README.MD'}/>}
</Page>
);
}
diff --git a/karavan-designer/src/builder/BuilderPage.tsx
b/karavan-designer/src/builder/BuilderPage.tsx
deleted file mode 100644
index 43c27d5..0000000
--- a/karavan-designer/src/builder/BuilderPage.tsx
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * 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,
- Button,
- Card,
- CardBody,
- CardHeader,
- CardHeaderMain,
- CardTitle,
- Flex,
- FlexItem,
- Form,
- FormGroup,
- InputGroup,
- PageSection,
- PageSectionVariants,
- Popover,
- PopoverPosition,
- ProgressStep,
- ProgressStepper,
- Spinner,
- Text,
- TextContent,
- TextInput,
- Toolbar,
- ToolbarContent,
- ToolbarItem,
-} from '@patternfly/react-core';
-import '../designer/karavan.css';
-import HelpIcon from "@patternfly/react-icons/dist/js/icons/help-icon";
-import InProgressIcon from
'@patternfly/react-icons/dist/esm/icons/in-progress-icon';
-import AutomationIcon from
'@patternfly/react-icons/dist/esm/icons/bundle-icon';
-import PendingIcon from '@patternfly/react-icons/dist/esm/icons/pending-icon';
-import ExclamationCircleIcon from
'@patternfly/react-icons/dist/esm/icons/exclamation-circle-icon';
-import CheckCircleIcon from
'@patternfly/react-icons/dist/esm/icons/check-circle-icon';
-import ProjectIcon from '@patternfly/react-icons/dist/esm/icons/cubes-icon';
-import ClipboardIcon from
'@patternfly/react-icons/dist/esm/icons/clipboard-icon';
-import RunIcon from '@patternfly/react-icons/dist/esm/icons/play-circle-icon';
-import {ProjectModel, StepStatus} from "karavan-core/lib/model/ProjectModel";
-import {PropertiesTable} from "./PropertiesTable";
-
-interface Props {
- project: ProjectModel,
- dark: boolean
- files: string
- onChange?: (project: ProjectModel) => void
- onAction?: (action: "start" | "stop" | "undeploy" | "run", project:
ProjectModel) => void
-}
-
-interface State {
- project: ProjectModel,
- key?: string,
- isOpen?: boolean
-}
-
-export class BuilderPage extends React.Component<Props, State> {
-
- public state: State = {
- project: this.props.project,
- };
- interval: any;
-
- componentDidUpdate = (prevProps: Readonly<Props>, prevState:
Readonly<State>, snapshot?: any) => {
- const project = this.state.project;
- if (project) this.props.onChange?.call(this, project);
- }
-
- componentDidMount() {
- this.interval = setInterval(() => this.setState(state => ({key:
Math.random().toString()})), 1000);
- }
-
- componentWillUnmount() {
- clearInterval(this.interval);
- }
-
- getHelp(text: string) {
- return <Popover
- aria-label={text}
- position={PopoverPosition.left}
- bodyContent={text}>
- <Button variant="plain" onClick={e => {
- }}>
- <HelpIcon/>
- </Button>
- </Popover>
- }
-
- getField(name: string, label: string, type: 'text' | 'date' |
'datetime-local' | 'email' | 'month' | 'number' | 'password' | 'search' | 'tel'
| 'time' | 'url',
- value: any, help: string, onChange: (val: any) => void,
isRequired: boolean = false, enabled: boolean = true) {
- return <FormGroup label={label} fieldId={name} isRequired={isRequired}>
- <InputGroup>
- <TextInput isRequired={isRequired} isDisabled={!enabled}
className="text-field" type={type} id={name} name={name} value={value}
- onChange={val => onChange?.call(this, val)}/>
- {this.getHelp(help)}
- </InputGroup>
- </FormGroup>
- }
-
- getCardHeader(title: string, icon: any) {
- return <CardHeader>
- <CardHeaderMain>
- <CardTitle className="card-header">
- {icon}{title}
- </CardTitle>
- </CardHeaderMain>
- </CardHeader>
- }
-
- getProjectForm() {
- return (
- <Card className="builder-card" isCompact style={{width: "100%"}}>
- {this.getCardHeader("Artifact", <ProjectIcon/>)}
- <CardBody>
- <Form isHorizontal>
- {/*{this.getField("name", "Name", "text",
this.state.profile.project.name, "Project name",*/}
- {/* val => this.setState(state =>
{state.profile.project.name= val; return state}), true)}*/}
- {/*{this.getField("version", "Version", "text",
this.state.profile.project.version, "Project version",*/}
- {/* val => this.setState(state =>
{state.profile.project.version= val; return state}), true)}*/}
- </Form>
- </CardBody>
- </Card>
- )
- }
-
- getProgressIcon(status?: 'pending' | 'progress' | 'done' | 'error') {
- switch (status) {
- case "pending":
- return <PendingIcon/>;
- case "progress":
- return <Spinner isSVG size="md"/>
- case "done":
- return <CheckCircleIcon/>;
- case "error":
- return <ExclamationCircleIcon/>;
- default:
- return undefined;
- }
- }
-
- getDescription(stepStatus?: StepStatus) {
- const now = Date.now();
- let time = 0;
- if (stepStatus?.status === 'progress') {
- time = stepStatus?.startTime ? (now - stepStatus.startTime) / 1000
: 0;
- } else if (stepStatus?.status === 'done' && stepStatus?.endTime) {
- time = (stepStatus?.endTime - stepStatus.startTime) / 1000
- }
- return time === 0 ? "" : Math.round(time) + "s";
- }
-
- getProgress() {
- const {status} = this.state.project;
- return (
- <ProgressStepper isCenterAligned style={{visibility: "visible"}}>
- <ProgressStep variant="pending" id="export" titleId="export"
aria-label="export"
- description={this.getDescription(status.export)}
-
icon={this.getProgressIcon(status.export?.status)}>Export
- </ProgressStep>
- <ProgressStep variant="pending" isCurrent id="package"
titleId="package" aria-label="package"
- description={this.getDescription(status.package)}
-
icon={this.getProgressIcon(status.package?.status)}>Package
- </ProgressStep>
- </ProgressStepper>
- )
- }
-
- getHeader() {
- return (
- <PageSection className="tools-section" variant={this.props.dark ?
PageSectionVariants.darker : PageSectionVariants.light}>
- <Flex className="tools" direction={{default: 'row'}}
justifyContent={{default: 'justifyContentSpaceBetween'}} spaceItems={{default:
'spaceItemsLg'}}>
- <FlexItem>
- <TextContent className="header">
- <Text component="h2">Build Runner</Text>
- <Badge isRead className="labels">Powered by Camel
JBang & Maven</Badge>
- </TextContent>
- </FlexItem>
- <FlexItem>
- <Toolbar id="toolbar-group-types">
- <ToolbarContent>
- <ToolbarItem>
- {/*<ProfileSelector
profiles={profiles.map(p => p.name)}*/}
- {/*
profile={profile.name}*/}
- {/* onDelete={profile =>
{*/}
- {/*
this.setState(state => {*/}
- {/*
state.profiles.splice(state.profiles.findIndex(p => p.name === profile), 1);*/}
- {/* return {*/}
- {/* profiles:
state.profiles,*/}
- {/* profile:
this.props.profiles.at(0) || Profile.createNew("application"),*/}
- {/* tab:
state.tab*/}
- {/* };*/}
- {/* })*/}
- {/* }}*/}
- {/* onChange={profileName
=> {*/}
- {/* const prof =
profiles.find(p => p.name === profileName);*/}
- {/* if (prof) {*/}
- {/*
this.setState({profile: prof, key: Math.random().toString()});*/}
- {/* } else {*/}
- {/*
this.setState(state => {*/}
- {/* const
newProfile = Profile.createNew(profileName);*/}
- {/*
newProfile.project = new ProjectModel(this.state.profile.project);*/}
- {/*
state.profiles.push(newProfile);*/}
- {/* return
{profiles: state.profiles, profile: newProfile, tab: state.tab};*/}
- {/* })*/}
- {/* }*/}
- {/* }}/>*/}
- </ToolbarItem>
- </ToolbarContent>
- </Toolbar>
- </FlexItem>
- </Flex>
- </PageSection>
- )
- }
-
- onButtonClick(action: "start" | "stop" | "undeploy" | "run") {
- this.props.onAction?.call(this, action, this.state.project);
- }
-
- getFooter() {
- const active = false;
- const label = active ? "Stop" : "Package";
- const icon = active ? <InProgressIcon/> : <AutomationIcon/>;
- return <div key={this.state.key} className="footer">
- <div className="progress">
- {active && this.getProgress()}
- </div>
- <div className="buttons">
- <Toolbar id="toolbar-items">
- <ToolbarContent>
- {!active && <ToolbarItem>
- <Button variant="secondary" isSmall onClick={event
=> this.onButtonClick("undeploy")}>Undeploy</Button>
- </ToolbarItem>}
- <ToolbarItem>
- <Button variant="primary" isSmall icon={icon}
onClick={event => this.onButtonClick(active ? "stop" :
"start")}>{label}</Button>
- </ToolbarItem>
- <ToolbarItem>
- <Button variant="primary" isSmall
icon={<RunIcon/>} onClick={event => this.onButtonClick("run")}>Run</Button>
- </ToolbarItem>
- </ToolbarContent>
- </Toolbar>
- </div>
- </div>
- }
-
- getPropertiesForm() {
- return (
- <div className="center">
- <div className="center-column">
- <Card className="builder-card" isCompact style={{width:
"100%"}}>
- {this.getCardHeader("Properties", <ClipboardIcon/>)}
- <CardBody>
- <PropertiesTable
properties={this.state.project.properties}
- onChange={properties =>
this.setState(state => {
- state.project.properties =
properties;
- return state
- })}/>
- </CardBody>
- </Card>
- </div>
- </div>
- )
- }
-
- render() {
- return (
- <PageSection className="project-builder" variant={this.props.dark
? PageSectionVariants.darker : PageSectionVariants.light}
- padding={{default: 'noPadding'}}>
- <div style={{height: "100%", display: "flex", flexDirection:
"column"}}>
- <div>
- {this.getHeader()}
- </div>
- <div style={{overflow: "auto", flexGrow: 1}}>
- {this.getPropertiesForm()}
- </div>
- <div>
- {this.getFooter()}
- </div>
- </div>
- </PageSection>
- )
- }
-}
\ No newline at end of file
diff --git a/karavan-designer/src/builder/FileSelector.tsx
b/karavan-designer/src/builder/FileSelector.tsx
deleted file mode 100644
index ead44b9..0000000
--- a/karavan-designer/src/builder/FileSelector.tsx
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 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 {
- Button,
- FormGroup,
- Checkbox, PopoverPosition, Popover, InputGroup
-} from '@patternfly/react-core';
-import '../designer/karavan.css';
-import HelpIcon from "@patternfly/react-icons/dist/js/icons/help-icon";
-
-interface Props {
- label: string
- help: string
- files: string
- filesSelected: string
- onChange: (files: string) => void
- source: boolean
-}
-
-interface State {
- selected: []
-}
-
-export class FileSelector extends React.Component<Props, State> {
-
- public state: State = {
- selected: []
- };
-
- isChecked(file: string) {
- const finalFile = this.props.source ? "file:" + file : file;
- const s = this.props.filesSelected ?
this.props.filesSelected.split(",").map(value => value.trim()) : [];
- return s.includes(finalFile);
- }
-
- onChange(file: string, checked: boolean) {
- const finalFile = this.props.source ? "file:" + file : file;
- const s = this.props.filesSelected.split(",").map(f =>
f.trim()).filter(f => f.length > 0);
- const already = s.includes(finalFile);
- if (checked && !already) {
- s.push(finalFile);
- this.props.onChange?.call(this, s.join(","));
- } else if (!checked) {
- const result = s.filter(f => f !== finalFile);
- this.props.onChange?.call(this, result.join(","));
- }
- }
-
- getFiles(): string[] {
- const allFiles = (this.props.files ? this.props.files.split(",") : []);
- if (this.props.source){
- const extensions = ['yaml', 'yml', 'java', 'js', 'kt', 'groovy',
'xml'];
- return allFiles.filter(file => {
- const extension = file.split(".").pop() || '';
- return extensions.includes(extension);
- }).map(file => file.replace("file:", ""))
- }
- return allFiles;
- }
-
- render() {
- const files = this.getFiles();
- return (
- <FormGroup label={this.props.label} fieldId="files">
- <InputGroup>
- <div style={{width:"100%"}}>
- {files.map(file => {
- const key = file + this.props.source;
- return <Checkbox key={key} label={file}
isChecked={this.isChecked(file)} onChange={checked => this.onChange(file,
checked)} id={key} name={key}/>
- })}
- </div>
- <Popover aria-label="files" position={PopoverPosition.left}
- bodyContent={this.props.help}>
- <Button variant="plain" onClick={e => {}}>
- <HelpIcon/>
- </Button>
- </Popover>
- </InputGroup>
- </FormGroup>
- )
- }
-};
\ No newline at end of file
diff --git a/karavan-designer/src/builder/ProfileSelector.tsx
b/karavan-designer/src/builder/ProfileSelector.tsx
deleted file mode 100644
index ef140a4..0000000
--- a/karavan-designer/src/builder/ProfileSelector.tsx
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * 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 {
- Button,
- Flex,
- FlexItem, Form, FormGroup, InputGroup, Modal, ModalVariant, Tab, Tabs,
TextInput, ToggleGroup, ToggleGroupItem, Tooltip, TooltipPosition
-} from '@patternfly/react-core';
-import '../designer/karavan.css';
-import AddIcon from "@patternfly/react-icons/dist/js/icons/plus-circle-icon";
-import DeleteIcon from "@patternfly/react-icons/dist/js/icons/times-icon";
-
-interface Props {
- profiles: string[]
- profile: string
- onChange?: (profile: string) => void
- onDelete?: (profile: string) => void
-}
-
-interface State {
- isSelectorOpen?: boolean
- showDeleteConfirmation?: boolean
- showCreate?: boolean
- newProfile?: string
-}
-
-export class ProfileSelector extends React.Component<Props, State> {
-
- public state: State = {
- isSelectorOpen: false,
- };
-
- onSelect(profile?: string){
- if (profile) this.props.onChange?.call(this, profile);
- this.setState({isSelectorOpen: false});
- }
-
- deleteProfile(){
- if (this.props.profile) this.props.onDelete?.call(this,
this.props.profile);
- this.setState({showDeleteConfirmation: false});
- }
-
- saveAndCloseCreateModal = () => {
- if (this.state.newProfile && this.state.newProfile.length > 0)
this.props.onChange?.call(this, this.state.newProfile);
- this.closeModal();
- }
-
- closeModal = () => {
- this.setState({showCreate: false, newProfile: undefined});
- }
-
- onKeyDown = (event: React.KeyboardEvent<HTMLDivElement>): void => {
- if (event.key === 'Enter' && this.state.newProfile !== undefined) {
- this.saveAndCloseCreateModal();
- }
- }
-
- createModalForm() {
- return (
- <Modal
- title="Create new profile"
- className='profile-modal'
- variant={ModalVariant.small}
- isOpen={this.state.showCreate}
- onClose={this.closeModal}
- onKeyDown={this.onKeyDown}
- actions={[
- <Button key="confirm" variant="primary"
onClick={this.saveAndCloseCreateModal}>Save</Button>,
- <Button key="cancel" variant="secondary"
onClick={this.closeModal}>Cancel</Button>
- ]}
- >
- <Form isHorizontal>
- <FormGroup label="Profile" fieldId="profile" isRequired>
- <TextInput className="text-field" type="text"
id="profile" name="profile"
- value={this.state.newProfile}
- onChange={e => this.setState({newProfile:
e})}/>
- </FormGroup>
- </Form>
- </Modal>
- )
- }
-
- getDeleteConfirmation() {
- return (<Modal
- className="modal-delete"
- title="Confirmation"
- isOpen={this.state.showDeleteConfirmation}
- onClose={() => this.setState({showDeleteConfirmation: false})}
- actions={[
- <Button key="confirm" variant="primary" onClick={e =>
this.deleteProfile()}>Delete</Button>,
- <Button key="cancel" variant="link"
- onClick={e => this.setState({showDeleteConfirmation:
false})}>Cancel</Button>
- ]}
- onEscapePress={e => this.setState({showDeleteConfirmation:
false})}>
- <div>Delete profile {this.props.profile}</div>
- </Modal>)
- }
-
- render() {
- const profile = this.props.profile;
- const tabs = this.props.profiles.map(p =>
- <ToggleGroupItem key={p} text={p} buttonId={p} isSelected={profile
=== p}
- onChange={selected => selected ? this.onSelect(p)
: {}}/>
- );
- return (
- <Flex>
- <FlexItem>
- <p className="profile-caption">Profile:</p>
- </FlexItem>
- <FlexItem>
- <InputGroup>
- <Tooltip
- aria-label="Add profile"
- position={TooltipPosition.bottom}
- content="Create new profile">
- <Button variant={"plain"} icon={<AddIcon/>}
onClick={event => this.setState({showCreate: true})}/>
- </Tooltip>
- <ToggleGroup aria-label="Select target">
- {tabs}
- </ToggleGroup>
- {this.props.profiles.length > 1 && <Tooltip
- aria-label="Delete profile"
- position={TooltipPosition.bottomEnd}
- content="Delete selected profile">
- <Button variant={"plain"} icon={<DeleteIcon/>}
onClick={event => this.setState({showDeleteConfirmation: true})}/>
- </Tooltip>}
- </InputGroup>
- </FlexItem>
- {this.createModalForm()}
- {this.getDeleteConfirmation()}
- </Flex>
- )
- }
-}
\ No newline at end of file
diff --git a/karavan-designer/src/builder/PropertiesTable.tsx
b/karavan-designer/src/builder/PropertiesTable.tsx
deleted file mode 100644
index e3f5958..0000000
--- a/karavan-designer/src/builder/PropertiesTable.tsx
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * 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 {
- Button, Flex, FlexItem,
- Modal,
- PageSection,
- Panel,
- PanelMain,
- PanelMainBody,
- TextInput
-} from '@patternfly/react-core';
-import '../designer/karavan.css';
-import {TableComposable, Tbody, Td, Th, Thead, Tr} from
"@patternfly/react-table";
-import DeleteIcon from "@patternfly/react-icons/dist/js/icons/times-icon";
-import PlusIcon from "@patternfly/react-icons/dist/esm/icons/plus-icon";
-import {ProjectProperty} from "karavan-core/lib/model/ProjectModel";
-
-interface Props {
- properties: ProjectProperty[]
- onChange?: (properties: ProjectProperty[]) => void
-}
-
-interface State {
- properties: ProjectProperty[]
- showDeleteConfirmation: boolean
- deleteId?: string
-}
-
-export class PropertiesTable extends React.Component<Props, State> {
-
- public state: State = {
- properties: this.props.properties,
- showDeleteConfirmation: false,
- };
-
- sendUpdate = (props: ProjectProperty[]) => {
- this.props.onChange?.call(this, props);
- }
-
- changeProperty(p: ProjectProperty, field: "key" | "value", val?: string) {
- const key: string = field === 'key' && val !== undefined ? val : p.key;
- const value: any = field === 'value' ? val : p.value;
- const property: ProjectProperty = {id: p.id, key: key, value: value};
- const props = this.state.properties.map(prop => prop.id ===
property.id ? property : prop);
- this.setState({properties: props});
- this.sendUpdate(props);
- }
-
- startDelete(id: string) {
- this.setState({showDeleteConfirmation: true, deleteId: id});
- }
-
- confirmDelete() {
- const props = this.state.properties.filter(p => p.id !==
this.state.deleteId);
- this.setState({properties: props, showDeleteConfirmation: false,
deleteId: undefined});
- this.sendUpdate(props);
- }
-
- addProperty() {
- const props = [...this.state.properties];
- props.push(ProjectProperty.createNew("", ""))
- this.setState({properties: props, showDeleteConfirmation: false,
deleteId: undefined});
- this.sendUpdate(props);
- }
-
- getDeleteConfirmation() {
- return (<Modal
- className="modal-delete"
- title="Confirmation"
- isOpen={this.state.showDeleteConfirmation}
- onClose={() => this.setState({showDeleteConfirmation: false})}
- actions={[
- <Button key="confirm" variant="primary" onClick={e =>
this.confirmDelete()}>Delete</Button>,
- <Button key="cancel" variant="link"
- onClick={e => this.setState({showDeleteConfirmation:
false})}>Cancel</Button>
- ]}
- onEscapePress={e => this.setState({showDeleteConfirmation:
false})}>
- <div>Delete property?</div>
- </Modal>)
- }
-
- getTextInputField(property: ProjectProperty, field: "key" | "value",
readOnly: boolean) {
- return (<TextInput isDisabled={readOnly} isRequired={true}
className="text-field" type={"text"} id={"key"} name={"key"}
- value={field === "key" ? property.key :
property.value}
- onChange={val => this.changeProperty(property,
field, val)}/>)
- }
-
- render() {
- const properties = this.state.properties;
- return (
- <PageSection padding={{default: "noPadding"}}>
- {properties.length > 0 &&
- <TableComposable aria-label="Property table"
variant='compact' borders={false}
- className="project-properties">
- <Thead>
- <Tr>
- <Th key='name'>Name</Th>
- <Th key='value'>Value</Th>
- <Td></Td>
- </Tr>
- </Thead>
- <Tbody>
- {properties.map((property, idx: number) => {
- const readOnly =
property.key.startsWith("camel.jbang");
- return (
- <Tr key={property.id}>
- <Td noPadding width={20}
dataLabel="key">{this.getTextInputField(property, "key", readOnly)}</Td>
- <Td noPadding width={10}
dataLabel="value">{this.getTextInputField(property, "value", readOnly)}</Td>
- <Td noPadding isActionCell
dataLabel="delete">
- {!readOnly && <Button
variant={"plain"} icon={<DeleteIcon/>} className={"delete-button"}
-
onClick={event => this.startDelete(property.id)}/>}
- </Td>
- </Tr>
- )})}
- </Tbody>
- </TableComposable>}
- <Panel>
- <PanelMain>
- <PanelMainBody>
- <Flex direction={{default:"row"}} >
- <FlexItem align={{ default: 'alignRight' }}>
- <Button isInline variant={"primary"}
icon={<PlusIcon/>}
- className={"add-button"}
- onClick={event =>
this.addProperty()}>Add property</Button>
- </FlexItem>
- </Flex>
- </PanelMainBody>
- </PanelMain>
- </Panel>
- </PageSection>
- )
- }
-}
\ No newline at end of file
diff --git a/karavan-vscode/package.json b/karavan-vscode/package.json
index 1cc46e5..135ec8e 100644
--- a/karavan-vscode/package.json
+++ b/karavan-vscode/package.json
@@ -381,7 +381,7 @@
]
},
"scripts": {
- "copy-designer": "cp -r ../karavan-designer/src/designer webview && cp -r
../karavan-designer/src/kamelets webview && cp -r
../karavan-designer/src/components webview && cp -r ../karavan-designer/src/eip
webview && cp -r ../karavan-designer/src/builder webview",
+ "copy-designer": "cp -r ../karavan-designer/src/designer webview && cp -r
../karavan-designer/src/kamelets webview && cp -r
../karavan-designer/src/components webview && cp -r ../karavan-designer/src/eip
webview",
"vscode:prepublish": "npm run copy-designer && npm run package",
"compile": "npm run copy-designer && cross-env NODE_ENV=development
webpack --progress",
"watch": "npm run copy-designer && cross-env NODE_ENV=development webpack
--progress --watch",
diff --git a/karavan-vscode/webview/builder/BuilderPage.tsx
b/karavan-vscode/webview/builder/BuilderPage.tsx
deleted file mode 100644
index 43c27d5..0000000
--- a/karavan-vscode/webview/builder/BuilderPage.tsx
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * 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,
- Button,
- Card,
- CardBody,
- CardHeader,
- CardHeaderMain,
- CardTitle,
- Flex,
- FlexItem,
- Form,
- FormGroup,
- InputGroup,
- PageSection,
- PageSectionVariants,
- Popover,
- PopoverPosition,
- ProgressStep,
- ProgressStepper,
- Spinner,
- Text,
- TextContent,
- TextInput,
- Toolbar,
- ToolbarContent,
- ToolbarItem,
-} from '@patternfly/react-core';
-import '../designer/karavan.css';
-import HelpIcon from "@patternfly/react-icons/dist/js/icons/help-icon";
-import InProgressIcon from
'@patternfly/react-icons/dist/esm/icons/in-progress-icon';
-import AutomationIcon from
'@patternfly/react-icons/dist/esm/icons/bundle-icon';
-import PendingIcon from '@patternfly/react-icons/dist/esm/icons/pending-icon';
-import ExclamationCircleIcon from
'@patternfly/react-icons/dist/esm/icons/exclamation-circle-icon';
-import CheckCircleIcon from
'@patternfly/react-icons/dist/esm/icons/check-circle-icon';
-import ProjectIcon from '@patternfly/react-icons/dist/esm/icons/cubes-icon';
-import ClipboardIcon from
'@patternfly/react-icons/dist/esm/icons/clipboard-icon';
-import RunIcon from '@patternfly/react-icons/dist/esm/icons/play-circle-icon';
-import {ProjectModel, StepStatus} from "karavan-core/lib/model/ProjectModel";
-import {PropertiesTable} from "./PropertiesTable";
-
-interface Props {
- project: ProjectModel,
- dark: boolean
- files: string
- onChange?: (project: ProjectModel) => void
- onAction?: (action: "start" | "stop" | "undeploy" | "run", project:
ProjectModel) => void
-}
-
-interface State {
- project: ProjectModel,
- key?: string,
- isOpen?: boolean
-}
-
-export class BuilderPage extends React.Component<Props, State> {
-
- public state: State = {
- project: this.props.project,
- };
- interval: any;
-
- componentDidUpdate = (prevProps: Readonly<Props>, prevState:
Readonly<State>, snapshot?: any) => {
- const project = this.state.project;
- if (project) this.props.onChange?.call(this, project);
- }
-
- componentDidMount() {
- this.interval = setInterval(() => this.setState(state => ({key:
Math.random().toString()})), 1000);
- }
-
- componentWillUnmount() {
- clearInterval(this.interval);
- }
-
- getHelp(text: string) {
- return <Popover
- aria-label={text}
- position={PopoverPosition.left}
- bodyContent={text}>
- <Button variant="plain" onClick={e => {
- }}>
- <HelpIcon/>
- </Button>
- </Popover>
- }
-
- getField(name: string, label: string, type: 'text' | 'date' |
'datetime-local' | 'email' | 'month' | 'number' | 'password' | 'search' | 'tel'
| 'time' | 'url',
- value: any, help: string, onChange: (val: any) => void,
isRequired: boolean = false, enabled: boolean = true) {
- return <FormGroup label={label} fieldId={name} isRequired={isRequired}>
- <InputGroup>
- <TextInput isRequired={isRequired} isDisabled={!enabled}
className="text-field" type={type} id={name} name={name} value={value}
- onChange={val => onChange?.call(this, val)}/>
- {this.getHelp(help)}
- </InputGroup>
- </FormGroup>
- }
-
- getCardHeader(title: string, icon: any) {
- return <CardHeader>
- <CardHeaderMain>
- <CardTitle className="card-header">
- {icon}{title}
- </CardTitle>
- </CardHeaderMain>
- </CardHeader>
- }
-
- getProjectForm() {
- return (
- <Card className="builder-card" isCompact style={{width: "100%"}}>
- {this.getCardHeader("Artifact", <ProjectIcon/>)}
- <CardBody>
- <Form isHorizontal>
- {/*{this.getField("name", "Name", "text",
this.state.profile.project.name, "Project name",*/}
- {/* val => this.setState(state =>
{state.profile.project.name= val; return state}), true)}*/}
- {/*{this.getField("version", "Version", "text",
this.state.profile.project.version, "Project version",*/}
- {/* val => this.setState(state =>
{state.profile.project.version= val; return state}), true)}*/}
- </Form>
- </CardBody>
- </Card>
- )
- }
-
- getProgressIcon(status?: 'pending' | 'progress' | 'done' | 'error') {
- switch (status) {
- case "pending":
- return <PendingIcon/>;
- case "progress":
- return <Spinner isSVG size="md"/>
- case "done":
- return <CheckCircleIcon/>;
- case "error":
- return <ExclamationCircleIcon/>;
- default:
- return undefined;
- }
- }
-
- getDescription(stepStatus?: StepStatus) {
- const now = Date.now();
- let time = 0;
- if (stepStatus?.status === 'progress') {
- time = stepStatus?.startTime ? (now - stepStatus.startTime) / 1000
: 0;
- } else if (stepStatus?.status === 'done' && stepStatus?.endTime) {
- time = (stepStatus?.endTime - stepStatus.startTime) / 1000
- }
- return time === 0 ? "" : Math.round(time) + "s";
- }
-
- getProgress() {
- const {status} = this.state.project;
- return (
- <ProgressStepper isCenterAligned style={{visibility: "visible"}}>
- <ProgressStep variant="pending" id="export" titleId="export"
aria-label="export"
- description={this.getDescription(status.export)}
-
icon={this.getProgressIcon(status.export?.status)}>Export
- </ProgressStep>
- <ProgressStep variant="pending" isCurrent id="package"
titleId="package" aria-label="package"
- description={this.getDescription(status.package)}
-
icon={this.getProgressIcon(status.package?.status)}>Package
- </ProgressStep>
- </ProgressStepper>
- )
- }
-
- getHeader() {
- return (
- <PageSection className="tools-section" variant={this.props.dark ?
PageSectionVariants.darker : PageSectionVariants.light}>
- <Flex className="tools" direction={{default: 'row'}}
justifyContent={{default: 'justifyContentSpaceBetween'}} spaceItems={{default:
'spaceItemsLg'}}>
- <FlexItem>
- <TextContent className="header">
- <Text component="h2">Build Runner</Text>
- <Badge isRead className="labels">Powered by Camel
JBang & Maven</Badge>
- </TextContent>
- </FlexItem>
- <FlexItem>
- <Toolbar id="toolbar-group-types">
- <ToolbarContent>
- <ToolbarItem>
- {/*<ProfileSelector
profiles={profiles.map(p => p.name)}*/}
- {/*
profile={profile.name}*/}
- {/* onDelete={profile =>
{*/}
- {/*
this.setState(state => {*/}
- {/*
state.profiles.splice(state.profiles.findIndex(p => p.name === profile), 1);*/}
- {/* return {*/}
- {/* profiles:
state.profiles,*/}
- {/* profile:
this.props.profiles.at(0) || Profile.createNew("application"),*/}
- {/* tab:
state.tab*/}
- {/* };*/}
- {/* })*/}
- {/* }}*/}
- {/* onChange={profileName
=> {*/}
- {/* const prof =
profiles.find(p => p.name === profileName);*/}
- {/* if (prof) {*/}
- {/*
this.setState({profile: prof, key: Math.random().toString()});*/}
- {/* } else {*/}
- {/*
this.setState(state => {*/}
- {/* const
newProfile = Profile.createNew(profileName);*/}
- {/*
newProfile.project = new ProjectModel(this.state.profile.project);*/}
- {/*
state.profiles.push(newProfile);*/}
- {/* return
{profiles: state.profiles, profile: newProfile, tab: state.tab};*/}
- {/* })*/}
- {/* }*/}
- {/* }}/>*/}
- </ToolbarItem>
- </ToolbarContent>
- </Toolbar>
- </FlexItem>
- </Flex>
- </PageSection>
- )
- }
-
- onButtonClick(action: "start" | "stop" | "undeploy" | "run") {
- this.props.onAction?.call(this, action, this.state.project);
- }
-
- getFooter() {
- const active = false;
- const label = active ? "Stop" : "Package";
- const icon = active ? <InProgressIcon/> : <AutomationIcon/>;
- return <div key={this.state.key} className="footer">
- <div className="progress">
- {active && this.getProgress()}
- </div>
- <div className="buttons">
- <Toolbar id="toolbar-items">
- <ToolbarContent>
- {!active && <ToolbarItem>
- <Button variant="secondary" isSmall onClick={event
=> this.onButtonClick("undeploy")}>Undeploy</Button>
- </ToolbarItem>}
- <ToolbarItem>
- <Button variant="primary" isSmall icon={icon}
onClick={event => this.onButtonClick(active ? "stop" :
"start")}>{label}</Button>
- </ToolbarItem>
- <ToolbarItem>
- <Button variant="primary" isSmall
icon={<RunIcon/>} onClick={event => this.onButtonClick("run")}>Run</Button>
- </ToolbarItem>
- </ToolbarContent>
- </Toolbar>
- </div>
- </div>
- }
-
- getPropertiesForm() {
- return (
- <div className="center">
- <div className="center-column">
- <Card className="builder-card" isCompact style={{width:
"100%"}}>
- {this.getCardHeader("Properties", <ClipboardIcon/>)}
- <CardBody>
- <PropertiesTable
properties={this.state.project.properties}
- onChange={properties =>
this.setState(state => {
- state.project.properties =
properties;
- return state
- })}/>
- </CardBody>
- </Card>
- </div>
- </div>
- )
- }
-
- render() {
- return (
- <PageSection className="project-builder" variant={this.props.dark
? PageSectionVariants.darker : PageSectionVariants.light}
- padding={{default: 'noPadding'}}>
- <div style={{height: "100%", display: "flex", flexDirection:
"column"}}>
- <div>
- {this.getHeader()}
- </div>
- <div style={{overflow: "auto", flexGrow: 1}}>
- {this.getPropertiesForm()}
- </div>
- <div>
- {this.getFooter()}
- </div>
- </div>
- </PageSection>
- )
- }
-}
\ No newline at end of file
diff --git a/karavan-vscode/webview/builder/FileSelector.tsx
b/karavan-vscode/webview/builder/FileSelector.tsx
deleted file mode 100644
index ead44b9..0000000
--- a/karavan-vscode/webview/builder/FileSelector.tsx
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 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 {
- Button,
- FormGroup,
- Checkbox, PopoverPosition, Popover, InputGroup
-} from '@patternfly/react-core';
-import '../designer/karavan.css';
-import HelpIcon from "@patternfly/react-icons/dist/js/icons/help-icon";
-
-interface Props {
- label: string
- help: string
- files: string
- filesSelected: string
- onChange: (files: string) => void
- source: boolean
-}
-
-interface State {
- selected: []
-}
-
-export class FileSelector extends React.Component<Props, State> {
-
- public state: State = {
- selected: []
- };
-
- isChecked(file: string) {
- const finalFile = this.props.source ? "file:" + file : file;
- const s = this.props.filesSelected ?
this.props.filesSelected.split(",").map(value => value.trim()) : [];
- return s.includes(finalFile);
- }
-
- onChange(file: string, checked: boolean) {
- const finalFile = this.props.source ? "file:" + file : file;
- const s = this.props.filesSelected.split(",").map(f =>
f.trim()).filter(f => f.length > 0);
- const already = s.includes(finalFile);
- if (checked && !already) {
- s.push(finalFile);
- this.props.onChange?.call(this, s.join(","));
- } else if (!checked) {
- const result = s.filter(f => f !== finalFile);
- this.props.onChange?.call(this, result.join(","));
- }
- }
-
- getFiles(): string[] {
- const allFiles = (this.props.files ? this.props.files.split(",") : []);
- if (this.props.source){
- const extensions = ['yaml', 'yml', 'java', 'js', 'kt', 'groovy',
'xml'];
- return allFiles.filter(file => {
- const extension = file.split(".").pop() || '';
- return extensions.includes(extension);
- }).map(file => file.replace("file:", ""))
- }
- return allFiles;
- }
-
- render() {
- const files = this.getFiles();
- return (
- <FormGroup label={this.props.label} fieldId="files">
- <InputGroup>
- <div style={{width:"100%"}}>
- {files.map(file => {
- const key = file + this.props.source;
- return <Checkbox key={key} label={file}
isChecked={this.isChecked(file)} onChange={checked => this.onChange(file,
checked)} id={key} name={key}/>
- })}
- </div>
- <Popover aria-label="files" position={PopoverPosition.left}
- bodyContent={this.props.help}>
- <Button variant="plain" onClick={e => {}}>
- <HelpIcon/>
- </Button>
- </Popover>
- </InputGroup>
- </FormGroup>
- )
- }
-};
\ No newline at end of file
diff --git a/karavan-vscode/webview/builder/ProfileSelector.tsx
b/karavan-vscode/webview/builder/ProfileSelector.tsx
deleted file mode 100644
index ef140a4..0000000
--- a/karavan-vscode/webview/builder/ProfileSelector.tsx
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * 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 {
- Button,
- Flex,
- FlexItem, Form, FormGroup, InputGroup, Modal, ModalVariant, Tab, Tabs,
TextInput, ToggleGroup, ToggleGroupItem, Tooltip, TooltipPosition
-} from '@patternfly/react-core';
-import '../designer/karavan.css';
-import AddIcon from "@patternfly/react-icons/dist/js/icons/plus-circle-icon";
-import DeleteIcon from "@patternfly/react-icons/dist/js/icons/times-icon";
-
-interface Props {
- profiles: string[]
- profile: string
- onChange?: (profile: string) => void
- onDelete?: (profile: string) => void
-}
-
-interface State {
- isSelectorOpen?: boolean
- showDeleteConfirmation?: boolean
- showCreate?: boolean
- newProfile?: string
-}
-
-export class ProfileSelector extends React.Component<Props, State> {
-
- public state: State = {
- isSelectorOpen: false,
- };
-
- onSelect(profile?: string){
- if (profile) this.props.onChange?.call(this, profile);
- this.setState({isSelectorOpen: false});
- }
-
- deleteProfile(){
- if (this.props.profile) this.props.onDelete?.call(this,
this.props.profile);
- this.setState({showDeleteConfirmation: false});
- }
-
- saveAndCloseCreateModal = () => {
- if (this.state.newProfile && this.state.newProfile.length > 0)
this.props.onChange?.call(this, this.state.newProfile);
- this.closeModal();
- }
-
- closeModal = () => {
- this.setState({showCreate: false, newProfile: undefined});
- }
-
- onKeyDown = (event: React.KeyboardEvent<HTMLDivElement>): void => {
- if (event.key === 'Enter' && this.state.newProfile !== undefined) {
- this.saveAndCloseCreateModal();
- }
- }
-
- createModalForm() {
- return (
- <Modal
- title="Create new profile"
- className='profile-modal'
- variant={ModalVariant.small}
- isOpen={this.state.showCreate}
- onClose={this.closeModal}
- onKeyDown={this.onKeyDown}
- actions={[
- <Button key="confirm" variant="primary"
onClick={this.saveAndCloseCreateModal}>Save</Button>,
- <Button key="cancel" variant="secondary"
onClick={this.closeModal}>Cancel</Button>
- ]}
- >
- <Form isHorizontal>
- <FormGroup label="Profile" fieldId="profile" isRequired>
- <TextInput className="text-field" type="text"
id="profile" name="profile"
- value={this.state.newProfile}
- onChange={e => this.setState({newProfile:
e})}/>
- </FormGroup>
- </Form>
- </Modal>
- )
- }
-
- getDeleteConfirmation() {
- return (<Modal
- className="modal-delete"
- title="Confirmation"
- isOpen={this.state.showDeleteConfirmation}
- onClose={() => this.setState({showDeleteConfirmation: false})}
- actions={[
- <Button key="confirm" variant="primary" onClick={e =>
this.deleteProfile()}>Delete</Button>,
- <Button key="cancel" variant="link"
- onClick={e => this.setState({showDeleteConfirmation:
false})}>Cancel</Button>
- ]}
- onEscapePress={e => this.setState({showDeleteConfirmation:
false})}>
- <div>Delete profile {this.props.profile}</div>
- </Modal>)
- }
-
- render() {
- const profile = this.props.profile;
- const tabs = this.props.profiles.map(p =>
- <ToggleGroupItem key={p} text={p} buttonId={p} isSelected={profile
=== p}
- onChange={selected => selected ? this.onSelect(p)
: {}}/>
- );
- return (
- <Flex>
- <FlexItem>
- <p className="profile-caption">Profile:</p>
- </FlexItem>
- <FlexItem>
- <InputGroup>
- <Tooltip
- aria-label="Add profile"
- position={TooltipPosition.bottom}
- content="Create new profile">
- <Button variant={"plain"} icon={<AddIcon/>}
onClick={event => this.setState({showCreate: true})}/>
- </Tooltip>
- <ToggleGroup aria-label="Select target">
- {tabs}
- </ToggleGroup>
- {this.props.profiles.length > 1 && <Tooltip
- aria-label="Delete profile"
- position={TooltipPosition.bottomEnd}
- content="Delete selected profile">
- <Button variant={"plain"} icon={<DeleteIcon/>}
onClick={event => this.setState({showDeleteConfirmation: true})}/>
- </Tooltip>}
- </InputGroup>
- </FlexItem>
- {this.createModalForm()}
- {this.getDeleteConfirmation()}
- </Flex>
- )
- }
-}
\ No newline at end of file
diff --git a/karavan-vscode/webview/builder/PropertiesTable.tsx
b/karavan-vscode/webview/builder/PropertiesTable.tsx
deleted file mode 100644
index e3f5958..0000000
--- a/karavan-vscode/webview/builder/PropertiesTable.tsx
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * 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 {
- Button, Flex, FlexItem,
- Modal,
- PageSection,
- Panel,
- PanelMain,
- PanelMainBody,
- TextInput
-} from '@patternfly/react-core';
-import '../designer/karavan.css';
-import {TableComposable, Tbody, Td, Th, Thead, Tr} from
"@patternfly/react-table";
-import DeleteIcon from "@patternfly/react-icons/dist/js/icons/times-icon";
-import PlusIcon from "@patternfly/react-icons/dist/esm/icons/plus-icon";
-import {ProjectProperty} from "karavan-core/lib/model/ProjectModel";
-
-interface Props {
- properties: ProjectProperty[]
- onChange?: (properties: ProjectProperty[]) => void
-}
-
-interface State {
- properties: ProjectProperty[]
- showDeleteConfirmation: boolean
- deleteId?: string
-}
-
-export class PropertiesTable extends React.Component<Props, State> {
-
- public state: State = {
- properties: this.props.properties,
- showDeleteConfirmation: false,
- };
-
- sendUpdate = (props: ProjectProperty[]) => {
- this.props.onChange?.call(this, props);
- }
-
- changeProperty(p: ProjectProperty, field: "key" | "value", val?: string) {
- const key: string = field === 'key' && val !== undefined ? val : p.key;
- const value: any = field === 'value' ? val : p.value;
- const property: ProjectProperty = {id: p.id, key: key, value: value};
- const props = this.state.properties.map(prop => prop.id ===
property.id ? property : prop);
- this.setState({properties: props});
- this.sendUpdate(props);
- }
-
- startDelete(id: string) {
- this.setState({showDeleteConfirmation: true, deleteId: id});
- }
-
- confirmDelete() {
- const props = this.state.properties.filter(p => p.id !==
this.state.deleteId);
- this.setState({properties: props, showDeleteConfirmation: false,
deleteId: undefined});
- this.sendUpdate(props);
- }
-
- addProperty() {
- const props = [...this.state.properties];
- props.push(ProjectProperty.createNew("", ""))
- this.setState({properties: props, showDeleteConfirmation: false,
deleteId: undefined});
- this.sendUpdate(props);
- }
-
- getDeleteConfirmation() {
- return (<Modal
- className="modal-delete"
- title="Confirmation"
- isOpen={this.state.showDeleteConfirmation}
- onClose={() => this.setState({showDeleteConfirmation: false})}
- actions={[
- <Button key="confirm" variant="primary" onClick={e =>
this.confirmDelete()}>Delete</Button>,
- <Button key="cancel" variant="link"
- onClick={e => this.setState({showDeleteConfirmation:
false})}>Cancel</Button>
- ]}
- onEscapePress={e => this.setState({showDeleteConfirmation:
false})}>
- <div>Delete property?</div>
- </Modal>)
- }
-
- getTextInputField(property: ProjectProperty, field: "key" | "value",
readOnly: boolean) {
- return (<TextInput isDisabled={readOnly} isRequired={true}
className="text-field" type={"text"} id={"key"} name={"key"}
- value={field === "key" ? property.key :
property.value}
- onChange={val => this.changeProperty(property,
field, val)}/>)
- }
-
- render() {
- const properties = this.state.properties;
- return (
- <PageSection padding={{default: "noPadding"}}>
- {properties.length > 0 &&
- <TableComposable aria-label="Property table"
variant='compact' borders={false}
- className="project-properties">
- <Thead>
- <Tr>
- <Th key='name'>Name</Th>
- <Th key='value'>Value</Th>
- <Td></Td>
- </Tr>
- </Thead>
- <Tbody>
- {properties.map((property, idx: number) => {
- const readOnly =
property.key.startsWith("camel.jbang");
- return (
- <Tr key={property.id}>
- <Td noPadding width={20}
dataLabel="key">{this.getTextInputField(property, "key", readOnly)}</Td>
- <Td noPadding width={10}
dataLabel="value">{this.getTextInputField(property, "value", readOnly)}</Td>
- <Td noPadding isActionCell
dataLabel="delete">
- {!readOnly && <Button
variant={"plain"} icon={<DeleteIcon/>} className={"delete-button"}
-
onClick={event => this.startDelete(property.id)}/>}
- </Td>
- </Tr>
- )})}
- </Tbody>
- </TableComposable>}
- <Panel>
- <PanelMain>
- <PanelMainBody>
- <Flex direction={{default:"row"}} >
- <FlexItem align={{ default: 'alignRight' }}>
- <Button isInline variant={"primary"}
icon={<PlusIcon/>}
- className={"add-button"}
- onClick={event =>
this.addProperty()}>Add property</Button>
- </FlexItem>
- </Flex>
- </PanelMainBody>
- </PanelMain>
- </Panel>
- </PageSection>
- )
- }
-}
\ No newline at end of file