You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ma...@apache.org on 2023/05/04 01:50:32 UTC
[camel-karavan] 03/07: Container creator UI prototype for #757
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 0d04346da532154a5140d0665e69b26569f7a5e4
Author: Marat Gubaidullin <ma...@gmail.com>
AuthorDate: Wed May 3 15:27:58 2023 -0400
Container creator UI prototype for #757
---
karavan-app/src/main/webui/src/api/KaravanApi.tsx | 9 ++
.../src/main/webui/src/projects/ProjectInfo.tsx | 156 +++++++++++++++++----
.../src/main/webui/src/projects/ProjectLog.tsx | 2 +-
.../src/main/webui/src/projects/ProjectPage.tsx | 2 -
.../main/webui/src/projects/ProjectPageToolbar.tsx | 145 +++++--------------
5 files changed, 174 insertions(+), 140 deletions(-)
diff --git a/karavan-app/src/main/webui/src/api/KaravanApi.tsx b/karavan-app/src/main/webui/src/api/KaravanApi.tsx
index 5210e0de..01ad51b7 100644
--- a/karavan-app/src/main/webui/src/api/KaravanApi.tsx
+++ b/karavan-app/src/main/webui/src/api/KaravanApi.tsx
@@ -300,6 +300,15 @@ export class KaravanApi {
});
}
+ static async runProject(project: Project, after: (res: AxiosResponse<string>) => void) {
+ instance.post('/api/runner', project)
+ .then(res => {
+ after(res);
+ }).catch(err => {
+ after(err);
+ });
+ }
+
static async pipelineRun(project: Project, environment: string, after: (res: AxiosResponse<any>) => void) {
instance.post('/api/kubernetes/pipeline/' + environment, project)
.then(res => {
diff --git a/karavan-app/src/main/webui/src/projects/ProjectInfo.tsx b/karavan-app/src/main/webui/src/projects/ProjectInfo.tsx
index cfdf0a88..9f9587b8 100644
--- a/karavan-app/src/main/webui/src/projects/ProjectInfo.tsx
+++ b/karavan-app/src/main/webui/src/projects/ProjectInfo.tsx
@@ -3,10 +3,23 @@ import {
DescriptionList,
DescriptionListTerm,
DescriptionListGroup,
- DescriptionListDescription, Tooltip, Flex, FlexItem, Label
+ DescriptionListDescription,
+ Tooltip,
+ Flex,
+ FlexItem,
+ Label,
+ Button,
+ Modal,
+ ModalVariant,
+ Form,
+ FormGroup,
+ TextInput,
+ FormHelperText
} from '@patternfly/react-core';
import '../designer/karavan.css';
-import {Project } from "./ProjectModels";
+import {Project} from "./ProjectModels";
+import {KaravanApi} from "../api/KaravanApi";
+import PushIcon from "@patternfly/react-icons/dist/esm/icons/code-branch-icon";
interface Props {
@@ -17,62 +30,147 @@ interface Props {
interface State {
environment: string,
+ isPushing: boolean,
+ commitMessageIsOpen: boolean,
+ commitMessage: string
}
export class ProjectInfo extends React.Component<Props, State> {
public state: State = {
- environment: this.props.config.environment
+ environment: this.props.config.environment,
+ isPushing: false,
+ commitMessageIsOpen: false,
+ commitMessage: ''
};
- getDate(lastUpdate: number):string {
+ push = (after?: () => void) => {
+ this.setState({isPushing: true, commitMessageIsOpen: false});
+ const params = {
+ "projectId": this.props.project.projectId,
+ "message": this.state.commitMessage
+ };
+ KaravanApi.push(params, res => {
+ if (res.status === 200 || res.status === 201) {
+ this.setState({isPushing: false});
+ after?.call(this);
+ // this.props.onRefresh.call(this);
+ } else {
+ // Todo notification
+ }
+ });
+ }
+
+ getDate(lastUpdate: number): string {
if (lastUpdate) {
const date = new Date(lastUpdate);
- return date.toDateString() + ' ' + date.toLocaleTimeString();
+ return date.toISOString().slice(0, 19).replace('T',' ');
} else {
return "N/A"
}
}
- getLastUpdatePanel(){
+ getLastUpdatePanel() {
const {project, needCommit} = this.props;
const color = needCommit ? "grey" : "green";
return (
- <Flex direction={{default:"row"}} justifyContent={{default: "justifyContentFlexStart"}}>
+ <Flex direction={{default: "row"}} justifyContent={{default: "justifyContentFlexStart"}}>
{project?.lastCommitTimestamp && project?.lastCommitTimestamp > 0 &&
<FlexItem>
<Label color={color}>{this.getDate(project?.lastCommitTimestamp)}</Label>
</FlexItem>
}
+ </Flex>
+ )
+ }
+
+ getCommitPanel() {
+ const {isPushing, commitMessage} = this.state;
+ const {project, needCommit} = this.props;
+ const color = needCommit ? "grey" : "green";
+ return (
+ <Flex direction={{default: "row"}} justifyContent={{default: "justifyContentSpaceBetween"}}>
<FlexItem>
<Tooltip content={project?.lastCommit} position={"right"}>
- <Label color={color}>{project?.lastCommit ? project?.lastCommit?.substr(0, 7) : "-"}</Label>
+ <Label
+ color={color}>{project?.lastCommit ? project?.lastCommit?.substr(0, 18) : "-"}</Label>
</Tooltip>
</FlexItem>
- </Flex>)
+ <FlexItem>
+ <Tooltip content="Commit and push to git" position={"bottom-end"}>
+ <Button isLoading={isPushing ? true : undefined}
+ isSmall
+ variant={needCommit ? "primary" : "secondary"}
+ className="project-button"
+ icon={!isPushing ? <PushIcon/> : <div></div>}
+ onClick={() => this.setState({
+ commitMessageIsOpen: true,
+ commitMessage : commitMessage === '' ? new Date().toLocaleString() : commitMessage
+ })}>
+ {isPushing ? "..." : "Push"}
+ </Button>
+ </Tooltip>
+ </FlexItem>
+ </Flex>
+ )
+ }
+
+ getCommitModal() {
+ let {commitMessage, commitMessageIsOpen} = this.state;
+ return (
+ <Modal
+ title="Commit"
+ variant={ModalVariant.small}
+ isOpen={commitMessageIsOpen}
+ onClose={() => this.setState({commitMessageIsOpen: false})}
+ actions={[
+ <Button key="confirm" variant="primary" onClick={() => this.push()}>Save</Button>,
+ <Button key="cancel" variant="secondary"
+ onClick={() => this.setState({commitMessageIsOpen: false})}>Cancel</Button>
+ ]}
+ >
+ <Form autoComplete="off" isHorizontal className="create-file-form">
+ <FormGroup label="Message" fieldId="name" isRequired>
+ <TextInput value={commitMessage} onChange={value => this.setState({commitMessage: value})}/>
+ <FormHelperText isHidden={false} component="div"/>
+ </FormGroup>
+ </Form>
+ </Modal>
+ )
}
render() {
const {project} = this.props;
- return (<DescriptionList isHorizontal>
- <DescriptionListGroup>
- <DescriptionListTerm>Project ID</DescriptionListTerm>
- <DescriptionListDescription>{project?.projectId}</DescriptionListDescription>
- </DescriptionListGroup>
- <DescriptionListGroup>
- <DescriptionListTerm>Name</DescriptionListTerm>
- <DescriptionListDescription>{project?.name}</DescriptionListDescription>
- </DescriptionListGroup>
- <DescriptionListGroup>
- <DescriptionListTerm>Description</DescriptionListTerm>
- <DescriptionListDescription>{project?.description}</DescriptionListDescription>
- </DescriptionListGroup>
- <DescriptionListGroup>
- <DescriptionListTerm>Updated</DescriptionListTerm>
- <DescriptionListDescription>
- {this.getLastUpdatePanel()}
- </DescriptionListDescription>
- </DescriptionListGroup>
- </DescriptionList>);
+ return (
+ <React.Fragment>
+ <DescriptionList isHorizontal>
+ <DescriptionListGroup>
+ <DescriptionListTerm>Project ID</DescriptionListTerm>
+ <DescriptionListDescription>{project?.projectId}</DescriptionListDescription>
+ </DescriptionListGroup>
+ <DescriptionListGroup>
+ <DescriptionListTerm>Name</DescriptionListTerm>
+ <DescriptionListDescription>{project?.name}</DescriptionListDescription>
+ </DescriptionListGroup>
+ <DescriptionListGroup>
+ <DescriptionListTerm>Description</DescriptionListTerm>
+ <DescriptionListDescription>{project?.description}</DescriptionListDescription>
+ </DescriptionListGroup>
+ <DescriptionListGroup>
+ <DescriptionListTerm>Updated</DescriptionListTerm>
+ <DescriptionListDescription>
+ {this.getLastUpdatePanel()}
+ </DescriptionListDescription>
+ </DescriptionListGroup>
+ <DescriptionListGroup>
+ <DescriptionListTerm>Commit</DescriptionListTerm>
+ <DescriptionListDescription>
+ {this.getCommitPanel()}
+ </DescriptionListDescription>
+ </DescriptionListGroup>
+ </DescriptionList>
+ {this.getCommitModal()}
+ </React.Fragment>
+ );
}
}
diff --git a/karavan-app/src/main/webui/src/projects/ProjectLog.tsx b/karavan-app/src/main/webui/src/projects/ProjectLog.tsx
index 3f314b9b..bd9cac9e 100644
--- a/karavan-app/src/main/webui/src/projects/ProjectLog.tsx
+++ b/karavan-app/src/main/webui/src/projects/ProjectLog.tsx
@@ -53,7 +53,7 @@ export class ProjectLog extends React.Component<Props, State> {
showLogs = (type: 'container' | 'pipeline', name: string, environment: string) => {
this.eventSource?.close();
- this.eventSource = new EventSource("/api/logwatch/"+type+"/"+environment+"/"+name);
+ this.eventSource = new EventSource("/api/logwatch/"+type+"/"+environment+"/"+name, { withCredentials: true });
this.eventSource.onerror = (event) => {
this.eventSource?.close();
}
diff --git a/karavan-app/src/main/webui/src/projects/ProjectPage.tsx b/karavan-app/src/main/webui/src/projects/ProjectPage.tsx
index 4ae933dd..052d8035 100644
--- a/karavan-app/src/main/webui/src/projects/ProjectPage.tsx
+++ b/karavan-app/src/main/webui/src/projects/ProjectPage.tsx
@@ -183,7 +183,6 @@ export class ProjectPage extends React.Component<Props, State> {
tools = () => {
return <ProjectPageToolbar key={this.state.key}
project={this.props.project}
- needCommit={this.needCommit()}
file={this.state.file}
mode={this.state.mode}
isTemplates={this.isTemplatesProject()}
@@ -197,7 +196,6 @@ export class ProjectPage extends React.Component<Props, State> {
setMode={mode => this.setState({mode: mode})}
setCreateModalOpen={() => this.setState({isCreateModalOpen: true})}
setUploadModalOpen={() => this.setState({isUploadModalOpen: true})}
- onRefresh={this.onRefresh}
/>
}
diff --git a/karavan-app/src/main/webui/src/projects/ProjectPageToolbar.tsx b/karavan-app/src/main/webui/src/projects/ProjectPageToolbar.tsx
index dc38966b..f72f7ce9 100644
--- a/karavan-app/src/main/webui/src/projects/ProjectPageToolbar.tsx
+++ b/karavan-app/src/main/webui/src/projects/ProjectPageToolbar.tsx
@@ -7,7 +7,7 @@ import {
FlexItem,
ToggleGroup,
ToggleGroupItem,
- Checkbox, Tooltip, ToolbarItem, Modal, ModalVariant, Form, FormGroup, TextInput, FormHelperText
+ Checkbox, Tooltip, ToolbarItem
} from '@patternfly/react-core';
import '../designer/karavan.css';
import {Project, ProjectFile} from "./ProjectModels";
@@ -16,12 +16,9 @@ import DownloadIcon from "@patternfly/react-icons/dist/esm/icons/download-icon";
import DownloadImageIcon from "@patternfly/react-icons/dist/esm/icons/image-icon";
import PlusIcon from "@patternfly/react-icons/dist/esm/icons/plus-icon";
import {CamelDefinitionYaml} from "karavan-core/lib/api/CamelDefinitionYaml";
-import PushIcon from "@patternfly/react-icons/dist/esm/icons/code-branch-icon";
-import {KaravanApi} from "../api/KaravanApi";
interface Props {
project: Project,
- needCommit: boolean,
isTemplates: boolean,
isKamelets: boolean,
config: any,
@@ -33,79 +30,50 @@ interface Props {
downloadImage: () => void,
setCreateModalOpen: () => void,
setUploadModalOpen: () => void,
- onRefresh: () => void,
setEditAdvancedProperties: (checked: boolean) => void,
setMode: (mode: "design" | "code") => void,
}
-interface State {
- isPushing: boolean,
- commitMessageIsOpen: boolean,
- commitMessage: string
-}
-
-export class ProjectPageToolbar extends React.Component<Props> {
-
- public state: State = {
- isPushing: false,
- commitMessageIsOpen: false,
- commitMessage: ''
- };
-
- push = (after?: () => void) => {
- this.setState({isPushing: true, commitMessageIsOpen: false});
- const params = {
- "projectId": this.props.project.projectId,
- "message": this.state.commitMessage
- };
- KaravanApi.push(params, res => {
- if (res.status === 200 || res.status === 201) {
- this.setState({isPushing: false});
- after?.call(this);
- this.props.onRefresh.call(this);
- } else {
- // Todo notification
- }
- });
- }
+export const ProjectPageToolbar = (props: Props) => {
- getTemplatesToolbar() {
- const {file, editAdvancedProperties, needCommit} = this.props;
- const {isPushing} = this.state;
+ function getTemplatesToolbar() {
+ const {file, editAdvancedProperties, download, setCreateModalOpen, setUploadModalOpen} = props;
+ const isFile = file !== undefined;
const isProperties = file !== undefined && file.name.endsWith("properties");
return <Toolbar id="toolbar-group-types">
<ToolbarContent>
<ToolbarItem>
- <Flex justifyContent={{default: "justifyContentSpaceBetween"}} alignItems={{default: "alignItemsCenter"}}>
+ <Flex className="toolbar" direction={{default: "row"}} justifyContent={{default: "justifyContentSpaceBetween"}} alignItems={{default: "alignItemsCenter"}}>
{isProperties && <FlexItem>
<Checkbox
id="advanced"
label="Edit advanced"
isChecked={editAdvancedProperties}
- onChange={checked => this.props.setEditAdvancedProperties.call(this, checked)}
+ onChange={checked => props.setEditAdvancedProperties(checked)}
/>
</FlexItem>}
- <FlexItem>
- <Tooltip content="Commit and push to git" position={"bottom"}>
- <Button isLoading={isPushing ? true : undefined}
- isSmall
- variant={needCommit ? "primary" : "secondary"}
- className="project-button"
- icon={!isPushing ? <PushIcon/> : <div></div>}
- onClick={() => this.setState({commitMessageIsOpen: true})}>
- {isPushing ? "..." : "Commit"}
- </Button>
+ {isFile && <FlexItem>
+ <Tooltip content="Download source" position={"bottom-end"}>
+ <Button isSmall variant="control" icon={<DownloadIcon/>} onClick={e => download()}/>
</Tooltip>
- </FlexItem>
+ </FlexItem>}
+ {!isFile && <FlexItem>
+ <Button isSmall variant={"secondary"} icon={<PlusIcon/>}
+ onClick={e => setCreateModalOpen()}>Create</Button>
+ </FlexItem>}
+ {!isFile && <FlexItem>
+ <Button isSmall variant="secondary" icon={<UploadIcon/>}
+ onClick={e => setUploadModalOpen()}>Upload</Button>
+ </FlexItem>}
</Flex>
</ToolbarItem>
</ToolbarContent>
</Toolbar>
}
- getProjectToolbar() {
- const {isPushing, commitMessage} = this.state;
- const {file, needCommit, mode, editAdvancedProperties, addProperty, setEditAdvancedProperties, download, downloadImage, setCreateModalOpen, setUploadModalOpen} = this.props;
+ function getProjectToolbar() {
+ const {file, mode, editAdvancedProperties,
+ addProperty, setEditAdvancedProperties, download, downloadImage, setCreateModalOpen, setUploadModalOpen} = props;
const isFile = file !== undefined;
const isYaml = file !== undefined && file.name.endsWith("yaml");
const isIntegration = isYaml && file?.code && CamelDefinitionYaml.yamlIsIntegration(file.code);
@@ -116,9 +84,9 @@ export class ProjectPageToolbar extends React.Component<Props> {
{isYaml && <FlexItem>
<ToggleGroup>
<ToggleGroupItem text="Design" buttonId="design" isSelected={mode === "design"}
- onChange={s => this.props.setMode.call(this, "design")}/>
+ onChange={s => props.setMode("design")}/>
<ToggleGroupItem text="Code" buttonId="code" isSelected={mode === "code"}
- onChange={s => this.props.setMode.call(this, "code")}/>
+ onChange={s => props.setMode("code")}/>
</ToggleGroup>
</FlexItem>}
@@ -127,80 +95,41 @@ export class ProjectPageToolbar extends React.Component<Props> {
id="advanced"
label="Edit advanced"
isChecked={editAdvancedProperties}
- onChange={checked => setEditAdvancedProperties.call(this, checked)}
+ onChange={checked => setEditAdvancedProperties(checked)}
/>
</FlexItem>}
{isProperties && <FlexItem>
- <Button isSmall variant="primary" icon={<PlusIcon/>} onClick={e => addProperty.call(this)}>Add property</Button>
+ <Button isSmall variant="primary" icon={<PlusIcon/>} onClick={e => addProperty()}>Add property</Button>
</FlexItem>}
{isFile && <FlexItem>
<Tooltip content="Download source" position={"bottom-end"}>
- <Button isSmall variant="control" icon={<DownloadIcon/>} onClick={e => download.call(this)}/>
+ <Button isSmall variant="control" icon={<DownloadIcon/>} onClick={e => download()}/>
</Tooltip>
</FlexItem>}
{isIntegration && <FlexItem>
<Tooltip content="Download image" position={"bottom-end"}>
- <Button isSmall variant="control" icon={<DownloadImageIcon/>} onClick={e => downloadImage.call(this)}/>
+ <Button isSmall variant="control" icon={<DownloadImageIcon/>} onClick={e => downloadImage()}/>
</Tooltip>
</FlexItem>}
{!isFile && <FlexItem>
<Button isSmall variant={"secondary"} icon={<PlusIcon/>}
- onClick={e => setCreateModalOpen.call(this)}>Create</Button>
+ onClick={e => setCreateModalOpen()}>Create</Button>
</FlexItem>}
{!isFile && <FlexItem>
<Button isSmall variant="secondary" icon={<UploadIcon/>}
- onClick={e => setUploadModalOpen.call(this)}>Upload</Button>
- </FlexItem>}
- {!isFile && <FlexItem>
- <Tooltip content="Commit and push to git" position={"bottom-end"}>
- <Button isLoading={isPushing ? true : undefined}
- isSmall
- variant={needCommit ? "primary" : "secondary"}
- className="project-button"
- icon={!isPushing ? <PushIcon/> : <div></div>}
- onClick={() => this.setState({
- commitMessageIsOpen: true,
- commitMessage : commitMessage === '' ? new Date().toLocaleString() : commitMessage
- })}>
- {isPushing ? "..." : "Push"}
- </Button>
- </Tooltip>
+ onClick={e => setUploadModalOpen()}>Upload</Button>
</FlexItem>}
</Flex>
</ToolbarContent>
</Toolbar>
}
- getCommitModal() {
- let {commitMessage, commitMessageIsOpen} = this.state;
- return (
- <Modal
- title="Commit"
- variant={ModalVariant.small}
- isOpen={commitMessageIsOpen}
- onClose={() => this.setState({commitMessageIsOpen: false})}
- actions={[
- <Button key="confirm" variant="primary" onClick={() => this.push()}>Save</Button>,
- <Button key="cancel" variant="secondary" onClick={() => this.setState({commitMessageIsOpen: false})}>Cancel</Button>
- ]}
- >
- <Form autoComplete="off" isHorizontal className="create-file-form">
- <FormGroup label="Message" fieldId="name" isRequired>
- <TextInput value={commitMessage} onChange={value => this.setState({commitMessage: value})}/>
- <FormHelperText isHidden={false} component="div"/>
- </FormGroup>
- </Form>
- </Modal>
- )
- }
-
- render() {
- const {isTemplates} = this.props;
- return <div>
- {isTemplates && this.getTemplatesToolbar()}
- {!isTemplates && this.getProjectToolbar()}
- {this.getCommitModal()}
- </div>
- }
+ const {isTemplates} = props;
+ return (
+ <>
+ {isTemplates && getTemplatesToolbar()}
+ {!isTemplates && getProjectToolbar()}
+ </>
+ )
}