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/02/28 19:56:45 UTC

[camel-karavan] branch main updated (e94020ca -> 13902116)

This is an automated email from the ASF dual-hosted git repository.

marat pushed a change to branch main
in repository https://gitbox.apache.org/repos/asf/camel-karavan.git


    from e94020ca Fix #660
     new 17cdea97 fix #644
     new 13902116 Copy files from designer

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../org/apache/camel/karavan/api/GitResource.java  |   7 +-
 .../apache/camel/karavan/service/GitService.java   |  14 +-
 karavan-app/src/main/webui/src/api/KaravanApi.tsx  |   5 +-
 .../main/webui/src/components/ComponentCard.tsx    |  12 +-
 .../src/main/webui/src/designer/karavan.css        | 102 ++++++++++----
 .../main/webui/src/designer/route/DslSelector.tsx  |  23 ++--
 .../src/main/webui/src/designer/utils/CamelUi.tsx  |   2 +
 .../main/webui/src/designer/utils/DslMetaModel.ts  |   1 +
 karavan-app/src/main/webui/src/eip/EipCard.tsx     |   7 +-
 .../src/main/webui/src/kamelets/KameletCard.tsx    |  12 +-
 .../main/webui/src/projects/ProjectPageToolbar.tsx | 150 +++++++++++++--------
 11 files changed, 218 insertions(+), 117 deletions(-)


[camel-karavan] 02/02: Copy files from designer

Posted by ma...@apache.org.
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 13902116852b1116bd57e27487a8c336feabc0eb
Author: Marat Gubaidullin <ma...@gmail.com>
AuthorDate: Tue Feb 28 14:56:35 2023 -0500

    Copy files from designer
---
 .../main/webui/src/components/ComponentCard.tsx    |  12 ++-
 .../src/main/webui/src/designer/karavan.css        | 102 +++++++++++++++------
 .../main/webui/src/designer/route/DslSelector.tsx  |  23 +++--
 .../src/main/webui/src/designer/utils/CamelUi.tsx  |   2 +
 .../main/webui/src/designer/utils/DslMetaModel.ts  |   1 +
 karavan-app/src/main/webui/src/eip/EipCard.tsx     |   7 +-
 .../src/main/webui/src/kamelets/KameletCard.tsx    |  12 ++-
 7 files changed, 110 insertions(+), 49 deletions(-)

diff --git a/karavan-app/src/main/webui/src/components/ComponentCard.tsx b/karavan-app/src/main/webui/src/components/ComponentCard.tsx
index ba18bd4f..83521a66 100644
--- a/karavan-app/src/main/webui/src/components/ComponentCard.tsx
+++ b/karavan-app/src/main/webui/src/components/ComponentCard.tsx
@@ -16,7 +16,7 @@
  */
 import React from 'react';
 import {
-    CardHeader, Card, CardTitle, CardBody, CardFooter,Badge
+    CardHeader, Card, CardTitle, CardBody, CardFooter, Badge, Text
 } from '@patternfly/react-core';
 import '../designer/karavan.css';
 import {camelIcon, CamelUi} from "../designer/utils/CamelUi";
@@ -48,14 +48,18 @@ export class ComponentCard extends React.Component<Props, State> {
             <Card isHoverable isCompact key={component.component.name} className="kamelet-card"
                 onClick={event => this.click(event)}
             >
+                <CardHeader className="header-labels">
+                    {component.component.supportType === 'Supported' && <Badge isRead className="support-type labels">{component.component.supportType}</Badge>}
+                    <Badge isRead className="support-level labels">{component.component.supportLevel}</Badge>
+                </CardHeader>
                 <CardHeader>
                     {CamelUi.getIconFromSource(camelIcon)}
+                    <CardTitle>{component.component.title}</CardTitle>
                 </CardHeader>
-                <CardTitle>{component.component.title}</CardTitle>
                 <CardBody>{component.component.description}</CardBody>
-                <CardFooter>
+                <CardFooter className="footer-labels">
                     <Badge isRead className="labels">{component.component.label}</Badge>
-                    <Badge isRead className="version">{component.component.version}</Badge>
+                    <Badge isRead className="version labels">{component.component.version}</Badge>
                 </CardFooter>
             </Card>
         );
