From 00e85f0f15b5c7bc7d94736ddf636fa0b2b7b021 Mon Sep 17 00:00:00 2001 From: Aviv Turgeman Date: Wed, 25 Sep 2024 11:34:51 +0300 Subject: [PATCH] Insert NNS topology Signed-off-by: Aviv Turgeman --- .../en/plugin__nmstate-console-plugin.json | 1 + .../components/TechPreview/TechPreview.scss | 7 ++++++ .../components/TechPreview/TechPreview.tsx | 15 +++++++++++++ src/views/states/list/StatesList.tsx | 12 +++++----- src/views/states/manifest.ts | 22 +++++++++---------- .../states/topology/components/BridgeIcon.tsx | 15 +++++++++++++ .../TopologyToolbar/TopologyToolbar.tsx | 2 ++ src/views/states/topology/utils/utils.ts | 6 ++++- 8 files changed, 62 insertions(+), 18 deletions(-) create mode 100644 src/utils/components/TechPreview/TechPreview.scss create mode 100644 src/utils/components/TechPreview/TechPreview.tsx create mode 100644 src/views/states/topology/components/BridgeIcon.tsx diff --git a/locales/en/plugin__nmstate-console-plugin.json b/locales/en/plugin__nmstate-console-plugin.json index b86c685b..233de861 100644 --- a/locales/en/plugin__nmstate-console-plugin.json +++ b/locales/en/plugin__nmstate-console-plugin.json @@ -138,6 +138,7 @@ "Server": "Server", "System Description": "System Description", "System Name": "System Name", + "Tech preview": "Tech preview", "The Open vSwitch bridge mapping is a list of Open vSwitch bridges and the physical interfaces that are connected to them.": "The Open vSwitch bridge mapping is a list of Open vSwitch bridges and the physical interfaces that are connected to them.", "This is the list of ports to copy MAC address from. Select one of the matched ports this policy will apply to": "This is the list of ports to copy MAC address from. Select one of the matched ports this policy will apply to", "This node already has a policy matching it": "This node already has a policy matching it", diff --git a/src/utils/components/TechPreview/TechPreview.scss b/src/utils/components/TechPreview/TechPreview.scss new file mode 100644 index 00000000..608b7572 --- /dev/null +++ b/src/utils/components/TechPreview/TechPreview.scss @@ -0,0 +1,7 @@ +.TechPreviewLabel { + color: var(--pf-v5-c-button--m-danger--Color); + background-color: var(--pf-v5-c-button--m-danger--BackgroundColor); + margin-left: var(--pf-v5-global--spacer--md); + padding: 0 var(--pf-v5-global--spacer--sm); + align-self: center; +} diff --git a/src/utils/components/TechPreview/TechPreview.tsx b/src/utils/components/TechPreview/TechPreview.tsx new file mode 100644 index 00000000..da362365 --- /dev/null +++ b/src/utils/components/TechPreview/TechPreview.tsx @@ -0,0 +1,15 @@ +import React, { FC } from 'react'; +import classNames from 'classnames'; + +import { useNMStateTranslation } from '@utils/hooks/useNMStateTranslation'; + +import './TechPreview.scss'; +const TechPreview: FC = () => { + const { t } = useNMStateTranslation(); + + return ( +
{t('Tech preview')}
+ ); +}; + +export default TechPreview; diff --git a/src/views/states/list/StatesList.tsx b/src/views/states/list/StatesList.tsx index 277516fa..a92e9288 100644 --- a/src/views/states/list/StatesList.tsx +++ b/src/views/states/list/StatesList.tsx @@ -1,5 +1,5 @@ import React, { FC, useCallback, useState } from 'react'; -// import { useNavigate } from 'react-router-dom-v5-compat'; +import { useNavigate } from 'react-router-dom-v5-compat'; import { useNMStateTranslation } from 'src/utils/hooks/useNMStateTranslation'; import { @@ -14,8 +14,8 @@ import { useK8sWatchResource, useListPageFilter, } from '@openshift-console/dynamic-plugin-sdk'; -import { Button, Flex, /*Icon*/ Pagination } from '@patternfly/react-core'; -// import { TopologyIcon } from '@patternfly/react-icons'; +import { Button, Flex, Icon, Pagination } from '@patternfly/react-core'; +import { TopologyIcon } from '@patternfly/react-icons'; import { Table, TableGridBreakpoint, Th, Thead, Tr } from '@patternfly/react-table'; import { V1beta1NodeNetworkState } from '@types'; import usePagination from '@utils/hooks/usePagination/usePagination'; @@ -35,7 +35,7 @@ import './states-list.scss'; const StatesList: FC = () => { const { t } = useNMStateTranslation(); - // const navigate = useNavigate(); + const navigate = useNavigate(); const { selectedInterfaceName, selectedStateName, @@ -77,11 +77,11 @@ const StatesList: FC = () => { return ( <> - {/* */} + diff --git a/src/views/states/manifest.ts b/src/views/states/manifest.ts index 43acadc6..3507c66e 100644 --- a/src/views/states/manifest.ts +++ b/src/views/states/manifest.ts @@ -2,14 +2,14 @@ import type { EncodedExtension } from '@openshift/dynamic-plugin-sdk'; import type { ResourceClusterNavItem, ResourceListPage, - // RoutePage, + RoutePage, } from '@openshift-console/dynamic-plugin-sdk'; import { NodeNetworkStateModelGroupVersionKind } from '../../console-models'; export const StateExposedModules = { StatesList: './views/states/list/StatesList', - // Topology: './views/states/topology/Topology', + Topology: './views/states/topology/Topology', }; export const StateExtensions: EncodedExtension[] = [ @@ -35,13 +35,13 @@ export const StateExtensions: EncodedExtension[] = [ component: { $codeRef: 'StatesList' }, }, } as EncodedExtension, - // { - // type: 'console.page/route', - // properties: { - // path: ['nmstate-topology'], - // component: { - // $codeRef: 'Topology', - // }, - // }, - // } as EncodedExtension, + { + type: 'console.page/route', + properties: { + path: ['nmstate-topology'], + component: { + $codeRef: 'Topology', + }, + }, + } as EncodedExtension, ]; diff --git a/src/views/states/topology/components/BridgeIcon.tsx b/src/views/states/topology/components/BridgeIcon.tsx new file mode 100644 index 00000000..ff754799 --- /dev/null +++ b/src/views/states/topology/components/BridgeIcon.tsx @@ -0,0 +1,15 @@ +import { createIcon } from '@patternfly/react-icons/dist/esm/createIcon'; + +export const BridgeIconConfig = { + name: 'BridgeIcon', + height: 32, + width: 32, + svgPath: + 'M28.3,6.8c.5-.5.5-1.3,0-1.8l-3.7-3.7c-.5-.5-1.3-.5-1.8,0s-.5,1.3,0,1.8l1.6,1.6h-11.8c-.7,0-1.2.6-1.2,1.2s.6,1.2,1.2,1.2h11.8l-1.6,1.6c-.5.5-.5,1.3,0,1.8s1.3.5,1.8,0l3.7-3.7h0Z M3.7,11.8c-.5.5-.5,1.3,0,1.8l3.7,3.7c.5.5,1.3.5,1.8,0s.5-1.3,0-1.8l-1.6-1.6h11.8c.7,0,1.2-.6,1.2-1.2s-.6-1.2-1.2-1.2H7.6l1.6-1.6c.5-.5.5-1.3,0-1.8s-1.3-.5-1.8,0l-3.7,3.7h0Z M28.3,20.2c.5-.5.5-1.3,0-1.8l-3.7-3.7c-.5-.5-1.3-.5-1.8,0s-.5,1.3,0,1.8l1.6,1.6h-11.8c-.7,0-1.2.6-1.2,1.2s.6,1.2,1.2,1.2h11.8l-1.6,1.6c-.5.5-.5,1.3,0,1.8s1.3.5,1.8,0l3.7-3.7h0Z M3.7,25.2c-.5.5-.5,1.3,0,1.8l3.7,3.7c.5.5,1.3.5,1.8,0s.5-1.3,0-1.8l-1.6-1.6h11.8c.7,0,1.2-.6,1.2-1.2s-.6-1.2-1.2-1.2H7.6l1.6-1.6c.5-.5.5-1.3,0-1.8s-1.3-.5-1.8,0l-3.7,3.7h0Z', + yOffset: 0, + xOffset: 0, +}; + +export const BridgeIcon = createIcon(BridgeIconConfig); + +export default BridgeIcon; diff --git a/src/views/states/topology/components/TopologyToolbar/TopologyToolbar.tsx b/src/views/states/topology/components/TopologyToolbar/TopologyToolbar.tsx index 094752e1..dc658dba 100644 --- a/src/views/states/topology/components/TopologyToolbar/TopologyToolbar.tsx +++ b/src/views/states/topology/components/TopologyToolbar/TopologyToolbar.tsx @@ -4,6 +4,7 @@ import { useNavigate } from 'react-router-dom-v5-compat'; import { NodeNetworkStateModelRef } from '@models'; import { Button, Toolbar, ToolbarContent, ToolbarGroup, ToolbarItem } from '@patternfly/react-core'; import { ListIcon } from '@patternfly/react-icons'; +import TechPreview from '@utils/components/TechPreview/TechPreview'; import TopologyToolbarFilter from './TopologyToolbarFilter'; @@ -24,6 +25,7 @@ const TopologyButton: FC = (props) => { + diff --git a/src/views/states/topology/utils/utils.ts b/src/views/states/topology/utils/utils.ts index 435747c7..c9716a1a 100644 --- a/src/views/states/topology/utils/utils.ts +++ b/src/views/states/topology/utils/utils.ts @@ -8,6 +8,9 @@ import { NodeStatus, } from '@patternfly/react-topology'; import { InterfaceType, NodeNetworkConfigurationInterface, V1beta1NodeNetworkState } from '@types'; +import { isEmpty } from '@utils/helpers'; + +import BridgeIcon from '../components/BridgeIcon'; import { GROUP, NODE_DIAMETER } from './constants'; @@ -22,6 +25,7 @@ const getStatus = (iface: NodeNetworkConfigurationInterface): NodeStatus => { }; const getIcon = (iface: NodeNetworkConfigurationInterface) => { + if (!isEmpty(iface.bridge)) return BridgeIcon; if (iface.ethernet || iface.type === InterfaceType.ETHERNET) return EthernetIcon; if (iface.type === InterfaceType.BOND) return LinkIcon; return NetworkIcon; @@ -95,7 +99,7 @@ const createEdges = ( }); } - if (iface.vlan?.['base-iface'] && iface.name !== iface.vlan?.['base-iface']) { + if (iface.vlan?.['base-iface'] && iface.name === iface.vlan?.['base-iface']) { edges.push({ id: `${nodeId}~${iface.vlan['base-iface']}-edge`, type: ModelKind.edge,