You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ma...@apache.org on 2022/11/19 02:03:36 UTC

[camel-karavan] 04/12: Align Look and feel

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 f1382d702f6ae8b9cd15f5c7478d3bcd3fb1b4a4
Author: Marat Gubaidullin <ma...@gmail.com>
AuthorDate: Fri Nov 18 17:05:42 2022 -0500

    Align Look and feel
---
 .../src/main/webui/src/dashboard/DashboardPage.tsx |  35 +++-
 .../src/main/webui/src/designer/karavan.css        |   1 +
 karavan-app/src/main/webui/src/index.css           |  14 +-
 .../src/main/webui/src/projects/ProjectPage.tsx    |   4 +-
 .../src/main/webui/src/projects/ProjectsPage.tsx   | 181 ++++++++++++---------
 karavan-designer/src/designer/karavan.css          |   1 +
 6 files changed, 135 insertions(+), 101 deletions(-)

diff --git a/karavan-app/src/main/webui/src/dashboard/DashboardPage.tsx b/karavan-app/src/main/webui/src/dashboard/DashboardPage.tsx
index 8f5fe20..e1e5ced 100644
--- a/karavan-app/src/main/webui/src/dashboard/DashboardPage.tsx
+++ b/karavan-app/src/main/webui/src/dashboard/DashboardPage.tsx
@@ -1,13 +1,13 @@
 import React from 'react';
 import {
-    Badge,
-    Button,
+    Badge, Bullseye,
+    Button, EmptyState, EmptyStateIcon, EmptyStateVariant,
     Flex,
     FlexItem, HelperText, HelperTextItem, Label, LabelGroup,
-    PageSection,
+    PageSection, Spinner,
     Text,
     TextContent,
-    TextInput, ToggleGroup, ToggleGroupItem,
+    TextInput, Title, ToggleGroup, ToggleGroupItem,
     Toolbar,
     ToolbarContent,
     ToolbarItem, Tooltip
@@ -22,6 +22,7 @@ import Icon from "../Logo";
 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 RefreshIcon from "@patternfly/react-icons/dist/esm/icons/sync-alt-icon";
+import SearchIcon from "@patternfly/react-icons/dist/esm/icons/search-icon";
 
 interface Props {
     config: any,
@@ -37,6 +38,7 @@ interface State {
     isCreateModalOpen: boolean,
     isDeleteModalOpen: boolean,
     isCopy: boolean,
+    loading: boolean,
     projectToCopy?: Project,
     projectToDelete?: Project,
     filter: string,
@@ -56,6 +58,7 @@ export class DashboardPage extends React.Component<Props, State> {
         isCreateModalOpen: false,
         isDeleteModalOpen: false,
         isCopy: false,
+        loading: true,
         filter: '',
         name: '',
         description: '',
@@ -75,7 +78,7 @@ export class DashboardPage extends React.Component<Props, State> {
     onGetProjects = () => {
         KaravanApi.getConfiguration((config: any) => {
             KaravanApi.getProjects((projects: Project[]) => {
-                this.setState({projects: projects})
+                this.setState({projects: projects, loading: false})
             });
             KaravanApi.getAllDeploymentStatuses((statuses: DeploymentStatus[]) => {
                 this.setState({deploymentStatuses: statuses});
@@ -223,6 +226,27 @@ export class DashboardPage extends React.Component<Props, State> {
         }
     }
 
+    getEmptyState() {
+        const {loading} = this.state;
+        return (
+            <Tr>
+                <Td colSpan={8}>
+                    <Bullseye>
+                        {loading && <Spinner className="progress-stepper" isSVG diameter="80px" aria-label="Loading..."/>}
+                        {!loading &&
+                            <EmptyState variant={EmptyStateVariant.small}>
+                                <EmptyStateIcon icon={SearchIcon}/>
+                                <Title headingLevel="h2" size="lg">
+                                    No results found
+                                </Title>
+                            </EmptyState>
+                        }
+                    </Bullseye>
+                </Td>
+            </Tr>
+        )
+    }
+
     render() {
         const deployments = Array.from(new Set(this.state.deploymentStatuses.filter(d => d.name.toLowerCase().includes(this.state.filter)).map(d => d.name)));
         return (
@@ -315,6 +339,7 @@ export class DashboardPage extends React.Component<Props, State> {
                                     </Td>
                                 </Tr>
                             ))}
+                            {deployments.length === 0 && this.getEmptyState()}
                         </Tbody>
                     </TableComposable>
                 </PageSection>
diff --git a/karavan-app/src/main/webui/src/designer/karavan.css b/karavan-app/src/main/webui/src/designer/karavan.css
index 38e2973..77ff41e 100644
--- a/karavan-app/src/main/webui/src/designer/karavan.css
+++ b/karavan-app/src/main/webui/src/designer/karavan.css
@@ -1274,6 +1274,7 @@
     overflow: auto;
     flex-shrink: unset;
     flex-grow: 1;
+    background-color: var(--pf-global--BackgroundColor--light-300);
 }
 
 .karavan .designer-page {
diff --git a/karavan-app/src/main/webui/src/index.css b/karavan-app/src/main/webui/src/index.css
index b19e0f5..efa6238 100644
--- a/karavan-app/src/main/webui/src/index.css
+++ b/karavan-app/src/main/webui/src/index.css
@@ -68,18 +68,6 @@
   background-color: var(--pf-global--BackgroundColor--dark-400);
 }
 
-.karavan .kamelet-section {
-  display: flex;
-  flex-direction: column;
-  height: 100%;
-}
-
-.karavan .kamelets-page {
-  overflow: auto;
-  flex-shrink: unset;
-  flex-grow: 1;
-}
-
 .karavan .integration-card .pf-c-card__footer {
   text-align: end;
 }
@@ -128,7 +116,7 @@
   font-size: 14px;
 }
 
-.karavan .project-page .project-page-section {
+.karavan .project-page .project-tabs {
   background-color: white;
 }
 
diff --git a/karavan-app/src/main/webui/src/projects/ProjectPage.tsx b/karavan-app/src/main/webui/src/projects/ProjectPage.tsx
index e09b981..e1edd56 100644
--- a/karavan-app/src/main/webui/src/projects/ProjectPage.tsx
+++ b/karavan-app/src/main/webui/src/projects/ProjectPage.tsx
@@ -420,7 +420,7 @@ export class ProjectPage extends React.Component<Props, State> {
                                  padding={{default: file !== undefined ? 'noPadding' : 'noPadding'}}>
                         <Flex direction={{default: "column"}} spaceItems={{default: "spaceItemsNone"}}>
                             {!isTemplates &&
-                                <FlexItem>
+                                <FlexItem className="project-tabs">
                                     <Tabs activeKey={tab} onSelect={(event, tabIndex) => this.setState({tab: tabIndex})}>
                                         <Tab eventKey="development" title="Development"/>
                                         <Tab eventKey="operations" title="Operations"/>
@@ -431,12 +431,12 @@ export class ProjectPage extends React.Component<Props, State> {
                                 <FlexItem>
                                     <PageSection padding={{default: "padding"}}>
                                         {tab === 'development' && <ProjectInfo project={this.props.project} config={this.props.config} deleteEntity={this.deleteEntity} showLog={this.showLogs}/>}
+                                        {tab === 'development' && this.getProjectFiles()}
                                         {tab === 'operations' && <ProjectOperations environments={this.state.environments} project={this.props.project} config={this.props.config}/>}
                                     </PageSection>
                                 </FlexItem>
                             }
                         </Flex>
-                        {tab === 'development' && this.getProjectFiles()}
                     </PageSection>}
                 {showDesigner && this.getDesigner()}
                 {showEditor && this.getEditor()}
diff --git a/karavan-app/src/main/webui/src/projects/ProjectsPage.tsx b/karavan-app/src/main/webui/src/projects/ProjectsPage.tsx
index 32a7a4d..320be76 100644
--- a/karavan-app/src/main/webui/src/projects/ProjectsPage.tsx
+++ b/karavan-app/src/main/webui/src/projects/ProjectsPage.tsx
@@ -23,7 +23,7 @@ import {
     OverflowMenuContent,
     OverflowMenuGroup,
     OverflowMenuItem,
-    Flex, FlexItem, Radio
+    Flex, FlexItem, Radio, Spinner
 } from '@patternfly/react-core';
 import '../designer/karavan.css';
 import {MainToolbar} from "../MainToolbar";
@@ -51,6 +51,7 @@ interface State {
     isCreateModalOpen: boolean,
     isDeleteModalOpen: boolean,
     isCopy: boolean,
+    loading: boolean,
     projectToCopy?: Project,
     projectToDelete?: Project,
     filter: string,
@@ -68,6 +69,7 @@ export class ProjectsPage extends React.Component<Props, State> {
         isCreateModalOpen: false,
         isDeleteModalOpen: false,
         isCopy: false,
+        loading: true,
         filter: '',
         name: '',
         description: '',
@@ -114,8 +116,9 @@ export class ProjectsPage extends React.Component<Props, State> {
     };
 
     onGetProjects = () => {
+        this.setState({loading: true});
         KaravanApi.getProjects((projects: Project[]) => {
-            this.setState({projects: projects})
+            this.setState({projects: projects, loading: false})
         });
         KaravanApi.getDeploymentStatuses(this.props.config.environment, (statuses: DeploymentStatus[]) => {
             this.setState({deploymentStatuses: statuses});
@@ -144,7 +147,7 @@ export class ProjectsPage extends React.Component<Props, State> {
     </TextContent>);
 
     closeModal = () => {
-        this.setState({isCreateModalOpen: false, isCopy: false, name: this.props.config.groupId, description: '', projectId: '', runtime: this.props.config.runtime });
+        this.setState({isCreateModalOpen: false, isCopy: false, name: this.props.config.groupId, description: '', projectId: '', runtime: this.props.config.runtime});
         this.onGetProjects();
     }
 
@@ -245,6 +248,99 @@ export class ProjectsPage extends React.Component<Props, State> {
         });
     }
 
+    getEmptyState() {
+        const {loading} = this.state;
+        return (
+            <Tr>
+                <Td colSpan={8}>
+                    <Bullseye>
+                        {loading && <Spinner className="progress-stepper" isSVG diameter="80px" aria-label="Loading..."/>}
+                        {!loading &&
+                            <EmptyState variant={EmptyStateVariant.small}>
+                                <EmptyStateIcon icon={SearchIcon}/>
+                                <Title headingLevel="h2" size="lg">
+                                    No results found
+                                </Title>
+                            </EmptyState>
+                        }
+                    </Bullseye>
+                </Td>
+            </Tr>
+        )
+    }
+
+    getProjectsTable() {
+        const {projects, filter} = this.state;
+        const projs = projects.filter(p => p.name.toLowerCase().includes(filter) || p.description.toLowerCase().includes(filter));
+        return (
+            <TableComposable aria-label="Projects" variant={"compact"}>
+                <Thead>
+                    <Tr>
+                        <Th key='type'>Runtime</Th>
+                        <Th key='projectId'>Project ID</Th>
+                        <Th key='name'>Name</Th>
+                        <Th key='description'>Description</Th>
+                        <Th key='commit'>Commit</Th>
+                        <Th key='deployment'>Environment</Th>
+                        <Th key='action'></Th>
+                    </Tr>
+                </Thead>
+                <Tbody>
+                    {projs.map(project => (
+                        <Tr key={project.projectId}>
+                            <Td modifier={"fitContent"}>
+                                <Tooltip content={project.runtime} position={"left"}>
+                                    <Badge className="runtime-badge">{project.runtime.substring(0, 1).toUpperCase()}</Badge>
+                                </Tooltip>
+                            </Td>
+                            <Td>
+                                <Button style={{padding: '6px'}} variant={"link"} onClick={e => this.props.onSelect?.call(this, project)}>
+                                    {project.projectId}
+                                </Button>
+                            </Td>
+                            <Td>{project.name}</Td>
+                            <Td>{project.description}</Td>
+                            <Td isActionCell>
+                                <Tooltip content={project.lastCommit} position={"bottom"}>
+                                    <Badge>{project.lastCommit?.substr(0, 7)}</Badge>
+                                </Tooltip>
+                            </Td>
+                            <Td noPadding style={{width: "180px"}}>
+                                <Flex direction={{default: "row"}}>
+                                    {this.getDeploymentByEnvironments(project.projectId).map(value => (
+                                        <FlexItem className="badge-flex-item" key={value[0]}>
+                                            <Badge className="badge" isRead={!value[1]}>{value[0]}</Badge>
+                                        </FlexItem>
+                                    ))}
+                                </Flex>
+                            </Td>
+                            <Td isActionCell>
+                                <OverflowMenu breakpoint="md">
+                                    <OverflowMenuContent>
+                                        <OverflowMenuGroup groupType="button">
+                                            <OverflowMenuItem>
+                                                <Tooltip content={"Copy project"} position={"bottom"}>
+                                                    <Button variant={"plain"} icon={<CopyIcon/>}
+                                                            onClick={e => this.setState({isCreateModalOpen: true, isCopy: true, projectToCopy: project})}></Button>
+                                                </Tooltip>
+                                            </OverflowMenuItem>
+                                            <OverflowMenuItem>
+                                                <Tooltip content={"Delete project"} position={"bottom"}>
+                                                    <Button variant={"plain"} icon={<DeleteIcon/>} onClick={e => this.onProjectDelete(project)}></Button>
+                                                </Tooltip>
+                                            </OverflowMenuItem>
+                                        </OverflowMenuGroup>
+                                    </OverflowMenuContent>
+                                </OverflowMenu>
+                            </Td>
+                        </Tr>
+                    ))}
+                    {projs.length === 0 && this.getEmptyState()}
+                </Tbody>
+            </TableComposable>
+        )
+    }
+
     render() {
         const projects = this.state.projects.filter(p => p.name.toLowerCase().includes(this.state.filter) || p.description.toLowerCase().includes(this.state.filter));
         return (
@@ -253,84 +349,7 @@ export class ProjectsPage extends React.Component<Props, State> {
                     <MainToolbar title={this.title()} tools={this.tools()}/>
                 </PageSection>
                 <PageSection isFilled className="kamelets-page">
-                    <TableComposable aria-label="Projects" variant={"compact"}>
-                        <Thead>
-                            <Tr>
-                                <Th key='type'>Runtime</Th>
-                                <Th key='projectId'>Project ID</Th>
-                                <Th key='name'>Name</Th>
-                                <Th key='description'>Description</Th>
-                                <Th key='commit'>Commit</Th>
-                                <Th key='deployment'>Environment</Th>
-                                <Th key='action'></Th>
-                            </Tr>
-                        </Thead>
-                        <Tbody>
-                            {projects.map(project => (
-                                <Tr key={project.projectId}>
-                                    <Td modifier={"fitContent"}>
-                                        <Tooltip content={project.runtime} position={"left"}>
-                                            <Badge className="runtime-badge">{project.runtime.substring(0, 1).toUpperCase()}</Badge>
-                                        </Tooltip>
-                                    </Td>
-                                    <Td>
-                                        <Button style={{padding: '6px'}} variant={"link"} onClick={e => this.props.onSelect?.call(this, project)}>
-                                            {project.projectId}
-                                        </Button>
-                                    </Td>
-                                    <Td>{project.name}</Td>
-                                    <Td>{project.description}</Td>
-                                    <Td isActionCell>
-                                        <Tooltip content={project.lastCommit} position={"bottom"}>
-                                            <Badge>{project.lastCommit?.substr(0, 7)}</Badge>
-                                        </Tooltip>
-                                    </Td>
-                                    <Td noPadding style={{width: "180px"}}>
-                                        <Flex direction={{default: "row"}}>
-                                            {this.getDeploymentByEnvironments(project.projectId).map(value => (
-                                                <FlexItem className="badge-flex-item" key={value[0]}>
-                                                    <Badge className="badge" isRead={!value[1]}>{value[0]}</Badge>
-                                                </FlexItem>
-                                            ))}
-                                        </Flex>
-                                    </Td>
-                                    <Td isActionCell>
-                                        <OverflowMenu breakpoint="md">
-                                            <OverflowMenuContent>
-                                                <OverflowMenuGroup groupType="button">
-                                                    <OverflowMenuItem>
-                                                        <Tooltip content={"Copy project"} position={"bottom"}>
-                                                            <Button variant={"plain"} icon={<CopyIcon/>}
-                                                                    onClick={e => this.setState({isCreateModalOpen: true, isCopy: true, projectToCopy: project})}></Button>
-                                                        </Tooltip>
-                                                    </OverflowMenuItem>
-                                                    <OverflowMenuItem>
-                                                        <Tooltip content={"Delete project"} position={"bottom"}>
-                                                            <Button variant={"plain"} icon={<DeleteIcon/>} onClick={e => this.onProjectDelete(project)}></Button>
-                                                        </Tooltip>
-                                                    </OverflowMenuItem>
-                                                </OverflowMenuGroup>
-                                            </OverflowMenuContent>
-                                        </OverflowMenu>
-                                    </Td>
-                                </Tr>
-                            ))}
-                            {projects.length === 0 &&
-                                <Tr>
-                                    <Td colSpan={8}>
-                                        <Bullseye>
-                                            <EmptyState variant={EmptyStateVariant.small}>
-                                                <EmptyStateIcon icon={SearchIcon}/>
-                                                <Title headingLevel="h2" size="lg">
-                                                    No results found
-                                                </Title>
-                                            </EmptyState>
-                                        </Bullseye>
-                                    </Td>
-                                </Tr>
-                            }
-                        </Tbody>
-                    </TableComposable>
+                    {this.getProjectsTable()}
                 </PageSection>
                 {this.createModalForm()}
                 {this.deleteModalForm()}
diff --git a/karavan-designer/src/designer/karavan.css b/karavan-designer/src/designer/karavan.css
index 38e2973..77ff41e 100644
--- a/karavan-designer/src/designer/karavan.css
+++ b/karavan-designer/src/designer/karavan.css
@@ -1274,6 +1274,7 @@
     overflow: auto;
     flex-shrink: unset;
     flex-grow: 1;
+    background-color: var(--pf-global--BackgroundColor--light-300);
 }
 
 .karavan .designer-page {