diff --git a/karavan-app/src/main/webui/src/designer/karavan.css b/karavan-app/src/main/webui/src/designer/karavan.css
index 3598b1ab..4e714245 100644
--- a/karavan-app/src/main/webui/src/designer/karavan.css
+++ b/karavan-app/src/main/webui/src/designer/karavan.css
@@ -43,9 +43,10 @@
     justify-content: space-between;
 }
 
-.karavan .page-header .top-toolbar .pf-c-page__header-tools{
+.karavan .page-header .top-toolbar .pf-c-page__header-tools {
     margin-right: 0;
 }
+
 .karavan .page-header .top-toolbar {
     width: 100%;
 }
@@ -124,10 +125,6 @@
     height: 160px;
 }
 
-.kamelets-page .kamelet-card .pf-c-card__header {
-    /*padding-right: 6px;*/
-}
-
 .kamelets-page .kamelet-card .pf-c-card__header .custom {
     margin-left: auto;
 }
@@ -140,12 +137,14 @@
 .kamelets-page .kamelet-card .pf-c-card__body {
     overflow: hidden;
     position: relative;
+    line-height: 1.6em;
 }
 
 .kamelets-page .kamelet-card .icon {
     height: 24px;
     margin-top: auto;
     margin-bottom: auto;
+    margin-right: 3px;
     border: none;
     -webkit-user-select: none;
     -khtml-user-select: none;
@@ -154,12 +153,33 @@
     user-select: none;
 }
 
