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 eac538ef Improvements for #981
eac538ef is described below

commit eac538ef5e7298bc84d2384bae728d6909b4d484
Author: Marat Gubaidullin <[email protected]>
AuthorDate: Thu Nov 9 17:15:46 2023 -0500

    Improvements for #981
---
 .../camel/karavan/api/ContainerResource.java       | 18 +++++---
 .../apache/camel/karavan/docker/DockerService.java | 12 ++++--
 .../src/main/webui/src/project/DevModeToolbar.tsx  | 50 +++++++++++-----------
 .../src/main/webui/src/project/ProjectPage.tsx     | 27 ++++++------
 .../main/webui/src/project/build/BuildPanel.tsx    |  3 +-
 .../webui/src/project/dashboard/DashboardTab.tsx   |  2 +-
 .../src/main/webui/src/project/devmode.css         | 39 +++++++++++++++++
 .../src/main/webui/src/project/trace/TraceTab.tsx  |  1 -
 8 files changed, 101 insertions(+), 51 deletions(-)

diff --git 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/ContainerResource.java
 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/ContainerResource.java
index a288a2a7..5eefe265 100644
--- 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/ContainerResource.java
+++ 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/ContainerResource.java
@@ -32,15 +32,15 @@ import 
org.apache.camel.karavan.infinispan.model.ContainerStatus;
 import org.apache.camel.karavan.kubernetes.KubernetesService;
 import org.apache.camel.karavan.service.ConfigService;
 import org.apache.camel.karavan.service.ProjectService;
+import org.apache.camel.karavan.shared.Constants;
 import org.eclipse.microprofile.config.inject.ConfigProperty;
 import org.jboss.logging.Logger;
 
-import java.util.Comparator;
-import java.util.List;
-import java.util.Objects;
+import java.util.*;
 import java.util.stream.Collectors;
 
 import static 
