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 8f242cc7 Fix #981
8f242cc7 is described below

commit 8f242cc7e0c5e45841121c27d497c0b3ad56cc7d
Author: Marat Gubaidullin <ma...@talismancloud.io>
AuthorDate: Fri Nov 3 18:31:33 2023 -0400

    Fix #981
---
 .../apache/camel/karavan/api/StatusResource.java   |   6 +-
 .../karavan/infinispan/InfinispanService.java      |   5 +-
 .../src/main/webui/src/api/KaravanApi.tsx          |   4 +-
 .../src/main/webui/src/api/ProjectService.ts       |  48 ++++++++-
 .../webui/src/containers/ContainerTableRow.tsx     |   4 +-
 .../main/webui/src/containers/ContainersPage.tsx   |  14 ++-
 .../karavan-app/src/main/webui/src/main/Main.tsx   |  83 +++------------
 .../src/main/webui/src/main/MainDataPoller.tsx     |  78 ---------------
 .../src/main/webui/src/main/MainLoader.tsx         | 111 +++++++++++++++++++++
 .../src/main/webui/src/main/MainLogin.tsx          |  80 ---------------
 .../src/main/webui/src/project/DevModeToolbar.tsx  |  63 +++++++++---
 .../main/webui/src/project/ProjectDataPoller.tsx   |  63 ------------
 .../src/main/webui/src/project/ProjectPage.tsx     |  20 +++-
 .../main/webui/src/projects/CreateProjectModal.tsx |   8 +-
 .../src/main/webui/src/projects/ProjectsPage.tsx   |  22 +++-
 .../src/main/webui/src/services/ServicesPage.tsx   |   5 +
 16 files changed, 290 insertions(+), 324 deletions(-)

diff --git 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/StatusResource.java
 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/StatusResource.java
