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

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

commit 482c50f108928c6c1c078886f2ec0b1c3c0637d3
Author: Marat Gubaidullin <[email protected]>
AuthorDate: Fri Sep 8 19:45:53 2023 -0400

    Kubernetesless forst full process for #817
---
 .../src/main/webui/src/project/ProjectPanel.tsx    |   4 +
 .../src/main/webui/src/project/ProjectToolbar.tsx  |   8 +-
 .../main/webui/src/project/build/BuildPanel.tsx    | 100 +++++++-----------
 .../webui/src/project/build/ContainersPanel.tsx    | 112 ---------------------
 .../webui/src/project/build/ProjectBuildTab.tsx    |   9 +-
 .../ContainerButtons.tsx}                          |  95 ++++++++++-------
 .../webui/src/project/container/ContainerPanel.tsx |  90 +++++++++++++++++
 .../ProjectContainerTab.tsx}                       |  14 +--
 8 files changed, 202 insertions(+), 230 deletions(-)

diff --git 
a/karavan-web/karavan-app/src/main/webui/src/project/ProjectPanel.tsx 
b/karavan-web/karavan-app/src/main/webui/src/project/ProjectPanel.tsx
index 27246306..6838dbf1 100644
--- a/karavan-web/karavan-app/src/main/webui/src/project/ProjectPanel.tsx
+++ b/karavan-web/karavan-app/src/main/webui/src/project/ProjectPanel.tsx
@@ -12,6 +12,8 @@ import {ProjectBuildTab} from "./build/ProjectBuildTab";
 import {ProjectService} from "../api/ProjectService";
 import {shallow} from "zustand/shallow";
 import {ImagesPanel} from "./build/ImagesPanel";
