mgr/dashboard: Left navigation improvements

Fixes: https://tracker.ceph.com/issues/62366

Signed-off-by: cloudbehl <cloudbehl@gmail.com>
This commit is contained in:
cloudbehl 2023-08-09 12:39:47 +05:30
parent 28cb4d10b1
commit 7a54ba3cc1
7 changed files with 281 additions and 168 deletions

View File

@ -6,33 +6,18 @@ export class NavigationPageHelper extends PageHelper {
}; };
navigations = [ navigations = [
{ menu: 'NFS', component: 'cd-error' },
{
menu: 'Object Gateway',
submenus: [
{ menu: 'Gateways', component: 'cd-rgw-daemon-list' },
{ menu: 'Users', component: 'cd-rgw-user-list' },
{ menu: 'Buckets', component: 'cd-rgw-bucket-list' }
]
},
{ menu: 'Dashboard', component: 'cd-dashboard' }, { menu: 'Dashboard', component: 'cd-dashboard' },
{ {
menu: 'Cluster', menu: 'Cluster',
submenus: [ submenus: [
{ menu: 'Pools', component: 'cd-pool-list' },
{ menu: 'Hosts', component: 'cd-hosts' }, { menu: 'Hosts', component: 'cd-hosts' },
{ menu: 'Physical Disks', component: 'cd-error' },
{ menu: 'Monitors', component: 'cd-monitor' },
{ menu: 'Services', component: 'cd-error' },
{ menu: 'OSDs', component: 'cd-osd-list' }, { menu: 'OSDs', component: 'cd-osd-list' },
{ menu: 'Configuration', component: 'cd-configuration' }, { menu: 'Physical Disks', component: 'cd-error' },
{ menu: 'CRUSH map', component: 'cd-crushmap' }, { menu: 'CRUSH map', component: 'cd-crushmap' },
{ menu: 'Manager Modules', component: 'cd-mgr-module-list' }, { menu: 'Monitors', component: 'cd-monitor' }
{ menu: 'Ceph Users', component: 'cd-crud-table' },
{ menu: 'Logs', component: 'cd-logs' },
{ menu: 'Alerts', component: 'cd-prometheus-tabs' }
] ]
}, },
{ menu: 'Pools', component: 'cd-pool-list' },
{ {
menu: 'Block', menu: 'Block',
submenus: [ submenus: [
@ -41,7 +26,41 @@ export class NavigationPageHelper extends PageHelper {
{ menu: 'iSCSI', component: 'cd-iscsi' } { menu: 'iSCSI', component: 'cd-iscsi' }
] ]
}, },
{ menu: 'File Systems', component: 'cd-cephfs-list' } {
menu: 'Object',
submenus: [
{ menu: 'Overview', component: 'cd-rgw-overview-dashboard' },
{ menu: 'Buckets', component: 'cd-rgw-bucket-list' },
{ menu: 'Users', component: 'cd-rgw-user-list' },
{ menu: 'Multi-site', component: 'cd-rgw-multisite-details' },
{ menu: 'Gateways', component: 'cd-rgw-daemon-list' },
{ menu: 'NFS', component: 'cd-error' }
]
},
{
menu: 'File',
submenus: [
{ menu: 'File Systems', component: 'cd-cephfs-list' },
{ menu: 'NFS', component: 'cd-error' }
]
},
{
menu: 'Observability',
submenus: [
{ menu: 'Logs', component: 'cd-logs' },
{ menu: 'Alerts', component: 'cd-prometheus-tabs' }
]
},
{
menu: 'Administration',
submenus: [
{ menu: 'Services', component: 'cd-error' },
{ menu: 'Upgrade', component: 'cd-error' },
{ menu: 'Ceph Users', component: 'cd-crud-table' },
{ menu: 'Manager Modules', component: 'cd-mgr-module-list' },
{ menu: 'Configuration', component: 'cd-configuration' }
]
}
]; ];
getVerticalMenu() { getVerticalMenu() {

View File

@ -124,7 +124,7 @@ const routes: Routes = [
path: 'ceph-users', path: 'ceph-users',
component: CRUDTableComponent, component: CRUDTableComponent,
data: { data: {
breadcrumbs: 'Cluster/Ceph Users', breadcrumbs: 'Administration/Ceph Users',
resource: 'api.cluster.user@1.0' resource: 'api.cluster.user@1.0'
} }
}, },
@ -132,7 +132,7 @@ const routes: Routes = [
path: 'cluster/user/create', path: 'cluster/user/create',
component: CrudFormComponent, component: CrudFormComponent,
data: { data: {
breadcrumbs: 'Cluster/Ceph Users/Create', breadcrumbs: 'Administration/Ceph Users/Create',
resource: 'api.cluster.user@1.0' resource: 'api.cluster.user@1.0'
} }
}, },
@ -140,7 +140,7 @@ const routes: Routes = [
path: 'cluster/user/import', path: 'cluster/user/import',
component: CrudFormComponent, component: CrudFormComponent,
data: { data: {
breadcrumbs: 'Cluster/Ceph Users/Import', breadcrumbs: 'Administration/Ceph Users/Import',
resource: 'api.cluster.user@1.0' resource: 'api.cluster.user@1.0'
} }
}, },
@ -148,7 +148,7 @@ const routes: Routes = [
path: 'cluster/user/edit', path: 'cluster/user/edit',
component: CrudFormComponent, component: CrudFormComponent,
data: { data: {
breadcrumbs: 'Cluster/Ceph Users/Edit', breadcrumbs: 'Administration/Ceph Users/Edit',
resource: 'api.cluster.user@1.0' resource: 'api.cluster.user@1.0'
} }
}, },
@ -169,7 +169,7 @@ const routes: Routes = [
section_info: 'Orchestrator', section_info: 'Orchestrator',
header: 'Orchestrator is not available' header: 'Orchestrator is not available'
}, },
breadcrumbs: 'Cluster/Services' breadcrumbs: 'Administration/Services'
}, },
children: [ children: [
{ {
@ -213,7 +213,7 @@ const routes: Routes = [
}, },
{ {
path: 'configuration', path: 'configuration',
data: { breadcrumbs: 'Cluster/Configuration' }, data: { breadcrumbs: 'Administration/Configuration' },
children: [ children: [
{ path: '', component: ConfigurationComponent }, { path: '', component: ConfigurationComponent },
{ {
@ -231,7 +231,7 @@ const routes: Routes = [
{ {
path: 'logs', path: 'logs',
component: LogsComponent, component: LogsComponent,
data: { breadcrumbs: 'Cluster/Logs' } data: { breadcrumbs: 'Observability/Logs' }
}, },
{ {
path: 'telemetry', path: 'telemetry',
@ -240,7 +240,7 @@ const routes: Routes = [
}, },
{ {
path: 'monitoring', path: 'monitoring',
data: { breadcrumbs: 'Cluster/Alerts' }, data: { breadcrumbs: 'Observability/Alerts' },
children: [ children: [
{ path: '', redirectTo: 'active-alerts', pathMatch: 'full' }, { path: '', redirectTo: 'active-alerts', pathMatch: 'full' },
{ {
@ -297,7 +297,7 @@ const routes: Routes = [
section_info: 'Orchestrator', section_info: 'Orchestrator',
header: 'Orchestrator is not available' header: 'Orchestrator is not available'
}, },
breadcrumbs: 'Cluster/Upgrade' breadcrumbs: 'Administration/Upgrade'
}, },
children: [ children: [
{ {
@ -321,7 +321,7 @@ const routes: Routes = [
// Mgr modules // Mgr modules
{ {
path: 'mgr-modules', path: 'mgr-modules',
data: { breadcrumbs: 'Cluster/Manager Modules' }, data: { breadcrumbs: 'Administrator/Manager Modules' },
children: [ children: [
{ {
path: '', path: '',
@ -339,7 +339,7 @@ const routes: Routes = [
// Pools // Pools
{ {
path: 'pool', path: 'pool',
data: { breadcrumbs: 'Pools' }, data: { breadcrumbs: 'Cluster/Pools' },
loadChildren: () => import('./ceph/pool/pool.module').then((m) => m.RoutedPoolModule) loadChildren: () => import('./ceph/pool/pool.module').then((m) => m.RoutedPoolModule)
}, },
// Block // Block
@ -352,7 +352,7 @@ const routes: Routes = [
{ {
path: 'cephfs', path: 'cephfs',
canActivate: [FeatureTogglesGuardService], canActivate: [FeatureTogglesGuardService],
data: { breadcrumbs: 'File Systems' }, data: { breadcrumbs: 'File/File Systems' },
children: [ children: [
{ path: '', component: CephfsListComponent }, { path: '', component: CephfsListComponent },
{ {
@ -380,7 +380,7 @@ const routes: Routes = [
header: 'The Object Gateway Service is not configured' header: 'The Object Gateway Service is not configured'
}, },
breadcrumbs: true, breadcrumbs: true,
text: 'Object Gateway', text: 'Object',
path: null path: null
}, },
loadChildren: () => import('./ceph/rgw/rgw.module').then((m) => m.RoutedRgwModule) loadChildren: () => import('./ceph/rgw/rgw.module').then((m) => m.RoutedRgwModule)

View File

@ -5,10 +5,10 @@
<cd-notifications-sidebar></cd-notifications-sidebar> <cd-notifications-sidebar></cd-notifications-sidebar>
<div class="cd-navbar-top"> <div class="cd-navbar-top">
<nav class="navbar navbar-expand-md navbar-dark cd-navbar-brand"> <nav class="navbar navbar-expand-md navbar-dark cd-navbar-brand">
<button class="btn btn-link py-0 ms-3" <button class="btn btn-link py-0"
(click)="showMenuSidebar = !showMenuSidebar" (click)="showMenuSidebar = !showMenuSidebar"
aria-label="toggle sidebar visibility"> aria-label="toggle sidebar visibility">
<i class="fa fa-bars fa-2x" <i [ngClass]="[icons.bars, icons.large2x]"
aria-hidden="true"></i> aria-hidden="true"></i>
</button> </button>
@ -23,8 +23,8 @@
(click)="toggleRightSidebar()"> (click)="toggleRightSidebar()">
<span i18n <span i18n
class="sr-only">Toggle navigation</span> class="sr-only">Toggle navigation</span>
<span class=""> <span>
<i class="fa fa-navicon fa-lg"></i> <i [ngClass]="[icons.navicon, icons.large]"></i>
</span> </span>
</button> </button>
@ -81,9 +81,14 @@
class="nav-item tc_menuitem_dashboard"> class="nav-item tc_menuitem_dashboard">
<a routerLink="/dashboard" <a routerLink="/dashboard"
class="nav-link"> class="nav-link">
<span i18n>Dashboard</span>&nbsp; <span i18n>
<i [ngClass]="[icons.health]" <i [ngClass]="[icons.areaChart]"></i>
[ngStyle]="summaryData?.health_status | healthColor"></i> Dashboard</span>
<i
*ngIf="summaryData?.health_status !== 'HEALTH_OK'"
[ngClass]="[icons.circle]"
[ngStyle]="summaryData?.health_status | healthColor">
</i>
</a> </a>
</li> </li>
@ -91,24 +96,38 @@
<li routerLinkActive="active" <li routerLinkActive="active"
class="nav-item tc_menuitem_cluster" class="nav-item tc_menuitem_cluster"
*ngIf="permissions.hosts.read || permissions.monitor.read || *ngIf="permissions.hosts.read || permissions.monitor.read ||
permissions.osd.read || permissions.configOpt.read || permissions.osd.read || permissions.pool.read">
permissions.log.read || permissions.prometheus.read">
<a (click)="toggleSubMenu('cluster')" <a (click)="toggleSubMenu('cluster')"
class="nav-link dropdown-toggle" class="nav-link dropdown-toggle"
[attr.aria-expanded]="displayedSubMenu === 'cluster'" [attr.aria-expanded]="displayedSubMenu.cluster"
aria-controls="cluster-nav" aria-controls="cluster-nav"
role="button"> role="button">
<ng-container i18n>Cluster</ng-container> <ng-container i18n>
<i [ngClass]="[icons.sitemap]"></i>
Cluster
</ng-container>
</a> </a>
<ul class="list-unstyled" <ul class="list-unstyled"
id="cluster-nav" id="cluster-nav"
[ngbCollapse]="displayedSubMenu !== 'cluster'"> [ngbCollapse]="!displayedSubMenu.cluster">
<li routerLinkActive="active" <li routerLinkActive="active"
class="tc_submenuitem tc_submenuitem_hosts" class="tc_submenuitem tc_submenuitem_cluster_pool"
*ngIf="permissions.pool.read">
<a i18n
routerLink="/pool">Pools</a>
</li>
<li routerLinkActive="active"
class="tc_submenuitem tc_submenuitem_cluster_hosts"
*ngIf="permissions.hosts.read"> *ngIf="permissions.hosts.read">
<a i18n <a i18n
routerLink="/hosts">Hosts</a> routerLink="/hosts">Hosts</a>
</li> </li>
<li routerLinkActive="active"
class="tc_submenuitem tc_submenuitem_cluster_osds"
*ngIf="permissions.osd.read">
<a i18n
routerLink="/osd">OSDs</a>
</li>
<li routerLinkActive="active" <li routerLinkActive="active"
class="tc_submenuitem tc_submenuitem_cluster_inventory" class="tc_submenuitem tc_submenuitem_cluster_inventory"
*ngIf="permissions.hosts.read"> *ngIf="permissions.hosts.read">
@ -116,99 +135,40 @@
routerLink="/inventory">Physical Disks</a> routerLink="/inventory">Physical Disks</a>
</li> </li>
<li routerLinkActive="active" <li routerLinkActive="active"
class="tc_submenuitem tc_submenuitem_cluster_monitor" class="tc_submenuitem tc_submenuitem_cluster_crush"
*ngIf="permissions.monitor.read">
<a i18n
routerLink="/monitor/">Monitors</a>
</li>
<li routerLinkActive="active"
class="tc_submenuitem tc_submenuitem_cluster_services"
*ngIf="permissions.hosts.read">
<a i18n
routerLink="/services/">Services</a>
</li>
<li routerLinkActive="active"
class="tc_submenuitem tc_submenuitem_osds"
*ngIf="permissions.osd.read">
<a i18n
routerLink="/osd">OSDs</a>
</li>
<li routerLinkActive="active"
class="tc_submenuitem tc_submenuitem_configuration"
*ngIf="permissions.configOpt.read">
<a i18n
routerLink="/configuration">Configuration</a>
</li>
<li routerLinkActive="active"
class="tc_submenuitem tc_submenuitem_crush"
*ngIf="permissions.osd.read"> *ngIf="permissions.osd.read">
<a i18n <a i18n
routerLink="/crush-map">CRUSH map</a> routerLink="/crush-map">CRUSH map</a>
</li> </li>
<li routerLinkActive="active" <li routerLinkActive="active"
class="tc_submenuitem tc_submenuitem_modules" class="tc_submenuitem tc_submenuitem_cluster_monitor"
*ngIf="permissions.configOpt.read"> *ngIf="permissions.monitor.read">
<a i18n <a i18n
routerLink="/mgr-modules">Manager Modules</a> routerLink="/monitor/">Monitors</a>
</li>
<li routerLinkActive="active"
class="tc_submenuitem tc_submenuitem_users"
*ngIf="permissions.configOpt.read">
<a i18n
routerLink="/ceph-users">Ceph Users</a>
</li>
<li routerLinkActive="active"
class="tc_submenuitem tc_submenuitem_log"
*ngIf="permissions.log.read">
<a i18n
routerLink="/logs">Logs</a>
</li>
<li routerLinkActive="active"
class="tc_submenuitem tc_submenuitem_monitoring"
*ngIf="permissions.prometheus.read">
<a routerLink="/monitoring">
<ng-container i18n>Alerts</ng-container>
<small *ngIf="prometheusAlertService.activeCriticalAlerts > 0"
class="badge badge-danger ms-1">{{ prometheusAlertService.activeCriticalAlerts }}</small>
<small *ngIf="prometheusAlertService.activeWarningAlerts > 0"
class="badge badge-warning ms-1">{{ prometheusAlertService.activeWarningAlerts }}</small>
</a>
</li>
<li routerLinkActive="active"
class="tc_submenuitem tc_submenuitem_upgrade"
*ngIf="permissions.configOpt.read">
<a i18n
routerLink="/upgrade">Upgrade</a>
</li> </li>
</ul> </ul>
</li> </li>
<!-- Pools --> <!-- Block Storage -->
<li routerLinkActive="active"
class="nav-item tc_menuitem_pool"
*ngIf="permissions.pool.read">
<a class="nav-link"
i18n
routerLink="/pool">Pools</a>
</li>
<!-- Block -->
<li routerLinkActive="active" <li routerLinkActive="active"
class="nav-item tc_menuitem_block" class="nav-item tc_menuitem_block"
*ngIf="(permissions.rbdImage.read || permissions.rbdMirroring.read || permissions.iscsi.read) && *ngIf="(permissions.rbdImage.read || permissions.rbdMirroring.read || permissions.iscsi.read) &&
(enabledFeature.rbd || enabledFeature.mirroring || enabledFeature.iscsi)"> (enabledFeature.rbd || enabledFeature.mirroring || enabledFeature.iscsi)">
<a class="nav-link dropdown-toggle" <a class="nav-link dropdown-toggle"
(click)="toggleSubMenu('block')" (click)="toggleSubMenu('block')"
[attr.aria-expanded]="displayedSubMenu === 'block'" [attr.aria-expanded]="displayedSubMenu.block"
aria-controls="block-nav" aria-controls="block-nav"
role="button" role="button"
[ngStyle]="blockHealthColor()"> [ngStyle]="blockHealthColor()">
<ng-container i18n>Block</ng-container> <ng-container i18n>
<i [ngClass]="[icons.database]"></i>
Block
</ng-container>
</a> </a>
<ul class="list-unstyled" <ul class="list-unstyled"
id="block-nav" id="block-nav"
[ngbCollapse]="displayedSubMenu !== 'block'"> [ngbCollapse]="!displayedSubMenu.block">
<li routerLinkActive="active" <li routerLinkActive="active"
class="tc_submenuitem tc_submenuitem_block_images" class="tc_submenuitem tc_submenuitem_block_images"
*ngIf="permissions.rbdImage.read && enabledFeature.rbd"> *ngIf="permissions.rbdImage.read && enabledFeature.rbd">
@ -237,47 +197,32 @@
</ul> </ul>
</li> </li>
<!-- NFS --> <!-- Object Storage -->
<li routerLinkActive="active"
class="nav-item tc_menuitem_nfs"
*ngIf="permissions.nfs.read && enabledFeature.nfs">
<a i18n
class="nav-link"
routerLink="/nfs">NFS</a>
</li>
<!-- Filesystem -->
<li routerLinkActive="active"
class="nav-item tc_menuitem_cephfs"
*ngIf="permissions.cephfs.read && enabledFeature.cephfs">
<a i18n
class="nav-link"
routerLink="/cephfs">File Systems</a>
</li>
<!-- Object Gateway -->
<li routerLinkActive="active" <li routerLinkActive="active"
class="nav-item tc_menuitem_rgw" class="nav-item tc_menuitem_rgw"
*ngIf="permissions.rgw.read && enabledFeature.rgw"> *ngIf="permissions.rgw.read && enabledFeature.rgw">
<a class="nav-link dropdown-toggle" <a class="nav-link dropdown-toggle"
(click)="toggleSubMenu('rgw')" (click)="toggleSubMenu('object')"
[attr.aria-expanded]="displayedSubMenu === 'rgw'" [attr.aria-expanded]="displayedSubMenu.object"
aria-controls="gateway-nav" aria-controls="gateway-nav"
role="button"> role="button">
<ng-container i18n>Object Gateway</ng-container> <ng-container i18n>
<i [ngClass]="[icons.cubes]"></i>
Object
</ng-container>
</a> </a>
<ul class="list-unstyled" <ul class="list-unstyled"
id="gateway-nav" id="gateway-nav"
[ngbCollapse]="displayedSubMenu !== 'rgw'"> [ngbCollapse]="!displayedSubMenu.object">
<li routerLinkActive="active" <li routerLinkActive="active"
class="tc_submenuitem tc_submenuitem_rgw_overview"> class="tc_submenuitem tc_submenuitem_rgw_overview">
<a i18n <a i18n
routerLink="/rgw/overview">Overview</a> routerLink="/rgw/overview">Overview</a>
</li> </li>
<li routerLinkActive="active" <li routerLinkActive="active"
class="tc_submenuitem tc_submenuitem_rgw_daemons"> class="tc_submenuitem tc_submenuitem_rgw_buckets">
<a i18n <a i18n
routerLink="/rgw/daemon">Gateways</a> routerLink="/rgw/bucket">Buckets</a>
</li> </li>
<li routerLinkActive="active" <li routerLinkActive="active"
class="tc_submenuitem tc_submenuitem_rgw_users"> class="tc_submenuitem tc_submenuitem_rgw_users">
@ -287,12 +232,141 @@
<li routerLinkActive="active" <li routerLinkActive="active"
class="tc_submenuitem tc_submenuitem_rgw_buckets"> class="tc_submenuitem tc_submenuitem_rgw_buckets">
<a i18n <a i18n
routerLink="/rgw/bucket">Buckets</a> routerLink="/rgw/multisite">Multi-site</a>
</li> </li>
<li routerLinkActive="active" <li routerLinkActive="active"
class="tc_submenuitem tc_submenuitem_rgw_buckets"> class="tc_submenuitem tc_submenuitem_rgw_daemons">
<a i18n <a i18n
routerLink="/rgw/multisite">Multi-Site</a> routerLink="/rgw/daemon">Gateways</a>
</li>
<li routerLinkActive="active"
class="tc_submenuitem tc_submenuitem_rgw_nfs"
*ngIf="permissions.nfs.read && enabledFeature.nfs">
<a i18n
class="nav-link"
routerLink="/nfs">NFS</a>
</li>
</ul>
</li>
<!-- Filesystem -->
<li routerLinkActive="active"
class="nav-item tc_menuitem_file"
*ngIf="permissions.nfs.read && enabledFeature.nfs
|| permissions.cephfs.read && enabledFeature.cephfs">
<a class="nav-link dropdown-toggle"
(click)="toggleSubMenu('file')"
[attr.aria-expanded]="displayedSubMenu.file"
aria-controls="filesystem-nav"
role="button">
<ng-container i18n>
<i [ngClass]="[icons.text]"></i>
File
</ng-container>
</a>
<ul class="list-unstyled"
id="filesystem-nav"
[ngbCollapse]="!displayedSubMenu.file">
<li routerLinkActive="active"
class="tc_submenuitem tc_submenuitem_file_cephfs"
*ngIf="permissions.cephfs.read && enabledFeature.cephfs">
<a i18n
class="nav-link"
routerLink="/cephfs">File Systems</a>
</li>
<li routerLinkActive="active"
class="tc_submenuitem tc_submenuitem_file_nfs"
*ngIf="permissions.nfs.read && enabledFeature.nfs">
<a i18n
class="nav-link"
routerLink="/nfs">NFS</a>
</li>
</ul>
</li>
<!-- Observability -->
<li routerLinkActive="active"
class="nav-item tc_menuitem_observe"
*ngIf="permissions.log.read || permissions.prometheus.read">
<a class="nav-link dropdown-toggle"
(click)="toggleSubMenu('observe')"
[attr.aria-expanded]="displayedSubMenu.observe"
aria-controls="observe-nav"
role="button">
<ng-container i18n>
<i [ngClass]="[icons.eye]"></i>
Observability
</ng-container>
</a>
<ul class="list-unstyled"
id="observe-nav"
[ngbCollapse]="!displayedSubMenu.observe">
<li routerLinkActive="active"
class="tc_submenuitem tc_submenuitem_observe_log"
*ngIf="permissions.log.read">
<a i18n
routerLink="/logs">Logs</a>
</li>
<li routerLinkActive="active"
class="tc_submenuitem tc_submenuitem_observe_monitoring"
*ngIf="permissions.prometheus.read">
<a routerLink="/monitoring">
<ng-container i18n>Alerts</ng-container>
<small *ngIf="prometheusAlertService.activeCriticalAlerts > 0"
class="badge badge-danger ms-1">{{ prometheusAlertService.activeCriticalAlerts }}</small>
<small *ngIf="prometheusAlertService.activeWarningAlerts > 0"
class="badge badge-warning ms-1">{{ prometheusAlertService.activeWarningAlerts }}</small>
</a>
</li>
</ul>
</li>
<li routerLinkActive="active"
class="nav-item tc_menuitem_admin"
*ngIf="permissions.configOpt.read ||
permissions.hosts.read">
<a class="nav-link dropdown-toggle"
(click)="toggleSubMenu('admin')"
[attr.aria-expanded]="displayedSubMenu.admin"
aria-controls="admin-nav"
role="button">
<ng-container i18n>
<i [ngClass]="[icons.cogs]"></i>
Administration
</ng-container>
</a>
<ul class="list-unstyled"
id="admin-nav"
[ngbCollapse]="!displayedSubMenu.admin">
<li routerLinkActive="active"
class="tc_submenuitem tc_submenuitem_admin_services"
*ngIf="permissions.hosts.read">
<a i18n
routerLink="/services/">Services</a>
</li>
<li routerLinkActive="active"
class="tc_submenuitem tc_submenuitem_admin_upgrade"
*ngIf="permissions.configOpt.read">
<a i18n
routerLink="/upgrade">Upgrade</a>
</li>
<li routerLinkActive="active"
class="tc_submenuitem tc_submenuitem_admin_users"
*ngIf="permissions.configOpt.read">
<a i18n
routerLink="/ceph-users">Ceph Users</a>
</li>
<li routerLinkActive="active"
class="tc_submenuitem tc_submenuitem_admin_modules"
*ngIf="permissions.configOpt.read">
<a i18n
routerLink="/mgr-modules">Manager Modules</a>
</li>
<li routerLinkActive="active"
class="tc_submenuitem tc_submenuitem_admin_configuration"
*ngIf="permissions.configOpt.read">
<a i18n
routerLink="/configuration">Configuration</a>
</li> </li>
</ul> </ul>
</li> </li>

View File

@ -195,9 +195,7 @@ $sidebar-width: 200px;
color: vv.$white; color: vv.$white;
display: block; display: block;
font-size: 1.3em; font-size: 1.3em;
padding: 10px; padding: 10px 23px 10px 10px;
padding-left: 27px;
text-decoration: none; text-decoration: none;
&:hover { &:hover {
@ -208,6 +206,25 @@ $sidebar-width: 200px;
> .badge { > .badge {
margin-left: 5px; margin-left: 5px;
} }
i.fa.fa-circle {
animation: blink 2s ease-in infinite;
font-size: 0.875em;
margin-top: 4px;
position: absolute;
right: 35px;
}
@keyframes blink {
from,
to {
opacity: 1;
}
50% {
opacity: 0;
}
}
} }
li.active > a, li.active > a,
@ -239,7 +256,7 @@ $sidebar-width: 200px;
ul ul a { ul ul a {
background: lighten(vv.$secondary, 10); background: lighten(vv.$secondary, 10);
font-size: 1.1em !important; font-size: 1.1em !important;
padding-left: 40px !important; padding-left: 35px !important;
} }
.cd-navbar-primary a:focus { .cd-navbar-primary a:focus {

View File

@ -102,31 +102,31 @@ describe('NavigationComponent', () => {
[ [
['hosts'], ['hosts'],
[ [
'.tc_submenuitem_hosts', '.tc_submenuitem_cluster_hosts',
'.tc_submenuitem_cluster_inventory', '.tc_submenuitem_cluster_inventory',
'.tc_submenuitem_cluster_services' '.tc_submenuitem_admin_services'
] ]
], ],
[['monitor'], ['.tc_submenuitem_cluster_monitor']], [['monitor'], ['.tc_submenuitem_cluster_monitor']],
[['osd'], ['.tc_submenuitem_osds', '.tc_submenuitem_crush']], [['osd'], ['.tc_submenuitem_cluster_osds', '.tc_submenuitem_cluster_crush']],
[ [
['configOpt'], ['configOpt'],
[ [
'.tc_submenuitem_configuration', '.tc_submenuitem_admin_configuration',
'.tc_submenuitem_modules', '.tc_submenuitem_admin_modules',
'.tc_submenuitem_users', '.tc_submenuitem_admin_users',
'.tc_submenuitem_upgrade' '.tc_submenuitem_admin_upgrade'
] ]
], ],
[['log'], ['.tc_submenuitem_log']], [['log'], ['.tc_submenuitem_observe_log']],
[['prometheus'], ['.tc_submenuitem_monitoring']], [['prometheus'], ['.tc_submenuitem_observe_monitoring']],
[['pool'], ['.tc_menuitem_pool']], [['pool'], ['.tc_submenuitem_cluster_pool']],
[['rbdImage'], ['.tc_submenuitem_block_images']], [['rbdImage'], ['.tc_submenuitem_block_images']],
[['rbdMirroring'], ['.tc_submenuitem_block_mirroring']], [['rbdMirroring'], ['.tc_submenuitem_block_mirroring']],
[['iscsi'], ['.tc_submenuitem_block_iscsi']], [['iscsi'], ['.tc_submenuitem_block_iscsi']],
[['rbdImage', 'rbdMirroring', 'iscsi'], ['.tc_menuitem_block']], [['rbdImage', 'rbdMirroring', 'iscsi'], ['.tc_menuitem_block']],
[['nfs'], ['.tc_menuitem_nfs']], [['nfs'], ['.tc_submenuitem_file_nfs']],
[['cephfs'], ['.tc_menuitem_cephfs']], [['cephfs'], ['.tc_submenuitem_file_cephfs']],
[ [
['rgw'], ['rgw'],
[ [
@ -173,8 +173,8 @@ describe('NavigationComponent', () => {
[['mirroring'], ['.tc_submenuitem_block_mirroring']], [['mirroring'], ['.tc_submenuitem_block_mirroring']],
[['iscsi'], ['.tc_submenuitem_block_iscsi']], [['iscsi'], ['.tc_submenuitem_block_iscsi']],
[['rbd', 'mirroring', 'iscsi'], ['.tc_menuitem_block']], [['rbd', 'mirroring', 'iscsi'], ['.tc_menuitem_block']],
[['nfs'], ['.tc_menuitem_nfs']], [['nfs'], ['.tc_submenuitem_file_nfs']],
[['cephfs'], ['.tc_menuitem_cephfs']], [['cephfs'], ['.tc_submenuitem_file_cephfs']],
[ [
['rgw'], ['rgw'],
[ [

View File

@ -33,11 +33,11 @@ export class NavigationComponent implements OnInit, OnDestroy {
rightSidebarOpen = false; // rightSidebar only opens when width is less than 768px rightSidebarOpen = false; // rightSidebar only opens when width is less than 768px
showMenuSidebar = true; showMenuSidebar = true;
displayedSubMenu = '';
simplebar = { simplebar = {
autoHide: false autoHide: false
}; };
displayedSubMenu = {};
private subs = new Subscription(); private subs = new Subscription();
constructor( constructor(
@ -97,11 +97,7 @@ export class NavigationComponent implements OnInit, OnDestroy {
} }
toggleSubMenu(menu: string) { toggleSubMenu(menu: string) {
if (this.displayedSubMenu === menu) { this.displayedSubMenu[menu] = !this.displayedSubMenu[menu];
this.displayedSubMenu = '';
} else {
this.displayedSubMenu = menu;
}
} }
toggleRightSidebar() { toggleRightSidebar() {

View File

@ -20,6 +20,7 @@ export enum Icons {
stop = 'fa fa-stop', // Disable stop = 'fa fa-stop', // Disable
analyse = 'fa fa-stethoscope', // Scrub analyse = 'fa fa-stethoscope', // Scrub
deepCheck = 'fa fa-cog', // Deep Scrub, Setting, Configuration deepCheck = 'fa fa-cog', // Deep Scrub, Setting, Configuration
cogs = 'fa fa-cogs', // Multiple Settings, Configurations
reweight = 'fa fa-balance-scale', // Reweight reweight = 'fa fa-balance-scale', // Reweight
up = 'fa fa-arrow-up', // Up up = 'fa fa-arrow-up', // Up
left = 'fa fa-arrow-left', // Mark out left = 'fa fa-arrow-left', // Mark out
@ -74,7 +75,13 @@ export enum Icons {
exit = 'fa fa-sign-out', // Exit exit = 'fa fa-sign-out', // Exit
restart = 'fa fa-history', // Restart restart = 'fa fa-history', // Restart
deploy = 'fa fa-cube', // Deploy, Redeploy deploy = 'fa fa-cube', // Deploy, Redeploy
cubes = 'fa fa-cubes', cubes = 'fa fa-cubes', // Object storage
sitemap = 'fa fa-sitemap', // Cluster, network, connections
database = 'fa fa-database', // Database, Block storage
bars = 'fa fa-bars', // Stack, bars
navicon = 'fa fa-navicon', // Navigation
areaChart = 'fa fa-area-chart', // Area Chart, dashboard
eye = 'fa fa-eye', // Observability
/* Icons for special effect */ /* Icons for special effect */
large = 'fa fa-lg', // icon becomes 33% larger large = 'fa fa-lg', // icon becomes 33% larger