org.apache.camel.karavan.service.ContainerStatusService.CONTAINER_STATUS;
+import static org.apache.camel.karavan.shared.Constants.*;
 
 @Path("/api/container")
 public class ContainerResource {
@@ -98,13 +98,21 @@ public class ContainerResource {
                             String code = projectService.getDevServiceCode();
                             DockerComposeService dockerComposeService = 
DockerComposeConverter.fromCode(code, name);
                             if (dockerComposeService != null) {
-                                
dockerService.createContainerFromCompose(dockerComposeService, 
ContainerStatus.ContainerType.devservice);
+                                Map<String,String> labels = new HashMap<>();
+                                labels.put(LABEL_TYPE, 
ContainerStatus.ContainerType.devservice.name());
+                                labels.put(LABEL_CAMEL_RUNTIME, 
Constants.CamelRuntime.CAMEL_MAIN.getValue());
+                                labels.put(LABEL_PROJECT_ID, name);
+                                
dockerService.createContainerFromCompose(dockerComposeService, labels);
                                 
dockerService.runContainer(dockerComposeService.getContainer_name());
                             }
                         } else if (Objects.equals(type, 
ContainerStatus.ContainerType.project.name())) {
                             DockerComposeService dockerComposeService = 
projectService.getProjectDockerComposeService(name);
                             if (dockerComposeService != null) {
-                                
dockerService.createContainerFromCompose(dockerComposeService, 
ContainerStatus.ContainerType.project);
+                                Map<String,String> labels = new HashMap<>();
+                                labels.put(LABEL_TYPE, 
ContainerStatus.ContainerType.project.name());
+                                labels.put(LABEL_CAMEL_RUNTIME, 
Constants.CamelRuntime.CAMEL_MAIN.getValue());
+                                labels.put(LABEL_PROJECT_ID, name);
+                                
dockerService.createContainerFromCompose(dockerComposeService, labels);
                                 
dockerService.runContainer(dockerComposeService.getContainer_name());
                             }
                         } else if (Objects.equals(type, 
ContainerStatus.ContainerType.devmode.name())) {
diff --git 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerService.java
 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerService.java
index 23ce0464..02bcf76e 100644
--- 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerService.java
+++ 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerService.java
@@ -33,6 +33,7 @@ import jakarta.inject.Inject;
 import org.apache.camel.karavan.code.CodeService;
 import org.apache.camel.karavan.code.model.DockerComposeService;
 import org.apache.camel.karavan.infinispan.model.ContainerStatus;
+import org.apache.camel.karavan.shared.Constants;
 import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
 import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
 import org.apache.commons.io.IOUtils;
@@ -45,8 +46,7 @@ import java.nio.file.Paths;
 import java.util.*;
 import java.util.stream.Collectors;
 
-import static org.apache.camel.karavan.shared.Constants.LABEL_PROJECT_ID;
-import static org.apache.camel.karavan.shared.Constants.LABEL_TYPE;
+import static org.apache.camel.karavan.shared.Constants.*;
 
 @ApplicationScoped
 public class DockerService extends DockerServiceUtils {
@@ -147,6 +147,12 @@ public class DockerService extends DockerServiceUtils {
     }
 
     public Container createContainerFromCompose(DockerComposeService compose, 
ContainerStatus.ContainerType type) throws InterruptedException {
+        Map<String,String> labels = new HashMap<>();
+        labels.put(LABEL_TYPE, type.name());
+        return createContainerFromCompose(compose, labels);
+    }
+
+    public Container createContainerFromCompose(DockerComposeService compose, 
Map<String, String> labels) throws InterruptedException {
         List<Container> containers = 
findContainer(compose.getContainer_name());
         if (containers.isEmpty()) {
             LOGGER.infof("Compose Service starting for %s", 
compose.getContainer_name());
@@ -164,7 +170,7 @@ public class DockerService extends DockerServiceUtils {
             }
 
             return createContainer(compose.getContainer_name(), 
compose.getImage(),
-                    env, compose.getPortsMap(), healthCheck, 
Map.of(LABEL_TYPE, type.name()), Map.of(), NETWORK_NAME, restartPolicy);
+                    env, compose.getPortsMap(), healthCheck, labels, Map.of(), 
NETWORK_NAME, restartPolicy);
 
         } else {
             LOGGER.info("Compose Service already exists: " + 
containers.get(0).getId());
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 76092d4c..f9056c14 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
@@ -16,18 +16,7 @@
  */
 
 import React, {useEffect, useState} from 'react';
-import {
-    Badge,
-    Button,
-    Flex,
-    FlexItem,
-    Label,
-    Spinner,
-    Switch,
-    ToolbarItem,
-    Tooltip,
-    TooltipPosition
-} from '@patternfly/react-core';
+import {Badge, Button, Flex, FlexItem, Label, Spinner, Switch, 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";
@@ -38,8 +27,9 @@ 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 StopIcon from "@patternfly/react-icons/dist/esm/icons/stop-icon";
 import {ContainerStatus} from "../api/ProjectModels";
+import "./devmode.css"
 
 interface Props {
     reloadOnly?: boolean
@@ -49,7 +39,7 @@ export function DevModeToolbar(props: Props) {
 
     const [config] = useAppConfigStore((state) => [state.config], shallow)
     const [status] = useDevModeStore((state) => [state.status], shallow)
-    const [project] = useProjectStore((state) => [state.project], shallow)
+    const [project, refreshTrace] = useProjectStore((state) => [state.project, 
state.refreshTrace], shallow)
     const [containers] = useStatusesStore((state) => [state.containers], 
shallow);
     const [verbose, setVerbose] = useState(false);
     const [setShowLog] = useLogStore((s) => [s.setShowLog], shallow);
@@ -68,13 +58,18 @@ export function DevModeToolbar(props: Props) {
     useEffect(() => {
         const interval = setInterval(() => {
             refreshContainer();
-        }, 1000)
+        }, 1300)
         return () => clearInterval(interval);
     }, [poll, currentContainerStatus, containers]);
 
     function refreshContainer(){
         if (poll) {
             ProjectService.refreshAllContainerStatuses();
+            ProjectService.refreshCamelStatus(project.projectId, 
config.environment);
+            ProjectService.refreshImages(project.projectId);
+            if (refreshTrace) {
+                ProjectService.refreshCamelTraces(project.projectId, 
config.environment);
+            }
             if (currentContainerStatus && !containerStatus) {
                 setPoll(false);
             }
@@ -83,16 +78,21 @@ export function DevModeToolbar(props: Props) {
     }
 
     return (<Flex className="toolbar" direction={{default: "row"}} 
alignItems={{default: "alignItemsCenter"}}>
-        <FlexItem>
-            <Button icon={<RefreshIcon/>}
+        <FlexItem className="refresher">
+            {poll && <Spinner className="spinner" size="lg" 
aria-label="Refresh"/>}
+            <Tooltip content={poll ? "Stop refresh" : "Refresh auto"} 
position={TooltipPosition.bottom}>
+            <Button className="button"
+                    icon={poll ? <StopIcon/> : <RefreshIcon/>}
                     variant={"link"}
-                    onClick={e => 
ProjectService.refreshAllContainerStatuses()}/>
+                    onClick={e => setPoll(!poll)}/>
+            </Tooltip>
         </FlexItem>
-        {(inTransit || isLoading) &&
-            <FlexItem>
-                <Spinner size="lg" aria-label="spinner"/>
-            </FlexItem>
-        }
+        {/*Replace with something else because Spinner is used fo refresh*/}
+        {/*{(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}>
@@ -129,7 +129,7 @@ export function DevModeToolbar(props: Props) {
             </Tooltip>
         </FlexItem>}
         {isRunning && inDevMode && <FlexItem>
-            <Tooltip content="Reload" position={TooltipPosition.bottom}>
+            <Tooltip content="Reload" position={TooltipPosition.bottomEnd}>
                 <Button size="sm"
                         isDisabled={inTransit}
                         variant={"primary"}
@@ -140,7 +140,7 @@ export function DevModeToolbar(props: Props) {
             </Tooltip>
         </FlexItem>}
         {inDevMode && <FlexItem>
-            <Tooltip content="Delete container" 
position={TooltipPosition.bottom}>
+            <Tooltip content="Delete container" 
position={TooltipPosition.bottomEnd}>
                 <Button size="sm"
                         isDisabled={!commands.includes('delete') || inTransit}
                         variant={"control"}
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 7cc8eca2..8928d4f9 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
@@ -41,7 +41,8 @@ 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);
+    const [project, setProject, tabIndex, setTabIndex, refreshTrace] =
+        useProjectStore((s) => [s.project, s.setProject, s.tabIndex, 
s.setTabIndex, s.refreshTrace], shallow);
 
     let {projectId} = useParams();
 
@@ -52,24 +53,20 @@ 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') {
-
-        }
-    }
+    useEffect(() => {
+        const interval = setInterval(() => {
+            if (tabIndex === 'build' || tabIndex === 'container') {
+                ProjectService.refreshAllContainerStatuses();
+                ProjectService.refreshImages(project.projectId);
+            }
+        }, 2000)
+        return () => clearInterval(interval);
+    }, [tabIndex]);
 
     function isBuildIn(): boolean {
         return ['kamelets', 'templates', 
'services'].includes(project.projectId);
@@ -89,7 +86,7 @@ export function ProjectPage() {
             <PageSection className="tools-section" padding={{default: 
'noPadding'}}>
                 <Flex direction={{default: "column"}} spaceItems={{default: 
"spaceItemsNone"}}>
                     <FlexItem className="project-tabs">
-                        {showTabs() && <Tabs activeKey={tab} onSelect={(event, 
tabIndex) => setTab(tabIndex)}>
+                        {showTabs() && <Tabs activeKey={tabIndex} 
onSelect={(event, tabIndex) => setTabIndex(tabIndex)}>
                             <Tab eventKey="files" title="Files"/>
                             <Tab eventKey="topology" title="Topology"/>
                             <Tab eventKey="dashboard" title="Dashboard"/>
diff --git 
a/karavan-web/karavan-app/src/main/webui/src/project/build/BuildPanel.tsx 
b/karavan-web/karavan-app/src/main/webui/src/project/build/BuildPanel.tsx
index ad0a4d2f..f1dedba6 100644
--- a/karavan-web/karavan-app/src/main/webui/src/project/build/BuildPanel.tsx
+++ b/karavan-web/karavan-app/src/main/webui/src/project/build/BuildPanel.tsx
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-import React, {useState} from 'react';
+import React, {useEffect, useState} from 'react';
 import {
     Button,
     DescriptionList,
@@ -34,6 +34,7 @@ import DeleteIcon from 
"@patternfly/react-icons/dist/esm/icons/times-circle-icon
 import {useAppConfigStore, useLogStore, useProjectStore, useStatusesStore} 
from "../../api/ProjectStore";
 import {shallow} from "zustand/shallow";
 import {EventBus} from "../../designer/utils/EventBus";
+import {ProjectService} from "../../api/ProjectService";
 
 export function BuildPanel () {
 
diff --git 
a/karavan-web/karavan-app/src/main/webui/src/project/dashboard/DashboardTab.tsx 
b/karavan-web/karavan-app/src/main/webui/src/project/dashboard/DashboardTab.tsx
index bccb0faf..e05795d8 100644
--- 
a/karavan-web/karavan-app/src/main/webui/src/project/dashboard/DashboardTab.tsx
+++ 
b/karavan-web/karavan-app/src/main/webui/src/project/dashboard/DashboardTab.tsx
@@ -48,7 +48,7 @@ export function DashboardTab() {
     return (
         <PageSection className="project-tab-panel" padding={{default: 
"padding"}}>
             {camelContainers.map((containerStatus, index) =>
-                <Card className="dashboard-card">
+                <Card className="dashboard-card" 
key={containerStatus.containerId}>
                     <CardBody>
                         <Flex direction={{default: "row"}}
                               justifyContent={{default: 
"justifyContentSpaceBetween"}}>
diff --git a/karavan-web/karavan-app/src/main/webui/src/project/devmode.css 
b/karavan-web/karavan-app/src/main/webui/src/project/devmode.css
new file mode 100644
index 00000000..fea70e8e
--- /dev/null
+++ b/karavan-web/karavan-app/src/main/webui/src/project/devmode.css
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+.karavan .refresher {
+    width: 34px;
+    height: 34px;
+}
+
+.karavan .refresher .spinner {
+    position: absolute;
+    width: 34px;
+    height: 34px;
+}
+
+.karavan .refresher .button {
+    position: absolute;
+    width: 34px;
+    height: 34px;
+    padding: 0;
+    font-size: 16px;
+}
+
+.karavan .refresher .button .pf-v5-c-button__icon {
+    margin: 0;
+}
\ No newline at end of file
diff --git 
a/karavan-web/karavan-app/src/main/webui/src/project/trace/TraceTab.tsx 
b/karavan-web/karavan-app/src/main/webui/src/project/trace/TraceTab.tsx
index 2cdf25e3..b34a5361 100644
--- a/karavan-web/karavan-app/src/main/webui/src/project/trace/TraceTab.tsx
+++ b/karavan-web/karavan-app/src/main/webui/src/project/trace/TraceTab.tsx
@@ -59,7 +59,6 @@ import {InfoMemory} from "../dashboard/InfoMemory";
 import {InfoContext} from "../dashboard/InfoContext";
 import {TraceTable} from "./TraceTable";
 
-
 export function TraceTab() {
 
     const [project, refreshTrace, setRefreshTrace, camelStatuses] = 
useProjectStore((state) =>

Reply via email to