+import {ContainerButtons} from "./container/ContainerButtons";
+import {ProjectContainerTab} from "./container/ProjectContainerTab";
 
 export function ProjectPanel () {
 
@@ -40,6 +42,7 @@ export function ProjectPanel () {
                     <Tab eventKey="dashboard" title="Dashboard"/>
                     <Tab eventKey="trace" title="Trace"/>
                     <Tab eventKey="build" title="Build"/>
+                    <Tab eventKey="container" title="Container"/>
                 </Tabs>}
             </FlexItem>
             <FlexItem>
@@ -51,6 +54,7 @@ export function ProjectPanel () {
                         {tab === 'trace' && project && <TraceTab/>}
                         {tab === 'build' && <ProjectBuildTab/>}
                         {tab === 'build' && <ImagesPanel/>}
+                        {tab === 'container' && <ProjectContainerTab/>}
                     </>
                 }
             </FlexItem>
diff --git 
a/karavan-web/karavan-app/src/main/webui/src/project/ProjectToolbar.tsx 
b/karavan-web/karavan-app/src/main/webui/src/project/ProjectToolbar.tsx
index 0dd876cc..84f0cd2c 100644
--- a/karavan-web/karavan-app/src/main/webui/src/project/ProjectToolbar.tsx
+++ b/karavan-web/karavan-app/src/main/webui/src/project/ProjectToolbar.tsx
@@ -109,7 +109,7 @@ export function ProjectToolbar () {
         return (<Toolbar id="toolbar-group-types">
             <ToolbarContent>
                 {isRunnable() && <DevModeToolbar/>}
-                {isBuild() && <BuildToolbar/>}
+                {isBuildContainer() && <BuildToolbar/>}
             </ToolbarContent>
         </Toolbar>)
     }
@@ -127,11 +127,11 @@ export function ProjectToolbar () {
     }
 
     function isRunnable(): boolean {
-        return !isKameletsProject() && !isTemplatesProject() && 
!isServicesProject() && tabIndex !== 'build';
+        return !isKameletsProject() && !isTemplatesProject() && 
!isServicesProject() && !['build', 'container'].includes(tabIndex.toString());
     }
 
-    function isBuild(): boolean {
-        return !isKameletsProject() && !isTemplatesProject() && 
!isServicesProject() && tabIndex === 'build';
+    function isBuildContainer(): boolean {
+        return !isKameletsProject() && !isTemplatesProject() && 
!isServicesProject() && ['build', 'container'].includes(tabIndex.toString());
     }
 
     function allowAddFiles(): boolean {
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 752f496c..eb4efa03 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
@@ -16,13 +16,9 @@ import TagIcon from 
"@patternfly/react-icons/dist/esm/icons/tag-icon";
 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 {ContainersPanel} from "./ContainersPanel";
+import {EventBus} from "../../designer/utils/EventBus";
 
-interface Props {
-    env: string,
-}
-
-export function BuildPanel (props: Props) {
+export function BuildPanel () {
 
     const [config] = useAppConfigStore((state) => [state.config], shallow)
     const [project] = useProjectStore((s) => [s.project], shallow);
@@ -32,31 +28,18 @@ export function BuildPanel (props: Props) {
     const [isPushing, setIsPushing] = useState<boolean>(false);
     const [isBuilding, setIsBuilding] = useState<boolean>(false);
     const [showDeleteConfirmation, setShowDeleteConfirmation] = 
useState<boolean>(false);
-    const [deleteEntityType, setDeleteEntityType] = useState<'pod' | 
'deployment' | 'build'>('pod');
     const [deleteEntityName, setDeleteEntityName] = useState<string>();
-    const [deleteEntityEnv, setDeleteEntityEnv] = useState<string>();
-    const [tag, setTag] = useState<string>(new 
Date().toISOString().substring(0,19).replaceAll(':', '-'));
+    const [tag, setTag] = useState<string>(
+        new Date().toISOString().substring(0,19).replaceAll(':', 
'').replaceAll('-', '')
+    );
 
-    function deleteEntity(type: 'pod' | 'deployment' | 'build', name: string, 
environment: string) {
-        switch (type) {
-            case "deployment":
-                KaravanApi.deleteDeployment(environment, name, (res: any) => {
-                    // if (Array.isArray(res) && Array.from(res).length > 0)
-                    // onRefresh();
-                });
-                break;
-            case "pod":
-                KaravanApi.deleteContainer(environment, 'project', name, (res: 
any) => {
-                    // if (Array.isArray(res) && Array.from(res).length > 0)
-                    // onRefresh();
-                });
-                break;
-            case "build":
-                KaravanApi.stopBuild(environment, name, (res: any) => {
-                    // if (Array.isArray(res) && Array.from(res).length > 0)
-                    // onRefresh();
-                });
-                break;
+    function deleteEntity() {
+        if (deleteEntityName) {
+            KaravanApi.stopBuild('dev', deleteEntityName, (res: any) => {
+                if (res.status === 200) {
+                    EventBus.sendAlert("Build deleted", "Build deleted: " + 
deleteEntityName, 'info');
+                }
+            });
         }
     }
 
@@ -72,7 +55,7 @@ export function BuildPanel (props: Props) {
         });
     }
 
-    function buildButton(env: string) {
+    function buildButton() {
         const status = pipelineStatuses.filter(p => p.projectId === 
project.projectId).at(0);
         const isRunning = status?.result === 'Running';
         return (<Tooltip content="Start build" position={"left"}>
@@ -95,8 +78,6 @@ export function BuildPanel (props: Props) {
                     icon={<DeleteIcon/>}
                     onClick={e => {
                         setShowDeleteConfirmation(true);
-                        setDeleteEntityType("deployment");
-                        setDeleteEntityEnv(env);
                         setDeleteEntityName(project?.projectId);
                     }}>
                 {"Delete"}
@@ -166,8 +147,6 @@ export function BuildPanel (props: Props) {
                                         className="labeled-button"
                                         variant="link" onClick={e => {
                                         setShowDeleteConfirmation(true);
-                                        setDeleteEntityType("build");
-                                        setDeleteEntityEnv(env);
                                         setDeleteEntityName(pipeline);
                                     }}></Button>
                                 </Tooltip>}
@@ -178,12 +157,12 @@ export function BuildPanel (props: Props) {
                         </LabelGroup>
                     </Tooltip>
                 </FlexItem>
-                <FlexItem>{env === "dev" && buildButton(env)}</FlexItem>
+                <FlexItem>{buildButton()}</FlexItem>
             </Flex>
         )
     }
 
-    function getBuildState(env: string) {
+    function getBuildState() {
         const status = containers.filter(c => c.projectId === 
project.projectId && c.type === 'build').at(0);
         const buildName = status?.containerName;
         const state = status?.state;
@@ -202,9 +181,6 @@ export function BuildPanel (props: Props) {
             <Flex justifyContent={{default: "justifyContentSpaceBetween"}} 
alignItems={{default: "alignItemsCenter"}}>
                 <FlexItem>
                     <LabelGroup numLabels={3}>
-                        <Label isEditable={!isRunning} onEditComplete={(_, v) 
=> setTag(v)}
-                               icon={<TagIcon className="not-spinner"/>}
-                               color={color}>{tag}</Label>
                         <Label icon={isRunning ? <Spinner diameter="16px" 
className="spinner"/> : icon}
                                color={color}>
                             {buildName
@@ -220,8 +196,6 @@ export function BuildPanel (props: Props) {
                                     className="labeled-button"
                                     variant="link" onClick={e => {
                                     setShowDeleteConfirmation(true);
-                                    setDeleteEntityType("build");
-                                    setDeleteEntityEnv(env);
                                     setDeleteEntityName(buildName);
                                 }}></Button>
                             </Tooltip>}
@@ -231,11 +205,24 @@ export function BuildPanel (props: Props) {
                                    color={color}>{buildTime + "s"}</Label>}
                     </LabelGroup>
                 </FlexItem>
-                <FlexItem>{env === "dev" && buildButton(env)}</FlexItem>
+                <FlexItem>{buildButton()}</FlexItem>
             </Flex>
         )
     }
 
+    function getBuildTag() {
+        const status = containers.filter(c => c.projectId === 
project.projectId && c.type === 'build').at(0);
+        const state = status?.state;
+        const isRunning = state === 'running';
+        const isExited = state === 'exited';
+        const color = isExited ? "grey" : (isRunning ? "blue" : "grey");
+        return (
+            <Label isEditable={!isRunning} onEditComplete={(_, v) => setTag(v)}
+                   icon={<TagIcon className="not-spinner"/>}
+                   color={color}>{tag}</Label>
+        )
+    }
+
     function getDeleteConfirmation() {
         return (<Modal
             className="modal-delete"
@@ -244,8 +231,8 @@ export function BuildPanel (props: Props) {
             onClose={() => setShowDeleteConfirmation(false)}
             actions={[
                 <Button key="confirm" variant="primary" onClick={e => {
-                    if (deleteEntityEnv && deleteEntityName && deleteEntity) {
-                        deleteEntity(deleteEntityType, deleteEntityName, 
deleteEntityEnv);
+                    if (deleteEntityName && deleteEntity) {
+                        deleteEntity();
                         setShowDeleteConfirmation(false);
                     }
                 }}>Delete
@@ -254,39 +241,24 @@ export function BuildPanel (props: Props) {
                         onClick={e => 
setShowDeleteConfirmation(false)}>Cancel</Button>
             ]}
             onEscapePress={e => setShowDeleteConfirmation(false)}>
-            <div>{"Delete " + deleteEntityType + " " + deleteEntityName + 
"?"}</div>
+            <div>{"Delete build " + deleteEntityName + "?"}</div>
         </Modal>)
     }
 
-    const env = props.env;
     return (
         <Card className="project-status">
             <CardBody>
                 <DescriptionList isHorizontal 
horizontalTermWidthModifier={{default: '20ch'}}>
                     <DescriptionListGroup>
-                        <DescriptionListTerm>Environment</DescriptionListTerm>
-                        <DescriptionListDescription>
-                            <Badge className="badge">{env}</Badge>
-                        </DescriptionListDescription>
-                    </DescriptionListGroup>
-                    <DescriptionListGroup>
-                        <DescriptionListTerm>Build container with 
tag</DescriptionListTerm>
+                        <DescriptionListTerm>Tag</DescriptionListTerm>
                         <DescriptionListDescription>
-                            {getBuildState(env)}
+                            {getBuildTag()}
                         </DescriptionListDescription>
                     </DescriptionListGroup>
-                    {config.infrastructure === 'kubernetes' &&
-                        <DescriptionListGroup>
-                        <DescriptionListTerm>Deployment</DescriptionListTerm>
-                        <DescriptionListDescription>
-                            {getReplicasPanel(env)}
-                        </DescriptionListDescription>
-                    </DescriptionListGroup>
-                    }
                     <DescriptionListGroup>
-                        <DescriptionListTerm>Containers</DescriptionListTerm>
+                        <DescriptionListTerm>Build 
container</DescriptionListTerm>
                         <DescriptionListDescription>
-                            <ContainersPanel env={props.env}/>
+                            {getBuildState()}
                         </DescriptionListDescription>
                     </DescriptionListGroup>
                 </DescriptionList>
diff --git 
a/karavan-web/karavan-app/src/main/webui/src/project/build/ContainersPanel.tsx 
b/karavan-web/karavan-app/src/main/webui/src/project/build/ContainersPanel.tsx
deleted file mode 100644
index 87a43f0f..00000000
--- 
a/karavan-web/karavan-app/src/main/webui/src/project/build/ContainersPanel.tsx
+++ /dev/null
@@ -1,112 +0,0 @@
-import React, {useState} from 'react';
-import {
-    Button, Tooltip, Flex, FlexItem, LabelGroup, Label, Modal
-} from '@patternfly/react-core';
-import '../../designer/karavan.css';
-import {KaravanApi} from "../../api/KaravanApi";
-import UpIcon from "@patternfly/react-icons/dist/esm/icons/check-circle-icon";
-import DownIcon from 
"@patternfly/react-icons/dist/esm/icons/error-circle-o-icon";
-import DeleteIcon from 
"@patternfly/react-icons/dist/esm/icons/times-circle-icon";
-import {ContainerStatus} from "../../api/ProjectModels";
-import {useLogStore, useProjectStore, useStatusesStore} from 
"../../api/ProjectStore";
-import {shallow} from "zustand/shallow";
-
-interface Props {
-    env: string,
-}
-
-export function ContainersPanel (props: Props) {
-
-    const [project] = useProjectStore((s) => [s.project], shallow);
-    const [setShowLog] = useLogStore((s) => [s.setShowLog], shallow);
-    const [containers, deployments, camels, pipelineStatuses] =
-        useStatusesStore((s) => [s.containers, s.deployments, s.camels, 
s.pipelineStatuses], shallow);
-    const [showDeleteConfirmation, setShowDeleteConfirmation] = 
useState<boolean>(false);
-    const [deleteEntityName, setDeleteEntityName] = useState<string>();
-    const [deleteEntityEnv, setDeleteEntityEnv] = useState<string>();
-
-    function deleteContainer(name: string, environment: string) {
-        KaravanApi.deleteContainer(environment, 'project', name, (res: any) => 
{
-            // if (Array.isArray(res) && Array.from(res).length > 0)
-            // onRefresh();
-        });
-    }
-
-    function deleteButton(env: string) {
-        return (<Tooltip content="Delete container" position={"left"}>
-            <Button size="sm" variant="secondary"
-                    className="project-button"
-                    icon={<DeleteIcon/>}
-                    onClick={e => {
-                        setShowDeleteConfirmation(true);
-                        setDeleteEntityEnv(env);
-                        setDeleteEntityName(project?.projectId);
-                    }}>
-                {"Delete"}
-            </Button>
-        </Tooltip>)
-    }
-
-    function getDeleteConfirmation() {
-        return (<Modal
-            className="modal-delete"
-            title="Confirmation"
-            isOpen={showDeleteConfirmation}
-            onClose={() => setShowDeleteConfirmation(false)}
-            actions={[
-                <Button key="confirm" variant="primary" onClick={e => {
-                    if (deleteEntityEnv && deleteEntityName) {
-                        deleteContainer(deleteEntityName, deleteEntityEnv);
-                        setShowDeleteConfirmation(false);
-                    }
-                }}>Delete
-                </Button>,
-                <Button key="cancel" variant="link"
-                        onClick={e => 
setShowDeleteConfirmation(false)}>Cancel</Button>
-            ]}
-            onEscapePress={e => setShowDeleteConfirmation(false)}>
-            <div>{"Delete container " + deleteEntityName + "?"}</div>
-        </Modal>)
-    }
-
-    const env = props.env;
-    const conts = containers.filter(d => d.projectId === project?.projectId && 
d.type === 'project');
-    return (
-        <Flex justifyContent={{default: "justifyContentSpaceBetween"}}
-              alignItems={{default: "alignItemsFlexStart"}}>
-            <FlexItem>
-                {conts.length === 0 && <Label icon={<DownIcon/>} 
color={"grey"}>No pods</Label>}
-                <LabelGroup numLabels={2} isVertical>
-                    {conts.map((pod: ContainerStatus) => {
-                            const ready = pod.state === 'running';
-                            return (
-                                <Tooltip key={pod.containerName} 
content={pod.state}>
-                                    <Label icon={ready ? <UpIcon/> : 
<DownIcon/>} color={ready ? "green" : "red"}>
-                                        <Button variant="link" 
className="labeled-button"
-                                                onClick={e => {
-                                                    
setShowLog(true,'container', pod.containerName);
-                                                }}>
-                                            {pod.containerName}
-                                        </Button>
-                                        <Tooltip content={"Delete Container"}>
-                                            <Button icon={<DeleteIcon/>}
-                                                    className="labeled-button"
-                                                    variant="link"
-                                                    onClick={e => {
-                                                        
setShowDeleteConfirmation(true);
-                                                        
setDeleteEntityEnv(env);
-                                                        
setDeleteEntityName(pod.containerName);
-                                                    }}></Button>
-                                        </Tooltip>
-                                    </Label>
-                                </Tooltip>
-                            )
-                        }
-                    )}
-                </LabelGroup>
-            </FlexItem>
-            <FlexItem>{env === "dev" && deleteButton(env)}</FlexItem>
-            {showDeleteConfirmation && getDeleteConfirmation()}
-        </Flex>
-    )
-}
diff --git 
a/karavan-web/karavan-app/src/main/webui/src/project/build/ProjectBuildTab.tsx 
b/karavan-web/karavan-app/src/main/webui/src/project/build/ProjectBuildTab.tsx
index e761bbcb..7c980820 100644
--- 
a/karavan-web/karavan-app/src/main/webui/src/project/build/ProjectBuildTab.tsx
+++ 
b/karavan-web/karavan-app/src/main/webui/src/project/build/ProjectBuildTab.tsx
@@ -2,20 +2,13 @@ import React from 'react';
 import '../../designer/karavan.css';
 import {BuildPanel} from "./BuildPanel";
 import {PageSection} from "@patternfly/react-core";
-import {useAppConfigStore, useProjectStore} from "../../api/ProjectStore";
 
 export function ProjectBuildTab () {
 
-    const {config} = useAppConfigStore();
-    const {project} = useProjectStore();
-
     return (
         <PageSection className="project-tab-panel project-build-panel" 
padding={{default: "padding"}}>
             <div>
-                {/*{["dev", "test", "prod"].map(env =>*/}
-                {config.environments.map(env =>
-                    <BuildPanel key={env} env={env}/>
-                )}
+                <BuildPanel/>
             </div>
         </PageSection>
     )
diff --git 
a/karavan-web/karavan-app/src/main/webui/src/project/ContainerPanel.tsx 
b/karavan-web/karavan-app/src/main/webui/src/project/container/ContainerButtons.tsx
similarity index 53%
rename from 
karavan-web/karavan-app/src/main/webui/src/project/ContainerPanel.tsx
rename to 
karavan-web/karavan-app/src/main/webui/src/project/container/ContainerButtons.tsx
index c32fb4a7..1fafb4d8 100644
--- a/karavan-web/karavan-app/src/main/webui/src/project/ContainerPanel.tsx
+++ 
b/karavan-web/karavan-app/src/main/webui/src/project/container/ContainerButtons.tsx
@@ -1,24 +1,19 @@
-import React from 'react';
-import {Button, Flex, FlexItem, Label, Spinner, Tooltip, TooltipPosition} from 
'@patternfly/react-core';
-import '../designer/karavan.css';
+import React, {useState} from 'react';
+import {Button, Flex, FlexItem, Modal, Spinner, Tooltip, TooltipPosition} from 
'@patternfly/react-core';
+import '../../designer/karavan.css';
 import DeleteIcon from "@patternfly/react-icons/dist/esm/icons/trash-icon";
-import {useAppConfigStore, useDevModeStore, useLogStore, useProjectStore, 
useStatusesStore} from "../api/ProjectStore";
+import {useAppConfigStore, useDevModeStore, useLogStore, useProjectStore, 
useStatusesStore} from "../../api/ProjectStore";
 import {shallow} from "zustand/shallow";
-import UpIcon from "@patternfly/react-icons/dist/esm/icons/check-circle-icon";
-import DownIcon from 
"@patternfly/react-icons/dist/esm/icons/error-circle-o-icon";
 import RunIcon from "@patternfly/react-icons/dist/esm/icons/play-icon";
-import {ProjectService} from "../api/ProjectService";
-import ReloadIcon from "@patternfly/react-icons/dist/esm/icons/bolt-icon";
-import {KaravanApi} from "../api/KaravanApi";
-import {ProjectEventBus} from "../api/ProjectEventBus";
-import {EventBus} from "../designer/utils/EventBus";
+import {KaravanApi} from "../../api/KaravanApi";
 import StopIcon from "@patternfly/react-icons/dist/js/icons/stop-icon";
 
+
 interface Props {
-    reloadOnly?: boolean
+    env: string,
 }
 
-export function ContainerPanel (props: Props) {
+export function ContainerButtons (props: Props) {
 
     const [config] = useAppConfigStore((state) => [state.config], shallow)
     const [status] = useDevModeStore((state) => [state.status], shallow)
@@ -26,29 +21,61 @@ export function ContainerPanel (props: Props) {
     const [containers] = useStatusesStore((state) => [state.containers], 
shallow);
     const [setShowLog] = useLogStore((s) => [s.setShowLog], shallow);
 
+    const [showConfirmation, setShowConfirmation] = useState<boolean>(false);
+    const [actionType, setActionType] = useState<'run' | 'stop' | 
'delete'>('run');
+
     const containerStatus = containers.filter(c => c.containerName === 
project.projectId).at(0);
     const commands = containerStatus?.commands || ['run'];
     const isRunning = containerStatus?.state === 'running';
     const inTransit = containerStatus?.inTransit;
     const isLoading = status === 'wip';
-    const color = containerStatus?.state === 'running' ? "green" : "grey";
-    const icon = isRunning ? <UpIcon/> : <DownIcon/>;
+
+    function act() {
+        switch (actionType) {
+            case "run":
+                KaravanApi.manageContainer(props.env, 'project', 
project.projectId, 'run', res => {
+                    setShowLog(false, 'container', undefined)
+                });
+                break;
+            case "stop":
+                KaravanApi.manageContainer(props.env, 'project', 
project.projectId, 'stop', res => {
+                    setShowLog(false, 'container', undefined)
+                });
+                break;
+            case "delete":
+                KaravanApi.manageContainer(props.env, 'project', 
project.projectId, 'delete', res => {
+                    setShowLog(false, 'container', undefined)
+                });
+                break;
+        }
+    }
+
+    function getDeleteConfirmation() {
+        return (<Modal
+            className="modal-delete"
+            title="Confirmation"
+            isOpen={showConfirmation}
+            onClose={() => setShowConfirmation(false)}
+            actions={[
+                <Button key="confirm" variant="primary" onClick={e => {
+                    if (actionType && project.projectId) {
+                        act();
+                        setShowConfirmation(false);
+                    }
+                }}>Delete
+                </Button>,
+                <Button key="cancel" variant="link"
+                        onClick={e => 
setShowConfirmation(false)}>Cancel</Button>
+            ]}
+            onEscapePress={e => setShowConfirmation(false)}>
+            <div>{"Confirm " + actionType + " container?"}</div>
+        </Modal>)
+    }
 
     return (<Flex className="toolbar" direction={{default: "row"}} 
alignItems={{default: "alignItemsCenter"}}>
         <FlexItem>
             {(inTransit || isLoading) && <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)}>
-                        {containerStatus.containerName}
-                    </Button>
-                </Tooltip>
-            </Label>
-        </FlexItem>}
         {!isRunning && <FlexItem>
             <Tooltip content="Run container" position={TooltipPosition.bottom}>
                 <Button size="sm"
@@ -56,9 +83,8 @@ export function ContainerPanel (props: Props) {
                         variant={"primary"}
                         icon={<RunIcon/>}
                         onClick={() => {
-                            KaravanApi.manageContainer('dev', 'project', 
project.projectId, 'run', res => {
-                                setShowLog(false, 'container', undefined)
-                            });
+                            setActionType('run');
+                            setShowConfirmation(true);
                         }}>
                     {"Run"}
                 </Button>
@@ -72,9 +98,8 @@ export function ContainerPanel (props: Props) {
                             variant={"control"}
                             icon={<StopIcon/>}
                             onClick={() => {
-                                KaravanApi.manageContainer('dev', 'project', 
project.projectId, 'stop', res => {
-                                    setShowLog(false, 'container', undefined)
-                                });
+                                setActionType('stop');
+                                setShowConfirmation(true);
                             }}>
                     </Button>
                 </Tooltip>
@@ -87,12 +112,12 @@ export function ContainerPanel (props: Props) {
                         variant={"control"}
                         icon={<DeleteIcon/>}
                         onClick={() => {
-                            KaravanApi.manageContainer('dev', 'project', 
project.projectId, 'delete', res => {
-                                setShowLog(false, 'container', undefined)
-                            });
+                            setActionType('delete');
+                            setShowConfirmation(true);
                         }}>
                 </Button>
             </Tooltip>
         </FlexItem>
+        {showConfirmation && getDeleteConfirmation()}
     </Flex>);
 }
\ No newline at end of file
diff --git 
a/karavan-web/karavan-app/src/main/webui/src/project/container/ContainerPanel.tsx
 
b/karavan-web/karavan-app/src/main/webui/src/project/container/ContainerPanel.tsx
new file mode 100644
index 00000000..f1bda323
--- /dev/null
+++ 
b/karavan-web/karavan-app/src/main/webui/src/project/container/ContainerPanel.tsx
@@ -0,0 +1,90 @@
+import React from 'react';
+import {
+    Badge,
+    Button,
+    Card,
+    CardBody,
+    DescriptionList,
+    DescriptionListDescription,
+    DescriptionListGroup,
+    DescriptionListTerm,
+    Flex,
+    FlexItem,
+    Label,
+    LabelGroup,
+    Tooltip,
+    TooltipPosition
+} from '@patternfly/react-core';
+import '../../designer/karavan.css';
+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 {useLogStore, useProjectStore, useStatusesStore} from 
"../../api/ProjectStore";
+import {shallow} from "zustand/shallow";
+import {ContainerStatus} from "../../api/ProjectModels";
+import {ContainerButtons} from "./ContainerButtons";
+
+interface Props {
+    env: string,
+}
+
+export function ContainerPanel (props: Props) {
+
+    const [project] = useProjectStore((s) => [s.project], shallow);
+    const [setShowLog] = useLogStore((s) => [s.setShowLog], shallow);
+    const [containers, deployments, camels, pipelineStatuses] =
+        useStatusesStore((s) => [s.containers, s.deployments, s.camels, 
s.pipelineStatuses], shallow);
+
+    function getButtons() {
+        const env = props.env;
+        const conts = containers.filter(d => d.projectId === 
project?.projectId && d.type === 'project');
+        return (
+            <Flex justifyContent={{default: "justifyContentSpaceBetween"}}
+                  alignItems={{default: "alignItemsFlexStart"}}>
+                <FlexItem>
+                    {conts.length === 0 && <Label icon={<DownIcon/>} 
color={"grey"}>No pods</Label>}
+                    <LabelGroup numLabels={2} isVertical>
+                        {conts.map((pod: ContainerStatus) => {
+                                const ready = pod.state === 'running';
+                                return (
+                                    <Tooltip key={pod.containerName} 
content={pod.state} position={TooltipPosition.left}>
+                                        <Label icon={ready ? <UpIcon/> : 
<DownIcon/>} color={ready ? "green" : "grey"}>
+                                            <Button variant="link" 
className="labeled-button"
+                                                    onClick={e => {
+                                                        setShowLog(true, 
'container', pod.containerName);
+                                                    }}>
+                                                {pod.containerName}
+                                            </Button>
+                                        </Label>
+                                    </Tooltip>
+                                )
+                            }
+                        )}
+                    </LabelGroup>
+                </FlexItem>
+                <FlexItem>{env === "dev" && <ContainerButtons 
env={env}/>}</FlexItem>
+            </Flex>
+        )
+    }
+
+    const env = props.env;
+    return (
+        <Card className="project-status">
+            <CardBody>
+                <DescriptionList isHorizontal 
horizontalTermWidthModifier={{default: '20ch'}}>
+                    <DescriptionListGroup>
+                        <DescriptionListTerm>Environment</DescriptionListTerm>
+                        <DescriptionListDescription>
+                            <Badge className="badge">{env}</Badge>
+                        </DescriptionListDescription>
+                    </DescriptionListGroup>
+                    <DescriptionListGroup>
+                        <DescriptionListTerm>Containers</DescriptionListTerm>
+                        <DescriptionListDescription>
+                            {getButtons()}
+                        </DescriptionListDescription>
+                    </DescriptionListGroup>
+                </DescriptionList>
+            </CardBody>
+        </Card>
+    )
+}
diff --git 
a/karavan-web/karavan-app/src/main/webui/src/project/build/ProjectBuildTab.tsx 
b/karavan-web/karavan-app/src/main/webui/src/project/container/ProjectContainerTab.tsx
similarity index 50%
copy from 
karavan-web/karavan-app/src/main/webui/src/project/build/ProjectBuildTab.tsx
copy to 
karavan-web/karavan-app/src/main/webui/src/project/container/ProjectContainerTab.tsx
index e761bbcb..08eb587a 100644
--- 
a/karavan-web/karavan-app/src/main/webui/src/project/build/ProjectBuildTab.tsx
+++ 
b/karavan-web/karavan-app/src/main/webui/src/project/container/ProjectContainerTab.tsx
@@ -1,20 +1,20 @@
 import React from 'react';
+import {
+    PageSection
+} from '@patternfly/react-core';
 import '../../designer/karavan.css';
-import {BuildPanel} from "./BuildPanel";
-import {PageSection} from "@patternfly/react-core";
-import {useAppConfigStore, useProjectStore} from "../../api/ProjectStore";
+import {useAppConfigStore} from "../../api/ProjectStore";
+import {ContainerPanel} from "./ContainerPanel";
 
-export function ProjectBuildTab () {
+export function ProjectContainerTab() {
 
     const {config} = useAppConfigStore();
-    const {project} = useProjectStore();
 
     return (
         <PageSection className="project-tab-panel project-build-panel" 
padding={{default: "padding"}}>
             <div>
-                {/*{["dev", "test", "prod"].map(env =>*/}
                 {config.environments.map(env =>
-                    <BuildPanel key={env} env={env}/>
+                    <ContainerPanel key={env} env={env}/>
                 )}
             </div>
         </PageSection>

Reply via email to