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/08/18 12:27:51 UTC
[camel-karavan] branch main updated: Fix #864
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 055b7128 Fix #864
055b7128 is described below
commit 055b712885c3f112c8a5bd27df58c71c76b9b98c
Author: Marat Gubaidullin <ma...@Marats-MacBook-Pro.local>
AuthorDate: Fri Aug 18 08:26:51 2023 -0400
Fix #864
---
.../src/main/resources/application.properties | 2 +
.../karavan-app/src/main/webui/package-lock.json | 39 +++++++++++
.../karavan-app/src/main/webui/package.json | 1 +
.../src/main/webui/src/api/KaravanApi.tsx | 2 +-
.../karavan-app/src/main/webui/src/index.tsx | 13 ++--
.../karavan-app/src/main/webui/src/main/Main.tsx | 78 ++++++++++------------
.../src/main/webui/src/main/PageNavigation.tsx | 9 ++-
.../src/main/webui/src/project/ProjectPage.tsx | 63 +++++------------
.../src/main/webui/src/projects/ProjectsPage.tsx | 29 +++++---
.../main/webui/src/projects/ProjectsTableRow.tsx | 7 +-
10 files changed, 135 insertions(+), 108 deletions(-)
diff --git a/karavan-web/karavan-app/src/main/resources/application.properties b/karavan-web/karavan-app/src/main/resources/application.properties
index 7b921f94..6f42cd08 100644
--- a/karavan-web/karavan-app/src/main/resources/application.properties
+++ b/karavan-web/karavan-app/src/main/resources/application.properties
@@ -86,6 +86,8 @@ quarkus.keycloak.devservices.enabled=false
%basic.quarkus.security.users.embedded.roles.admin=administrator,developer
# Quarkus configuration
+quarkus.quinoa.enable-spa-routing=true
+quarkus.http.enable-compression=true
quarkus.log.level=INFO
quarkus.banner.enabled=false
quarkus.package.type=uber-jar
diff --git a/karavan-web/karavan-app/src/main/webui/package-lock.json b/karavan-web/karavan-app/src/main/webui/package-lock.json
index 422f0e5b..3f9da293 100644
--- a/karavan-web/karavan-app/src/main/webui/package-lock.json
+++ b/karavan-web/karavan-app/src/main/webui/package-lock.json
@@ -28,6 +28,7 @@
"keycloak-js": "21.1.1",
"react": "18.2.0",
"react-dom": "18.2.0",
+ "react-router-dom": "^6.15.0",
"rxjs": "7.8.1",
"uuid": "9.0.0",
"zustand": "^4.3.8"
@@ -3442,6 +3443,14 @@
}
}
},
+ "node_modules/@remix-run/router": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.8.0.tgz",
+ "integrity": "sha512-mrfKqIHnSZRyIzBcanNJmVQELTnX+qagEDlcKO90RgRBVOZGSGvZKeDihTRfWcqoDn5N/NkUcwWTccnpN18Tfg==",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
"node_modules/@rollup/plugin-babel": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz",
@@ -15645,6 +15654,36 @@
"node": ">=0.10.0"
}
},
+ "node_modules/react-router": {
+ "version": "6.15.0",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.15.0.tgz",
+ "integrity": "sha512-NIytlzvzLwJkCQj2HLefmeakxxWHWAP+02EGqWEZy+DgfHHKQMUoBBjUQLOtFInBMhWtb3hiUy6MfFgwLjXhqg==",
+ "dependencies": {
+ "@remix-run/router": "1.8.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8"
+ }
+ },
+ "node_modules/react-router-dom": {
+ "version": "6.15.0",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.15.0.tgz",
+ "integrity": "sha512-aR42t0fs7brintwBGAv2+mGlCtgtFQeOzK0BM1/OiqEzRejOZtpMZepvgkscpMUnKb8YO84G7s3LsHnnDNonbQ==",
+ "dependencies": {
+ "@remix-run/router": "1.8.0",
+ "react-router": "6.15.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8",
+ "react-dom": ">=16.8"
+ }
+ },
"node_modules/react-scripts": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz",
diff --git a/karavan-web/karavan-app/src/main/webui/package.json b/karavan-web/karavan-app/src/main/webui/package.json
index bf5945fc..359446c9 100644
--- a/karavan-web/karavan-app/src/main/webui/package.json
+++ b/karavan-web/karavan-app/src/main/webui/package.json
@@ -46,6 +46,7 @@
"keycloak-js": "21.1.1",
"react": "18.2.0",
"react-dom": "18.2.0",
+ "react-router-dom": "^6.15.0",
"rxjs": "7.8.1",
"uuid": "9.0.0",
"zustand": "^4.3.8"
diff --git a/karavan-web/karavan-app/src/main/webui/src/api/KaravanApi.tsx b/karavan-web/karavan-app/src/main/webui/src/api/KaravanApi.tsx
index 4c94484a..43919f12 100644
--- a/karavan-web/karavan-app/src/main/webui/src/api/KaravanApi.tsx
+++ b/karavan-web/karavan-app/src/main/webui/src/api/KaravanApi.tsx
@@ -21,7 +21,7 @@ export class KaravanApi {
static me?: any;
static basicToken: string = '';
- static authType: string = '';
+ static authType?: string = undefined;
static isAuthorized: boolean = false;
static setAuthType(authType: string) {
diff --git a/karavan-web/karavan-app/src/main/webui/src/index.tsx b/karavan-web/karavan-app/src/main/webui/src/index.tsx
index 8eeda047..a072e007 100644
--- a/karavan-web/karavan-app/src/main/webui/src/index.tsx
+++ b/karavan-web/karavan-app/src/main/webui/src/index.tsx
@@ -1,9 +1,14 @@
import React from 'react';
-import {createRoot} from "react-dom/client";
+import ReactDOM from 'react-dom/client';
import "@patternfly/patternfly/patternfly.css";
import './index.css';
import {Main} from "./main/Main";
+import {BrowserRouter} from "react-router-dom";
-const container = document.getElementById('root');
-const root = createRoot(container!);
-root.render(<Main/>);
\ No newline at end of file
+ReactDOM.createRoot(document.getElementById("root")!).render(
+ <React.StrictMode>
+ <BrowserRouter>
+ <Main />
+ </BrowserRouter>
+ </React.StrictMode>
+);
diff --git a/karavan-web/karavan-app/src/main/webui/src/main/Main.tsx b/karavan-web/karavan-app/src/main/webui/src/main/Main.tsx
index 0c68bf5e..c98fcf68 100644
--- a/karavan-web/karavan-app/src/main/webui/src/main/Main.tsx
+++ b/karavan-web/karavan-app/src/main/webui/src/main/Main.tsx
@@ -1,29 +1,25 @@
-import React, {useEffect, useState} from 'react';
-import {
- Page,
- Flex,
- FlexItem,
- Spinner, Bullseye
-} from '@patternfly/react-core';
+import {Routes, Route, useNavigate, Navigate} from 'react-router-dom';
+import {useLocation} from 'react-router-dom';
+import React, {useEffect, useState} from "react";
import {KaravanApi} from "../api/KaravanApi";
-import {SsoApi} from "../api/SsoApi";
-import {KameletApi} from "karavan-core/lib/api/KameletApi";
-import '../designer/karavan.css';
-import {v4 as uuidv4} from "uuid";
-import {ComponentApi} from "karavan-core/lib/api/ComponentApi";
+import {Bullseye, Flex, FlexItem, Page, Spinner} from "@patternfly/react-core";
import Icon from "../Logo";
-import {ProjectsPage} from "../projects/ProjectsPage";
import {MainLogin} from "./MainLogin";
+import {Notification} from "./Notification";
import {DashboardPage} from "../dashboard/DashboardPage";
+import {ProjectsPage} from "../projects/ProjectsPage";
+import {ProjectPage} from "../project/ProjectPage";
+import {ServicesPage} from "../services/ServicesPage";
import {ContainersPage} from "../containers/ContainersPage";
+import {KnowledgebasePage} from "../knowledgebase/KnowledgebasePage";
import {ProjectEventBus} from "../api/ProjectEventBus";
import {AppConfig, ContainerStatus, Project, ToastMessage} from "../api/ProjectModels";
-import {ProjectPage} from "../project/ProjectPage";
-import {useAppConfigStore, useStatusesStore} from "../api/ProjectStore";
-import {Notification} from "./Notification";
+import {SsoApi} from "../api/SsoApi";
+import {v4 as uuidv4} from "uuid";
import {InfrastructureAPI} from "../designer/utils/InfrastructureAPI";
-import {KnowledgebasePage} from "../knowledgebase/KnowledgebasePage";
-import {ServicesPage} from "../services/ServicesPage";
+import {KameletApi} from "karavan-core/lib/api/KameletApi";
+import {ComponentApi} from "karavan-core/lib/api/ComponentApi";
+import {useAppConfigStore, useStatusesStore} from "../api/ProjectStore";
import {shallow} from "zustand/shallow";
import {PageNavigation} from "./PageNavigation";
@@ -32,6 +28,8 @@ export const Main = () => {
const [config, pageId, setPageId, setConfig] = useAppConfigStore((state) => [state.config, state.pageId, state.setPageId, state.setConfig], shallow)
const [setContainers] = useStatusesStore((state) => [state.setContainers], shallow);
const [request, setRequest] = useState<string>(uuidv4());
+ let location = useLocation();
+ const navigate = useNavigate();
useEffect(() => {
console.log("Main Start");
@@ -68,6 +66,7 @@ export const Main = () => {
}
});
}
+
function getStatuses() {
if (KaravanApi.isAuthorized || KaravanApi.authType === 'public') {
KaravanApi.getAllContainerStatuses((statuses: ContainerStatus[]) => {
@@ -125,38 +124,35 @@ export const Main = () => {
ProjectEventBus.sendAlert(new ToastMessage(title, text, variant))
}
- function getMain() {
- return (
- <>
+ return (
+ <Page className="karavan">
+ {KaravanApi.authType === undefined &&
+ <Bullseye className="loading-page">
+ <Spinner className="spinner" diameter="140px" aria-label="Loading..."/>
+ <div className="logo-placeholder">{Icon()}</div>
+ </Bullseye>}
+ {(KaravanApi.isAuthorized || KaravanApi.authType === 'public') &&
<Flex direction={{default: "row"}} style={{width: "100%", height: "100%"}}
alignItems={{default: "alignItemsStretch"}} spaceItems={{default: 'spaceItemsNone'}}>
<FlexItem>
{<PageNavigation/>}
</FlexItem>
<FlexItem flex={{default: "flex_2"}} style={{height: "100%"}}>
- {pageId === 'dashboard' && <DashboardPage key='dashboard'/>}
- {pageId === 'projects' && <ProjectsPage key={request}/>}
- {pageId === 'project' && <ProjectPage key="projects"/>}
- {pageId === 'services' && <ServicesPage key="services"/>}
- {pageId === 'containers' && <ContainersPage key="containers"/>}
- {pageId === 'knowledgebase' && <KnowledgebasePage dark={false}/>}
+ <Routes>
+ <Route path="/dashboard" element={<DashboardPage key={'dashboard'}/>}/>
+ <Route path="/projects" element={<ProjectsPage key={'projects'}/>}/>
+ <Route path="/projects/:projectId" element={<ProjectPage key={'project'}/>}/>
+ <Route path="/services" element={<ServicesPage key="services"/>}/>
+ <Route path="/containers" element={<ContainersPage key="services"/>}/>
+ <Route path="/knowledgebase" element={<KnowledgebasePage dark={false}/>}/>
+ <Route path="*" element={<Navigate to="/projects" replace/>}/>
+ </Routes>
</FlexItem>
</Flex>
- </>
- )
- }
-
- return (
- <Page className="karavan">
- {KaravanApi.authType === undefined &&
- <Bullseye className="loading-page">
- <Spinner className="spinner" diameter="140px" aria-label="Loading..."/>
- <div className="logo-placeholder">{Icon()}</div>
- </Bullseye>}
- {(KaravanApi.isAuthorized || KaravanApi.authType === 'public') && getMain()}
+ }
{!KaravanApi.isAuthorized && KaravanApi.authType === 'basic' &&
<MainLogin config={config} onLogin={onLogin}/>}
<Notification/>
</Page>
- )
-}
\ No newline at end of file
+ );
+};
diff --git a/karavan-web/karavan-app/src/main/webui/src/main/PageNavigation.tsx b/karavan-web/karavan-app/src/main/webui/src/main/PageNavigation.tsx
index 76497ce3..155affcc 100644
--- a/karavan-web/karavan-app/src/main/webui/src/main/PageNavigation.tsx
+++ b/karavan-web/karavan-app/src/main/webui/src/main/PageNavigation.tsx
@@ -17,6 +17,7 @@ import DashboardIcon from "@patternfly/react-icons/dist/js/icons/tachometer-alt-
import ServicesIcon from "@patternfly/react-icons/dist/js/icons/services-icon";
import {useAppConfigStore, useDevModeStore, useFileStore} from "../api/ProjectStore";
import {shallow} from "zustand/shallow";
+import {useNavigate} from "react-router-dom";
class MenuItem {
pageId: string = '';
@@ -36,6 +37,7 @@ export const PageNavigation = () => {
const [setFile] = useFileStore((state) => [state.setFile], shallow)
const [setStatus, setPodName] = useDevModeStore((state) => [state.setStatus, state.setPodName], shallow)
const [showUser, setShowUser] = useState<boolean>(false);
+ const navigate = useNavigate();
function getMenu() : MenuItem[] {
const pages: MenuItem[] = [
@@ -70,6 +72,7 @@ export const PageNavigation = () => {
setPodName(undefined);
setStatus("none");
setPageId(page.pageId);
+ navigate(page.pageId);
}}
/>
</Tooltip>
@@ -87,11 +90,11 @@ export const PageNavigation = () => {
isVisible={showUser}
shouldClose={(_event, tip) => setShowUser(false)}
shouldOpen={(_event, tip) => setShowUser(true)}
- headerContent={<div>{KaravanApi.me.userName}</div>}
+ headerContent={<div>{KaravanApi.me?.userName}</div>}
bodyContent={
<Flex direction={{default: "row"}}>
- {KaravanApi.me.roles && Array.isArray(KaravanApi.me.roles)
- && KaravanApi.me.roles
+ {KaravanApi.me?.roles && Array.isArray(KaravanApi.me?.roles)
+ && KaravanApi.me?.roles
.filter((r: string) => ['administrator', 'developer', 'viewer'].includes(r))
.map((role: string) => <Badge id={role} isRead>{role}</Badge>)}
</Flex>
diff --git a/karavan-web/karavan-app/src/main/webui/src/project/ProjectPage.tsx b/karavan-web/karavan-app/src/main/webui/src/project/ProjectPage.tsx
index a71af8cd..cb6bb96a 100644
--- a/karavan-web/karavan-app/src/main/webui/src/project/ProjectPage.tsx
+++ b/karavan-web/karavan-app/src/main/webui/src/project/ProjectPage.tsx
@@ -1,68 +1,37 @@
-import React, {useState} from 'react';
+import React, {useEffect, useState} from 'react';
import {
PageSection,
} from '@patternfly/react-core';
import '../designer/karavan.css';
-import {KaravanApi} from "../api/KaravanApi";
-import FileSaver from "file-saver";
import {ProjectToolbar} from "./ProjectToolbar";
import {ProjectLogPanel} from "./log/ProjectLogPanel";
-import {ProjectFile, ProjectFileTypes} from "../api/ProjectModels";
-import {useFileStore, useProjectStore} from "../api/ProjectStore";
+import {ProjectFileTypes} from "../api/ProjectModels";
+import {useFileStore, useProjectsStore, useProjectStore} from "../api/ProjectStore";
import {MainToolbar} from "../designer/MainToolbar";
import {ProjectTitle} from "./ProjectTitle";
import {ProjectPanel} from "./ProjectPanel";
import {FileEditor} from "./file/FileEditor";
import {shallow} from "zustand/shallow";
+import {useParams} from "react-router-dom";
+import {KaravanApi} from "../api/KaravanApi";
export const ProjectPage = () => {
const {file, operation} = useFileStore();
const [mode, setMode] = useState<"design" | "code">("design");
const [key, setKey] = useState<string>('');
- const [project] = useProjectStore((state) => [state.project], shallow )
-
- // useEffect(() => {
- // // TODO: make status request only when started or just opened
- // const interval = setInterval(() => {
- // ProjectService.getDevModeStatus(project);
- // }, 1000);
- // return () => {
- // clearInterval(interval)
- // };
- // }, []);
-
- function post (file: ProjectFile) {
- KaravanApi.postProjectFile(file, res => {
- if (res.status === 200) {
- const newFile = res.data;
- // setFiles((files => {
- // const index = files.findIndex(f => f.name === newFile.name);
- // if (index !== -1) files.splice(index, 1, newFile)
- // else files.push(newFile);
- // return files
- // }))
- } else {
- // console.log(res) //TODO show notification
- }
- })
- }
-
- function save (name: string, code: string) {
- if (file) {
- file.code = code;
- // setFile(file);
- post(file);
+ const [projects] = useProjectsStore((state) => [state.projects], shallow)
+ const [project, setProject] = useProjectStore((state) => [state.project, state.setProject], shallow )
+ let { projectId } = useParams();
+
+ useEffect(() => {
+ const p = projects.filter(project => project.projectId === projectId).at(0);
+ if (p) {
+ setProject(p, "select");
+ } else if (projectId){
+ KaravanApi.getProject(projectId, project1 => setProject(project1, "select"));
}
- }
-
- function download () {
- if (file) {
- const type = file.name.endsWith("yaml") ? "application/yaml;charset=utf-8" : undefined;
- const f = new File([file.code], file.name, {type: type});
- FileSaver.saveAs(f);
- }
- }
+ }, []);
function isBuildIn(): boolean {
return ['kamelets', 'templates'].includes(project.projectId);
diff --git a/karavan-web/karavan-app/src/main/webui/src/projects/ProjectsPage.tsx b/karavan-web/karavan-app/src/main/webui/src/projects/ProjectsPage.tsx
index 2c345339..64c5fd40 100644
--- a/karavan-web/karavan-app/src/main/webui/src/projects/ProjectsPage.tsx
+++ b/karavan-web/karavan-app/src/main/webui/src/projects/ProjectsPage.tsx
@@ -12,20 +12,20 @@ import {
EmptyState,
EmptyStateVariant,
EmptyStateIcon,
- Spinner, EmptyStateHeader
+ Spinner, EmptyStateHeader, Flex, FlexItem
} from '@patternfly/react-core';
import '../designer/karavan.css';
import RefreshIcon from '@patternfly/react-icons/dist/esm/icons/sync-alt-icon';
import PlusIcon from '@patternfly/react-icons/dist/esm/icons/plus-icon';
import {
- Tbody,
- Td,
- Th,
- Thead,
- Tr
+ Tbody,
+ Td,
+ Th,
+ Thead,
+ Tr
} from '@patternfly/react-table';
import {
- Table
+ Table
} from '@patternfly/react-table/deprecated';
import SearchIcon from '@patternfly/react-icons/dist/esm/icons/search-icon';
import {ProjectsTableRow} from "./ProjectsTableRow";
@@ -36,6 +36,12 @@ import {ProjectService} from "../api/ProjectService";
import {MainToolbar} from "../designer/MainToolbar";
import {Project, ProjectType} from "../api/ProjectModels";
import {shallow} from "zustand/shallow";
+import {PageNavigation} from "../main/PageNavigation";
+import {DashboardPage} from "../dashboard/DashboardPage";
+import {ProjectPage} from "../project/ProjectPage";
+import {ServicesPage} from "../services/ServicesPage";
+import {ContainersPage} from "../containers/ContainersPage";
+import {KnowledgebasePage} from "../knowledgebase/KnowledgebasePage";
export const ProjectsPage = () => {
@@ -63,6 +69,7 @@ export const ProjectsPage = () => {
ProjectService.refreshAllContainerStatuses();
setLoading(false);
}
+
function getTools() {
return <Toolbar id="toolbar-group-types">
<ToolbarContent>
@@ -81,7 +88,7 @@ export const ProjectsPage = () => {
<ToolbarItem>
<Button icon={<PlusIcon/>}
onClick={e =>
- useProjectStore.setState({operation:"create", project: new Project()})}
+ useProjectStore.setState({operation: "create", project: new Project()})}
>Create</Button>
</ToolbarItem>
</ToolbarContent>
@@ -103,7 +110,8 @@ export const ProjectsPage = () => {
<Spinner className="progress-stepper" diameter="80px" aria-label="Loading..."/>}
{!loading &&
<EmptyState variant={EmptyStateVariant.sm}>
- <EmptyStateHeader titleText="No results found" icon={<EmptyStateIcon icon={SearchIcon}/>} headingLevel="h2" />
+ <EmptyStateHeader titleText="No results found"
+ icon={<EmptyStateIcon icon={SearchIcon}/>} headingLevel="h2"/>
</EmptyState>
}
</Bullseye>
@@ -120,7 +128,7 @@ export const ProjectsPage = () => {
<Table aria-label="Projects" variant={"compact"}>
<Thead>
<Tr>
- <Th key='type' >Runtime</Th>
+ <Th key='type'>Runtime</Th>
<Th key='projectId'>Project ID</Th>
<Th key='name'>Name</Th>
<Th key='description'>Description</Th>
@@ -152,5 +160,6 @@ export const ProjectsPage = () => {
{["create", "copy"].includes(operation) && <CreateProjectModal/>}
{["delete"].includes(operation) && <DeleteProjectModal/>}
</PageSection>
+
)
}
\ No newline at end of file
diff --git a/karavan-web/karavan-app/src/main/webui/src/projects/ProjectsTableRow.tsx b/karavan-web/karavan-app/src/main/webui/src/projects/ProjectsTableRow.tsx
index 053f0a2f..6dfa00b7 100644
--- a/karavan-web/karavan-app/src/main/webui/src/projects/ProjectsTableRow.tsx
+++ b/karavan-web/karavan-app/src/main/webui/src/projects/ProjectsTableRow.tsx
@@ -18,6 +18,7 @@ import {
import {ProjectEventBus} from "../api/ProjectEventBus";
import {shallow} from "zustand/shallow";
import {CamelIcon, QuarkusIcon, SpringIcon} from "../designer/utils/KaravanIcons";
+import {useNavigate} from "react-router-dom";
interface Props {
project: Project
@@ -29,6 +30,7 @@ export const ProjectsTableRow = (props: Props) => {
const {config} = useAppConfigStore();
const [setProject] = useProjectStore((state) => [state.setProject, state.setOperation], shallow);
const [setShowLog] = useLogStore((state) => [state.setShowLog], shallow);
+ const navigate = useNavigate();
function getEnvironments(): string [] {
return config.environments && Array.isArray(config.environments) ? Array.from(config.environments) : [];
@@ -61,9 +63,10 @@ export const ProjectsTableRow = (props: Props) => {
</Td>
<Td>
<Button style={{padding: '6px'}} variant={"link"} onClick={e => {
- setProject(project, "select");
+ // setProject(project, "select");
setShowLog(false);
- ProjectEventBus.selectProject(project);
+ // ProjectEventBus.selectProject(project);
+ navigate("/projects/"+ project.projectId);
}}>
{project.projectId}
</Button>