-.karavan .kamelets-page .kamelet-card .pf-c-card__footer {
+.kamelets-page .kamelet-card .header-labels {
+    padding: 5px;
+    display: flex;
+    flex-direction: row;
+    justify-content: flex-end;
+}
+
+.kamelets-page .kamelet-card .footer-labels {
+    padding: 5px;
     display: flex;
     flex-direction: row;
     justify-content: space-between;
 }
 
+.kamelets-page .kamelet-card .version,
+.kamelets-page .kamelet-card .support-type,
+.kamelets-page .kamelet-card .support-level {
+    white-space: nowrap;
+}
+
+.kamelets-page .kamelet-card .labels {
+    opacity: 0.5;
+}
+
+.kamelets-page .kamelet-card:hover .labels {
+    opacity: 1;
+}
 
 /*kamelet modal*/
 .kamelet-modal-card .pf-c-card__header {
@@ -277,7 +297,7 @@
     flex-direction: row;
 }
 
-.karavan .properties .headers .top h1{
+.karavan .properties .headers .top h1 {
     width: 100%;
     margin-top: auto;
     margin-bottom: auto;
@@ -321,16 +341,17 @@
 .karavan .properties .input-group .pf-c-chip-group .pf-c-chip-group__list,
 .karavan .properties .input-group .pf-c-chip-group .pf-c-chip-group__list .pf-c-chip-group__list-item,
 .karavan .properties .input-group .pf-c-chip-group .pf-c-chip-group__main {
-    display:block;
+    display: block;
 }
 
 .karavan .properties .input-group .pf-c-chip-group {
     margin-left: 0;
 }
 
-.karavan .properties .input-group .pf-c-chip-group .pf-c-chip .pf-c-chip__text{
+.karavan .properties .input-group .pf-c-chip-group .pf-c-chip .pf-c-chip__text {
     max-width: inherit;
 }
+
 .karavan .properties .input-group .pf-c-chip-group .pf-c-chip {
     width: 100%;
 }
@@ -340,8 +361,8 @@
     margin-top: auto;
 }
 
-.karavan .properties .chip .pf-c-button{
-    position:absolute;
+.karavan .properties .chip .pf-c-button {
+    position: absolute;
     right: 0;
 }
 
@@ -464,7 +485,7 @@
 .karavan .properties .expression .pf-c-select__menu-wrapper,
 .karavan .properties .object .pf-c-select__menu-wrapper,
 .karavan .properties .dataformat .pf-c-select__menu-wrapper,
-.karavan .properties .parameters .pf-c-select__menu-wrapper{
+.karavan .properties .parameters .pf-c-select__menu-wrapper {
     width: 350px;
 }
 
@@ -487,7 +508,7 @@
 }
 
 .karavan .properties .delete-button {
-    color:  #909090;
+    color: #909090;
 }
 
 .karavan .properties .pf-c-expandable-section__toggle {
@@ -592,7 +613,11 @@
     fill: transparent;
 }
 
-@keyframes dashdraw{0%{stroke-dashoffset:10}}
+@keyframes dashdraw {
+    0% {
+        stroke-dashoffset: 10
+    }
+}
 
 .karavan .dsl-page .flows .step-element {
     align-items: center;
@@ -617,14 +642,14 @@
 .karavan .dsl-page .flows .children {
     display: flex;
     flex-wrap: wrap;
-    flex-wrap:nowrap;
+    flex-wrap: nowrap;
     gap: 6px;
 }
 
 .karavan .dsl-page .flows .has-child {
     display: flex;
     flex-direction: column;
-    flex-wrap:nowrap;
+    flex-wrap: nowrap;
     gap: 6px;
 }
 
@@ -700,16 +725,19 @@
     display: flex;
     flex-direction: row;
 }
+
 .karavan .step-element .header .spacer {
     width: 50%
 }
+
 .karavan .step-element .header .text-bottom {
     background-color: rgba(255, 255, 255, 0.5);
 }
+
 .karavan .step-element .header .text-right {
     padding-left: 17px;
     width: 50%;
-    text-align:start;
+    text-align: start;
 }
 
 .karavan .step-element .header .header-text-required {
@@ -867,7 +895,7 @@
 }
 
 
-.dsl-modal .search .pf-c-form__group-label{
+.dsl-modal .search .pf-c-form__group-label {
     padding: 0;
     margin: auto;
 }
@@ -896,16 +924,23 @@
     flex-wrap: wrap;
 }
 
-.dsl-modal .version {
-    opacity: 0.5;
-    white-space: nowrap;
-    margin-left: auto;
+.dsl-modal .pf-c-card.pf-m-compact .header-labels {
+    padding: 5px;
+    display: flex;
+    flex-direction: row;
+    justify-content: flex-end;
+}
+
+.dsl-modal .pf-c-card.pf-m-compact .footer-labels {
+    padding: 5px;
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
 }
 
+.dsl-modal .version,
+.dsl-modal .support-type,
 .dsl-modal .support-level {
-    position: absolute;
-    right: 6px;
-    top: 6px;
     white-space: nowrap;
 }
 
@@ -913,6 +948,10 @@
     opacity: 0.5;
 }
 
+.dsl-modal .dsl-card:hover .labels {
+    opacity: 1;
+}
+
 .move-modal {
     width: 270px !important;
 }
@@ -920,6 +959,7 @@
 .move-modal .pf-c-modal-box__body {
     margin-right: 0 !important;
 }
+
 .move-modal .pf-m-plain {
     display: none;
 }
@@ -1128,13 +1168,14 @@
 .karavan .yaml-page {
     height: 100px;
 }
+
 /*Exception*/
 /*Template*/
 /*Error*/
 
 .karavan .templates-page,
 .karavan .exception-page,
-.karavan .error-page{
+.karavan .error-page {
     flex: 1;
     overflow: auto;
 }
@@ -1163,6 +1204,7 @@
     display: flex;
     flex-direction: row;
 }
+
 .karavan .tools-section .tools .header .labels {
     height: fit-content;
     margin-left: 3px;
@@ -1185,8 +1227,7 @@
 
 .karavan .project-builder .pf-c-tabs__link,
 .karavan .project-builder .pf-c-card__title,
-.karavan .project-builder .profile-caption
-{
+.karavan .project-builder .profile-caption {
     font-size: 14px;
 }
 
@@ -1238,6 +1279,7 @@
     gap: 10px;
     padding: 10px;
 }
+
 .karavan .project-builder .center-column {
     width: 100%;
     display: flex;
@@ -1262,18 +1304,22 @@
     flex-direction: column;
     justify-content: space-around;
 }
+
 .karavan .project-builder .project-properties td {
     padding: 0;
     margin: 0;
 }
+
 .karavan .project-builder .project-properties td,
 .karavan .project-builder .project-properties tr {
     border: none;
 }
+
 .karavan .project-builder .project-properties .delete-button {
     padding: 0 0 0 6px;
     margin: 0;
 }
+
 .karavan .project-builder .add-button {
     width: fit-content;
     margin-top: 6px;
diff --git a/karavan-app/src/main/webui/src/designer/route/DslSelector.tsx b/karavan-app/src/main/webui/src/designer/route/DslSelector.tsx
index dd68403b..f394a92e 100644
--- a/karavan-app/src/main/webui/src/designer/route/DslSelector.tsx
+++ b/karavan-app/src/main/webui/src/designer/route/DslSelector.tsx
@@ -88,28 +88,31 @@ export class DslSelector extends React.Component<Props, State> {
         return (
             <Card key={dsl.dsl + index} isHoverable isCompact className="dsl-card"
                   onClick={event => this.selectDsl(event, dsl)}>
+                <CardHeader className="header-labels">
+                    {dsl.supportType === 'Supported' && <Badge isRead className="support-type labels">{dsl.supportType}</Badge>}
+                    <Badge isRead className="support-level labels">{dsl.supportLevel}</Badge>
+                </CardHeader>
                 <CardHeader>
                     {CamelUi.getIconForDsl(dsl)}
                     <Text>{dsl.title}</Text>
-                    {dsl.supportLevel && dsl.supportLevel === 'Preview' && <Badge isRead className="support-level">{dsl.supportLevel}</Badge>}
                 </CardHeader>
                 <CardBody>
                     <Text>{dsl.description}</Text>
                 </CardBody>
-                <CardFooter>
                     {dsl.navigation.toLowerCase() === "kamelet"
-                        && <div className="footer" style={{justifyContent: "space-between"}}>
+                        && <CardFooter className="footer-labels">
                             <Badge isRead className="labels">{dsl.labels}</Badge>
-                            <Badge isRead className="version">{dsl.version}</Badge>
-                        </div>}
+                            <Badge isRead className="version labels">{dsl.version}</Badge>
+                        </CardFooter>}
                     {dsl.navigation.toLowerCase() === "component"
-                        && <div className="footer" style={{justifyContent: "flex-start"}}>
-                            {dsl.labels.split(',').map((s: string,  i: number) => <Badge key={s + i} isRead
+                        && <CardFooter className="footer-labels">
+                            <div>
+                                {dsl.labels.split(',').map((s: string,  i: number) => <Badge key={s + i} isRead
                                                                                          className="labels">{s}</Badge>)}
-                            <Badge isRead className="version">{dsl.version}</Badge>
-                        </div>
+                            </div>
+                            <Badge isRead className="version labels">{dsl.version}</Badge>
+                        </CardFooter>
                     }
-                </CardFooter>
             </Card>
         )
     }
diff --git a/karavan-app/src/main/webui/src/designer/utils/CamelUi.tsx b/karavan-app/src/main/webui/src/designer/utils/CamelUi.tsx
index 334607ef..a8985521 100644
--- a/karavan-app/src/main/webui/src/designer/utils/CamelUi.tsx
+++ b/karavan-app/src/main/webui/src/designer/utils/CamelUi.tsx
@@ -177,6 +177,8 @@ export class CamelUi {
                     title: c.component.title,
                     description: c.component.description,
                     version: c.component.version,
+                    supportLevel: c.component.supportLevel,
+                    supportType: c.component.supportType,
                 }));
     }
 
diff --git a/karavan-app/src/main/webui/src/designer/utils/DslMetaModel.ts b/karavan-app/src/main/webui/src/designer/utils/DslMetaModel.ts
index 53318bd0..d267a56d 100644
--- a/karavan-app/src/main/webui/src/designer/utils/DslMetaModel.ts
+++ b/karavan-app/src/main/webui/src/designer/utils/DslMetaModel.ts
@@ -25,6 +25,7 @@ export class DslMetaModel {
     navigation: string = ''
     version: string = ''
     supportLevel: string = ''
+    supportType: string = ''
     properties: any;
 
     public constructor(init?: Partial<DslMetaModel>) {
diff --git a/karavan-app/src/main/webui/src/eip/EipCard.tsx b/karavan-app/src/main/webui/src/eip/EipCard.tsx
index bfb2f8de..d288ac6f 100644
--- a/karavan-app/src/main/webui/src/eip/EipCard.tsx
+++ b/karavan-app/src/main/webui/src/eip/EipCard.tsx
@@ -53,8 +53,11 @@ export class EipCard extends React.Component<Props, State> {
                 </CardHeader>
                 <CardTitle>{component.title}</CardTitle>
                 <CardBody>{component.description}</CardBody>
-                <CardFooter>
-                        <Badge isRead className="labels">{component.labels}</Badge>
+                <CardFooter className="footer-labels">
+                    <div>
+                        {component.labels.split(',').map((s: string,  i: number) => <Badge key={s + i} isRead
+                                                                                     className="labels">{s}</Badge>)}
+                    </div>
                 </CardFooter>
             </Card>
         )
diff --git a/karavan-app/src/main/webui/src/kamelets/KameletCard.tsx b/karavan-app/src/main/webui/src/kamelets/KameletCard.tsx
index 5d4faafa..cfe3d48d 100644
--- a/karavan-app/src/main/webui/src/kamelets/KameletCard.tsx
+++ b/karavan-app/src/main/webui/src/kamelets/KameletCard.tsx
@@ -50,16 +50,18 @@ export class KameletCard extends React.Component<Props, State> {
             <Card isHoverable isCompact key={kamelet.metadata.name} className="kamelet-card"
                   onClick={event => this.click(event)}
             >
+                <CardHeader className="header-labels">
+                    {isCustom && <Badge className="custom">custom</Badge>}
+                    <Badge isRead className="support-level labels">{kamelet.metadata.annotations["camel.apache.org/kamelet.support.level"]}</Badge>
+                </CardHeader>
                 <CardHeader>
                     {CamelUi.getIconFromSource(kamelet.icon())}
-                    {isCustom && <Badge className="custom">custom</Badge>}
+                    <CardTitle>{kamelet.spec.definition.title}</CardTitle>
                 </CardHeader>
-                <CardTitle>{kamelet.spec.definition.title}</CardTitle>
                 <CardBody>{kamelet.spec.definition.description}</CardBody>
-                <CardFooter>
-                    {/*<div style={{justifyContent: "space-between"}}>*/}
+                <CardFooter className="footer-labels">
                     <Badge isRead className="labels">{kamelet.metadata.labels["camel.apache.org/kamelet.type"].toLowerCase()}</Badge>
-                    <Badge isRead className="version">{kamelet.metadata.annotations["camel.apache.org/catalog.version"].toLowerCase()}</Badge>
+                    <Badge isRead className="version labels">{kamelet.metadata.annotations["camel.apache.org/catalog.version"].toLowerCase()}</Badge>
                     {/*</div>*/}
                 </CardFooter>
             </Card>


[camel-karavan] 01/02: fix #644

Posted by ma...@apache.org.
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 17cdea97e7ba4f38e6b3acdaf4a56a982fdaa709
Author: Marat Gubaidullin <ma...@gmail.com>
AuthorDate: Tue Feb 28 14:56:21 2023 -0500

    fix #644
---
 .../org/apache/camel/karavan/api/GitResource.java  |   7 +-
 .../apache/camel/karavan/service/GitService.java   |  14 +-
 karavan-app/src/main/webui/src/api/KaravanApi.tsx  |   5 +-
 .../main/webui/src/projects/ProjectPageToolbar.tsx | 150 +++++++++++++--------
 4 files changed, 108 insertions(+), 68 deletions(-)

diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/api/GitResource.java b/karavan-app/src/main/java/org/apache/camel/karavan/api/GitResource.java
index 2f85a37b..9bd7d21a 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/api/GitResource.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/api/GitResource.java
@@ -26,6 +26,7 @@ import javax.ws.rs.POST;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
+import java.util.HashMap;
 
 @Path("/api/git")
 public class GitResource {
@@ -35,10 +36,12 @@ public class GitResource {
 
     private static final Logger LOGGER = Logger.getLogger(GitResource.class.getName());
 
+
     @POST
     @Produces(MediaType.APPLICATION_JSON)
     @Consumes(MediaType.APPLICATION_JSON)
-    public Project push(Project project) throws Exception {
-        return gitService.commitAndPushProject(project);
+    public Project push(HashMap<String, String> params) throws Exception {
+        System.out.println(params);
+        return gitService.commitAndPushProject(params.get("projectId"), params.get("message"));
     }
 }
\ No newline at end of file
diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/service/GitService.java b/karavan-app/src/main/java/org/apache/camel/karavan/service/GitService.java
index be83abf2..26f2c821 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/service/GitService.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/service/GitService.java
@@ -95,10 +95,10 @@ public class GitService {
         }
     }
 
-    public Project commitAndPushProject(Project project) throws Exception {
-        Project p = infinispanService.getProject(project.getProjectId());
-        List<ProjectFile> files = infinispanService.getProjectFiles(project.getProjectId());
-        RevCommit commit = commitAndPushProject(p, files);
+    public Project commitAndPushProject(String projectId, String message) throws Exception {
+        Project p = infinispanService.getProject(projectId);
+        List<ProjectFile> files = infinispanService.getProjectFiles(projectId);
+        RevCommit commit = commitAndPushProject(p, files, message);
         String commitId = commit.getId().getName();
         Long lastUpdate = commit.getCommitTime() * 1000L;
         p.setLastCommit(commitId);
@@ -107,7 +107,7 @@ public class GitService {
         return p;
     }
 
-    public RevCommit commitAndPushProject(Project project, List<ProjectFile> files) throws GitAPIException, IOException, URISyntaxException {
+    public RevCommit commitAndPushProject(Project project, List<ProjectFile> files, String message) throws GitAPIException, IOException, URISyntaxException {
         LOGGER.info("Commit and push project " + project.getProjectId());
         GitConfig gitConfig = getGitConfig();
         CredentialsProvider cred = new UsernamePasswordCredentialsProvider(gitConfig.getUsername(), gitConfig.getPassword());
@@ -126,7 +126,7 @@ public class GitService {
         }
         writeProjectToFolder(folder, project, files);
         addDeletedFilesToIndex(git, folder, project, files);
-        return commitAddedAndPush(git, gitConfig.getBranch(), cred, project.getProjectId());
+        return commitAddedAndPush(git, gitConfig.getBranch(), cred, message);
     }
 
     public List<GitRepo> readProjectsFromRepository() {
@@ -248,7 +248,7 @@ public class GitService {
     public RevCommit commitAddedAndPush(Git git, String branch, CredentialsProvider cred, String message) throws GitAPIException, IOException, URISyntaxException {
         LOGGER.info("Commit and push changes");
         LOGGER.info("Git add: " + git.add().addFilepattern(".").call());
-        RevCommit commit = git.commit().setMessage(LocalDateTime.now() + ": " + message).call();
+        RevCommit commit = git.commit().setMessage(message).call();
         LOGGER.info("Git commit: " + commit);
         Iterable<PushResult> result = git.push().add(branch).setRemote("origin").setCredentialsProvider(cred).call();
         LOGGER.info("Git push: " + result);
diff --git a/karavan-app/src/main/webui/src/api/KaravanApi.tsx b/karavan-app/src/main/webui/src/api/KaravanApi.tsx
index 5d9e84d0..53af69f5 100644
--- a/karavan-app/src/main/webui/src/api/KaravanApi.tsx
+++ b/karavan-app/src/main/webui/src/api/KaravanApi.tsx
@@ -273,8 +273,9 @@ export class KaravanApi {
         });
     }
 
-    static async push(project: Project, after: (res: AxiosResponse<any>) => void) {
-        instance.post('/api/git', project)
+    static async push(params: {}, after: (res: AxiosResponse<any>) => void) {
+        console.log(params)
+        instance.post('/api/git', params)
             .then(res => {
                 after(res);
             }).catch(err => {
diff --git a/karavan-app/src/main/webui/src/projects/ProjectPageToolbar.tsx b/karavan-app/src/main/webui/src/projects/ProjectPageToolbar.tsx
index e4acc565..35facb46 100644
--- a/karavan-app/src/main/webui/src/projects/ProjectPageToolbar.tsx
+++ b/karavan-app/src/main/webui/src/projects/ProjectPageToolbar.tsx
@@ -7,10 +7,10 @@ import {
     FlexItem,
     ToggleGroup,
     ToggleGroupItem,
-    Checkbox, Tooltip, ToolbarItem
+    Checkbox, Tooltip, ToolbarItem, Modal, ModalVariant, Form, FormGroup, TextInput, FormHelperText, HelperText, HelperTextItem
 } from '@patternfly/react-core';
 import '../designer/karavan.css';
-import {Project, ProjectFile} from "./ProjectModels";
+import {Project, ProjectFile, ProjectFileTypes} from "./ProjectModels";
 import UploadIcon from "@patternfly/react-icons/dist/esm/icons/upload-icon";
 import DownloadIcon from "@patternfly/react-icons/dist/esm/icons/download-icon";
 import DownloadImageIcon from "@patternfly/react-icons/dist/esm/icons/image-icon";
@@ -18,6 +18,7 @@ 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";
+import {CamelUi} from "../designer/utils/CamelUi";
 
 interface Props {
     project: Project,
@@ -40,17 +41,25 @@ interface Props {
 
 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});
-        KaravanApi.push(this.props.project, res => {
+        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);
@@ -84,7 +93,7 @@ export class ProjectPageToolbar extends React.Component<Props> {
                                         variant={needCommit ? "primary" : "secondary"}
                                         className="project-button"
                                         icon={!isPushing ? <PushIcon/> : <div></div>}
-                                        onClick={e => this.push()}>
+                                        onClick={() => this.setState({commitMessageIsOpen: true})}>
                                     {isPushing ? "..." : "Commit"}
                                 </Button>
                             </Tooltip>
@@ -96,7 +105,7 @@ export class ProjectPageToolbar extends React.Component<Props> {
     }
 
     getProjectToolbar() {
-        const {isPushing} = this.state;
+        const {isPushing, commitMessage} = this.state;
         const {file, needCommit, mode, editAdvancedProperties, addProperty, setEditAdvancedProperties, download, downloadImage, setCreateModalOpen, setUploadModalOpen} = this.props;
         const isFile = file !== undefined;
         const isYaml = file !== undefined && file.name.endsWith("yaml");
@@ -104,68 +113,95 @@ export class ProjectPageToolbar extends React.Component<Props> {
         const isProperties = file !== undefined && file.name.endsWith("properties");
         return <Toolbar id="toolbar-group-types">
             <ToolbarContent>
-                    <Flex className="toolbar" direction={{default: "row"}} alignItems={{default:"alignItemsCenter"}}>
-                        {isYaml && <FlexItem>
-                            <ToggleGroup>
-                                <ToggleGroupItem text="Design" buttonId="design" isSelected={mode === "design"}
-                                                 onChange={s => this.props.setMode.call(this, "design")} />
-                                <ToggleGroupItem text="Code" buttonId="code" isSelected={mode === "code"}
-                                                 onChange={s => this.props.setMode.call(this, "code")} />
-                            </ToggleGroup>
-                        </FlexItem>}
+                <Flex className="toolbar" direction={{default: "row"}} alignItems={{default: "alignItemsCenter"}}>
+                    {isYaml && <FlexItem>
+                        <ToggleGroup>
+                            <ToggleGroupItem text="Design" buttonId="design" isSelected={mode === "design"}
+                                             onChange={s => this.props.setMode.call(this, "design")}/>
+                            <ToggleGroupItem text="Code" buttonId="code" isSelected={mode === "code"}
+                                             onChange={s => this.props.setMode.call(this, "code")}/>
+                        </ToggleGroup>
+                    </FlexItem>}
 
-                        {isProperties && <FlexItem>
-                            <Checkbox
-                                id="advanced"
-                                label="Edit advanced"
-                                isChecked={editAdvancedProperties}
-                                onChange={checked => setEditAdvancedProperties.call(this, checked)}
-                            />
-                        </FlexItem>}
-                        {isProperties && <FlexItem>
-                            <Button isSmall variant="primary" icon={<PlusIcon/>} onClick={e => addProperty.call(this)}>Add property</Button>
-                        </FlexItem>}
+                    {isProperties && <FlexItem>
+                        <Checkbox
+                            id="advanced"
+                            label="Edit advanced"
+                            isChecked={editAdvancedProperties}
+                            onChange={checked => setEditAdvancedProperties.call(this, checked)}
+                        />
+                    </FlexItem>}
+                    {isProperties && <FlexItem>
+                        <Button isSmall variant="primary" icon={<PlusIcon/>} onClick={e => addProperty.call(this)}>Add property</Button>
+                    </FlexItem>}
 
-                        {isFile && <FlexItem>
-                            <Tooltip content="Download source" position={"bottom-end"}>
-                                <Button isSmall variant="control" icon={<DownloadIcon/>} onClick={e => download.call(this)}/>
-                            </Tooltip>
-                        </FlexItem>}
-                        {isIntegration && <FlexItem>
-                            <Tooltip content="Download image" position={"bottom-end"}>
-                                <Button isSmall variant="control" icon={<DownloadImageIcon/>} onClick={e => downloadImage.call(this)}/>
-                            </Tooltip>
-                        </FlexItem>}
-                        {!isFile && <FlexItem>
-                            <Button isSmall variant={"secondary"} icon={<PlusIcon/>}
-                                    onClick={e => setCreateModalOpen.call(this)}>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={e => this.push()}>
-                                    {isPushing ? "..." : "Commit"}
-                                </Button>
-                            </Tooltip>
-                        </FlexItem>}
-                    </Flex>
+                    {isFile && <FlexItem>
+                        <Tooltip content="Download source" position={"bottom-end"}>
+                            <Button isSmall variant="control" icon={<DownloadIcon/>} onClick={e => download.call(this)}/>
+                        </Tooltip>
+                    </FlexItem>}
+                    {isIntegration && <FlexItem>
+                        <Tooltip content="Download image" position={"bottom-end"}>
+                            <Button isSmall variant="control" icon={<DownloadImageIcon/>} onClick={e => downloadImage.call(this)}/>
+                        </Tooltip>
+                    </FlexItem>}
+                    {!isFile && <FlexItem>
+                        <Button isSmall variant={"secondary"} icon={<PlusIcon/>}
+                                onClick={e => setCreateModalOpen.call(this)}>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 ? "..." : "Commit"}
+                            </Button>
+                        </Tooltip>
+                    </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>
     }
 }