* Remember the selected tab and restore the state on tabset init.
* Remove tab headers where only one tab is shown.
Fixes: https://tracker.ceph.com/issues/43120
Signed-off-by: Volker Theile <vtheile@suse.com>
configuration.getTableSelectedCount().should('eq', 1);
});
- it('should check that details table opens and tab is correct', () => {
+ it('should check that details table opens (w/o tab header)', () => {
configuration.getStatusTables().should('be.visible');
- configuration.getTabsCount().should('eq', 1);
- configuration.getTabText(0).should('eq', 'Details');
+ configuration.getTabs().should('not.exist');
});
});
cy.get('.breadcrumb-item.active').should('have.text', text);
}
+ getTabs() {
+ return cy.get('.nav.nav-tabs li');
+ }
+
getTabText(index: number) {
- return cy.get('.nav.nav-tabs li').its(index).text();
+ return this.getTabs().its(index).text();
}
getTabsCount(): any {
- return cy.get('.nav.nav-tabs li').its('length');
+ return this.getTabs().its('length');
}
/**
<ul ngbNav
#nav="ngbNav"
- class="nav-tabs">
- <li ngbNavItem>
+ class="nav-tabs"
+ cdStatefulTab="image-list">
+ <li ngbNavItem="issues">
<a ngbNavLink
i18n>Issues</a>
<ng-template ngbNavContent>
</cd-table>
</ng-template>
</li>
- <li ngbNavItem>
+ <li ngbNavItem="syncing">
<a ngbNavLink
i18n>Syncing</a>
<ng-template ngbNavContent>
</cd-table>
</ng-template>
</li>
- <li ngbNavItem>
+ <li ngbNavItem="ready">
<a ngbNavLink
i18n>Ready</a>
<ng-template ngbNavContent>
<ng-container *ngIf="selection">
<ul ngbNav
#nav="ngbNav"
- class="nav-tabs">
- <li ngbNavItem>
+ class="nav-tabs"
+ cdStatefulTab="rbd-details">
+ <li ngbNavItem="details">
<a ngbNavLink
i18n>Details</a>
<ng-template ngbNavContent>
</table>
</ng-template>
</li>
- <li ngbNavItem>
+ <li ngbNavItem="snapshots">
<a ngbNavLink
i18n>Snapshots</a>
<ng-template ngbNavContent>
[rbdName]="selection.name"></cd-rbd-snapshot-list>
</ng-template>
</li>
- <li ngbNavItem>
+ <li ngbNavItem="configuration">
<a ngbNavLink
i18n>Configuration</a>
<ng-template ngbNavContent>
<ul ngbNav
#nav="ngbNav"
(navChange)="softRefresh()"
- class="nav-tabs">
- <li ngbNavItem>
+ class="nav-tabs"
+ cdStatefulTab="cephfs-tabs">
+ <li ngbNavItem="details">
<a ngbNavLink
i18n>Details</a>
<ng-template ngbNavContent>
</cd-cephfs-detail>
</ng-template>
</li>
- <li ngbNavItem>
+ <li ngbNavItem="clients">
<a ngbNavLink>
<ng-container i18n>Clients</ng-container>
<span class="badge badge-pill badge-tab ml-1">{{ clients.data.length }}</span>
</cd-cephfs-clients>
</ng-template>
</li>
- <li ngbNavItem>
+ <li ngbNavItem="directories">
<a ngbNavLink
i18n>Directories</a>
<ng-template ngbNavContent>
<cd-cephfs-directories [id]="id"></cd-cephfs-directories>
</ng-template>
</li>
- <li ngbNavItem>
+ <li ngbNavItem="performance-details">
<a ngbNavLink
i18n>Performance Details</a>
<ng-template ngbNavContent>
<ng-container *ngIf="selection">
- <ul ngbNav
- #nav="ngbNav"
- class="nav-tabs">
- <li ngbNavItem>
- <a ngbNavLink
- i18n>Details</a>
- <ng-template ngbNavContent>
- <table class="table table-striped table-bordered">
- <tbody>
- <tr>
- <td i18n
- class="bold w-25">Name</td>
- <td class="w-75">{{ selection.name }}</td>
- </tr>
- <tr>
- <td i18n
- class="bold">Description</td>
- <td>{{ selection.desc }}</td>
- </tr>
- <tr>
- <td i18n
- class="bold">Long description</td>
- <td>{{ selection.long_desc }}</td>
- </tr>
- <tr>
- <td i18n
- class="bold">Current values</td>
- <td>
- <span *ngFor="let conf of selection.value; last as isLast">
- {{ conf.section }}: {{ conf.value }}{{ !isLast ? "," : "" }}<br />
- </span>
- </td>
- </tr>
- <tr>
- <td i18n
- class="bold">Default</td>
- <td>{{ selection.default }}</td>
- </tr>
- <tr>
- <td i18n
- class="bold">Daemon default</td>
- <td>{{ selection.daemon_default }}</td>
- </tr>
- <tr>
- <td i18n
- class="bold">Type</td>
- <td>{{ selection.type }}</td>
- </tr>
- <tr>
- <td i18n
- class="bold">Min</td>
- <td>{{ selection.min }}</td>
- </tr>
- <tr>
- <td i18n
- class="bold">Max</td>
- <td>{{ selection.max }}</td>
- </tr>
- <tr>
- <td i18n
- class="bold">Flags</td>
- <td>
- <span *ngFor="let flag of selection.flags">
- <span title="{{ flags[flag] }}">
- <span class="badge badge-dark mr-2">{{ flag | uppercase }}</span>
- </span>
- </span>
- </td>
- </tr>
- <tr>
- <td i18n
- class="bold">Services</td>
- <td>
- <span *ngFor="let service of selection.services">
- <span class="badge badge-dark mr-2">{{ service }}</span>
- </span>
- </td>
- </tr>
- <tr>
- <td i18n
- class="bold">Source</td>
- <td>{{ selection.source }}</td>
- </tr>
- <tr>
- <td i18n
- class="bold">Level</td>
- <td>{{ selection.level }}</td>
- </tr>
- <tr>
- <td i18n
- class="bold">Can be updated at runtime (editable)</td>
- <td>{{ selection.can_update_at_runtime | booleanText }}</td>
- </tr>
- <tr>
- <td i18n
- class="bold">Tags</td>
- <td>{{ selection.tags }}</td>
- </tr>
- <tr>
- <td i18n
- class="bold">Enum values</td>
- <td>{{ selection.enum_values }}</td>
- </tr>
- <tr>
- <td i18n
- class="bold">See also</td>
- <td>{{ selection.see_also }}</td>
- </tr>
- </tbody>
- </table>
- </ng-template>
- </li>
- </ul>
-
- <div [ngbNavOutlet]="nav"></div>
+ <table class="table table-striped table-bordered">
+ <tbody>
+ <tr>
+ <td i18n
+ class="bold w-25">Name</td>
+ <td class="w-75">{{ selection.name }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold">Description</td>
+ <td>{{ selection.desc }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold">Long description</td>
+ <td>{{ selection.long_desc }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold">Current values</td>
+ <td>
+ <span *ngFor="let conf of selection.value; last as isLast">
+ {{ conf.section }}: {{ conf.value }}{{ !isLast ? "," : "" }}<br />
+ </span>
+ </td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold">Default</td>
+ <td>{{ selection.default }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold">Daemon default</td>
+ <td>{{ selection.daemon_default }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold">Type</td>
+ <td>{{ selection.type }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold">Min</td>
+ <td>{{ selection.min }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold">Max</td>
+ <td>{{ selection.max }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold">Flags</td>
+ <td>
+ <span *ngFor="let flag of selection.flags">
+ <span title="{{ flags[flag] }}">
+ <span class="badge badge-dark mr-2">{{ flag | uppercase }}</span>
+ </span>
+ </span>
+ </td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold">Services</td>
+ <td>
+ <span *ngFor="let service of selection.services">
+ <span class="badge badge-dark mr-2">{{ service }}</span>
+ </span>
+ </td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold">Source</td>
+ <td>{{ selection.source }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold">Level</td>
+ <td>{{ selection.level }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold">Can be updated at runtime (editable)</td>
+ <td>{{ selection.can_update_at_runtime | booleanText }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold">Tags</td>
+ <td>{{ selection.tags }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold">Enum values</td>
+ <td>{{ selection.enum_values }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold">See also</td>
+ <td>{{ selection.see_also }}</td>
+ </tr>
+ </tbody>
+ </table>
</ng-container>
import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { NgbNavModule } from '@ng-bootstrap/ng-bootstrap';
-
import { configureTestBed, i18nProviders } from '../../../../../testing/unit-test-helper';
import { DataTableModule } from '../../../../shared/datatable/datatable.module';
import { SharedModule } from '../../../../shared/shared.module';
configureTestBed({
declarations: [ConfigurationDetailsComponent],
- imports: [DataTableModule, SharedModule, NgbNavModule],
+ imports: [DataTableModule, SharedModule],
providers: [i18nProviders]
});
<ng-container *ngIf="selection">
<ul ngbNav
#nav="ngbNav"
- class="nav-tabs">
- <li ngbNavItem>
+ class="nav-tabs"
+ cdStatefulTab="host-details">
+ <li ngbNavItem="devices">
<a ngbNavLink
i18n>Devices</a>
<ng-template ngbNavContent>
<cd-device-list [hostname]="selection['hostname']"></cd-device-list>
</ng-template>
</li>
- <li ngbNavItem
+ <li ngbNavItem="inventory"
*ngIf="permissions.hosts.read">
<a ngbNavLink
i18n>Inventory</a>
<cd-inventory [hostname]="selectedHostname"></cd-inventory>
</ng-template>
</li>
- <li ngbNavItem
+ <li ngbNavItem="daemons"
*ngIf="permissions.hosts.read">
<a ngbNavLink
i18n>Daemons</a>
</cd-service-daemon-list>
</ng-template>
</li>
- <li ngbNavItem
+ <li ngbNavItem="performance-details"
*ngIf="permissions.grafana.read">
<a ngbNavLink
i18n>Performance Details</a>
</cd-grafana>
</ng-template>
</li>
- <li ngbNavItem>
+ <li ngbNavItem="device-health">
<a ngbNavLink
i18n>Device health</a>
<ng-template ngbNavContent>
<ul ngbNav
#nav="ngbNav"
- class="nav-tabs">
- <li ngbNavItem>
+ class="nav-tabs"
+ cdStatefulTab="logs">
+ <li ngbNavItem="cluster-logs">
<a ngbNavLink
i18n>Cluster Logs</a>
<ng-template ngbNavContent>
</div>
</ng-template>
</li>
- <li ngbNavItem>
+ <li ngbNavItem="audit-logs">
<a ngbNavLink
i18n>Audit Logs</a>
<ng-template ngbNavContent>
<ng-container *ngIf="selection">
- <ul ngbNav
- #nav="ngbNav"
- class="nav-tabs">
- <li ngbNavItem>
- <a ngbNavLink
- i18n>Details</a>
- <ng-template ngbNavContent>
- <cd-table-key-value [data]="module_config">
- </cd-table-key-value>
- </ng-template>
- </li>
- </ul>
-
- <div [ngbNavOutlet]="nav"></div>
+ <cd-table-key-value [data]="module_config">
+ </cd-table-key-value>
</ng-container>
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { NgbNavModule } from '@ng-bootstrap/ng-bootstrap';
-
import { configureTestBed, i18nProviders } from '../../../../../testing/unit-test-helper';
import { SharedModule } from '../../../../shared/shared.module';
import { MgrModuleDetailsComponent } from './mgr-module-details.component';
configureTestBed({
declarations: [MgrModuleDetailsComponent],
- imports: [HttpClientTestingModule, SharedModule, NgbNavModule],
+ imports: [HttpClientTestingModule, SharedModule],
providers: [i18nProviders]
});
<ul ngbNav
#nav="ngbNav"
id="tabset-osd-details"
- class="nav-tabs">
- <li ngbNavItem>
+ class="nav-tabs"
+ cdStatefulTab="osd-details">
+ <li ngbNavItem="devices">
<a ngbNavLink
i18n>Devices</a>
<ng-template ngbNavContent>
<cd-device-list [osdId]="osd?.id"></cd-device-list>
</ng-template>
</li>
- <li ngbNavItem>
+ <li ngbNavItem="attributes">
<a ngbNavLink
i18n>Attributes (OSD map)</a>
<ng-template ngbNavContent>
</cd-table-key-value>
</ng-template>
</li>
- <li ngbNavItem>
+ <li ngbNavItem="metadata">
<a ngbNavLink
i18n>Metadata</a>
<ng-template ngbNavContent>
</ng-template>
</ng-template>
</li>
- <li ngbNavItem>
+ <li ngbNavItem="device-health">
<a ngbNavLink
i18n>Device health</a>
<ng-template ngbNavContent>
<cd-smart-list [osdId]="osd?.id"></cd-smart-list>
</ng-template>
</li>
- <li ngbNavItem>
+ <li ngbNavItem="performance-counter">
<a ngbNavLink
i18n>Performance counter</a>
<ng-template ngbNavContent>
</cd-table-performance-counter>
</ng-template>
</li>
- <li ngbNavItem>
+ <li ngbNavItem="histogram">
<a ngbNavLink
i18n>Histogram</a>
<ng-template ngbNavContent>
</div>
</ng-template>
</li>
- <li ngbNavItem
+ <li ngbNavItem="performance-details"
*ngIf="grafanaPermission.read">
<a ngbNavLink
i18n>Performance Details</a>
<ng-container *ngIf="selection">
- <ul ngbNav
- #nav="ngbNav"
- class="nav-tabs">
- <li ngbNavItem>
- <a ngbNavLink
- i18n>Daemons</a>
- <ng-template ngbNavContent>
- <cd-service-daemon-list [serviceName]="selection['service_name']">
- </cd-service-daemon-list>
- </ng-template>
- </li>
- </ul>
-
- <div [ngbNavOutlet]="nav"></div>
+ <cd-service-daemon-list [serviceName]="selection['service_name']">
+ </cd-service-daemon-list>
</ng-container>
import { NgbNavModule } from '@ng-bootstrap/ng-bootstrap';
-import {
- configureTestBed,
- i18nProviders,
- TabHelper
-} from '../../../../../testing/unit-test-helper';
+import { configureTestBed, i18nProviders } from '../../../../../testing/unit-test-helper';
import { CdTableSelection } from '../../../../shared/models/cd-table-selection';
import { SummaryService } from '../../../../shared/services/summary.service';
import { SharedModule } from '../../../../shared/shared.module';
fixture.detectChanges();
expect(component).toBeTruthy();
});
-
- describe('Service details tabset', () => {
- beforeEach(() => {
- component.selection.selected = [{ serviceName: 'osd' }];
- fixture.detectChanges();
- });
-
- it('should have a NgbNav', () => {
- const ngbNav = TabHelper.getNgbNav(fixture);
- expect(ngbNav).toBeDefined();
- });
-
- it('should show tabs', () => {
- const ngbNavItems = TabHelper.getTextContents(fixture);
- expect(ngbNavItems).toEqual(['Daemons']);
- });
- });
});
<ng-container *ngIf="selection">
<ul ngbNav
#nav="ngbNav"
- class="nav-tabs">
- <li ngbNavItem>
+ class="nav-tabs"
+ cdStatefulTab="nfs-details">
+ <li ngbNavItem="details">
<a ngbNavLink
i18n>Details</a>
<ng-template ngbNavContent>
</cd-table-key-value>
</ng-template>
</li>
- <li ngbNavItem>
+ <li ngbNavItem="clients">
<a ngbNavLink
i18n>Clients ({{ clients.length }})</a>
<ng-template ngbNavContent>
cdTableDetail>
<ul ngbNav
#nav="ngbNav"
- class="nav-tabs">
- <li ngbNavItem>
+ class="nav-tabs"
+ cdStatefulTab="pool-details">
+ <li ngbNavItem="details">
<a ngbNavLink
i18n>Details</a>
<ng-template ngbNavContent>
</cd-table-key-value>
</ng-template>
</li>
- <li ngbNavItem
+ <li ngbNavItem="performance-details"
*ngIf="permissions.grafana.read">
<a ngbNavLink
i18n>Performance Details</a>
</cd-grafana>
</ng-template>
</li>
- <li ngbNavItem
+ <li ngbNavItem="configuration"
*ngIf="selection.type === 'replicated'">
<a ngbNavLink
i18n>Configuration</a>
<cd-rbd-configuration-table [data]="selectedPoolConfiguration"></cd-rbd-configuration-table>
</ng-template>
</li>
- <li ngbNavItem
+ <li ngbNavItem="cache-tiers-details"
*ngIf="selection['tiers']?.length > 0">
<a ngbNavLink
i18n>Cache Tiers Details</a>
<ng-container *ngIf="selection">
- <ul ngbNav
- #nav="ngbNav"
- class="nav-tabs">
- <li ngbNavItem>
- <a ngbNavLink
- i18n>Details</a>
- <ng-template ngbNavContent>
- <table class="table table-striped table-bordered">
- <tbody>
- <tr>
- <td i18n
- class="bold w-25">Name</td>
- <td class="w-75">{{ selection.bid }}</td>
- </tr>
- <tr>
- <td i18n
- class="bold">ID</td>
- <td>{{ selection.id }}</td>
- </tr>
- <tr>
- <td i18n
- class="bold">Owner</td>
- <td>{{ selection.owner }}</td>
- </tr>
- <tr>
- <td i18n
- class="bold">Index type</td>
- <td>{{ selection.index_type }}</td>
- </tr>
- <tr>
- <td i18n
- class="bold">Placement rule</td>
- <td>{{ selection.placement_rule }}</td>
- </tr>
- <tr>
- <td i18n
- class="bold">Marker</td>
- <td>{{ selection.marker }}</td>
- </tr>
- <tr>
- <td i18n
- class="bold">Maximum marker</td>
- <td>{{ selection.max_marker }}</td>
- </tr>
- <tr>
- <td i18n
- class="bold">Version</td>
- <td>{{ selection.ver }}</td>
- </tr>
- <tr>
- <td i18n
- class="bold">Master version</td>
- <td>{{ selection.master_ver }}</td>
- </tr>
- <tr>
- <td i18n
- class="bold">Modification time</td>
- <td>{{ selection.mtime | cdDate }}</td>
- </tr>
- <tr>
- <td i18n
- class="bold">Zonegroup</td>
- <td>{{ selection.zonegroup }}</td>
- </tr>
- <tr>
- <td i18n
- class="bold">Versioning</td>
- <td>{{ selection.versioning }}</td>
- </tr>
- <tr>
- <td i18n
- class="bold">MFA Delete</td>
- <td>{{ selection.mfa_delete }}</td>
- </tr>
- </tbody>
- </table>
+ <table class="table table-striped table-bordered">
+ <tbody>
+ <tr>
+ <td i18n
+ class="bold w-25">Name</td>
+ <td class="w-75">{{ selection.bid }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold">ID</td>
+ <td>{{ selection.id }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold">Owner</td>
+ <td>{{ selection.owner }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold">Index type</td>
+ <td>{{ selection.index_type }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold">Placement rule</td>
+ <td>{{ selection.placement_rule }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold">Marker</td>
+ <td>{{ selection.marker }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold">Maximum marker</td>
+ <td>{{ selection.max_marker }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold">Version</td>
+ <td>{{ selection.ver }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold">Master version</td>
+ <td>{{ selection.master_ver }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold">Modification time</td>
+ <td>{{ selection.mtime | cdDate }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold">Zonegroup</td>
+ <td>{{ selection.zonegroup }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold">Versioning</td>
+ <td>{{ selection.versioning }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold">MFA Delete</td>
+ <td>{{ selection.mfa_delete }}</td>
+ </tr>
+ </tbody>
+ </table>
- <!-- Bucket quota -->
- <div *ngIf="selection.bucket_quota">
- <legend i18n>Bucket quota</legend>
- <table class="table table-striped table-bordered">
- <tbody>
- <tr>
- <td i18n
- class="bold w-25">Enabled</td>
- <td class="w-75">{{ selection.bucket_quota.enabled | booleanText }}</td>
- </tr>
- <tr>
- <td i18n
- class="bold">Maximum size</td>
- <td *ngIf="selection.bucket_quota.max_size <= -1"
- i18n>Unlimited</td>
- <td *ngIf="selection.bucket_quota.max_size > -1">
- {{ selection.bucket_quota.max_size | dimless }}
- </td>
- </tr>
- <tr>
- <td i18n
- class="bold">Maximum objects</td>
- <td *ngIf="selection.bucket_quota.max_objects <= -1"
- i18n>Unlimited</td>
- <td *ngIf="selection.bucket_quota.max_objects > -1">
- {{ selection.bucket_quota.max_objects }}
- </td>
- </tr>
- </tbody>
- </table>
- </div>
+ <!-- Bucket quota -->
+ <div *ngIf="selection.bucket_quota">
+ <legend i18n>Bucket quota</legend>
+ <table class="table table-striped table-bordered">
+ <tbody>
+ <tr>
+ <td i18n
+ class="bold w-25">Enabled</td>
+ <td class="w-75">{{ selection.bucket_quota.enabled | booleanText }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold">Maximum size</td>
+ <td *ngIf="selection.bucket_quota.max_size <= -1"
+ i18n>Unlimited</td>
+ <td *ngIf="selection.bucket_quota.max_size > -1">
+ {{ selection.bucket_quota.max_size | dimless }}
+ </td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold">Maximum objects</td>
+ <td *ngIf="selection.bucket_quota.max_objects <= -1"
+ i18n>Unlimited</td>
+ <td *ngIf="selection.bucket_quota.max_objects > -1">
+ {{ selection.bucket_quota.max_objects }}
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
- <!-- Locking -->
- <legend i18n>Locking</legend>
- <table class="table table-striped table-bordered">
- <tbody>
- <tr>
- <td i18n
- class="bold w-25">Enabled</td>
- <td class="w-75">{{ selection.lock_enabled | booleanText }}</td>
- </tr>
- <ng-container *ngIf="selection.lock_enabled">
- <tr>
- <td i18n
- class="bold">Mode</td>
- <td>{{ selection.lock_mode }}</td>
- </tr>
- <tr>
- <td i18n
- class="bold">Days</td>
- <td>{{ selection.lock_retention_period_days }}</td>
- </tr>
- <tr>
- <td i18n
- class="bold">Years</td>
- <td>{{ selection.lock_retention_period_years }}</td>
- </tr>
- </ng-container>
- </tbody>
- </table>
- </ng-template>
- </li>
- </ul>
-
- <div [ngbNavOutlet]="nav"></div>
+ <!-- Locking -->
+ <legend i18n>Locking</legend>
+ <table class="table table-striped table-bordered">
+ <tbody>
+ <tr>
+ <td i18n
+ class="bold w-25">Enabled</td>
+ <td class="w-75">{{ selection.lock_enabled | booleanText }}</td>
+ </tr>
+ <ng-container *ngIf="selection.lock_enabled">
+ <tr>
+ <td i18n
+ class="bold">Mode</td>
+ <td>{{ selection.lock_mode }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold">Days</td>
+ <td>{{ selection.lock_retention_period_days }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold">Years</td>
+ <td>{{ selection.lock_retention_period_years }}</td>
+ </tr>
+ </ng-container>
+ </tbody>
+ </table>
</ng-container>
import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { NgbNavModule } from '@ng-bootstrap/ng-bootstrap';
-
import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
import { CdTableSelection } from '../../../shared/models/cd-table-selection';
import { SharedModule } from '../../../shared/shared.module';
configureTestBed({
declarations: [RgwBucketDetailsComponent],
- imports: [SharedModule, NgbNavModule],
+ imports: [SharedModule],
providers: [i18nProviders]
});
<ng-container *ngIf="selection">
<ul ngbNav
#nav="ngbNav"
- class="nav-tabs">
- <li ngbNavItem>
+ class="nav-tabs"
+ cdStatefulTab="rgw-daemon-details">
+ <li ngbNavItem="details">
<a ngbNavLink
i18n>Details</a>
<ng-template ngbNavContent>
</cd-table-key-value>
</ng-template>
</li>
- <li ngbNavItem>
+ <li ngbNavItem="performance-counters">
<a ngbNavLink
i18n>Performance Counters</a>
<ng-template ngbNavContent>
</cd-table-performance-counter>
</ng-template>
</li>
- <li ngbNavItem
+ <li ngbNavItem="performance-details"
*ngIf="grafanaPermission.read">
<a ngbNavLink
i18n>Performance Details</a>
<ng-container *ngIf="selection">
<ul ngbNav
#nav="ngbNav"
- class="nav-tabs">
- <li ngbNavItem>
+ class="nav-tabs"
+ cdStatefulTab="rgw-user-details">
+ <li ngbNavItem="details">
<a ngbNavLink
i18n>Details</a>
<ng-template ngbNavContent>
</div>
</ng-template>
</li>
- <li ngbNavItem
+ <li ngbNavItem="keys"
*ngIf="keys.length">
<a ngbNavLink
i18n>Keys</a>
<ng-container *ngIf="selection">
- <ul ngbNav
- #nav="ngbNav"
- class="nav-tabs">
- <li ngbNavItem>
- <a ngbNavLink
- i18n>Details</a>
- <ng-template ngbNavContent>
- <cd-table [data]="scopes_permissions"
- [columns]="columns"
- columnMode="flex"
- [toolHeader]="false"
- [autoReload]="false"
- [autoSave]="false"
- [footer]="false"
- [limit]="0">
- </cd-table>
- </ng-template>
- </li>
- </ul>
-
- <div [ngbNavOutlet]="nav"></div>
+ <cd-table [data]="scopes_permissions"
+ [columns]="columns"
+ columnMode="flex"
+ [toolHeader]="false"
+ [autoReload]="false"
+ [autoSave]="false"
+ [footer]="false"
+ [limit]="0">
+ </cd-table>
</ng-container>
import { IopsDirective } from './iops.directive';
import { MillisecondsDirective } from './milliseconds.directive';
import { PasswordButtonDirective } from './password-button.directive';
+import { StatefulTabDirective } from './stateful-tab.directive';
import { TrimDirective } from './trim.directive';
@NgModule({
TrimDirective,
MillisecondsDirective,
IopsDirective,
- FormLoadingDirective
+ FormLoadingDirective,
+ StatefulTabDirective
],
exports: [
AutofocusDirective,
TrimDirective,
MillisecondsDirective,
IopsDirective,
- FormLoadingDirective
+ FormLoadingDirective,
+ StatefulTabDirective
]
})
export class DirectivesModule {}
--- /dev/null
+import { NgbNav, NgbNavChangeEvent, NgbNavConfig } from '@ng-bootstrap/ng-bootstrap';
+
+import { StatefulTabDirective } from './stateful-tab.directive';
+
+describe('StatefulTabDirective', () => {
+ it('should create an instance', () => {
+ const directive = new StatefulTabDirective(null);
+ expect(directive).toBeTruthy();
+ });
+
+ it('should get and select active tab', () => {
+ const nav = new NgbNav('tablist', new NgbNavConfig(), <any>null, null);
+ spyOn(nav, 'select');
+ spyOn(window.localStorage, 'getItem').and.returnValue('foo');
+ const directive = new StatefulTabDirective(nav);
+ directive.ngOnInit();
+ expect(window.localStorage.getItem).toHaveBeenCalled();
+ expect(nav.select).toHaveBeenCalledWith('foo');
+ });
+
+ it('should store active tab', () => {
+ spyOn(window.localStorage, 'setItem');
+ const directive = new StatefulTabDirective(null);
+ directive.cdStatefulTab = 'bar';
+ const event: NgbNavChangeEvent<string> = { activeId: '', nextId: 'xyz', preventDefault: null };
+ directive.onNavChange(event);
+ expect(window.localStorage.setItem).toHaveBeenCalledWith('tabset_bar', 'xyz');
+ });
+});
--- /dev/null
+import { Directive, Host, HostListener, Input, OnInit, Optional } from '@angular/core';
+
+import { NgbNav, NgbNavChangeEvent } from '@ng-bootstrap/ng-bootstrap';
+
+@Directive({
+ selector: '[cdStatefulTab]'
+})
+export class StatefulTabDirective implements OnInit {
+ @Input()
+ cdStatefulTab: string;
+
+ private localStorage = window.localStorage;
+
+ constructor(@Optional() @Host() private nav: NgbNav) {}
+
+ ngOnInit() {
+ // Is an activate tab identifier stored in the local storage?
+ const activeId = this.localStorage.getItem(`tabset_${this.cdStatefulTab}`);
+ if (activeId) {
+ this.nav.select(activeId);
+ }
+ }
+
+ @HostListener('navChange', ['$event'])
+ onNavChange(event: NgbNavChangeEvent) {
+ // Store the current active tab identifier in the local storage.
+ if (this.cdStatefulTab && event.nextId) {
+ this.localStorage.setItem(`tabset_${this.cdStatefulTab}`, event.nextId);
+ }
+ }
+}