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:33 UTC
[camel-karavan] 04/07: Project title 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 ccff8612d2c3ee7d19a20826c4f8405c5b119839
Author: Marat Gubaidullin <ma...@gmail.com>
AuthorDate: Wed May 3 16:50:29 2023 -0400
Project title UI prototype for #757
---
karavan-app/src/main/webui/src/index.css | 11 ++
.../main/webui/src/projects/ProjectDevelopment.tsx | 3 +-
.../src/main/webui/src/projects/ProjectInfo.tsx | 4 +-
.../src/main/webui/src/projects/ProjectPage.tsx | 71 ++++++-----
.../main/webui/src/projects/ProjectPageToolbar.tsx | 135 ++++++++++++++++++++-
.../{ProjectInfo.tsx => ProjectRunner.tsx} | 2 +-
6 files changed, 190 insertions(+), 36 deletions(-)
diff --git a/karavan-app/src/main/webui/src/index.css b/karavan-app/src/main/webui/src/index.css
index 50158792..72cf3111 100644
--- a/karavan-app/src/main/webui/src/index.css
+++ b/karavan-app/src/main/webui/src/index.css
@@ -117,6 +117,17 @@
font-size: 14px;
}
+.karavan .project-page .project-title .pf-l-flex.pf-m-column > * {
+ margin-bottom: 0;
+}
+
+.karavan .project-page .project-title .project-breadcrumb {
+ font-size: 20px;
+ font-weight: 400;
+ height: 30px;
+ line-height: 30px;
+}
+
.karavan .project-page .project-tabs {
background-color: white;
}
diff --git a/karavan-app/src/main/webui/src/projects/ProjectDevelopment.tsx b/karavan-app/src/main/webui/src/projects/ProjectDevelopment.tsx
index b27963d9..fd1a6e1d 100644
--- a/karavan-app/src/main/webui/src/projects/ProjectDevelopment.tsx
+++ b/karavan-app/src/main/webui/src/projects/ProjectDevelopment.tsx
@@ -6,6 +6,7 @@ import {
import '../designer/karavan.css';
import {Project} from "./ProjectModels";
import {ProjectInfo} from "./ProjectInfo";
+import {ProjectRunner} from "./ProjectRunner";
interface Props {
@@ -37,7 +38,7 @@ export class ProjectDevelopment extends React.Component<Props, State> {
</FlexItem>
<Divider orientation={{default: "vertical"}}/>
<FlexItem flex={{default: "flex_3"}}>
- {/*{this.getEnvPanel("dev")}*/}
+ <ProjectRunner project={project} config={config} needCommit={needCommit} />
</FlexItem>
</Flex>
</CardBody>
diff --git a/karavan-app/src/main/webui/src/projects/ProjectInfo.tsx b/karavan-app/src/main/webui/src/projects/ProjectInfo.tsx
index 9f9587b8..a7a6ed2d 100644
--- a/karavan-app/src/main/webui/src/projects/ProjectInfo.tsx
+++ b/karavan-app/src/main/webui/src/projects/ProjectInfo.tsx
@@ -105,7 +105,9 @@ export class ProjectInfo extends React.Component<Props, State> {
icon={!isPushing ? <PushIcon/> : <div></div>}
onClick={() => this.setState({
commitMessageIsOpen: true,
- commitMessage : commitMessage === '' ? new Date().toLocaleString() : commitMessage
+ commitMessage : commitMessage === ''
+ ? new Date().toISOString().slice(0, 19).replace('T',' ')
+ : commitMessage
})}>
{isPushing ? "..." : "Push"}
</Button>
diff --git a/karavan-app/src/main/webui/src/projects/ProjectPage.tsx b/karavan-app/src/main/webui/src/projects/ProjectPage.tsx
index 052d8035..e8f373db 100644
--- a/karavan-app/src/main/webui/src/projects/ProjectPage.tsx
+++ b/karavan-app/src/main/webui/src/projects/ProjectPage.tsx
@@ -182,20 +182,22 @@ export class ProjectPage extends React.Component<Props, State> {
tools = () => {
return <ProjectPageToolbar key={this.state.key}
- project={this.props.project}
- file={this.state.file}
- mode={this.state.mode}
- isTemplates={this.isTemplatesProject()}
- isKamelets={this.isKameletsProject()}
- config={this.props.config}
- addProperty={() => this.addProperty()}
- download={() => this.download()}
- downloadImage={() => this.downloadImage()}
- editAdvancedProperties={this.state.editAdvancedProperties}
- setEditAdvancedProperties={checked => this.setState({editAdvancedProperties: checked})}
- setMode={mode => this.setState({mode: mode})}
- setCreateModalOpen={() => this.setState({isCreateModalOpen: true})}
- setUploadModalOpen={() => this.setState({isUploadModalOpen: true})}
+ project={this.props.project}
+ file={this.state.file}
+ mode={this.state.mode}
+ isTemplates={this.isTemplatesProject()}
+ isKamelets={this.isKameletsProject()}
+ config={this.props.config}
+ addProperty={() => this.addProperty()}
+ download={() => this.download()}
+ downloadImage={() => this.downloadImage()}
+ editAdvancedProperties={this.state.editAdvancedProperties}
+ setEditAdvancedProperties={checked => this.setState({editAdvancedProperties: checked})}
+ setMode={mode => this.setState({mode: mode})}
+ setCreateModalOpen={() => this.setState({isCreateModalOpen: true})}
+ setUploadModalOpen={() => this.setState({isUploadModalOpen: true})}
+ needCommit={this.needCommit()}
+ onRefresh={this.onRefresh}
/>
}
@@ -206,28 +208,43 @@ export class ProjectPage extends React.Component<Props, State> {
const isFile = file !== undefined;
const isLog = file !== undefined && file.name.endsWith("log");
const filename = file ? file.name.substring(0, file.name.lastIndexOf('.')) : "";
- return (<div className="dsl-title">
- {isFile &&
- <div>
+ return (<div className="dsl-title project-title">
+ {isFile && <Flex direction={{default: "column"}} >
+ <FlexItem>
<Breadcrumb>
<BreadcrumbItem to="#" onClick={event => {
this.setState({file: undefined})
this.onRefresh();
}}>
- <Flex direction={{default: "row"}}>
- <FlexItem>{"Project: " + project?.projectId}</FlexItem>
- <FlexItem><Badge>{getProjectFileType(file)}</Badge></FlexItem>
- </Flex>
+ <div className={"project-breadcrumb"}>{project?.name + " (" + project?.projectId + ")"}</div>
</BreadcrumbItem>
</Breadcrumb>
+ </FlexItem>
+ <FlexItem>
+ <Flex direction={{default: "row"}}>
+ <FlexItem>
+ <Badge>{getProjectFileType(file)}</Badge>
+ </FlexItem>
+ <FlexItem>
+ <TextContent className="description">
+ <Text>{isLog ? filename : file.name}</Text>
+ </TextContent>
+ </FlexItem>
+ </Flex>
+ </FlexItem>
+ </Flex>}
+ {!isFile && <Flex direction={{default: "column"}} >
+ <FlexItem>
<TextContent className="title">
- <Text component="h1">{isLog ? filename : file.name}</Text>
+ <Text component="h2">{project?.name + " (" + project?.projectId + ")"}</Text>
</TextContent>
- </div>
- }
- {!isFile && <TextContent className="title">
- <Text component="h2">{project?.name}</Text>
- </TextContent>}
+ </FlexItem>
+ <FlexItem>
+ <TextContent className="description">
+ <Text>{project?.description}</Text>
+ </TextContent>
+ </FlexItem>
+ </Flex>}
</div>)
};
diff --git a/karavan-app/src/main/webui/src/projects/ProjectPageToolbar.tsx b/karavan-app/src/main/webui/src/projects/ProjectPageToolbar.tsx
index f72f7ce9..6d71d911 100644
--- a/karavan-app/src/main/webui/src/projects/ProjectPageToolbar.tsx
+++ b/karavan-app/src/main/webui/src/projects/ProjectPageToolbar.tsx
@@ -1,13 +1,23 @@
-import React from 'react';
+import React, {useState} from 'react';
import {
Button,
- Toolbar,
- ToolbarContent,
+ Checkbox,
Flex,
FlexItem,
+ Form,
+ FormGroup,
+ FormHelperText,
+ Label,
+ Modal,
+ ModalVariant,
+ TextInput,
ToggleGroup,
ToggleGroupItem,
- Checkbox, Tooltip, ToolbarItem
+ Toolbar,
+ ToolbarContent,
+ ToolbarItem,
+ Tooltip,
+ TooltipPosition
} from '@patternfly/react-core';
import '../designer/karavan.css';
import {Project, ProjectFile} from "./ProjectModels";
@@ -16,9 +26,12 @@ 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,
@@ -32,18 +45,87 @@ interface Props {
setUploadModalOpen: () => void,
setEditAdvancedProperties: (checked: boolean) => void,
setMode: (mode: "design" | "code") => void,
+ onRefresh: () => void,
}
export const ProjectPageToolbar = (props: Props) => {
+ const [isPushing, setIsPushing] = useState(false);
+ const [commitMessageIsOpen, setCommitMessageIsOpen] = useState(false);
+ const [commitMessage, setCommitMessage] = useState('');
+
+ function push () {
+ setIsPushing(true);
+ setCommitMessageIsOpen(false);
+ const params = {
+ "projectId": props.project.projectId,
+ "message": commitMessage
+ };
+ KaravanApi.push(params, res => {
+ if (res.status === 200 || res.status === 201) {
+ setIsPushing(false);
+ props.onRefresh();
+ } else {
+ // Todo notification
+ }
+ });
+ }
+
+ function getDate(lastUpdate: number): string {
+ if (lastUpdate) {
+ const date = new Date(lastUpdate);
+ return date.toISOString().slice(0, 19).replace('T',' ');
+ } else {
+ return "N/A"
+ }
+ }
+
+ function getLastUpdatePanel() {
+ const {project, needCommit} = props;
+ const color = needCommit ? "grey" : "green";
+ const commit = project?.lastCommit;
+ return (
+ <Flex direction={{default: "row"}} justifyContent={{default: "justifyContentFlexStart"}}>
+ {project?.lastCommitTimestamp && project?.lastCommitTimestamp > 0 &&
+ <FlexItem>
+ <Tooltip content="Last update" position={TooltipPosition.bottom}>
+ <Label color={color}>{getDate(project?.lastCommitTimestamp)}</Label>
+ </Tooltip>
+ </FlexItem>
+ }
+ <FlexItem>
+ <Tooltip content={commit} position={TooltipPosition.bottom}>
+ <Label
+ color={color}>{commit ? commit?.substring(0, 18) : "-"}</Label>
+ </Tooltip>
+ </FlexItem>
+ </Flex>
+ )
+ }
+
function getTemplatesToolbar() {
- const {file, editAdvancedProperties, download, setCreateModalOpen, setUploadModalOpen} = props;
+ const {file,needCommit, 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 className="toolbar" direction={{default: "row"}} justifyContent={{default: "justifyContentSpaceBetween"}} alignItems={{default: "alignItemsCenter"}}>
+ {!isFile && <FlexItem>
+ {getLastUpdatePanel()}
+ </FlexItem>}
+ {!isFile && <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={() => setCommitMessageIsOpen(true)}>
+ {isPushing ? "..." : "Commit"}
+ </Button>
+ </Tooltip>
+ </FlexItem>}
{isProperties && <FlexItem>
<Checkbox
id="advanced"
@@ -72,7 +154,7 @@ export const ProjectPageToolbar = (props: Props) => {
}
function getProjectToolbar() {
- const {file, mode, editAdvancedProperties,
+ const {file,needCommit, mode, editAdvancedProperties,
addProperty, setEditAdvancedProperties, download, downloadImage, setCreateModalOpen, setUploadModalOpen} = props;
const isFile = file !== undefined;
const isYaml = file !== undefined && file.name.endsWith("yaml");
@@ -81,6 +163,24 @@ export const ProjectPageToolbar = (props: Props) => {
return <Toolbar id="toolbar-group-types">
<ToolbarContent>
<Flex className="toolbar" direction={{default: "row"}} alignItems={{default: "alignItemsCenter"}}>
+ {!isFile && <FlexItem>
+ {getLastUpdatePanel()}
+ </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={() => {
+ setCommitMessage(commitMessage === '' ? new Date().toLocaleString() : commitMessage);
+ setCommitMessageIsOpen(true);
+ }}>
+ {isPushing ? "..." : "Push"}
+ </Button>
+ </Tooltip>
+ </FlexItem>}
{isYaml && <FlexItem>
<ToggleGroup>
<ToggleGroupItem text="Design" buttonId="design" isSelected={mode === "design"}
@@ -125,11 +225,34 @@ export const ProjectPageToolbar = (props: Props) => {
</Toolbar>
}
+ function getCommitModal() {
+ return (
+ <Modal
+ title="Commit"
+ variant={ModalVariant.small}
+ isOpen={commitMessageIsOpen}
+ onClose={() => setCommitMessageIsOpen(false)}
+ actions={[
+ <Button key="confirm" variant="primary" onClick={() => push()}>Save</Button>,
+ <Button key="cancel" variant="secondary" onClick={() => setCommitMessageIsOpen(false)}>Cancel</Button>
+ ]}
+ >
+ <Form autoComplete="off" isHorizontal className="create-file-form">
+ <FormGroup label="Message" fieldId="name" isRequired>
+ <TextInput value={commitMessage} onChange={value => setCommitMessage(value)}/>
+ <FormHelperText isHidden={false} component="div"/>
+ </FormGroup>
+ </Form>
+ </Modal>
+ )
+ }
+
const {isTemplates} = props;
return (
<>
{isTemplates && getTemplatesToolbar()}
{!isTemplates && getProjectToolbar()}
+ {getCommitModal()}
</>
)
}
diff --git a/karavan-app/src/main/webui/src/projects/ProjectInfo.tsx b/karavan-app/src/main/webui/src/projects/ProjectRunner.tsx
similarity index 98%
copy from karavan-app/src/main/webui/src/projects/ProjectInfo.tsx
copy to karavan-app/src/main/webui/src/projects/ProjectRunner.tsx
index 9f9587b8..bb91a453 100644
--- a/karavan-app/src/main/webui/src/projects/ProjectInfo.tsx
+++ b/karavan-app/src/main/webui/src/projects/ProjectRunner.tsx
@@ -35,7 +35,7 @@ interface State {
commitMessage: string
}
-export class ProjectInfo extends React.Component<Props, State> {
+export class ProjectRunner extends React.Component<Props, State> {
public state: State = {
environment: this.props.config.environment,