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 8ab2174 Saas fix1 (#361) 8ab2174 is described below commit 8ab217452014d37c5da087101dc14b51c3b41678 Author: Marat Gubaidullin <marat.gubaidul...@gmail.com> AuthorDate: Thu Jun 9 17:11:09 2022 -0400 Saas fix1 (#361) * New menu * Dockerfile * Dockerfile * Project create/copy * UI improvements * UI improvements * UI improvements --- karavan-app/pom.xml | 4 + .../org/apache/camel/karavan/api/GitResource.java | 4 +- .../apache/camel/karavan/api/ProjectResource.java | 21 ++- .../org/apache/camel/karavan/model/Project.java | 52 +++++-- .../apache/camel/karavan/service/GitService.java | 2 +- .../camel/karavan/service/InfinispanService.java | 25 ++-- karavan-app/src/main/webapp/src/Logo.tsx | 135 +++++++++--------- karavan-app/src/main/webapp/src/Main.tsx | 152 ++++++++++++--------- karavan-app/src/main/webapp/src/api/KaravanApi.tsx | 16 ++- .../main/webapp/src/components/ComponentCard.tsx | 1 - karavan-app/src/main/webapp/src/index.css | 40 ++++++ .../src/main/webapp/src/models/ProjectModels.ts | 29 +++- .../main/webapp/src/projects/CreateFileModal.tsx | 2 +- .../src/main/webapp/src/projects/ProjectPage.tsx | 99 ++++++++------ .../src/main/webapp/src/projects/ProjectsPage.tsx | 97 +++++++++---- karavan-docker/Dockerfile | 25 +++- karavan-docker/demo/application.properties | 2 - 17 files changed, 455 insertions(+), 251 deletions(-) diff --git a/karavan-app/pom.xml b/karavan-app/pom.xml index 67e2ada..2830d0a 100644 --- a/karavan-app/pom.xml +++ b/karavan-app/pom.xml @@ -94,6 +94,10 @@ <artifactId>camel-quarkus-kubernetes</artifactId> <version>2.9.0</version> </dependency> + <dependency> + <groupId>com.google.guava</groupId> + <artifactId>guava</artifactId> + </dependency> <!-- <dependency>--> <!-- <groupId>io.quarkus</groupId>--> <!-- <artifactId>quarkus-openshift</artifactId>--> 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 0368459..05966b4 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 @@ -64,8 +64,8 @@ public class GitResource { @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) public Project push(@HeaderParam("username") String username, Project project) throws Exception { - Project p = infinispanService.getProject(project.getName()); - List<ProjectFile> files = infinispanService.getProjectFiles(project.getName()); + Project p = infinispanService.getProject(project.getKey()); + List<ProjectFile> files = infinispanService.getProjectFiles(project.getKey()); String commitId = gitService.save(p, files); p.setLastCommit(commitId); infinispanService.saveProject(p); diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/api/ProjectResource.java b/karavan-app/src/main/java/org/apache/camel/karavan/api/ProjectResource.java index e22ff6a..b0cc160 100644 --- a/karavan-app/src/main/java/org/apache/camel/karavan/api/ProjectResource.java +++ b/karavan-app/src/main/java/org/apache/camel/karavan/api/ProjectResource.java @@ -16,6 +16,7 @@ */ package org.apache.camel.karavan.api; +import org.apache.camel.karavan.model.GroupedKey; import org.apache.camel.karavan.model.Project; import org.apache.camel.karavan.model.ProjectFile; import org.apache.camel.karavan.service.InfinispanService; @@ -34,6 +35,7 @@ import java.net.URLDecoder; import java.nio.charset.StandardCharsets; import java.util.Comparator; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; @Path("/project") @@ -46,7 +48,7 @@ public class ProjectResource { @Produces(MediaType.APPLICATION_JSON) public List<Project> getAll(@HeaderParam("username") String username) throws Exception { return infinispanService.getProjects().stream() - .sorted(Comparator.comparing(Project::getName)) + .sorted(Comparator.comparing(Project::getKey)) .collect(Collectors.toList()); } @@ -72,4 +74,21 @@ public class ProjectResource { @PathParam("project") String project) throws Exception { infinispanService.deleteProject(URLDecoder.decode(project, StandardCharsets.UTF_8.toString())); } + + @POST + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + @Path("/copy/{sourceProject}") + public Project copy(@HeaderParam("username") String username, @PathParam("sourceProject") String sourceProject, Project project) throws Exception { +// Save project + Project s = infinispanService.getProject(sourceProject); + project.setType(s.getType()); + infinispanService.saveProject(project); + +// Copy files + Map<GroupedKey, ProjectFile> map = infinispanService.getProjectFiles(sourceProject).stream() + .collect(Collectors.toMap(f -> new GroupedKey(project.getKey(), f.getName()), f -> f)); + infinispanService.saveProjectFiles(map); + return project; + } } \ No newline at end of file diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/model/Project.java b/karavan-app/src/main/java/org/apache/camel/karavan/model/Project.java index c432cd4..b90dff2 100644 --- a/karavan-app/src/main/java/org/apache/camel/karavan/model/Project.java +++ b/karavan-app/src/main/java/org/apache/camel/karavan/model/Project.java @@ -1,5 +1,6 @@ package org.apache.camel.karavan.model; +import com.google.common.base.CaseFormat; import org.infinispan.protostream.annotations.ProtoEnumValue; import org.infinispan.protostream.annotations.ProtoFactory; import org.infinispan.protostream.annotations.ProtoField; @@ -8,14 +9,16 @@ public class Project { public static final String CACHE = "projects"; @ProtoField(number = 1) - String name; + String groupId; @ProtoField(number = 2) - String version; + String artifactId; @ProtoField(number = 3) - String folder; + String version; @ProtoField(number = 4) - ProjectType type; + String folder; @ProtoField(number = 5) + ProjectType type; + @ProtoField(number = 6) String lastCommit; public enum ProjectType { @@ -28,30 +31,53 @@ public class Project { } @ProtoFactory - public Project(String name, String version, String folder, ProjectType type, String lastCommit) { - this.name = name; + public Project(String groupId, String artifactId, String version, String folder, ProjectType type, String lastCommit) { + this.groupId = groupId; + this.artifactId = artifactId; this.version = version; this.folder = folder; this.type = type; this.lastCommit = lastCommit; } - public Project(String name, String version, String folder, ProjectType type) { - this.name = name; + public Project(String groupId, String artifactId, String version, String folder, ProjectType type) { + this.groupId = groupId; + this.artifactId = artifactId; this.version = version; - this.folder = folder; + this.folder = folder != null && folder.trim().length() > 0 ? folder : toFolder(groupId, artifactId, version); this.type = type; } + private String toFolder(String groupId, String artifactId, String version){ + String folder = toKey(groupId, artifactId, version).replaceAll("[^A-Za-z0-9 ]", "_"); + return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, folder); + } + + private String toKey(String groupId, String artifactId, String version){ + return groupId + ":" + artifactId + ":" + version; + } + + public String getKey(){ + return toKey(groupId, artifactId, version); + } + public Project() { } - public String getName() { - return name; + public String getGroupId() { + return groupId; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public String getArtifactId() { + return artifactId; } - public void setName(String name) { - this.name = name; + public void setArtifactId(String artifactId) { + this.artifactId = artifactId; } public String getVersion() { 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 611f186..4dbcd60 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 @@ -78,7 +78,7 @@ public class GitService { } public String save(Project project, List<ProjectFile> files) throws GitAPIException, IOException, URISyntaxException { - LOGGER.info("Save project " + project.getName()); + LOGGER.info("Save project " + project.getKey()); String uuid = UUID.randomUUID().toString(); String folder = vertx.fileSystem().createTempDirectoryBlocking(uuid); LOGGER.infof("Temp folder created: {}", folder); diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/service/InfinispanService.java b/karavan-app/src/main/java/org/apache/camel/karavan/service/InfinispanService.java index accd14f..4b043e5 100644 --- a/karavan-app/src/main/java/org/apache/camel/karavan/service/InfinispanService.java +++ b/karavan-app/src/main/java/org/apache/camel/karavan/service/InfinispanService.java @@ -39,6 +39,7 @@ import javax.enterprise.context.ApplicationScoped; import javax.enterprise.event.Observes; import javax.inject.Inject; import java.util.List; +import java.util.Map; import java.util.Random; import java.util.stream.Collectors; @@ -75,12 +76,14 @@ public class InfinispanService { } for (int i = 0; i < 10; i++){ - String project = "parcel-demo" + i; - projects.put(GroupedKey.create(project, project), new Project(project, "1.0.0", project, Project.ProjectType.values()[new Random().nextInt(3)])); - - files.put(GroupedKey.create(project,"new-parcels.yaml"), new ProjectFile("new-parcels.yaml", "flows:", project)); - files.put(GroupedKey.create(project,"parcel-confirmation.yaml"), new ProjectFile("parcel-confirmation.yaml", "rest:", project)); - files.put(GroupedKey.create(project,"CustomProcessor.java"), new ProjectFile("CustomProcessor.java", "import org.apache.camel.BindToRegistry;\n" + + String groupId = "org.apache.camel.karavan"; + String artifactId = "parcel-demo" + i; + Project p = new Project(groupId, artifactId, "1.0.0", null, Project.ProjectType.values()[new Random().nextInt(3)]); + projects.put(GroupedKey.create(p.getKey(), p.getKey()), p); + + files.put(GroupedKey.create(p.getKey(),"new-parcels.yaml"), new ProjectFile("new-parcels.yaml", "flows:", p.getKey())); + files.put(GroupedKey.create(p.getKey(),"parcel-confirmation.yaml"), new ProjectFile("parcel-confirmation.yaml", "rest:", p.getKey())); + files.put(GroupedKey.create(p.getKey(),"CustomProcessor.java"), new ProjectFile("CustomProcessor.java", "import org.apache.camel.BindToRegistry;\n" + "import org.apache.camel.Exchange;\n" + "import org.apache.camel.Processor;\n" + "\n" + @@ -90,8 +93,8 @@ public class InfinispanService { " public void process(Exchange exchange) throws Exception {\n" + " exchange.getIn().setBody(\"Hello world\");\n" + " }\n" + - "}", project)); - files.put(GroupedKey.create(project,"application.properties"), new ProjectFile("application.properties", "parameter1:hello", project)); + "}", p.getKey())); + files.put(GroupedKey.create(p.getKey(),"application.properties"), new ProjectFile("application.properties", "parameter1:hello", p.getKey())); } } @@ -100,7 +103,7 @@ public class InfinispanService { } public void saveProject(Project project) { - projects.put(GroupedKey.create(project.getName(), project.getName()), project); + projects.put(GroupedKey.create(project.getKey(), project.getKey()), project); } public List<ProjectFile> getProjectFiles(String projectName) { @@ -121,6 +124,10 @@ public class InfinispanService { files.put(GroupedKey.create(file.getProject(), file.getName()), file); } + public void saveProjectFiles(Map<GroupedKey, ProjectFile> f) { + files.putAll(f); + } + public void deleteProject(String project) { projects.remove(GroupedKey.create(project, project)); } diff --git a/karavan-app/src/main/webapp/src/Logo.tsx b/karavan-app/src/main/webapp/src/Logo.tsx index 82c49d4..b59e932 100644 --- a/karavan-app/src/main/webapp/src/Logo.tsx +++ b/karavan-app/src/main/webapp/src/Logo.tsx @@ -2,20 +2,31 @@ import React from "react"; function Icon() { return ( - <div className="logo"> <svg xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink" - width="1132.022" - height="360.139" + id="svg50" + width="256" + height="256" preserveAspectRatio="xMidYMid" version="1.1" - viewBox="0 0 1132.022 360.139" + viewBox="0 0 256 256" + className="logo" > - <defs> + <defs id="defs31"> <linearGradient id="linearGradient1351"> - <stop offset="0" stopColor="#dcffff" stopOpacity="1"></stop> - <stop offset="1" stopColor="#96d2e6" stopOpacity="1"></stop> + <stop + id="stop1347" + offset="0" + stopColor="#dcffff" + stopOpacity="1" + ></stop> + <stop + id="stop1349" + offset="1" + stopColor="#96d2e6" + stopOpacity="1" + ></stop> </linearGradient> <circle id="path-1" cx="128" cy="128" r="128"></circle> <linearGradient @@ -26,9 +37,24 @@ function Icon() { y2="0.048" gradientUnits="userSpaceOnUse" > - <stop offset="0%" stopColor="#4790bb" stopOpacity="1"></stop> - <stop offset="10.996%" stopColor="#64b7db" stopOpacity="1"></stop> - <stop offset="94.502%" stopColor="#326ea0" stopOpacity="1"></stop> + <stop + id="stop10" + offset="0%" + stopColor="#4790bb" + stopOpacity="1" + ></stop> + <stop + id="stop12" + offset="10.996%" + stopColor="#64b7db" + stopOpacity="1" + ></stop> + <stop + id="stop14" + offset="94.502%" + stopColor="#326ea0" + stopOpacity="1" + ></stop> </linearGradient> <linearGradient id="linearGradient-4" @@ -38,9 +64,9 @@ function Icon() { y2="-5.028" gradientUnits="userSpaceOnUse" > - <stop offset="0%" stopColor="#F69923"></stop> - <stop offset="8.048%" stopColor="#F79A23"></stop> - <stop offset="41.874%" stopColor="#E97826"></stop> + <stop id="stop17" offset="0%" stopColor="#F69923"></stop> + <stop id="stop19" offset="8.048%" stopColor="#F79A23"></stop> + <stop id="stop21" offset="41.874%" stopColor="#E97826"></stop> </linearGradient> <linearGradient id="linearGradient-5" @@ -52,15 +78,30 @@ function Icon() { gradientUnits="userSpaceOnUse" xlinkHref="#linearGradient-4" > - <stop offset="0%" stopColor="#92d6d5" stopOpacity="1"></stop> - <stop offset="41.191%" stopColor="#79b7cc" stopOpacity="1"></stop> - <stop offset="73.271%" stopColor="#5891c5" stopOpacity="1"></stop> + <stop + id="stop24" + offset="0%" + stopColor="#92d6d5" + stopOpacity="1" + ></stop> + <stop + id="stop26" + offset="41.191%" + stopColor="#79b7cc" + stopOpacity="1" + ></stop> + <stop + id="stop28" + offset="73.271%" + stopColor="#5891c5" + stopOpacity="1" + ></stop> </linearGradient> <mask id="mask-2" fill="#fff"> - <use width="100%" height="100%" x="0" y="0" xlinkHref="#path-1"></use> + <use id="use33" xlinkHref="#path-1"></use> </mask> <mask id="mask-2-7" fill="#fff"> - <use width="100%" height="100%" x="0" y="0" xlinkHref="#path-1"></use> + <use id="use137" xlinkHref="#path-1"></use> </mask> <linearGradient id="linearGradient1345" @@ -73,16 +114,17 @@ function Icon() { ></linearGradient> </defs> <circle + id="circle38" cx="127.994" cy="127.994" r="123.111" fill="url(#linearGradient-3)" fillRule="nonzero" mask="url(#mask-2)" - transform="translate(45.105 56.042)" ></circle> - <g transform="translate(45.105 56.042)"> + <g id="g2266"> <path + id="path42" fill="url(#linearGradient-5)" fillOpacity="1" fillRule="nonzero" @@ -92,76 +134,33 @@ function Icon() { ></path> </g> <path + id="path44" fill="#1e4b7b" fillOpacity="1" fillRule="nonzero" d="M84.752 77.368C66.895 83.378 32.83 104.546.079 132.81c2.487 67.334 57.028 121.313 124.548 123.07 33.233-64.016 13.901-137.68-39.875-178.513z" mask="url(#mask-2)" opacity="0.75" - transform="translate(45.105 56.042)" ></path> <path + id="path150" fill="url(#linearGradient1345)" fillOpacity="1" fillRule="nonzero" d="M128.747 54.005c-10.985 5.495 0 27.466 0 27.466C95.774 108.954 102.78 155.9 64.312 155.9c-20.97 0-42.242-24.077-64.233-38.828-.283 3.479-.785 6.972-.785 10.524 0 48.095 26.263 89.924 65.42 111.897 10.952-1.38 22.838-4.114 31.05-9.592 43.146-28.765 53.857-83.491 71.487-109.925 10.979-16.492 62.434-15.061 65.906-22.01 5.502-10.991-10.99-27.467-16.491-27.467h-43.958c-3.071 0-7.897-5.456-10.974-5.456h-16.492s-7.307-11.085-13.794-11.526c-.93-.066-1.83.053-2.7.488z" mask="url(#mask-2-7)" - transform="translate(44.336 55.909)" + transform="translate(-.769 -.133)" ></path> <path + id="path40" fill="#2d4150" fillOpacity="1" fillRule="nonzero" d="M128 256C57.308 256 0 198.692 0 128 0 57.308 57.308 0 128 0c70.692 0 128 57.308 128 128 0 70.692-57.308 128-128 128zm0-9.768c65.298 0 118.232-52.934 118.232-118.232S193.298 9.768 128 9.768 9.768 62.702 9.768 128 62.702 246.232 128 246.232z" mask="url(#mask-2)" - transform="matrix(1.02035 0 0 1.02035 41.98 53.958)" + transform="translate(-.59) scale(1.00078)" ></path> - <text - xmlSpace="preserve" - style={{ - lineHeight: "1.25", - fontVariantLigatures: "normal", - fontVariantCaps: "normal", - fontVariantNumeric: "normal", - fontVariantEastAsian: "normal", - }} - x="346.913" - y="259.391" - fill="#96d2e6" - fillOpacity="1" - stroke="none" - strokeWidth="5.349" - fontFamily="M PLUS 1 Code" - fontSize="213.949" - fontStretch="normal" - fontStyle="normal" - fontVariant="normal" - fontWeight="normal" - > - <tspan - x="346.913" - y="259.391" - style={{ - fontVariantLigatures: "normal", - fontVariantCaps: "normal", - fontVariantNumeric: "normal", - fontVariantEastAsian: "normal", - }} - fill="#96d2e6" - fillOpacity="1" - strokeWidth="5.349" - fontFamily="M PLUS 1 Code" - fontSize="213.949" - fontStretch="normal" - fontStyle="normal" - fontVariant="normal" - fontWeight="normal" - > - Karavan - </tspan> - </text> </svg> - </div> ); } diff --git a/karavan-app/src/main/webapp/src/Main.tsx b/karavan-app/src/main/webapp/src/Main.tsx index 82454cb..d994bdb 100644 --- a/karavan-app/src/main/webapp/src/Main.tsx +++ b/karavan-app/src/main/webapp/src/Main.tsx @@ -2,10 +2,6 @@ import React from 'react'; import { Page, PageHeader, - PageSidebar, - NavItem, - NavList, - Nav, ModalVariant, Button, Modal, @@ -16,7 +12,11 @@ import { Avatar, PageHeaderTools, PageHeaderToolsGroup, - PageHeaderToolsItem, Dropdown, DropdownToggle, NavExpandable, NavGroup + PageHeaderToolsItem, + Dropdown, + DropdownToggle, + Tooltip, + Divider } from '@patternfly/react-core'; import {KaravanApi} from "./api/KaravanApi"; import {KameletApi} from "karavan-core/lib/api/KameletApi"; @@ -33,6 +33,13 @@ import {OpenApiPage} from "./integrations/OpenApiPage"; import {ProjectsPage} from "./projects/ProjectsPage"; import {Project} from "./models/ProjectModels"; import {ProjectPage} from "./projects/ProjectPage"; +import TachometerAltIcon from "@patternfly/react-icons/dist/js/icons/tachometer-alt-icon"; +import UsersIcon from "@patternfly/react-icons/dist/js/icons/users-icon"; +import ProjectsIcon from "@patternfly/react-icons/dist/js/icons/repository-icon"; +import KameletsIcon from "@patternfly/react-icons/dist/js/icons/registry-icon"; +import EipIcon from "@patternfly/react-icons/dist/js/icons/topology-icon"; +import ComponentsIcon from "@patternfly/react-icons/dist/js/icons/module-icon"; +import ConfigurationIcon from "@patternfly/react-icons/dist/js/icons/cogs-icon"; class ToastMessage { id: string = '' @@ -48,6 +55,18 @@ class ToastMessage { } } +class MenuItem { + pageId: string = ''; + tooltip: string = ''; + icon: any; + + constructor(pageId: string, tooltip: string, icon: any) { + this.pageId = pageId; + this.tooltip = tooltip; + this.icon = icon; + } +} + interface Props { } @@ -55,7 +74,7 @@ interface State { version: string, mode: 'local' | 'gitops' | 'serverless', isNavOpen: boolean, - pageId: 'projects' | 'project' | 'configuration' | 'kamelets' | 'designer' | "components" | "eip" | "openapi" | "acl" + pageId: string, projects: Project[], project?: Project, isModalOpen: boolean, @@ -118,13 +137,6 @@ export class Main extends React.Component<Props, State> { <div className="top-toolbar"> <Flex direction={{default: "row"}} justifyContent={{default: "justifyContentSpaceBetween"}} style={{width: "100%"}}> - <FlexItem style={{marginTop: "auto", marginBottom: "auto"}}> - {/*<FlexItem>*/} - {/* <TextContent>*/} - {/* <Text component={TextVariants.h5}>{"v. " + version}</Text>*/} - {/* </TextContent>*/} - {/*</FlexItem>*/} - </FlexItem> <FlexItem style={{marginTop: "auto", marginBottom: "auto"}}> <PageHeaderTools> <PageHeaderToolsGroup> @@ -157,40 +169,42 @@ export class Main extends React.Component<Props, State> { logo={Icon()} headerTools={this.toolBar(version)} /> - ); - - pageNav = () => (<Nav onSelect={this.onNavSelect}> - <NavList> - <NavItem id="projects" to="#" itemId={'projects'} - isActive={this.state.pageId === 'projects'}> - Projects - </NavItem> - <NavItem id="configuration" to="#" itemId={"configuration"} - isActive={this.state.pageId === 'configuration'}> - Configuration - </NavItem> - <NavItem id="acl" to="#" itemId={"acl"} - isActive={this.state.pageId === 'acl'}> - User Management - </NavItem> - <NavExpandable id="help" title={"Help"} isExpanded={false}> - <NavItem id="eip" to="#" itemId={"eip"} - isActive={this.state.pageId === 'eip'}> - Enterprise Integration Patterns - </NavItem> - <NavItem id="kamelets" to="#" itemId={"kamelets"} - isActive={this.state.pageId === 'kamelets'}> - Kamelets - </NavItem> - <NavItem id="components" to="#" itemId={"components"} - isActive={this.state.pageId === 'components'}> - Components - </NavItem> - </NavExpandable> - </NavList> - </Nav>); + ) - sidebar = () => (<PageSidebar nav={this.pageNav()} isNavOpen={this.state.isNavOpen}/>); + pageNav = () => { + const pages: MenuItem[] = [ + new MenuItem("dashboard", "Dashboard", <TachometerAltIcon/>), + new MenuItem("projects", "Projects", <ProjectsIcon/>), + new MenuItem("eip", "Enterprise Integration Patterns", <EipIcon/>), + new MenuItem("kamelets", "Kamelets", <KameletsIcon/>), + new MenuItem("components", "Components", <ComponentsIcon/>), + new MenuItem("acl", "Access Control", <UsersIcon/>), + new MenuItem("configuration", "Configuration", <ConfigurationIcon/>) + ] + return (<Flex className="nav-buttons" direction={{default: "column"}} style={{height:"100%"}} spaceItems={{default:"spaceItemsNone"}}> + <FlexItem alignSelf={{default:"alignSelfCenter"}}> + <Tooltip content={"Apache Camel Karavan"} position={"right"}> + {Icon()} + </Tooltip> + </FlexItem> + {pages.map(page => + <FlexItem className={this.state.pageId === page.pageId ? "nav-button-selected" : ""}> + <Tooltip content={page.tooltip} position={"right"}> + <Button id={page.pageId} icon={page.icon} variant={"plain"} + className={this.state.pageId === page.pageId ? "nav-button-selected" : ""} + onClick={event => this.setState({pageId: page.pageId})} + /> + </Tooltip> + </FlexItem> + )} + <FlexItem flex={{default:"flex_2"}} alignSelf={{default:"alignSelfCenter"}}> + <Divider/> + </FlexItem> + <FlexItem alignSelf={{default:"alignSelfCenter"}}> + <Avatar src={avatarImg} alt="avatar" border="dark"/> + </FlexItem> + </Flex>) + } onProjectDelete = (project: Project) => { this.setState({isModalOpen: true, projectToDelete: project}) @@ -235,7 +249,7 @@ export class Main extends React.Component<Props, State> { }; onGetProjects() { - KaravanApi.getProjects((projects: []) => { + KaravanApi.getProjects((projects: Project[]) => { this.setState({ projects: projects, request: uuidv4() }) @@ -244,24 +258,30 @@ export class Main extends React.Component<Props, State> { render() { return ( - <Page className="karavan" header={this.header(this.state.version)} sidebar={this.sidebar()}> - {this.state.pageId === 'projects' && - <ProjectsPage key={this.state.request} - projects={this.state.projects} - onDelete={this.onProjectDelete} - onSelect={this.onProjectSelect} - onRefresh={() => { - this.onGetProjects(); - }} - onCreate={this.onProjectCreate}/>} - {this.state.pageId === 'project' && this.state.project && <ProjectPage project={this.state.project}/>} - {this.state.pageId === 'configuration' && <ConfigurationPage/>} - {this.state.pageId === 'kamelets' && <KameletsPage dark={false}/>} - {this.state.pageId === 'components' && <ComponentsPage dark={false}/>} - {this.state.pageId === 'eip' && <EipPage dark={false}/>} - {this.state.pageId === 'openapi' && - <OpenApiPage dark={false} openapi={this.state.openapi} filename={this.state.filename}/>} - + <Page className="karavan"> + <Flex style={{width: "100%", height:"100%"}} alignItems={{default:"alignItemsStretch"}} spaceItems={{ default: 'spaceItemsNone' }}> + <FlexItem> + {this.pageNav()} + </FlexItem> + <FlexItem flex={{default:"flex_2"}} style={{height:"100%"}}> + {this.state.pageId === 'projects' && + <ProjectsPage key={this.state.request} + projects={this.state.projects} + onDelete={this.onProjectDelete} + onSelect={this.onProjectSelect} + onRefresh={() => { + this.onGetProjects(); + }} + onCreate={this.onProjectCreate}/>} + {this.state.pageId === 'project' && this.state.project && <ProjectPage project={this.state.project}/>} + {this.state.pageId === 'configuration' && <ConfigurationPage/>} + {this.state.pageId === 'kamelets' && <KameletsPage dark={false}/>} + {this.state.pageId === 'components' && <ComponentsPage dark={false}/>} + {this.state.pageId === 'eip' && <EipPage dark={false}/>} + {this.state.pageId === 'openapi' && + <OpenApiPage dark={false} openapi={this.state.openapi} filename={this.state.filename}/>} + </FlexItem> + </Flex> <Modal title="Confirmation" variant={ModalVariant.small} @@ -273,7 +293,7 @@ export class Main extends React.Component<Props, State> { onClick={e => this.setState({isModalOpen: false})}>Cancel</Button> ]} onEscapePress={e => this.setState({isModalOpen: false})}> - <div>{"Are you sure you want to delete the project " + this.state.projectToDelete?.name + "?"}</div> + <div>{"Are you sure you want to delete the project " + this.state.projectToDelete?.getKey() + "?"}</div> </Modal> {this.state.alerts.map((e: ToastMessage) => ( <Alert key={e.id} className="main-alert" variant={e.variant} title={e.title} diff --git a/karavan-app/src/main/webapp/src/api/KaravanApi.tsx b/karavan-app/src/main/webapp/src/api/KaravanApi.tsx index c5adbac..cb59783 100644 --- a/karavan-app/src/main/webapp/src/api/KaravanApi.tsx +++ b/karavan-app/src/main/webapp/src/api/KaravanApi.tsx @@ -27,12 +27,12 @@ export const KaravanApi = { }); }, - getProjects: async (after: (projects: []) => void) => { + getProjects: async (after: (projects: Project[]) => void) => { axios.get('/project', {headers: {'Accept': 'application/json', 'username': 'cameleer'}}) .then(res => { if (res.status === 200) { - after(res.data); + after(res.data.map((p: Partial<Project> | undefined) => new Project(p))); } }).catch(err => { console.log(err); @@ -49,8 +49,18 @@ export const KaravanApi = { }); }, + copyProject: async (sourceProject: string, project: Project, after: (res: AxiosResponse<any>) => void) => { + axios.post('/project/copy/' + sourceProject, project, + {headers: {'Accept': 'application/json', 'Content-Type': 'application/json', 'username': 'cameleer'}}) + .then(res => { + after(res); + }).catch(err => { + after(err); + }); + }, + deleteProject: async (project: Project, after: (res: AxiosResponse<any>) => void) => { - axios.delete('/project/' + encodeURI(project.name), + axios.delete('/project/' + encodeURI(project.getKey()), {headers:{'username': 'cameleer'}}) .then(res => { after(res); diff --git a/karavan-app/src/main/webapp/src/components/ComponentCard.tsx b/karavan-app/src/main/webapp/src/components/ComponentCard.tsx index 925c720..2b56994 100644 --- a/karavan-app/src/main/webapp/src/components/ComponentCard.tsx +++ b/karavan-app/src/main/webapp/src/components/ComponentCard.tsx @@ -3,7 +3,6 @@ import { CardHeader, Card, CardTitle, CardBody, CardActions, CardFooter,Badge } from '@patternfly/react-core'; import '../designer/karavan.css'; -import {KameletModel} from "karavan-core/lib/model/KameletModels"; import {camelIcon, CamelUi} from "../designer/utils/CamelUi"; import {Component} from "karavan-core/lib/model/ComponentModels"; diff --git a/karavan-app/src/main/webapp/src/index.css b/karavan-app/src/main/webapp/src/index.css index 8810b6b..26e7528 100644 --- a/karavan-app/src/main/webapp/src/index.css +++ b/karavan-app/src/main/webapp/src/index.css @@ -19,6 +19,46 @@ width: unset; } +.karavan .nav-buttons { + background: var(--pf-c-page__header--BackgroundColor); +} + +.karavan .nav-buttons .logo { + margin-top: 16px; + margin-bottom: 10px; + width: 32px; + height: 32px; +} + +.karavan .nav-buttons .pf-c-button { + padding: 0; + width: 64px; + height: 64px; + color: var(--pf-global--Color--light-100); +} + +.karavan .nav-buttons .pf-c-button svg { + width: 24px; +} + +.karavan .nav-buttons .pf-c-avatar { + width: 32px; + height: 32px; + margin-bottom: 6px; +} + +.karavan .nav-buttons .pf-c-button.pf-m-plain { + border-left-width: 3px; + border-left-style: solid; + border-left-color: transparent; + border-radius: 0; +} + +.karavan .nav-button-selected .pf-c-button.pf-m-plain { + border-left-color: var(--pf-global--active-color--400); + background-color: var(--pf-global--BackgroundColor--dark-400); +} + .karavan .kamelet-section { display: flex; flex-direction: column; diff --git a/karavan-app/src/main/webapp/src/models/ProjectModels.ts b/karavan-app/src/main/webapp/src/models/ProjectModels.ts index 2ef6775..add44cc 100644 --- a/karavan-app/src/main/webapp/src/models/ProjectModels.ts +++ b/karavan-app/src/main/webapp/src/models/ProjectModels.ts @@ -1,16 +1,31 @@ export class Project { - name: string = ''; + groupId: string = ''; + artifactId: string = ''; version: string = ''; folder: string = ''; type: string = ''; lastCommit: string = ''; - constructor(name: string, version: string, folder: string, type: string, lastCommit: string) { - this.name = name; - this.version = version; - this.folder = folder; - this.type = type; - this.lastCommit = lastCommit; + + public constructor(groupId: string, artifactId: string, version: string, folder: string, type: string, lastCommit: string); + public constructor(init?: Partial<Project>); + public constructor(...args: any[]) { + if (args.length === 1){ + Object.assign(this, args[0]); + return; + } else { + this.groupId = args[0]; + this.artifactId = args[1]; + this.version = args[2]; + this.folder = args[3]; + this.type = args[4]; + this.lastCommit = args[5]; + return; + } + } + + getKey():string{ + return this.groupId + ":" + this.artifactId + ":" + this.version; } } diff --git a/karavan-app/src/main/webapp/src/projects/CreateFileModal.tsx b/karavan-app/src/main/webapp/src/projects/CreateFileModal.tsx index e965583..cdc3822 100644 --- a/karavan-app/src/main/webapp/src/projects/CreateFileModal.tsx +++ b/karavan-app/src/main/webapp/src/projects/CreateFileModal.tsx @@ -38,7 +38,7 @@ export class CreateFileModal extends React.Component<Props, State> { const {name, extension} = this.state; const filename = (extension !== 'java') ? CamelUi.nameFromTitle(name) : CamelUi.javaNameFromTitle(name) if (filename && extension){ - const file = new ProjectFile(filename + '.' + extension, this.props.project.name, ''); + const file = new ProjectFile(filename + '.' + extension, this.props.project.getKey(), ''); KaravanApi.postProjectFile(file, res => { if (res.status === 200) { console.log(res) //TODO show notification diff --git a/karavan-app/src/main/webapp/src/projects/ProjectPage.tsx b/karavan-app/src/main/webapp/src/projects/ProjectPage.tsx index a8d353e..f02cff3 100644 --- a/karavan-app/src/main/webapp/src/projects/ProjectPage.tsx +++ b/karavan-app/src/main/webapp/src/projects/ProjectPage.tsx @@ -4,14 +4,9 @@ import { Breadcrumb, BreadcrumbItem, Button, - Form, - FormGroup, PageSection, Text, TextContent, - TextInput, - ToggleGroup, - ToggleGroupItem, Toolbar, ToolbarContent, ToolbarItem, @@ -26,14 +21,13 @@ import { EmptyStateVariant, EmptyStateIcon, Title, - ModalVariant, Modal, Spinner, Tooltip + ModalVariant, Modal, Spinner, Tooltip, Flex, FlexItem, } from '@patternfly/react-core'; import '../designer/karavan.css'; import {MainToolbar} from "../MainToolbar"; import {KaravanApi} from "../api/KaravanApi"; import {Project, ProjectFile, ProjectFileTypes} from "../models/ProjectModels"; import {CamelUi} from "../designer/utils/CamelUi"; -import {CamelUtil} from "karavan-core/lib/api/CamelUtil"; import UploadIcon from "@patternfly/react-icons/dist/esm/icons/upload-icon"; import {TableComposable, Tbody, Td, Th, Thead, Tr} from "@patternfly/react-table"; import DeleteIcon from "@patternfly/react-icons/dist/js/icons/times-icon"; @@ -160,7 +154,7 @@ export class ProjectPage extends React.Component<Props, State> { <div> <Breadcrumb> <BreadcrumbItem to="#" - onClick={event => this.setState({file: undefined})}>{"Project: " + this.props.project?.name}</BreadcrumbItem> + onClick={event => this.setState({file: undefined})}>{"Project: " + this.props.project?.getKey()}</BreadcrumbItem> <BreadcrumbItem to="#" isActive>{this.getType(file?.name)}</BreadcrumbItem> </Breadcrumb> <TextContent className="title"> @@ -176,12 +170,12 @@ export class ProjectPage extends React.Component<Props, State> { onRefresh = () => { if (this.props.project) { - KaravanApi.getProject(this.props.project.name, (project: Project) => { + KaravanApi.getProject(this.props.project.getKey(), (project: Project) => { this.setState({ project: project }) }); - KaravanApi.getFiles(this.props.project.name, (files: []) => { + KaravanApi.getFiles(this.props.project.getKey(), (files: []) => { this.setState({ files: files }) @@ -246,41 +240,56 @@ export class ProjectPage extends React.Component<Props, State> { const project = this.state.project; return ( <Card> - <CardBody> - <DescriptionList isHorizontal> - <DescriptionListGroup> - <DescriptionListTerm>Name</DescriptionListTerm> - <DescriptionListDescription>{CamelUi.titleFromName(project?.name)}</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Version</DescriptionListTerm> - <DescriptionListDescription>{project?.version}</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Folder</DescriptionListTerm> - <DescriptionListDescription>{project?.folder}</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Type</DescriptionListTerm> - <DescriptionListDescription> - <ToggleGroup aria-label="Default with single selectable"> - {["KARAVAN", "QUARKUS", "SPRING"].map(value => - <ToggleGroupItem key={value} - text={CamelUtil.capitalizeName(value.toLowerCase())} - buttonId={value} isSelected={project?.type === value}/> - )} - </ToggleGroup> - </DescriptionListDescription> - </DescriptionListGroup> - {project?.lastCommit && <DescriptionListGroup> - <DescriptionListTerm>Latest Commit</DescriptionListTerm> - <DescriptionListDescription> - <Tooltip content={project?.lastCommit} position={"right"}> - <Badge>{project?.lastCommit.substr(0, 7)}</Badge> - </Tooltip> - </DescriptionListDescription> - </DescriptionListGroup>} - </DescriptionList> + <CardBody isFilled> + <Flex direction={{default: "row"}} alignContent={{default: "alignContentSpaceBetween"}} + style={{width: "100%"}}> + <FlexItem flex={{default: "flex_1"}}> + <DescriptionList isHorizontal> + <DescriptionListGroup> + <DescriptionListTerm>Group</DescriptionListTerm> + <DescriptionListDescription>{project?.groupId}</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Artifact</DescriptionListTerm> + <DescriptionListDescription>{project?.artifactId}</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Version</DescriptionListTerm> + <DescriptionListDescription>{project?.version}</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Type</DescriptionListTerm> + <DescriptionListDescription> + <Tooltip content={"Folder: " + project?.folder} position={"bottom"}> + <Badge>{project?.type.toLowerCase()}</Badge> + </Tooltip> + </DescriptionListDescription> + </DescriptionListGroup> + </DescriptionList> + </FlexItem> + <FlexItem flex={{default: "flex_1"}}> + <DescriptionList isHorizontal> + <DescriptionListGroup> + <DescriptionListTerm>Latest Commit</DescriptionListTerm> + <DescriptionListDescription> + <Tooltip content={project?.lastCommit} position={"bottom"}> + <Badge>{project?.lastCommit?.substr(0, 7)}</Badge> + </Tooltip> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Deployment</DescriptionListTerm> + <DescriptionListDescription> + <Flex direction={{default: "row"}}> + <FlexItem><Badge isRead>dev</Badge></FlexItem> + <FlexItem><Badge isRead>test</Badge></FlexItem> + <FlexItem><Badge isRead>prod</Badge></FlexItem> + </Flex> + </DescriptionListDescription> + </DescriptionListGroup> + </DescriptionList> + </FlexItem> + </Flex> </CardBody> </Card> ) diff --git a/karavan-app/src/main/webapp/src/projects/ProjectsPage.tsx b/karavan-app/src/main/webapp/src/projects/ProjectsPage.tsx index e8c933f..5033c0b 100644 --- a/karavan-app/src/main/webapp/src/projects/ProjectsPage.tsx +++ b/karavan-app/src/main/webapp/src/projects/ProjectsPage.tsx @@ -18,18 +18,25 @@ import { ToggleGroupItem, Bullseye, EmptyState, - EmptyStateVariant, EmptyStateIcon, Title + EmptyStateVariant, + EmptyStateIcon, + Title, + OverflowMenu, + OverflowMenuContent, + OverflowMenuGroup, + OverflowMenuItem, + Flex, FlexItem } from '@patternfly/react-core'; import '../designer/karavan.css'; import {MainToolbar} from "../MainToolbar"; import RefreshIcon from '@patternfly/react-icons/dist/esm/icons/sync-alt-icon'; import PlusIcon from '@patternfly/react-icons/dist/esm/icons/plus-icon'; import {Project} from "../models/ProjectModels"; -import {CamelUi} from "../designer/utils/CamelUi"; import {TableComposable, Tbody, Td, Th, Thead, Tr} from "@patternfly/react-table"; import DeleteIcon from "@patternfly/react-icons/dist/js/icons/times-icon"; import {CamelUtil} from "karavan-core/lib/api/CamelUtil"; import SearchIcon from '@patternfly/react-icons/dist/esm/icons/search-icon'; +import CopyIcon from "@patternfly/react-icons/dist/esm/icons/copy-icon"; interface Props { projects: Project[], @@ -42,8 +49,11 @@ interface Props { interface State { projects: Project[], isCreateModalOpen: boolean, + isCopy: boolean, + projectToCopy?: Project, filter: string, - name: string, + groupId: string, + artifactId: string, version: string, folder: string, type: string, @@ -54,8 +64,10 @@ export class ProjectsPage extends React.Component<Props, State> { public state: State = { projects: this.props.projects, isCreateModalOpen: false, + isCopy: false, filter: '', - name: '', + groupId: '', + artifactId: '', version: '', folder: '', type: 'KARAVAN', @@ -74,7 +86,7 @@ export class ProjectsPage extends React.Component<Props, State> { onClick={e => this.props.onRefresh.call(this)}>Refresh</Button> </ToolbarItem> <ToolbarItem> - <Button icon={<PlusIcon/>} onClick={e => this.setState({isCreateModalOpen: true})}>Create</Button> + <Button icon={<PlusIcon/>} onClick={e => this.setState({isCreateModalOpen: true, isCopy: false})}>Create</Button> </ToolbarItem> </ToolbarContent> </Toolbar>); @@ -84,27 +96,28 @@ export class ProjectsPage extends React.Component<Props, State> { </TextContent>); closeModal = () => { - this.setState({isCreateModalOpen: false, name: '', version: '', folder: '', type: 'KARAVAN'}); + this.setState({isCreateModalOpen: false, isCopy: false, groupId: '', artifactId:'', version: '', folder: '', type: 'KARAVAN'}); this.props.onRefresh.call(this); } saveAndCloseCreateModal = () => { - const p = new Project(this.state.name, this.state.version, this.state.folder, this.state.type? this.state.type : "KARAVAN", ''); + const {groupId, artifactId, version, type} = this.state; + const p = new Project(groupId, artifactId, version, '', type? type : "KARAVAN", ''); this.props.onCreate.call(this, p); - this.setState({isCreateModalOpen: false, name: '', version: '', folder: '', type: 'KARAVAN'}); + this.setState({isCreateModalOpen: false, isCopy: false, groupId: '', artifactId: '', version: '', folder: '', type: 'KARAVAN'}); } onKeyDown = (event: React.KeyboardEvent<HTMLDivElement>): void => { - if (event.key === 'Enter' && this.state.name !== undefined && this.state.version !== undefined) { + if (event.key === 'Enter' && this.state.groupId !== undefined && this.state.artifactId !== undefined && this.state.version !== undefined) { this.saveAndCloseCreateModal(); } } createModalForm() { - const {type } = this.state; + const {type, isCopy, projectToCopy } = this.state; return ( <Modal - title="Create new Project" + title={!isCopy ? "Create new project" : "Copy project from " + projectToCopy?.artifactId} variant={ModalVariant.small} isOpen={this.state.isCreateModalOpen} onClose={this.closeModal} @@ -115,10 +128,15 @@ export class ProjectsPage extends React.Component<Props, State> { ]} > <Form isHorizontal={true} autoComplete="off"> - <FormGroup label="Name" fieldId="name" isRequired> - <TextInput className="text-field" type="text" id="name" name="name" - value={this.state.name} - onChange={e => this.setState({name: e, folder: CamelUi.nameFromTitle(e.trim())})}/> + <FormGroup label="GroupId" fieldId="group" isRequired> + <TextInput className="text-field" type="text" id="group" name="group" + value={this.state.groupId} + onChange={e => this.setState({groupId: e})}/> + </FormGroup> + <FormGroup label="ArtifactId" fieldId="artifact" isRequired> + <TextInput className="text-field" type="text" id="artifact" name="artifact" + value={this.state.artifactId} + onChange={e => this.setState({artifactId: e})}/> </FormGroup> <FormGroup label="Version" fieldId="version" isRequired> <TextInput className="text-field" type="text" id="version" name="version" @@ -138,7 +156,7 @@ export class ProjectsPage extends React.Component<Props, State> { } render() { - const projects = this.state.projects.filter(p => p.name.includes(this.state.filter)); + const projects = this.state.projects.filter(p => p.groupId.includes(this.state.filter) || p.artifactId.includes(this.state.filter)); return ( <PageSection className="kamelet-section projects-page" padding={{default: 'noPadding'}}> <PageSection className="tools-section" padding={{default: 'noPadding'}}> @@ -149,33 +167,58 @@ export class ProjectsPage extends React.Component<Props, State> { <Thead> <Tr> <Th key='type'>Type</Th> - <Th key='name'>Name</Th> + <Th key='group'>GroupId</Th> + <Th key='artifact'>ArtifactId</Th> <Th key='version'>Version</Th> - <Th key='folder'>Folder</Th> - <Th key='status'>Status</Th> + <Th key='commit'>Commit</Th> + <Th key='deployment'>Deployment</Th> <Th key='action'></Th> </Tr> </Thead> <Tbody> {projects.map(project => ( - <Tr key={project.name}> + <Tr key={project.artifactId}> <Td modifier={"fitContent"}> <Tooltip content={project.type} position={"left"}> <Badge>{project.type.charAt(0)}</Badge> </Tooltip> </Td> + <Td>{project.groupId}</Td> <Td> <Button style={{padding: '6px'}} variant={"link"} onClick={e=>this.props.onSelect?.call(this, project)}> - {CamelUi.titleFromName(project.name)} + {project.artifactId} </Button> </Td> <Td>{project.version}</Td> - <Td>{project.folder}</Td> - <Td>Active</Td> - <Td modifier={"fitContent"}> - <Button style={{padding: '0'}} variant={"plain"} onClick={e=>this.props.onDelete?.call(this, project)}> - <DeleteIcon/> - </Button> + <Td isActionCell> + <Tooltip content={project.lastCommit} position={"bottom"}> + <Badge>{project.lastCommit?.substr(0, 7)}</Badge> + </Tooltip> + </Td> + <Td noPadding style={{width:"180px"}}> + <Flex direction={{default: "row"}}> + <FlexItem><Badge isRead>dev</Badge></FlexItem> + <FlexItem><Badge isRead>test</Badge></FlexItem> + <FlexItem><Badge isRead>prod</Badge></FlexItem> + </Flex> + </Td> + <Td isActionCell> + <OverflowMenu breakpoint="md"> + <OverflowMenuContent> + <OverflowMenuGroup groupType="button"> + <OverflowMenuItem> + <Tooltip content={"Copy project"} position={"bottom"}> + <Button variant={"plain"} icon={<CopyIcon/>} onClick={e=>this.setState({isCreateModalOpen: true, isCopy: true, projectToCopy: project})}></Button> + </Tooltip> + </OverflowMenuItem> + <OverflowMenuItem> + <Tooltip content={"Delete project"} position={"bottom"}> + <Button variant={"plain"} icon={<DeleteIcon/>} onClick={e=>this.props.onDelete?.call(this, project)}></Button> + </Tooltip> + </OverflowMenuItem> + </OverflowMenuGroup> + </OverflowMenuContent> + </OverflowMenu> </Td> </Tr> ))} diff --git a/karavan-docker/Dockerfile b/karavan-docker/Dockerfile index 295a5df..06b4d18 100644 --- a/karavan-docker/Dockerfile +++ b/karavan-docker/Dockerfile @@ -1,8 +1,23 @@ -FROM jbangdev/jbang-action +FROM adoptopenjdk/maven-openjdk11 -WORKDIR /ws +# Install JBang +RUN curl -Ls "https://github.com/jbangdev/jbang/releases/download/v0.94.0/jbang-0.94.0.zip" --output jbang-0.94.0.zip && \ + apt-get update -y && apt-get install unzip git -y && apt-get clean && \ + unzip jbang-0.94.0.zip && \ + rm jbang-0.94.0.zip && \ + chmod +x jbang-0.94.0/bin/jbang + +# Environment variables +ENV PATH="${PATH}:/jbang-0.94.0/bin" +ENV JBANG_VERSION 0.94.0 +ENV JBANG_PATH=/jbang/bin +ENV PATH="${PATH}:/jbang/bin" +ENV JBANG_DIR="/jbang/.jbang" -RUN jbang trust add -o --fresh --quiet https://github.com/apache/camel/blob/HEAD/dsl/camel-jbang/camel-jbang-main/dist/CamelJBang.java -RUN jbang -Dcamel.jbang.version=3.18.0-SNAPSHOT camel@apache/camel --version +# Install Camel-JBang +RUN jbang trust add -o --fresh --quiet https://github.com/apache/camel/blob/HEAD/dsl/camel-jbang/camel-jbang-main/dist/CamelJBang.java && \ + jbang -Dcamel.jbang.version=3.18.0-SNAPSHOT camel@apache/camel --version -ENTRYPOINT ["entrypoint"] \ No newline at end of file + +WORKDIR /ws +ENTRYPOINT ["/jbang-0.94.0/bin/jbang"] \ No newline at end of file diff --git a/karavan-docker/demo/application.properties b/karavan-docker/demo/application.properties deleted file mode 100644 index 97a2189..0000000 --- a/karavan-docker/demo/application.properties +++ /dev/null @@ -1,2 +0,0 @@ -camel.jbang.project.name=postman -camel.jbang.project.version=1.0.0