Loading modules/cloud_dashboard/cloud_dashboard/src/constant/others/other.ts +10 −0 Changes for modules/cloud_dashboard/cloud_dashboard/src/constant/others/other.ts: 10 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -33,6 +33,16 @@ export const CLOUD_SERVICE_PROVIDER_LIST: CloudServiceProvider[] = [ 'aws_cloud', 'k8s', 'openstack', 'vmware', ]; export const CLOUD_SERVICE_PROVIDER_INFO: Record<CloudServiceProvider, { entityTypeId: string, label: string, }> = { 'aws_cloud': { entityTypeId: 'instance', label: 'AWS Cloud' }, 'k8s': { entityTypeId: 'node', label: 'K8s' }, 'openstack': { entityTypeId: 'instance', label: 'OpenStack' }, 'vmware': { entityTypeId: 'vm', label: 'VMware' }, }; export const VMWARE_OS_DICT: Record<string, string> = { 'WINDOWS_HYPERV': 'Windows Hyper-V', 'WINDOWS_9_SERVER_64': 'Windows 10 Server (64 bit)', Loading modules/cloud_dashboard/cloud_dashboard/src/molecules/DataTableRow.tsx +4 −0 Changes for modules/cloud_dashboard/cloud_dashboard/src/molecules/DataTableRow.tsx: 4 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -24,9 +24,13 @@ const DataTableRow = ({ dataRecord, dataColumnList, className, detailInfo }: { {dataColumnList.map((dataColumn) => { let link = undefined; if (dataColumn.key === detailInfo?.column) { if ('url' in dataRecord.value) { link = dataRecord.value['url']; } else { const temp = detailInfo.path.split('/'); link = `/${temp[1]}/${dataRecord.cloudContext}/${temp[2]}/${dataRecord.id}`; } } return <DataTableData key={dataColumn.key} text={ dataColumn.key in dataRecord.value Loading modules/cloud_dashboard/cloud_dashboard/src/organisms/CloudServiceProviderTable.tsx +10 −1 Changes for modules/cloud_dashboard/cloud_dashboard/src/organisms/CloudServiceProviderTable.tsx: 10 added lines, 1 removed line. Original line number Diff line number Diff line import { CLOUD_SERVICE_PROVIDER_INFO } from 'constant/others/other'; import SortInfo from 'model/SortInfo'; import LoadingSpinner from 'molecules/LoadingSpinner'; import DataTable from 'organisms/DataTable'; Loading Loading @@ -39,10 +40,14 @@ const CloudServiceProviderTable = () => { }) .filter((r) => r.name !== 'ALL') .map((r) => { const temp = CLOUD_SERVICE_PROVIDER_INFO[r.cloudServiceProvider]; return { id: `${r.cloudServiceProvider}_${r.name}`, entityTypeId: '', value: { 'labelName': r.labelName }, value: { 'labelName': r.labelName, 'url': `/${r.cloudServiceProvider}/${r.name}/${temp.entityTypeId}` }, cloudContext: r.name }; }) Loading @@ -51,6 +56,10 @@ const CloudServiceProviderTable = () => { setSortInfo={setSortInfo} hasOperationLinks={false} operationLinksName="Operations" detailInfo={{ column: 'labelName', path: 'test' }} /> } </Form>; Loading modules/cloud_dashboard/cloud_dashboard/src/organisms/SideBar.tsx +225 −128 Changes for modules/cloud_dashboard/cloud_dashboard/src/organisms/SideBar.tsx: 225 added lines, 128 removed lines. Original line number Diff line number Diff line import { CLOUD_SERVICE_PROVIDER_LIST, ROUTE_URL } from 'constant/others/other'; import { CLOUD_SERVICE_PROVIDER_INFO, CLOUD_SERVICE_PROVIDER_LIST, ROUTE_URL } from 'constant/others/other'; import CloudServiceProvider from 'model/CloudServiceProvider'; import { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useParams } from 'react-router-dom'; import { Link, useParams } from 'react-router-dom'; import { useAppState } from 'service/state'; const DEFAULT_CLOUD_CONTEXT_NAME = 'Cloud Service Provider'; const CLOUD_SERVICE_PROVIDER_INFO: Record<CloudServiceProvider, { entityTypeId: string, label: string, }> = { 'aws_cloud': { entityTypeId: 'instance', label: 'AWS Cloud' }, 'k8s': { entityTypeId: 'node', label: 'K8s' }, 'openstack': { entityTypeId: 'instance', label: 'OpenStack' }, 'vmware': { entityTypeId: 'vm', label: 'VMware' }, }; const SideBar = () => { const params: { cloudServiceProvider?: string, cloudContext?: string, entityName?: string, entityId?: string, action?: string } = useParams(); const { cloudContextList } = useAppState(); const { t } = useTranslation(); const [cloudContextName, setCloudContextName] = useState(DEFAULT_CLOUD_CONTEXT_NAME); const [submenuStatus, setSubmenuStatus] = useState<CloudServiceProvider | ''>(''); const DEFAULT_CLOUD_CONTEXT_NAME = 'Cloud service providers'; useEffect(() => { const temp = cloudContextList.filter((c) => c.name === params.cloudContext); setCloudContextName( temp.length > 0 ? temp[0].labelName : DEFAULT_CLOUD_CONTEXT_NAME ); }, [params, cloudContextList]); const getFilteredList = (cloudServiceProvider: CloudServiceProvider) => { return cloudContextList.filter((c) => { return c.name !== 'ALL' && c.cloudServiceProvider === cloudServiceProvider; }) } // Note: The magic number 78.9843px comes from the style set in the body tag. return <div className="col-lg-3 col-xl-3 col-xxl-2 left-section" style={{ top: '78.9843px' }}> <header className="navbar-default"> <nav className="navbar navbar-expand-lg navbar-light d-block"> <div className="navbar-header"> const HeaderLogo = () => { return <div className="navbar-header"> <button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbar-collapse" aria-controls="navbar-collapse" aria-expanded="false" aria-label="Toggle navigation"> <svg focusable="false" aria-hidden="true" viewBox="0 0 24 24" tabIndex={-1} fill="#fff"><path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"></path></svg> </button> Loading @@ -59,115 +20,251 @@ const SideBar = () => { </a> <a className="name navbar-brand d-none" href={`${ROUTE_URL}/providers`} title="Home" rel="home">sample-site</a> </div> </div> <div className="navbar-collapse collapse"> <div className="region region-navigation"> </div>; } const HeaderLogo2 = () => { return <div className="region region-navigation"> <a className="logo navbar-btn pull-left m-md-auto text-md-center" href={`${ROUTE_URL}/providers`} title="Home" rel="home"> <img src="/themes/contrib/rigel/logo.svg" alt="Home" /> </a> <a className="name navbar-brand d-none" href={`${ROUTE_URL}/providers`} title="Home" rel="home">sample-site</a> </div> <div className="region region-navigation-collapsible"> <nav role="navigation" aria-labelledby="block-rigel-main-menu-menu" className="contextual-region open"> <h2 className="sr-only" >Main navigation</h2> <ul className="nav navbar-nav" role="menu"> <li><a href={`${ROUTE_URL}/providers`}>{t('Home')}</a></li> <li className="dropdown"> <a href={`${ROUTE_URL}/providers`} className="dropdown-toggle" data-toggle="dropdown">{cloudContextName}<span className="caret"></span></a> <ul className="dropdown-menu" role="menu"> <li className="dropdown-submenu" onClick={() => setSubmenuStatus('')}> </div>; } const MenuLink = ({ url, label }: { url: string, label: string }) => { if (url.startsWith(ROUTE_URL)) { const url2 = url.replace(`${ROUTE_URL}/`, '/'); return <li> <Link to={url2}> {label} </Link> </li>; } return <li> <a href={url}> {label} </a> </li>; } const SubMenu = ({ isOpen, label, menuLink }: { isOpen: boolean, label: string, menuLink: { url: string, label: string }[] }) => { return <li className={"dropdown-submenu" + (isOpen ? ' open' : '')}> {/* eslint-disable-next-line jsx-a11y/anchor-is-valid */} <a href="#" className="dropdown-submenu-toggle dropdown-toggle" data-toggle="dropdown">All<span className="caret"></span></a> <a href="#" className="dropdown-submenu-toggle dropdown-toggle" data-toggle="dropdown"> {label}<span className="caret"></span> </a> <ul className="dropdown-menu" role="menu"> <li><a href={`${ROUTE_URL}/providers`}>Cloud Service Providers</a></li> { CLOUD_SERVICE_PROVIDER_LIST.map((csp) => { const list = getFilteredList(csp); const pair = CLOUD_SERVICE_PROVIDER_INFO[csp]; return list.length > 0 ? <li key={csp}><a href={`${ROUTE_URL}/${csp}/${pair.entityTypeId}`}>{pair.label} resources</a></li> : <></>; menuLink.map((pair) => { return <MenuLink key={pair.label} url={pair.url} label={pair.label} />; }) } </ul> </li> { CLOUD_SERVICE_PROVIDER_LIST.map((csp) => { </li>; } const AllCspSubMenu = ({ isOpen }: { isOpen: boolean }) => { const { cloudContextList } = useAppState(); const getFilteredList = (cloudServiceProvider: CloudServiceProvider) => { return cloudContextList.filter((c) => { return c.name !== 'ALL' && c.cloudServiceProvider === cloudServiceProvider; }) } return <SubMenu label="All" isOpen={isOpen} menuLink={[ { url: `${ROUTE_URL}/providers`, label: 'Cloud Service Providers' }, ...CLOUD_SERVICE_PROVIDER_LIST .filter((csp) => { const list = getFilteredList(csp); return list.length > 0; }) .map((csp) => { const pair = CLOUD_SERVICE_PROVIDER_INFO[csp]; return list.length > 0 ? <li className={'dropdown-submenu' + (submenuStatus === csp ? ' open' : '')} onClick={() => setSubmenuStatus(csp)} key={csp}> {/* eslint-disable-next-line jsx-a11y/anchor-is-valid */} <a href="#" className="dropdown-submenu-toggle dropdown-toggle" data-toggle="dropdown">{pair.label}<span className="caret"></span></a> <ul className="dropdown-menu" role="menu"> { list.map((c) => { return <li key={c.name}><a href={`${ROUTE_URL}/${c.cloudServiceProvider}/${c.name}/${pair.entityTypeId}`}>{c.labelName}</a></li>; return { url: `${ROUTE_URL}/${csp}/${pair.entityTypeId}`, label: pair.label }; }) ]} />; } </ul> </li> : <></>; const CspSubMenu = ({ csp, isOpen }: { csp: CloudServiceProvider, isOpen: boolean }) => { const { cloudContextList } = useAppState(); const getFilteredList = (cloudServiceProvider: CloudServiceProvider) => { return cloudContextList.filter((c) => { return c.name !== 'ALL' && c.cloudServiceProvider === cloudServiceProvider; }) } </ul> </li> <li className="dropdown"> <a href="/clouds/design" className="dropdown-toggle" data-toggle="dropdown">Design<span className="caret"></span></a> <ul className="dropdown-menu" role="menu"> <li className="dropdown-submenu"> <a href="/clouds" className="dropdown-submenu-toggle dropdown-toggle" data-toggle="dropdown">All<span className="caret"></span></a> <ul className="dropdown-menu" role="menu"> { getFilteredList('aws_cloud').length > 0 ? <li><a href={`${ROUTE_URL}/aws_cloud/server_template`}>AWS launch templates</a></li> : <></> const list = getFilteredList(csp); const pair = CLOUD_SERVICE_PROVIDER_INFO[csp]; if (list.length === 0) { return <></>; } { getFilteredList('k8s').length > 0 ? <> <li><a href={`${ROUTE_URL}/k8s/server_template`}>K8s launch templates</a></li> <li><a href={`${ROUTE_URL}/k8s/project`}>K8s cloud projects</a></li> </> : <></> return <SubMenu label={pair.label} isOpen={isOpen} menuLink={list.map((c) => { return { url: `${ROUTE_URL}/${c.cloudServiceProvider}/${c.name}/${pair.entityTypeId}`, label: c.labelName }; })} />; } </ul> </li> <li className="dropdown-submenu"> <a href="/clouds" className="dropdown-submenu-toggle dropdown-toggle" data-toggle="dropdown">Launch templates<span className="caret"></span></a> <ul className="dropdown-menu" role="menu"> { const AllCltSubMenu = ({ isOpen }: { isOpen: boolean }) => { const { cloudContextList } = useAppState(); const getFilteredList = (cloudServiceProvider: CloudServiceProvider) => { return cloudContextList.filter((c) => { return c.name !== 'ALL' && c.cloudServiceProvider === cloudServiceProvider; }) } const menuLinks = []; if (getFilteredList('aws_cloud').length > 0) { menuLinks.push({ url: `${ROUTE_URL}/aws_cloud/server_template`, label: 'AWS launch templates' }); } if (getFilteredList('k8s').length > 0) { menuLinks.push({ url: `${ROUTE_URL}/k8s/server_template`, label: 'K8s launch templates' }); menuLinks.push({ url: `${ROUTE_URL}/k8s/project`, label: 'K8s cloud projects' }); } return <SubMenu isOpen={isOpen} label="All" menuLink={menuLinks} />; } const CltSubMenu = ({ isOpen }: { isOpen: boolean }) => { const { cloudContextList } = useAppState(); return <SubMenu label="Launch templates" isOpen={isOpen} menuLink={ cloudContextList.filter((c) => { return c.name !== 'ALL'; }).map((c) => { return <li><a href={`${ROUTE_URL}/${c.cloudServiceProvider}/${c.name}/server_template`}>{c.labelName}</a></li> return { url: `${ROUTE_URL}/${c.cloudServiceProvider}/${c.name}/server_template`, label: c.labelName }; }) } />; } </ul> </li> <li className="dropdown-submenu"> <a href="/clouds" className="dropdown-submenu-toggle dropdown-toggle" data-toggle="dropdown">Projects<span className="caret"></span></a> <ul className="dropdown-menu" role="menu"> { getFilteredList('k8s').map((c) => { return <li key={c.name}><a href={`${ROUTE_URL}/${c.cloudServiceProvider}/${c.name}/project`}>{c.labelName}</a></li>; const ProjectSubMenu = ({ isOpen }: { isOpen: boolean }) => { const { cloudContextList } = useAppState(); const getFilteredList = (cloudServiceProvider: CloudServiceProvider) => { return cloudContextList.filter((c) => { return c.name !== 'ALL' && c.cloudServiceProvider === cloudServiceProvider; }) } </ul> </li> <li className="dropdown-submenu"> <a href="/clouds" className="dropdown-submenu-toggle dropdown-toggle" data-toggle="dropdown">Stores<span className="caret"></span></a> return <SubMenu label="Projects" isOpen={isOpen} menuLink={ getFilteredList('k8s').map((c) => { return { url: `${ROUTE_URL}/${c.cloudServiceProvider}/${c.name}/project`, label: c.labelName }; })} />; } const StoreSubMenu = ({ isOpen }: { isOpen: boolean }) => { return <SubMenu label="Stores" isOpen={isOpen} menuLink={[ { url: `${ROUTE_URL}/k8s_cost_store`, label: 'K8s cost store' }, { url: `${ROUTE_URL}/k8s_namespace_resource_store`, label: 'K8s namespace resource store' }, { url: `${ROUTE_URL}/k8s_node_resource_store`, label: 'K8s node resource store' }, { url: `${ROUTE_URL}/k8s_pod_resource_store`, label: 'K8s pod resource store' }, ]} />; } const DropdownMenu = ({ isOpen, label, children }: { isOpen: boolean, label: string, children: React.ReactNode }) => { return <li className={"dropdown" + (isOpen ? ' open' : '')}> {/* eslint-disable-next-line jsx-a11y/anchor-is-valid */} <a href="#" className="dropdown-toggle" data-toggle="dropdown"> {label}<span className="caret"></span> </a> <ul className="dropdown-menu" role="menu"> <li><a href={`${ROUTE_URL}/k8s_cost_store`}>K8s cost store</a></li> <li><a href={`${ROUTE_URL}/k8s_namespace_resource_store`}>K8s namespace resource store</a></li> <li><a href={`${ROUTE_URL}/k8s_node_resource_store`}>K8s node resource store</a></li> <li><a href={`${ROUTE_URL}/k8s_pod_resource_store`}>K8s pod resource store</a></li> {children} </ul> </li> </ul> </li> <li><a href="/admin/structure/cloud_config">Config</a></li> </li>; } const CspMenu = ({ isOpen, cloudContextName }: { isOpen: boolean, cloudContextName: string }) => { return <DropdownMenu isOpen={isOpen} label={cloudContextName}> <AllCspSubMenu isOpen={true} /> { CLOUD_SERVICE_PROVIDER_LIST.map((csp) => { return <CspSubMenu key={csp} csp={csp} isOpen={true} />; }) } </DropdownMenu>; } const DesignMenu = ({ isOpen }: { isOpen: boolean }) => { return <DropdownMenu isOpen={isOpen} label="Design"> <AllCltSubMenu isOpen={true} /> <CltSubMenu isOpen={true} /> <ProjectSubMenu isOpen={true} /> <StoreSubMenu isOpen={true} /> </DropdownMenu>; } const SideBar = () => { const params: { cloudServiceProvider?: string, cloudContext?: string, entityName?: string, entityId?: string, action?: string } = useParams(); const { cloudContextList } = useAppState(); const { t } = useTranslation(); const [cloudContextName, setCloudContextName] = useState(DEFAULT_CLOUD_CONTEXT_NAME); useEffect(() => { const temp = cloudContextList.filter((c) => c.name === params.cloudContext); setCloudContextName( temp.length > 0 ? temp[0].labelName : DEFAULT_CLOUD_CONTEXT_NAME ); }, [params, cloudContextList]); // Note: The magic number 78.9843px comes from the style set in the body tag. return <div className="col-lg-3 col-xl-3 col-xxl-2 left-section" style={{ top: '78.9843px' }}> <header className="navbar-default"> <nav className="navbar navbar-expand-lg navbar-light d-block"> <HeaderLogo /> <div className="navbar-collapse collapse"> <HeaderLogo2 /> <div className="region region-navigation-collapsible"> <nav role="navigation" aria-labelledby="block-rigel-main-menu-menu" className="contextual-region open"> <h2 className="sr-only" >Main navigation</h2> <ul className="nav navbar-nav" role="menu"> <MenuLink url={`${ROUTE_URL}/providers`} label={t('Home')} /> <CspMenu isOpen={true} cloudContextName={cloudContextName} /> <DesignMenu isOpen={true} /> <MenuLink url="/admin/structure/cloud_config" label="Config" /> </ul> </nav> </div> Loading Loading
modules/cloud_dashboard/cloud_dashboard/src/constant/others/other.ts +10 −0 Changes for modules/cloud_dashboard/cloud_dashboard/src/constant/others/other.ts: 10 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -33,6 +33,16 @@ export const CLOUD_SERVICE_PROVIDER_LIST: CloudServiceProvider[] = [ 'aws_cloud', 'k8s', 'openstack', 'vmware', ]; export const CLOUD_SERVICE_PROVIDER_INFO: Record<CloudServiceProvider, { entityTypeId: string, label: string, }> = { 'aws_cloud': { entityTypeId: 'instance', label: 'AWS Cloud' }, 'k8s': { entityTypeId: 'node', label: 'K8s' }, 'openstack': { entityTypeId: 'instance', label: 'OpenStack' }, 'vmware': { entityTypeId: 'vm', label: 'VMware' }, }; export const VMWARE_OS_DICT: Record<string, string> = { 'WINDOWS_HYPERV': 'Windows Hyper-V', 'WINDOWS_9_SERVER_64': 'Windows 10 Server (64 bit)', Loading
modules/cloud_dashboard/cloud_dashboard/src/molecules/DataTableRow.tsx +4 −0 Changes for modules/cloud_dashboard/cloud_dashboard/src/molecules/DataTableRow.tsx: 4 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -24,9 +24,13 @@ const DataTableRow = ({ dataRecord, dataColumnList, className, detailInfo }: { {dataColumnList.map((dataColumn) => { let link = undefined; if (dataColumn.key === detailInfo?.column) { if ('url' in dataRecord.value) { link = dataRecord.value['url']; } else { const temp = detailInfo.path.split('/'); link = `/${temp[1]}/${dataRecord.cloudContext}/${temp[2]}/${dataRecord.id}`; } } return <DataTableData key={dataColumn.key} text={ dataColumn.key in dataRecord.value Loading
modules/cloud_dashboard/cloud_dashboard/src/organisms/CloudServiceProviderTable.tsx +10 −1 Changes for modules/cloud_dashboard/cloud_dashboard/src/organisms/CloudServiceProviderTable.tsx: 10 added lines, 1 removed line. Original line number Diff line number Diff line import { CLOUD_SERVICE_PROVIDER_INFO } from 'constant/others/other'; import SortInfo from 'model/SortInfo'; import LoadingSpinner from 'molecules/LoadingSpinner'; import DataTable from 'organisms/DataTable'; Loading Loading @@ -39,10 +40,14 @@ const CloudServiceProviderTable = () => { }) .filter((r) => r.name !== 'ALL') .map((r) => { const temp = CLOUD_SERVICE_PROVIDER_INFO[r.cloudServiceProvider]; return { id: `${r.cloudServiceProvider}_${r.name}`, entityTypeId: '', value: { 'labelName': r.labelName }, value: { 'labelName': r.labelName, 'url': `/${r.cloudServiceProvider}/${r.name}/${temp.entityTypeId}` }, cloudContext: r.name }; }) Loading @@ -51,6 +56,10 @@ const CloudServiceProviderTable = () => { setSortInfo={setSortInfo} hasOperationLinks={false} operationLinksName="Operations" detailInfo={{ column: 'labelName', path: 'test' }} /> } </Form>; Loading
modules/cloud_dashboard/cloud_dashboard/src/organisms/SideBar.tsx +225 −128 Changes for modules/cloud_dashboard/cloud_dashboard/src/organisms/SideBar.tsx: 225 added lines, 128 removed lines. Original line number Diff line number Diff line import { CLOUD_SERVICE_PROVIDER_LIST, ROUTE_URL } from 'constant/others/other'; import { CLOUD_SERVICE_PROVIDER_INFO, CLOUD_SERVICE_PROVIDER_LIST, ROUTE_URL } from 'constant/others/other'; import CloudServiceProvider from 'model/CloudServiceProvider'; import { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useParams } from 'react-router-dom'; import { Link, useParams } from 'react-router-dom'; import { useAppState } from 'service/state'; const DEFAULT_CLOUD_CONTEXT_NAME = 'Cloud Service Provider'; const CLOUD_SERVICE_PROVIDER_INFO: Record<CloudServiceProvider, { entityTypeId: string, label: string, }> = { 'aws_cloud': { entityTypeId: 'instance', label: 'AWS Cloud' }, 'k8s': { entityTypeId: 'node', label: 'K8s' }, 'openstack': { entityTypeId: 'instance', label: 'OpenStack' }, 'vmware': { entityTypeId: 'vm', label: 'VMware' }, }; const SideBar = () => { const params: { cloudServiceProvider?: string, cloudContext?: string, entityName?: string, entityId?: string, action?: string } = useParams(); const { cloudContextList } = useAppState(); const { t } = useTranslation(); const [cloudContextName, setCloudContextName] = useState(DEFAULT_CLOUD_CONTEXT_NAME); const [submenuStatus, setSubmenuStatus] = useState<CloudServiceProvider | ''>(''); const DEFAULT_CLOUD_CONTEXT_NAME = 'Cloud service providers'; useEffect(() => { const temp = cloudContextList.filter((c) => c.name === params.cloudContext); setCloudContextName( temp.length > 0 ? temp[0].labelName : DEFAULT_CLOUD_CONTEXT_NAME ); }, [params, cloudContextList]); const getFilteredList = (cloudServiceProvider: CloudServiceProvider) => { return cloudContextList.filter((c) => { return c.name !== 'ALL' && c.cloudServiceProvider === cloudServiceProvider; }) } // Note: The magic number 78.9843px comes from the style set in the body tag. return <div className="col-lg-3 col-xl-3 col-xxl-2 left-section" style={{ top: '78.9843px' }}> <header className="navbar-default"> <nav className="navbar navbar-expand-lg navbar-light d-block"> <div className="navbar-header"> const HeaderLogo = () => { return <div className="navbar-header"> <button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbar-collapse" aria-controls="navbar-collapse" aria-expanded="false" aria-label="Toggle navigation"> <svg focusable="false" aria-hidden="true" viewBox="0 0 24 24" tabIndex={-1} fill="#fff"><path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"></path></svg> </button> Loading @@ -59,115 +20,251 @@ const SideBar = () => { </a> <a className="name navbar-brand d-none" href={`${ROUTE_URL}/providers`} title="Home" rel="home">sample-site</a> </div> </div> <div className="navbar-collapse collapse"> <div className="region region-navigation"> </div>; } const HeaderLogo2 = () => { return <div className="region region-navigation"> <a className="logo navbar-btn pull-left m-md-auto text-md-center" href={`${ROUTE_URL}/providers`} title="Home" rel="home"> <img src="/themes/contrib/rigel/logo.svg" alt="Home" /> </a> <a className="name navbar-brand d-none" href={`${ROUTE_URL}/providers`} title="Home" rel="home">sample-site</a> </div> <div className="region region-navigation-collapsible"> <nav role="navigation" aria-labelledby="block-rigel-main-menu-menu" className="contextual-region open"> <h2 className="sr-only" >Main navigation</h2> <ul className="nav navbar-nav" role="menu"> <li><a href={`${ROUTE_URL}/providers`}>{t('Home')}</a></li> <li className="dropdown"> <a href={`${ROUTE_URL}/providers`} className="dropdown-toggle" data-toggle="dropdown">{cloudContextName}<span className="caret"></span></a> <ul className="dropdown-menu" role="menu"> <li className="dropdown-submenu" onClick={() => setSubmenuStatus('')}> </div>; } const MenuLink = ({ url, label }: { url: string, label: string }) => { if (url.startsWith(ROUTE_URL)) { const url2 = url.replace(`${ROUTE_URL}/`, '/'); return <li> <Link to={url2}> {label} </Link> </li>; } return <li> <a href={url}> {label} </a> </li>; } const SubMenu = ({ isOpen, label, menuLink }: { isOpen: boolean, label: string, menuLink: { url: string, label: string }[] }) => { return <li className={"dropdown-submenu" + (isOpen ? ' open' : '')}> {/* eslint-disable-next-line jsx-a11y/anchor-is-valid */} <a href="#" className="dropdown-submenu-toggle dropdown-toggle" data-toggle="dropdown">All<span className="caret"></span></a> <a href="#" className="dropdown-submenu-toggle dropdown-toggle" data-toggle="dropdown"> {label}<span className="caret"></span> </a> <ul className="dropdown-menu" role="menu"> <li><a href={`${ROUTE_URL}/providers`}>Cloud Service Providers</a></li> { CLOUD_SERVICE_PROVIDER_LIST.map((csp) => { const list = getFilteredList(csp); const pair = CLOUD_SERVICE_PROVIDER_INFO[csp]; return list.length > 0 ? <li key={csp}><a href={`${ROUTE_URL}/${csp}/${pair.entityTypeId}`}>{pair.label} resources</a></li> : <></>; menuLink.map((pair) => { return <MenuLink key={pair.label} url={pair.url} label={pair.label} />; }) } </ul> </li> { CLOUD_SERVICE_PROVIDER_LIST.map((csp) => { </li>; } const AllCspSubMenu = ({ isOpen }: { isOpen: boolean }) => { const { cloudContextList } = useAppState(); const getFilteredList = (cloudServiceProvider: CloudServiceProvider) => { return cloudContextList.filter((c) => { return c.name !== 'ALL' && c.cloudServiceProvider === cloudServiceProvider; }) } return <SubMenu label="All" isOpen={isOpen} menuLink={[ { url: `${ROUTE_URL}/providers`, label: 'Cloud Service Providers' }, ...CLOUD_SERVICE_PROVIDER_LIST .filter((csp) => { const list = getFilteredList(csp); return list.length > 0; }) .map((csp) => { const pair = CLOUD_SERVICE_PROVIDER_INFO[csp]; return list.length > 0 ? <li className={'dropdown-submenu' + (submenuStatus === csp ? ' open' : '')} onClick={() => setSubmenuStatus(csp)} key={csp}> {/* eslint-disable-next-line jsx-a11y/anchor-is-valid */} <a href="#" className="dropdown-submenu-toggle dropdown-toggle" data-toggle="dropdown">{pair.label}<span className="caret"></span></a> <ul className="dropdown-menu" role="menu"> { list.map((c) => { return <li key={c.name}><a href={`${ROUTE_URL}/${c.cloudServiceProvider}/${c.name}/${pair.entityTypeId}`}>{c.labelName}</a></li>; return { url: `${ROUTE_URL}/${csp}/${pair.entityTypeId}`, label: pair.label }; }) ]} />; } </ul> </li> : <></>; const CspSubMenu = ({ csp, isOpen }: { csp: CloudServiceProvider, isOpen: boolean }) => { const { cloudContextList } = useAppState(); const getFilteredList = (cloudServiceProvider: CloudServiceProvider) => { return cloudContextList.filter((c) => { return c.name !== 'ALL' && c.cloudServiceProvider === cloudServiceProvider; }) } </ul> </li> <li className="dropdown"> <a href="/clouds/design" className="dropdown-toggle" data-toggle="dropdown">Design<span className="caret"></span></a> <ul className="dropdown-menu" role="menu"> <li className="dropdown-submenu"> <a href="/clouds" className="dropdown-submenu-toggle dropdown-toggle" data-toggle="dropdown">All<span className="caret"></span></a> <ul className="dropdown-menu" role="menu"> { getFilteredList('aws_cloud').length > 0 ? <li><a href={`${ROUTE_URL}/aws_cloud/server_template`}>AWS launch templates</a></li> : <></> const list = getFilteredList(csp); const pair = CLOUD_SERVICE_PROVIDER_INFO[csp]; if (list.length === 0) { return <></>; } { getFilteredList('k8s').length > 0 ? <> <li><a href={`${ROUTE_URL}/k8s/server_template`}>K8s launch templates</a></li> <li><a href={`${ROUTE_URL}/k8s/project`}>K8s cloud projects</a></li> </> : <></> return <SubMenu label={pair.label} isOpen={isOpen} menuLink={list.map((c) => { return { url: `${ROUTE_URL}/${c.cloudServiceProvider}/${c.name}/${pair.entityTypeId}`, label: c.labelName }; })} />; } </ul> </li> <li className="dropdown-submenu"> <a href="/clouds" className="dropdown-submenu-toggle dropdown-toggle" data-toggle="dropdown">Launch templates<span className="caret"></span></a> <ul className="dropdown-menu" role="menu"> { const AllCltSubMenu = ({ isOpen }: { isOpen: boolean }) => { const { cloudContextList } = useAppState(); const getFilteredList = (cloudServiceProvider: CloudServiceProvider) => { return cloudContextList.filter((c) => { return c.name !== 'ALL' && c.cloudServiceProvider === cloudServiceProvider; }) } const menuLinks = []; if (getFilteredList('aws_cloud').length > 0) { menuLinks.push({ url: `${ROUTE_URL}/aws_cloud/server_template`, label: 'AWS launch templates' }); } if (getFilteredList('k8s').length > 0) { menuLinks.push({ url: `${ROUTE_URL}/k8s/server_template`, label: 'K8s launch templates' }); menuLinks.push({ url: `${ROUTE_URL}/k8s/project`, label: 'K8s cloud projects' }); } return <SubMenu isOpen={isOpen} label="All" menuLink={menuLinks} />; } const CltSubMenu = ({ isOpen }: { isOpen: boolean }) => { const { cloudContextList } = useAppState(); return <SubMenu label="Launch templates" isOpen={isOpen} menuLink={ cloudContextList.filter((c) => { return c.name !== 'ALL'; }).map((c) => { return <li><a href={`${ROUTE_URL}/${c.cloudServiceProvider}/${c.name}/server_template`}>{c.labelName}</a></li> return { url: `${ROUTE_URL}/${c.cloudServiceProvider}/${c.name}/server_template`, label: c.labelName }; }) } />; } </ul> </li> <li className="dropdown-submenu"> <a href="/clouds" className="dropdown-submenu-toggle dropdown-toggle" data-toggle="dropdown">Projects<span className="caret"></span></a> <ul className="dropdown-menu" role="menu"> { getFilteredList('k8s').map((c) => { return <li key={c.name}><a href={`${ROUTE_URL}/${c.cloudServiceProvider}/${c.name}/project`}>{c.labelName}</a></li>; const ProjectSubMenu = ({ isOpen }: { isOpen: boolean }) => { const { cloudContextList } = useAppState(); const getFilteredList = (cloudServiceProvider: CloudServiceProvider) => { return cloudContextList.filter((c) => { return c.name !== 'ALL' && c.cloudServiceProvider === cloudServiceProvider; }) } </ul> </li> <li className="dropdown-submenu"> <a href="/clouds" className="dropdown-submenu-toggle dropdown-toggle" data-toggle="dropdown">Stores<span className="caret"></span></a> return <SubMenu label="Projects" isOpen={isOpen} menuLink={ getFilteredList('k8s').map((c) => { return { url: `${ROUTE_URL}/${c.cloudServiceProvider}/${c.name}/project`, label: c.labelName }; })} />; } const StoreSubMenu = ({ isOpen }: { isOpen: boolean }) => { return <SubMenu label="Stores" isOpen={isOpen} menuLink={[ { url: `${ROUTE_URL}/k8s_cost_store`, label: 'K8s cost store' }, { url: `${ROUTE_URL}/k8s_namespace_resource_store`, label: 'K8s namespace resource store' }, { url: `${ROUTE_URL}/k8s_node_resource_store`, label: 'K8s node resource store' }, { url: `${ROUTE_URL}/k8s_pod_resource_store`, label: 'K8s pod resource store' }, ]} />; } const DropdownMenu = ({ isOpen, label, children }: { isOpen: boolean, label: string, children: React.ReactNode }) => { return <li className={"dropdown" + (isOpen ? ' open' : '')}> {/* eslint-disable-next-line jsx-a11y/anchor-is-valid */} <a href="#" className="dropdown-toggle" data-toggle="dropdown"> {label}<span className="caret"></span> </a> <ul className="dropdown-menu" role="menu"> <li><a href={`${ROUTE_URL}/k8s_cost_store`}>K8s cost store</a></li> <li><a href={`${ROUTE_URL}/k8s_namespace_resource_store`}>K8s namespace resource store</a></li> <li><a href={`${ROUTE_URL}/k8s_node_resource_store`}>K8s node resource store</a></li> <li><a href={`${ROUTE_URL}/k8s_pod_resource_store`}>K8s pod resource store</a></li> {children} </ul> </li> </ul> </li> <li><a href="/admin/structure/cloud_config">Config</a></li> </li>; } const CspMenu = ({ isOpen, cloudContextName }: { isOpen: boolean, cloudContextName: string }) => { return <DropdownMenu isOpen={isOpen} label={cloudContextName}> <AllCspSubMenu isOpen={true} /> { CLOUD_SERVICE_PROVIDER_LIST.map((csp) => { return <CspSubMenu key={csp} csp={csp} isOpen={true} />; }) } </DropdownMenu>; } const DesignMenu = ({ isOpen }: { isOpen: boolean }) => { return <DropdownMenu isOpen={isOpen} label="Design"> <AllCltSubMenu isOpen={true} /> <CltSubMenu isOpen={true} /> <ProjectSubMenu isOpen={true} /> <StoreSubMenu isOpen={true} /> </DropdownMenu>; } const SideBar = () => { const params: { cloudServiceProvider?: string, cloudContext?: string, entityName?: string, entityId?: string, action?: string } = useParams(); const { cloudContextList } = useAppState(); const { t } = useTranslation(); const [cloudContextName, setCloudContextName] = useState(DEFAULT_CLOUD_CONTEXT_NAME); useEffect(() => { const temp = cloudContextList.filter((c) => c.name === params.cloudContext); setCloudContextName( temp.length > 0 ? temp[0].labelName : DEFAULT_CLOUD_CONTEXT_NAME ); }, [params, cloudContextList]); // Note: The magic number 78.9843px comes from the style set in the body tag. return <div className="col-lg-3 col-xl-3 col-xxl-2 left-section" style={{ top: '78.9843px' }}> <header className="navbar-default"> <nav className="navbar navbar-expand-lg navbar-light d-block"> <HeaderLogo /> <div className="navbar-collapse collapse"> <HeaderLogo2 /> <div className="region region-navigation-collapsible"> <nav role="navigation" aria-labelledby="block-rigel-main-menu-menu" className="contextual-region open"> <h2 className="sr-only" >Main navigation</h2> <ul className="nav navbar-nav" role="menu"> <MenuLink url={`${ROUTE_URL}/providers`} label={t('Home')} /> <CspMenu isOpen={true} cloudContextName={cloudContextName} /> <DesignMenu isOpen={true} /> <MenuLink url="/admin/structure/cloud_config" label="Config" /> </ul> </nav> </div> Loading