index 97710ad1..5faabe0d 100644
--- 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/StatusResource.java
+++ 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/StatusResource.java
@@ -52,10 +52,10 @@ public class StatusResource {
 
     @GET
     @Produces(MediaType.APPLICATION_JSON)
-    @Path("/camel/context/{env}")
-    public List<CamelStatus> getCamelContextStatusByEnv(@PathParam("env") 
String env) {
+    @Path("/camel/context")
+    public List<CamelStatus> getCamelContextStatusByEnv() {
         if (infinispanService.isReady()) {
-            return infinispanService.getCamelStatusesByEnv(env, 
CamelStatusValue.Name.context);
+            return 
infinispanService.getCamelStatusesByEnv(CamelStatusValue.Name.context);
         } else {
             return List.of();
         }
diff --git 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/InfinispanService.java
 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/InfinispanService.java
index 30440c1c..6b1e9d6e 100644
--- 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/InfinispanService.java
+++ 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/InfinispanService.java
@@ -293,10 +293,9 @@ public class InfinispanService implements HealthCheck {
         return camelStatuses.get(key);
     }
 
-    public List<CamelStatus> getCamelStatusesByEnv(String env, 
CamelStatusValue.Name name) {
+    public List<CamelStatus> getCamelStatusesByEnv(CamelStatusValue.Name name) 
{
         QueryFactory queryFactory = Search.getQueryFactory(camelStatuses);
-        List<CamelStatus> statuses = queryFactory.<CamelStatus>create("FROM 
karavan.CamelStatus WHERE env = :env")
-                .setParameter("env", env)
+        List<CamelStatus> statuses = queryFactory.<CamelStatus>create("FROM 
karavan.CamelStatus")
                 .execute().list();
         return statuses.stream().map(cs -> {
             var values = cs.getStatuses();
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 a8663494..d24ecaa7 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
@@ -209,8 +209,8 @@ export class KaravanApi {
         });
     }
 
-    static async getAllCamelContextStatuses(env: string, after: (statuses: 
CamelStatus[]) => void) {
-        instance.get('/api/status/camel/context/' + env)
+    static async getAllCamelContextStatuses(after: (statuses: CamelStatus[]) 
=> void) {
+        instance.get('/api/status/camel/context')
             .then(res => {
                 if (res.status === 200) {
                     after(res.data);
diff --git a/karavan-web/karavan-app/src/main/webui/src/api/ProjectService.ts 
b/karavan-web/karavan-app/src/main/webui/src/api/ProjectService.ts
index da4cef52..b7ea258c 100644
--- a/karavan-web/karavan-app/src/main/webui/src/api/ProjectService.ts
+++ b/karavan-web/karavan-app/src/main/webui/src/api/ProjectService.ts
@@ -16,7 +16,7 @@
  */
 
 import {KaravanApi} from './KaravanApi';
-import {DeploymentStatus, ContainerStatus, Project, ProjectFile} from 
'./ProjectModels';
+import {DeploymentStatus, ContainerStatus, Project, ProjectFile, 
ServiceStatus, CamelStatus} from './ProjectModels';
 import {TemplateApi} from 'karavan-core/lib/api/TemplateApi';
 import {InfrastructureAPI} from '../designer/utils/InfrastructureAPI';
 import {unstable_batchedUpdates} from 'react-dom'
@@ -182,6 +182,44 @@ export class ProjectService {
         });
     }
 
+    public static refreshAllServicesStatuses() {
+        KaravanApi.getAllServiceStatuses((statuses: ServiceStatus[]) => {
+            useStatusesStore.setState({services: statuses});
+        });
+    }
+
+    public static refreshAllCamelStatuses() {
+        KaravanApi.getAllCamelContextStatuses( (statuses: CamelStatus[]) => {
+            useStatusesStore.setState({camels: statuses});
+        });
+    }
+
+    public static refreshCamelStatus(projectId: string, env: string) {
+        KaravanApi.getProjectCamelStatuses(projectId, env, (res) => {
+            if (res.status === 200) {
+                useProjectStore.setState({camelStatuses: res.data})
+            } else {
+                useProjectStore.setState({camelStatuses: []})
+            }
+        })
+    }
+
+    public static refreshCamelTraces(projectId: string, env: string) {
+        KaravanApi.getProjectCamelTraces(projectId, env, res => {
+            if (res.status === 200) {
+                useProjectStore.setState({camelTraces: res.data})
+            } else {
+                useProjectStore.setState({camelTraces: []})
+            }
+        })
+    }
+
+    public static refreshImages(projectId: string) {
+        KaravanApi.getImages(projectId, (res: any) => {
+            useProjectStore.setState({images: res});
+        });
+    }
+
     public static refreshAllDeploymentStatuses() {
         KaravanApi.getAllDeploymentStatuses( (statuses: DeploymentStatus[]) => 
{
             useStatusesStore.setState({deployments: statuses});
@@ -209,6 +247,7 @@ export class ProjectService {
         KaravanApi.postProject(project, res => {
             if (res.status === 200 || res.status === 201) {
                 ProjectService.refreshProjectData(project.projectId);
+                ProjectService.refreshProjects();
                 // this.props.toast?.call(this, 'Success', 'Project created', 
'success');
             } else {
                 // this.props.toast?.call(this, 'Error', res.status + ', ' + 
res.statusText, 'danger');
@@ -236,6 +275,13 @@ export class ProjectService {
         });
     }
 
+    public static getAllStatuses() {
+        ProjectService.refreshAllDeploymentStatuses();
+        ProjectService.refreshAllContainerStatuses();
+        ProjectService.refreshAllServicesStatuses();
+        ProjectService.refreshAllCamelStatuses();
+    }
+
     public static refreshProjectData(projectId: string) {
         KaravanApi.getProject(projectId, (project: Project) => {
             // ProjectEventBus.selectProject(project);
diff --git 
a/karavan-web/karavan-app/src/main/webui/src/containers/ContainerTableRow.tsx 
b/karavan-web/karavan-app/src/main/webui/src/containers/ContainerTableRow.tsx
index a0f81f0e..d08ee906 100644
--- 
a/karavan-web/karavan-app/src/main/webui/src/containers/ContainerTableRow.tsx
+++ 
b/karavan-web/karavan-app/src/main/webui/src/containers/ContainerTableRow.tsx
@@ -63,7 +63,7 @@ export function ContainerTableRow (props: Props) {
                         setCommand(undefined);
                         setShowConfirmation(false);
                     }
-                }}>Delete
+                }}>Confirm
                 </Button>,
                 <Button key="cancel" variant="link"
                         onClick={e => {
@@ -72,7 +72,7 @@ export function ContainerTableRow (props: Props) {
                         }}>Cancel</Button>
             ]}
             onEscapePress={e => setShowConfirmation(false)}>
-            <div>{"Confirm " + commands + " container " + 
container.containerName + " ?"}</div>
+            <div>{"Confirm " + command + " container " + 
container.containerName + " ?"}</div>
         </Modal>)
     }
 
diff --git 
a/karavan-web/karavan-app/src/main/webui/src/containers/ContainersPage.tsx 
b/karavan-web/karavan-app/src/main/webui/src/containers/ContainersPage.tsx
index aa2ca131..5fe8adc4 100644
--- a/karavan-web/karavan-app/src/main/webui/src/containers/ContainersPage.tsx
+++ b/karavan-web/karavan-app/src/main/webui/src/containers/ContainersPage.tsx
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-import React, {useState} from 'react';
+import React, {useEffect, useState} from 'react';
 import {
     Bullseye,
     EmptyState, EmptyStateIcon, EmptyStateVariant,
@@ -28,7 +28,7 @@ import {
     ToolbarItem, EmptyStateHeader
 } from '@patternfly/react-core';
 import '../designer/karavan.css';
-import {ContainerStatus} from "../api/ProjectModels";
+import {ContainerStatus, ProjectType} from "../api/ProjectModels";
 import {
        TableVariant,
        Tbody,
@@ -45,6 +45,9 @@ import {MainToolbar} from "../designer/MainToolbar";
 import {useAppConfigStore, useStatusesStore} from "../api/ProjectStore";
 import {shallow} from "zustand/shallow";
 import {ContainerTableRow} from "./ContainerTableRow";
+import {ProjectService} from "../api/ProjectService";
+import {KaravanApi} from "../api/KaravanApi";
+import {DockerCompose, ServicesYaml} from "../api/ServiceModels";
 
 export function ContainersPage () {
 
@@ -54,6 +57,13 @@ export function ContainersPage () {
     const [loading] = useState<boolean>(true);
     const [selectedEnv, setSelectedEnv] = 
useState<string[]>([config.environment]);
 
+    useEffect(() => {
+        const interval = setInterval(() => {
+            ProjectService.refreshAllContainerStatuses();
+        }, 1000)
+        return () => clearInterval(interval);
+    }, []);
+
     function selectEnvironment(name: string, selected: boolean) {
         if (selected && !selectedEnv.includes(name)) {
             setSelectedEnv((state: string[]) => {
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 404ff522..592a6978 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
@@ -16,23 +16,13 @@
  */
 
 import {Navigate, Route, Routes} from 'react-router-dom';
-import React, {useEffect, useMemo, useRef} from "react";
+import React, {useEffect, useRef} from "react";
 import {KaravanApi} from "../api/KaravanApi";
 import {
-    Bullseye,
     Flex,
     FlexItem,
     Page,
-    ProgressStep,
-    ProgressStepper,
-    Spinner,
-    Text, TextContent, TextVariants,
-    Tooltip,
-    TooltipPosition
 } from "@patternfly/react-core";
-import Icon from "../Logo";
-import {MainLogin} from "./MainLogin";
-import {DashboardPage} from "../dashboard/DashboardPage";
 import {ProjectsPage} from "../projects/ProjectsPage";
 import {ProjectPage} from "../project/ProjectPage";
 import {ServicesPage} from "../services/ServicesPage";
@@ -43,27 +33,35 @@ import {useAppConfigStore} from "../api/ProjectStore";
 import {shallow} from "zustand/shallow";
 import {PageNavigation} from "./PageNavigation";
 import {useMainHook} from "./useMainHook";
-import {MainDataPoller} from "./MainDataPoller";
 import {TemplatesPage} from "../templates/TemplatesPage";
-import {EventBus} from "../designer/utils/EventBus";
 import {Notification} from "../designer/utils/Notification";
+import {MainLoader} from "./MainLoader";
 
 export function Main() {
 
-    const [readiness] = useAppConfigStore((s) => [s.readiness], shallow)
+    const [readiness, setReadiness] = useAppConfigStore((s) => [s.readiness, 
s.setReadiness], shallow)
     const {getData, getStatuses} = useMainHook();
 
     const initialized = useRef(false)
 
     useEffect(() => {
+        console.log("Main");
         if (!initialized.current) {
             initialized.current = true
             effect()
         }
+        const interval = setInterval(() => {
+            KaravanApi.getReadiness((r: any) => {
+                setReadiness(r);
+            })
+        }, 10000)
+        return () => {
+            clearInterval(interval);
+        };
     }, [])
 
     function effect() {
-        console.log("Main Start");
+        console.log("Main effect start");
         KaravanApi.getAuthType((authType: string) => {
             console.log("authType", authType);
             if (authType === 'oidc') {
@@ -76,15 +74,10 @@ export function Main() {
             getData();
         });
         return () => {
-            console.log("Main End");
+            console.log("Main effect end");
         };
     }
 
-
-    function toast(title: string, text: string, variant: 'success' | 'danger' 
| 'warning' | 'info' | 'custom') {
-        EventBus.sendAlert(title, text, variant)
-    }
-
     function showSpinner() {
         return KaravanApi.authType === undefined || readiness === undefined;
     }
@@ -93,56 +86,13 @@ export function Main() {
         return readiness !== undefined && readiness.status !== true;
     }
 
-    function getStepper() {
-        const steps: any[] = Array.isArray(readiness?.checks) ? 
readiness.checks : [];
-        return (
-            <Bullseye className="">
-                <Flex direction={{default:"column"}} justifyContent={{default: 
"justifyContentCenter"}}>
-                    <FlexItem style={{textAlign: "center"}}>
-                        {Icon()}
-                        <TextContent>
-                            <Text component={TextVariants.h2}>
-                                Waiting for services
-                            </Text>
-                        </TextContent>
-                    </FlexItem>
-                    <FlexItem>
-                        <ProgressStepper aria-label="Readiness progress" 
isCenterAligned isVertical >
-                            {steps.map(step => (
-                                <ProgressStep
-                                    key={step.name}
-                                    variant={step.status === 'UP' ? "success" 
: "info"}
-                                    isCurrent={step.status !== 'UP'}
-                                    icon={step.status !== 'UP' ? <Spinner 
isInline aria-label="Loading..."/> : undefined}
-                                    id={step.name}
-                                    titleId={step.name}
-                                    aria-label={step.name}
-                                >
-                                    {step.name}
-                                </ProgressStep>
-                            ))}
-                        </ProgressStepper>
-                    </FlexItem>
-                </Flex>
-            </Bullseye>
-        )
-    }
-
     function showMain() {
         return !showStepper() && !showSpinner() && (KaravanApi.isAuthorized || 
KaravanApi.authType === 'public');
     }
 
     return (
         <Page className="karavan">
-            {showSpinner() &&
-                <Bullseye className="loading-page">
-                    <Spinner className="spinner" diameter="140px" 
aria-label="Loading..."/>
-                    <Tooltip content="Connecting to server..." 
position={TooltipPosition.bottom}>
-                        <div className="logo-placeholder">{Icon()}</div>
-                    </Tooltip>
-                </Bullseye>
-            }
-            {showStepper() && getStepper()}
+            {!showMain() && <MainLoader/>}
             {showMain() &&
                 <Flex direction={{default: "row"}} style={{width: "100%", 
height: "100%"}}
                       alignItems={{default: "alignItemsStretch"}} 
spaceItems={{default: 'spaceItemsNone'}}>
@@ -163,10 +113,7 @@ export function Main() {
                     </FlexItem>
                 </Flex>
             }
-            {!KaravanApi.isAuthorized && KaravanApi.authType === 'basic' &&
-                <MainLogin/>}
             <Notification/>
-            <MainDataPoller/>
         </Page>
     );
 };
diff --git a/karavan-web/karavan-app/src/main/webui/src/main/MainDataPoller.tsx 
b/karavan-web/karavan-app/src/main/webui/src/main/MainDataPoller.tsx
deleted file mode 100644
index 6d58dc35..00000000
--- a/karavan-web/karavan-app/src/main/webui/src/main/MainDataPoller.tsx
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import React, {useEffect, useState} from 'react';
-
-import {KaravanApi} from "../api/KaravanApi";
-import '../designer/karavan.css';
-import {
-    CamelStatus,
-    ContainerStatus,
-    DeploymentStatus,
-    Project,
-    ServiceStatus
-} from "../api/ProjectModels";
-import {useAppConfigStore, useProjectsStore, useProjectStore, 
useStatusesStore} from "../api/ProjectStore";
-import {shallow} from "zustand/shallow";
-
-export function MainDataPoller () {
-
-    const [config, setLoading, readiness, setReadiness] = 
useAppConfigStore((s) =>
-        [s.config, s.setLoading, s.readiness, s.setReadiness], shallow)
-    const [projects, setProjects] = useProjectsStore((state) => 
[state.projects, state.setProjects], shallow)
-    const [deployments, services, containers, camels, setDeployments, 
setServices, setContainers, setCamels]
-        = useStatusesStore((s) => [s.deployments, s.services, s.containers, 
s.camels,
-        s.setDeployments, s.setServices, s.setContainers, s.setCamels], 
shallow);
-
-    const [project] = useProjectStore((state) => [state.project], shallow )
-
-    useEffect(() => {
-        const interval = setInterval(() => getData(), 1300)
-        return () => {
-            clearInterval(interval);
-        };
-    }, [project, readiness]);
-
-    function getData() {
-        KaravanApi.getReadiness((r: any) => {
-            setReadiness(r);
-        })
-        if (readiness) {
-            setLoading(true);
-            if (project.projectId === undefined) {
-                KaravanApi.getProjects((projects: Project[]) => {
-                    setProjects(projects);
-                });
-            }
-            KaravanApi.getAllDeploymentStatuses((statuses: DeploymentStatus[]) 
=> {
-                setDeployments(statuses);
-            });
-            KaravanApi.getAllServiceStatuses((statuses: ServiceStatus[]) => {
-                setServices(statuses);
-            });
-            KaravanApi.getAllContainerStatuses((statuses: ContainerStatus[]) 
=> {
-                setContainers(statuses);
-            });
-            KaravanApi.getAllCamelContextStatuses(config.environment, 
(statuses: CamelStatus[]) => {
-                setCamels(statuses);
-            });
-            setLoading(false);
-        }
-    }
-
-    return (<></>)
-}
\ No newline at end of file
diff --git a/karavan-web/karavan-app/src/main/webui/src/main/MainLoader.tsx 
b/karavan-web/karavan-app/src/main/webui/src/main/MainLoader.tsx
new file mode 100644
index 00000000..5cdb9624
--- /dev/null
+++ b/karavan-web/karavan-app/src/main/webui/src/main/MainLoader.tsx
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React, {useEffect} from "react";
+import {KaravanApi} from "../api/KaravanApi";
+import {
+    Bullseye,
+    Flex,
+    FlexItem,
+    Page,
+    ProgressStep,
+    ProgressStepper,
+    Spinner,
+    Text, TextContent, TextVariants,
+    Tooltip,
+    TooltipPosition
+} from "@patternfly/react-core";
+import Icon from "../Logo";
+import {useAppConfigStore} from "../api/ProjectStore";
+import {shallow} from "zustand/shallow";
+
+export function MainLoader() {
+
+    const [readiness, setReadiness] = useAppConfigStore((s) => [s.readiness, 
s.setReadiness], shallow)
+
+    useEffect(() => {
+        const interval = setInterval(() => {
+            KaravanApi.getReadiness((r: any) => {
+                setReadiness(r);
+            })
+        }, 1300)
+        return () => {
+            clearInterval(interval);
+        };
+    }, []);
+
+    function showSpinner() {
+        return KaravanApi.authType === undefined || readiness === undefined;
+    }
+
+    function showStepper() {
+        return readiness !== undefined && readiness.status !== true;
+    }
+
+    function getStepper() {
+        const steps: any[] = Array.isArray(readiness?.checks) ? 
readiness.checks : [];
+        return (
+            <Bullseye className="">
+                <Flex direction={{default:"column"}} justifyContent={{default: 
"justifyContentCenter"}}>
+                    <FlexItem style={{textAlign: "center"}}>
+                        {Icon()}
+                        <TextContent>
+                            <Text component={TextVariants.h2}>
+                                Waiting for services
+                            </Text>
+                        </TextContent>
+                    </FlexItem>
+                    <FlexItem>
+                        <ProgressStepper aria-label="Readiness progress" 
isCenterAligned isVertical >
+                            {steps.map(step => (
+                                <ProgressStep
+                                    key={step.name}
+                                    variant={step.status === 'UP' ? "success" 
: "info"}
+                                    isCurrent={step.status !== 'UP'}
+                                    icon={step.status !== 'UP' ? <Spinner 
isInline aria-label="Loading..."/> : undefined}
+                                    id={step.name}
+                                    titleId={step.name}
+                                    aria-label={step.name}
+                                >
+                                    {step.name}
+                                </ProgressStep>
+                            ))}
+                        </ProgressStepper>
+                    </FlexItem>
+                </Flex>
+            </Bullseye>
+        )
+    }
+
+    function getSpinner() {
+        return (
+            <Bullseye className="loading-page">
+                <Spinner className="spinner" diameter="140px" 
aria-label="Loading..."/>
+                <Tooltip content="Connecting to server..." 
position={TooltipPosition.bottom}>
+                    <div className="logo-placeholder">{Icon()}</div>
+                </Tooltip>
+            </Bullseye>
+        )
+    }
+
+    return (
+        <>
+            {showSpinner() && getSpinner()}
+            {showStepper() && getStepper()}
+        </>
+    )
+}
diff --git a/karavan-web/karavan-app/src/main/webui/src/main/MainLogin.tsx 
b/karavan-web/karavan-app/src/main/webui/src/main/MainLogin.tsx
deleted file mode 100644
index a509f498..00000000
--- a/karavan-web/karavan-app/src/main/webui/src/main/MainLogin.tsx
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import React, {useState} from 'react';
-import {
-    Bullseye, Card, CardBody, CardTitle, LoginForm, Text
-} from '@patternfly/react-core';
-import {KaravanApi} from "../api/KaravanApi";
-import {useAppConfigStore} from "../api/ProjectStore";
-import {shallow} from "zustand/shallow";
-import {ProjectEventBus} from "../api/ProjectEventBus";
-import {EventBus} from "../designer/utils/EventBus";
-
-export function MainLogin () {
-
-    const [config] = useAppConfigStore((state) => [state.config], shallow)
-    const [username, setUsername] = useState<string>();
-    const [password, setPassword] = useState<string>();
-    const [isValidUsername, setIsValidUsername] = useState<boolean>(true);
-    const [isValidPassword, setIsValidPassword] = useState<boolean>(true);
-    const [isRememberMeChecked, setIsRememberMeChecked] = 
useState<boolean>(false);
-
-    function onLoginButtonClick(event: any) {
-        event.preventDefault();
-        if (username && password) {
-            onLogin(username, password);
-        }
-    }
-
-    function onLogin(username: string, password: string) {
-        KaravanApi.auth(username, password, (res: any) => {
-            if (res?.status === 200) {
-            } else {
-                EventBus.sendAlert("Error", "Incorrect username and/or 
password!", "danger")
-            }
-        });
-    }
-
-    return (
-        <Bullseye>
-            <Card isFlat isCompact>
-                <CardTitle>
-                    <img alt="karavan-logo" src="karavan-logo-light.png" 
className="login-logo"/>
-                    <Text component="h3"
-                          style={{width: "fit-content", marginLeft: 
"auto"}}>{config.version}</Text>
-                </CardTitle>
-                <CardBody>
-                    <LoginForm
-                        showHelperText={true}
-                        usernameLabel="Username"
-                        usernameValue={username}
-                        onChangeUsername={(_event, value) => 
setUsername(value)}
-                        isValidUsername={isValidUsername}
-                        passwordLabel="Password"
-                        passwordValue={password}
-                        isShowPasswordEnabled
-                        onChangePassword={(_event, value) => 
setPassword(value)}
-                        isValidPassword={isValidPassword}
-                        onLoginButtonClick={onLoginButtonClick}
-                        loginButtonLabel="Log in"
-                    />
-                </CardBody>
-            </Card>
-        </Bullseye>
-    );
-}
\ No newline at end of file
diff --git 
a/karavan-web/karavan-app/src/main/webui/src/project/DevModeToolbar.tsx 
b/karavan-web/karavan-app/src/main/webui/src/project/DevModeToolbar.tsx
index d8c15671..76092d4c 100644
--- a/karavan-web/karavan-app/src/main/webui/src/project/DevModeToolbar.tsx
+++ b/karavan-web/karavan-app/src/main/webui/src/project/DevModeToolbar.tsx
@@ -15,8 +15,19 @@
  * limitations under the License.
  */
 
-import React, {useState} from 'react';
-import {Badge, Button, Flex, FlexItem, Label, Spinner, Switch, Tooltip, 
TooltipPosition} from '@patternfly/react-core';
+import React, {useEffect, useState} from 'react';
+import {
+    Badge,
+    Button,
+    Flex,
+    FlexItem,
+    Label,
+    Spinner,
+    Switch,
+    ToolbarItem,
+    Tooltip,
+    TooltipPosition
+} from '@patternfly/react-core';
 import '../designer/karavan.css';
 import RocketIcon from "@patternfly/react-icons/dist/esm/icons/rocket-icon";
 import ReloadIcon from "@patternfly/react-icons/dist/esm/icons/bolt-icon";
@@ -26,12 +37,15 @@ import {ProjectService} from "../api/ProjectService";
 import {shallow} from "zustand/shallow";
 import UpIcon from "@patternfly/react-icons/dist/esm/icons/running-icon";
 import DownIcon from 
"@patternfly/react-icons/dist/esm/icons/error-circle-o-icon";
+import RefreshIcon from "@patternfly/react-icons/dist/esm/icons/sync-alt-icon";
+import {KaravanApi} from "../api/KaravanApi";
+import {ContainerStatus} from "../api/ProjectModels";
 
 interface Props {
     reloadOnly?: boolean
 }
 
-export function DevModeToolbar (props: Props) {
+export function DevModeToolbar(props: Props) {
 
     const [config] = useAppConfigStore((state) => [state.config], shallow)
     const [status] = useDevModeStore((state) => [state.status], shallow)
@@ -39,6 +53,8 @@ export function DevModeToolbar (props: Props) {
     const [containers] = useStatusesStore((state) => [state.containers], 
shallow);
     const [verbose, setVerbose] = useState(false);
     const [setShowLog] = useLogStore((s) => [s.setShowLog], shallow);
+    const [poll, setPoll] = useState(false);
+    const [currentContainerStatus, setCurrentContainerStatus] = 
useState<ContainerStatus>();
 
     const containerStatus = containers.filter(c => c.containerName === 
project.projectId).at(0);
     const commands = containerStatus?.commands || ['run'];
@@ -49,20 +65,40 @@ export function DevModeToolbar (props: Props) {
     const icon = isRunning ? <UpIcon/> : <DownIcon/>;
     const inDevMode = containerStatus?.type === 'devmode';
 
+    useEffect(() => {
+        const interval = setInterval(() => {
+            refreshContainer();
+        }, 1000)
+        return () => clearInterval(interval);
+    }, [poll, currentContainerStatus, containers]);
+
+    function refreshContainer(){
+        if (poll) {
+            ProjectService.refreshAllContainerStatuses();
+            if (currentContainerStatus && !containerStatus) {
+                setPoll(false);
+            }
+            setCurrentContainerStatus(containerStatus);
+        }
+    }
+
     return (<Flex className="toolbar" direction={{default: "row"}} 
alignItems={{default: "alignItemsCenter"}}>
         <FlexItem>
-            <Button style={{visibility:"hidden"}} size="sm" 
variant={"control"} icon={<DeleteIcon/>} onClick={() => {}}>
-            </Button>
-        </FlexItem>
-        <FlexItem>
-            {(inTransit || isLoading) && <Spinner size="lg" 
aria-label="spinner"/>}
+            <Button icon={<RefreshIcon/>}
+                    variant={"link"}
+                    onClick={e => 
ProjectService.refreshAllContainerStatuses()}/>
         </FlexItem>
+        {(inTransit || isLoading) &&
+            <FlexItem>
+                <Spinner size="lg" aria-label="spinner"/>
+            </FlexItem>
+        }
         {containerStatus?.containerId && <FlexItem>
             <Label icon={icon} color={color}>
                 <Tooltip content={"Show log"} 
position={TooltipPosition.bottom}>
                     <Button className='labeled-button' variant="link" 
isDisabled={!isRunning}
                             onClick={e =>
-                                setShowLog( true, 'container', 
containerStatus.containerName)}>
+                                setShowLog(true, 'container', 
containerStatus.containerName)}>
                         {containerStatus.containerName}
                     </Button>
                 </Tooltip>
@@ -74,17 +110,20 @@ export function DevModeToolbar (props: Props) {
                 <Switch aria-label="verbose"
                         id="verbose"
                         isChecked={verbose}
-                         onChange={(_, checked) => setVerbose(checked)}
+                        onChange={(_, checked) => setVerbose(checked)}
                 />
             </Tooltip>
         </FlexItem>}
         {!isRunning && <FlexItem>
-            <Tooltip content="Run in developer mode" 
position={TooltipPosition.bottom}>
+            <Tooltip content="Run in developer mode" 
position={TooltipPosition.bottomEnd}>
                 <Button size="sm"
                         isDisabled={(!(commands.length === 0) && 
!commands.includes('run')) || inTransit}
                         variant={"primary"}
                         icon={<RocketIcon/>}
-                        onClick={() => 
ProjectService.startDevModeContainer(project, verbose)}>
+                        onClick={() => {
+                            ProjectService.startDevModeContainer(project, 
verbose);
+                            setPoll(true);
+                        }}>
                     {"Run"}
                 </Button>
             </Tooltip>
diff --git 
a/karavan-web/karavan-app/src/main/webui/src/project/ProjectDataPoller.tsx 
b/karavan-web/karavan-app/src/main/webui/src/project/ProjectDataPoller.tsx
deleted file mode 100644
index 776ac3f5..00000000
--- a/karavan-web/karavan-app/src/main/webui/src/project/ProjectDataPoller.tsx
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import React, {useEffect} from 'react';
-
-import {KaravanApi} from "../api/KaravanApi";
-import '../designer/karavan.css';
-import {useAppConfigStore, useProjectStore} from "../api/ProjectStore";
-import {shallow} from "zustand/shallow";
-import {CamelStatus} from "../api/ProjectModels";
-
-export function ProjectDataPoller() {
-
-    const [config] = useAppConfigStore((state) => [state.config], shallow)
-    const [project, setCamelStatuses, setCamelTraces, refreshTrace, setImages] 
= useProjectStore((s) =>
-        [s.project, s.setCamelStatuses, s.setCamelTraces, s.refreshTrace, 
s.setImages], shallow);
-
-    useEffect(() => {
-        const interval = setInterval(() => onRefreshStatus(), 1000);
-        return () => {
-            clearInterval(interval)
-        };
-    }, [project, refreshTrace]);
-
-    function onRefreshStatus() {
-        const projectId = project.projectId;
-        KaravanApi.getProjectCamelStatuses(projectId, config.environment, 
(res) => {
-            if (res.status === 200) {
-                setCamelStatuses(res.data);
-            } else {
-                setCamelStatuses([]);
-            }
-        })
-        KaravanApi.getImages(project.projectId, (res: any) => {
-            setImages(res)
-        });
-        if (refreshTrace) {
-            KaravanApi.getProjectCamelTraces(projectId, config.environment, 
res => {
-                if (res.status === 200) {
-                    setCamelTraces(res.data);
-                } else {
-                    setCamelTraces([]);
-                }
-            })
-        }
-    }
-
-    return (<></>)
-}
\ No newline at end of file
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 a8f6d9ba..7cc8eca2 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
@@ -25,7 +25,7 @@ import '../designer/karavan.css';
 import {ProjectToolbar} from "./ProjectToolbar";
 import {ProjectLogPanel} from "./log/ProjectLogPanel";
 import {Project} from "../api/ProjectModels";
-import {useFileStore, useProjectsStore, useProjectStore} from 
"../api/ProjectStore";
+import {useAppConfigStore, useFileStore, useProjectsStore, useProjectStore} 
from "../api/ProjectStore";
 import {MainToolbar} from "../designer/MainToolbar";
 import {ProjectTitle} from "./ProjectTitle";
 import {ProjectPanel} from "./ProjectPanel";
@@ -33,11 +33,12 @@ import {FileEditor} from "./file/FileEditor";
 import {shallow} from "zustand/shallow";
 import {useParams} from "react-router-dom";
 import {KaravanApi} from "../api/KaravanApi";
-import {ProjectDataPoller} from "./ProjectDataPoller";
 import {ImageDownloadToolbar} from "./ImageDownloadToolbar";
+import {ProjectService} from "../api/ProjectService";
 
 export function ProjectPage() {
 
+    const [config] = useAppConfigStore((state) => [state.config], shallow)
     const {file, operation} = useFileStore();
     const [projects] = useProjectsStore((state) => [state.projects], shallow)
     const [project, setProject, tab, setTab] = useProjectStore((s) => 
[s.project, s.setProject, s.tabIndex, s.setTabIndex], shallow);
@@ -51,11 +52,25 @@ export function ProjectPage() {
         } else if (projectId) {
             KaravanApi.getProject(projectId, project1 => setProject(project1, 
"select"));
         }
+        const interval = setInterval(() => onRefreshStatus(), 1000);
         return () => {
+            clearInterval(interval);
             setProject(new Project(), "none");
         }
     }, []);
 
+    function onRefreshStatus(){
+        if (tab === 'dashboard') {
+            ProjectService.refreshCamelStatus(project.projectId, 
config.environment);
+        } else if (tab === 'trace') {
+            ProjectService.refreshCamelTraces(project.projectId, 
config.environment);
+        } else if (tab === 'build') {
+            ProjectService.refreshImages(project.projectId);
+        } else if (tab === 'container') {
+
+        }
+    }
+
     function isBuildIn(): boolean {
         return ['kamelets', 'templates', 
'services'].includes(project.projectId);
     }
@@ -88,7 +103,6 @@ export function ProjectPage() {
             {showFilePanel && <FileEditor projectId={project.projectId}/>}
             {!showFilePanel && <ProjectPanel/>}
             <ProjectLogPanel/>
-            <ProjectDataPoller/>
         </PageSection>
     )
 }
diff --git 
a/karavan-web/karavan-app/src/main/webui/src/projects/CreateProjectModal.tsx 
b/karavan-web/karavan-app/src/main/webui/src/projects/CreateProjectModal.tsx
index 7d3ae0a4..87a2bf45 100644
--- a/karavan-web/karavan-app/src/main/webui/src/projects/CreateProjectModal.tsx
+++ b/karavan-web/karavan-app/src/main/webui/src/projects/CreateProjectModal.tsx
@@ -26,11 +26,11 @@ import {useProjectStore} from "../api/ProjectStore";
 import {ProjectService} from "../api/ProjectService";
 import {Project} from "../api/ProjectModels";
 import {CamelUi} from "../designer/utils/CamelUi";
-
+import {shallow} from "zustand/shallow";
 
 export function CreateProjectModal () {
 
-    const {project, operation} = useProjectStore();
+    const [operation, project, setOperation] = useProjectStore((s) => 
[s.operation, s.project, s.setOperation], shallow)
     const [name, setName] = useState('');
     const [description, setDescription] = useState('');
     const [projectId, setProjectId] = useState('');
@@ -42,13 +42,13 @@ export function CreateProjectModal () {
     }
 
     function closeModal() {
-        useProjectStore.setState({operation: "none"});
+        setOperation('none');
         cleanValues();
     }
 
     function confirmAndCloseModal() {
         ProjectService.createProject(new Project({name: name, description: 
description, projectId: projectId}));
-        useProjectStore.setState({operation: "none"});
+        setOperation('none');
         cleanValues();
     }
 
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 26eca189..60cc0f65 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
@@ -50,16 +50,32 @@ import {useProjectsStore, useProjectStore} from 
"../api/ProjectStore";
 import {MainToolbar} from "../designer/MainToolbar";
 import {Project, ProjectType} from "../api/ProjectModels";
 import {shallow} from "zustand/shallow";
+import {KaravanApi} from "../api/KaravanApi";
+import RefreshIcon from "@patternfly/react-icons/dist/esm/icons/sync-alt-icon";
+import {ProjectService} from "../api/ProjectService";
 
 export function ProjectsPage () {
 
-    const [projects] = useProjectsStore((state) => [state.projects], shallow)
-    const [operation] = useProjectStore((state) => [state.operation], shallow)
+    const [projects, setProjects] = useProjectsStore((s) => [s.projects, 
s.setProjects], shallow)
+    const [operation, setProject] = useProjectStore((s) => [s.operation, 
s.setProject], shallow)
     const [filter, setFilter] = useState<string>('');
 
+    useEffect(() => {
+        console.log("ProjectsPage", "useEffect");
+        KaravanApi.getProjects((projects: Project[]) => {
+            setProjects(projects);
+        });
+    }, []);
+
     function getTools() {
         return <Toolbar id="toolbar-group-types">
             <ToolbarContent>
+                <ToolbarItem>
+                    <Button icon={<RefreshIcon/>}
+                            variant={"link"}
+                            onClick={e => ProjectService.refreshProjects()}
+                    />
+                </ToolbarItem>
                 <ToolbarItem>
                     <TextInput className="text-field" type="search" 
id="search" name="search"
                                autoComplete="off" placeholder="Search by name"
@@ -69,7 +85,7 @@ export function ProjectsPage () {
                 <ToolbarItem>
                     <Button icon={<PlusIcon/>}
                             onClick={e =>
-                                useProjectStore.setState({operation: "create", 
project: new Project()})}
+                                setProject(new Project(), 'create')}
                     >Create</Button>
                 </ToolbarItem>
             </ToolbarContent>
diff --git 
a/karavan-web/karavan-app/src/main/webui/src/services/ServicesPage.tsx 
b/karavan-web/karavan-app/src/main/webui/src/services/ServicesPage.tsx
index 136b0120..5aad2969 100644
--- a/karavan-web/karavan-app/src/main/webui/src/services/ServicesPage.tsx
+++ b/karavan-web/karavan-app/src/main/webui/src/services/ServicesPage.tsx
@@ -53,6 +53,7 @@ import {KaravanApi} from "../api/KaravanApi";
 import {DockerComposeService, DockerCompose, ServicesYaml} from 
"../api/ServiceModels";
 import {shallow} from "zustand/shallow";
 import {ProjectLogPanel} from "../project/log/ProjectLogPanel";
+import {ProjectService} from "../api/ProjectService";
 
 
 export function ServicesPage () {
@@ -64,6 +65,10 @@ export function ServicesPage () {
 
     useEffect(() => {
         getServices();
+        const interval = setInterval(() => {
+            ProjectService.refreshAllContainerStatuses();
+        }, 1000)
+        return () => clearInterval(interval);
     }, []);
 
     function getServices() {


Reply via email to