From 24a2495ba375e61a40a78c1741046cfa5e9c4255 Mon Sep 17 00:00:00 2001 From: Volker Theile Date: Wed, 11 Nov 2020 09:02:23 +0100 Subject: [PATCH] mgr/dashboard: Use pipe instead of calling function within template wherever possible https://tracker.ceph.com/issues/48181 Signed-off-by: Volker Theile --- .../src/app/ceph/block/block.module.ts | 2 + .../rbd-configuration-list.component.html | 1 - .../rbd-configuration-list.component.spec.ts | 7 ++-- .../rbd-trash-list.component.html | 5 ++- .../rbd-trash-list.component.spec.ts | 2 + .../rbd-trash-list.component.ts | 7 +--- .../cephfs-directories.component.spec.ts | 5 ++- .../src/app/ceph/cluster/cluster.module.ts | 4 +- .../osd/osd-list/osd-list.component.html | 5 ++- .../osd/osd-list/osd-list.component.spec.ts | 2 +- .../osd/osd-list/osd-list.component.ts | 9 ++++- .../service-daemon-list.component.html | 2 +- .../service-daemon-list.component.spec.ts | 3 +- .../service-daemon-list.component.ts | 4 +- .../service-details.component.spec.ts | 9 ++++- .../pool/pool-form/pool-form.component.ts | 2 +- .../rgw-user-form.component.html | 4 +- .../rgw-user-form.component.spec.ts | 6 ++- .../rgw-user-form/rgw-user-form.component.ts | 7 ++-- .../frontend/src/app/ceph/rgw/rgw.module.ts | 4 +- .../frontend/src/app/core/auth/auth.module.ts | 2 + .../app/shared/datatable/datatable.module.ts | 2 + .../table-actions.component.html | 20 +++++----- .../table-actions.component.spec.ts | 10 +++-- .../table-actions/table-actions.component.ts | 37 +++++++++++-------- .../table-key-value.component.spec.ts | 4 +- .../datatable/table/table.component.html | 2 +- .../datatable/table/table.component.spec.ts | 2 + .../frontend/src/testing/unit-test-helper.ts | 26 +++++++++---- 29 files changed, 123 insertions(+), 72 deletions(-) diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/block.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/block.module.ts index e6c5e68ca0d63..472fe37f19fa6 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/block.module.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/block.module.ts @@ -5,6 +5,7 @@ import { RouterModule, Routes } from '@angular/router'; import { TreeModule } from '@circlon/angular-tree-component'; import { NgbNavModule, NgbPopoverModule, NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap'; +import { NgxPipeFunctionModule } from 'ngx-pipe-function'; import { ActionLabels, URLVerbs } from '~/app/shared/constants/app.constants'; import { FeatureTogglesGuardService } from '~/app/shared/services/feature-toggles-guard.service'; @@ -45,6 +46,7 @@ import { RbdTrashRestoreModalComponent } from './rbd-trash-restore-modal/rbd-tra NgbNavModule, NgbPopoverModule, NgbTooltipModule, + NgxPipeFunctionModule, SharedModule, RouterModule, TreeModule diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-list/rbd-configuration-list.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-list/rbd-configuration-list.component.html index 64364f67da63c..6c3e8c0278ca7 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-list/rbd-configuration-list.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-list/rbd-configuration-list.component.html @@ -5,7 +5,6 @@
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-list/rbd-configuration-list.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-list/rbd-configuration-list.component.spec.ts index ae1a52657351e..f54ad02720c52 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-list/rbd-configuration-list.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-list/rbd-configuration-list.component.spec.ts @@ -8,11 +8,10 @@ import { NgxDatatableModule } from '@swimlane/ngx-datatable'; import { ChartsModule } from 'ng2-charts'; import { ComponentsModule } from '~/app/shared/components/components.module'; -import { TableComponent } from '~/app/shared/datatable/table/table.component'; import { RbdConfigurationEntry } from '~/app/shared/models/configuration'; -import { PipesModule } from '~/app/shared/pipes/pipes.module'; import { FormatterService } from '~/app/shared/services/formatter.service'; import { RbdConfigurationService } from '~/app/shared/services/rbd-configuration.service'; +import { SharedModule } from '~/app/shared/shared.module'; import { configureTestBed } from '~/testing/unit-test-helper'; import { RbdConfigurationListComponent } from './rbd-configuration-list.component'; @@ -29,10 +28,10 @@ describe('RbdConfigurationListComponent', () => { ComponentsModule, NgbDropdownModule, ChartsModule, - PipesModule, + SharedModule, NgbTooltipModule ], - declarations: [RbdConfigurationListComponent, TableComponent], + declarations: [RbdConfigurationListComponent], providers: [FormatterService, RbdConfigurationService] }); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-list/rbd-trash-list.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-list/rbd-trash-list.component.html index 340d0d0d4993a..044a1e9ac0abf 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-list/rbd-trash-list.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-list/rbd-trash-list.component.html @@ -41,9 +41,10 @@ + let-expiresAt="expiresAt" + let-isExpired="isExpired">

+ *ngIf="!isExpired"> This image is protected until {{ expiresAt | cdDate }}. diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-list/rbd-trash-list.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-list/rbd-trash-list.component.spec.ts index 939f04e66f8f7..17d8eed0fb686 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-list/rbd-trash-list.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-list/rbd-trash-list.component.spec.ts @@ -6,6 +6,7 @@ import { RouterTestingModule } from '@angular/router/testing'; import { NgbNavModule } from '@ng-bootstrap/ng-bootstrap'; import moment from 'moment'; +import { NgxPipeFunctionModule } from 'ngx-pipe-function'; import { ToastrModule } from 'ngx-toastr'; import { of } from 'rxjs'; @@ -34,6 +35,7 @@ describe('RbdTrashListComponent', () => { RouterTestingModule, SharedModule, NgbNavModule, + NgxPipeFunctionModule, ToastrModule.forRoot() ], providers: [TaskListService] diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-list/rbd-trash-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-list/rbd-trash-list.component.ts index a0fafc192382f..43fe42b99fa38 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-list/rbd-trash-list.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-list/rbd-trash-list.component.ts @@ -201,13 +201,14 @@ export class RbdTrashListComponent implements OnInit { const namespace = this.selection.first().namespace; const imageId = this.selection.first().id; const expiresAt = this.selection.first().deferment_end_time; + const isExpired = moment().isAfter(expiresAt); const imageIdSpec = new ImageSpec(poolName, namespace, imageId); this.modalRef = this.modalService.show(CriticalConfirmationModalComponent, { itemDescription: 'RBD', itemNames: [imageIdSpec], bodyTemplate: this.deleteTpl, - bodyContext: { $implicit: expiresAt }, + bodyContext: { expiresAt, isExpired }, submitActionObservable: () => this.taskWrapper.wrapTaskAroundCall({ task: new FinishedTask('rbd/trash/remove', { @@ -218,10 +219,6 @@ export class RbdTrashListComponent implements OnInit { }); } - isExpired(expiresAt: string): boolean { - return moment().isAfter(expiresAt); - } - purgeModal() { this.modalService.show(RbdTrashPurgeModalComponent); } diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-directories/cephfs-directories.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-directories/cephfs-directories.component.spec.ts index f23ae749f5bd4..c8f6c22a14b9a 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-directories/cephfs-directories.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-directories/cephfs-directories.component.spec.ts @@ -936,7 +936,10 @@ describe('CephfsDirectoriesComponent', () => { }); it('should test all quota table actions permission combinations', () => { - const permissionHelper: PermissionHelper = new PermissionHelper(component.permission); + const permissionHelper: PermissionHelper = new PermissionHelper(component.permission, { + single: { dirValue: 0 }, + multiple: [{ dirValue: 0 }, {}] + }); const tableActions = permissionHelper.setPermissionsAndGetActions( component.quota.tableActions ); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/cluster.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/cluster.module.ts index 62464cadefe94..e52aa979081b4 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/cluster.module.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/cluster.module.ts @@ -13,6 +13,7 @@ import { NgbTooltipModule, NgbTypeaheadModule } from '@ng-bootstrap/ng-bootstrap'; +import { NgxPipeFunctionModule } from 'ngx-pipe-function'; import { SharedModule } from '~/app/shared/shared.module'; import { PerformanceCounterModule } from '../performance-counter/performance-counter.module'; @@ -70,7 +71,8 @@ import { TelemetryComponent } from './telemetry/telemetry.component'; CephSharedModule, NgbDatepickerModule, NgbPopoverModule, - NgbDropdownModule + NgbDropdownModule, + NgxPipeFunctionModule ], declarations: [ HostsComponent, diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.html index fe236902e9781..9f4f3e2152cf4 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.html @@ -54,8 +54,9 @@

- OSD(s) {{ getSelectedOsdIds() | join }} will be marked + let-markActionDescription="markActionDescription" + let-osdIds="osdIds"> + OSD(s) {{ osdIds | join }} will be marked {{ markActionDescription }} if you proceed. diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.spec.ts index 7d4c85e44f57b..d6f865471481b 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.spec.ts @@ -425,7 +425,7 @@ describe('OsdListComponent', () => { const tableActionElement = fixture.debugElement.query(By.directive(TableActionsComponent)); const toClassName = TestBed.inject(TableActionsComponent).toClassName; const getActionClasses = (action: CdTableAction) => - tableActionElement.query(By.css(`[ngbDropdownItem].${toClassName(action.name)}`)).classes; + tableActionElement.query(By.css(`[ngbDropdownItem].${toClassName(action)}`)).classes; component.tableActions.forEach((action) => { if (action.name === 'Create') { diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.ts index b03daa392df71..45dc840655ddd 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.ts @@ -373,7 +373,10 @@ export class OsdListComponent extends ListWithDetails implements OnInit { */ getSelectedOsdIds(): number[] { const osdIds = this.osds.map((osd) => osd.id); - return this.selection.selected.map((row) => row.id).filter((id) => osdIds.includes(id)); + return this.selection.selected + .map((row) => row.id) + .filter((id) => osdIds.includes(id)) + .sort(); } getSelectedOsds(): any[] { @@ -483,12 +486,14 @@ export class OsdListComponent extends ListWithDetails implements OnInit { } showConfirmationModal(markAction: string, onSubmit: (id: number) => Observable) { + const osdIds = this.getSelectedOsdIds(); this.bsModalRef = this.modalService.show(ConfirmationModalComponent, { titleText: $localize`Mark OSD ${markAction}`, buttonText: $localize`Mark ${markAction}`, bodyTpl: this.markOsdConfirmationTpl, bodyContext: { - markActionDescription: markAction + markActionDescription: markAction, + osdIds }, onSubmit: () => { observableForkJoin( diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-daemon-list/service-daemon-list.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-daemon-list/service-daemon-list.component.html index 078ac04d42ed0..f649726a3fe76 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-daemon-list/service-daemon-list.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-daemon-list/service-daemon-list.component.html @@ -11,7 +11,7 @@ + [ngClass]="row | pipeFunction:getStatusClass"> {{ row.status_desc }} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-daemon-list/service-daemon-list.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-daemon-list/service-daemon-list.component.spec.ts index 89b06b9791016..184e2e7ef6fa8 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-daemon-list/service-daemon-list.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-daemon-list/service-daemon-list.component.spec.ts @@ -2,6 +2,7 @@ import { HttpClientTestingModule } from '@angular/common/http/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import _ from 'lodash'; +import { NgxPipeFunctionModule } from 'ngx-pipe-function'; import { of } from 'rxjs'; import { CephModule } from '~/app/ceph/ceph.module'; @@ -77,7 +78,7 @@ describe('ServiceDaemonListComponent', () => { }; configureTestBed({ - imports: [HttpClientTestingModule, CephModule, CoreModule, SharedModule] + imports: [HttpClientTestingModule, CephModule, CoreModule, NgxPipeFunctionModule, SharedModule] }); beforeEach(() => { diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-daemon-list/service-daemon-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-daemon-list/service-daemon-list.component.ts index 5a7b223bc8748..95795f6228512 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-daemon-list/service-daemon-list.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-daemon-list/service-daemon-list.component.ts @@ -149,14 +149,14 @@ export class ServiceDaemonListComponent implements OnInit, OnChanges, AfterViewI } } - getStatusClass(status: number) { + getStatusClass(row: Daemon): string { return _.get( { '-1': 'badge-danger', '0': 'badge-warning', '1': 'badge-success' }, - status, + row.status, 'badge-dark' ); } diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-details/service-details.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-details/service-details.component.spec.ts index 23bb679414b15..6be3b2689526f 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-details/service-details.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-details/service-details.component.spec.ts @@ -3,6 +3,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; import { NgbNavModule } from '@ng-bootstrap/ng-bootstrap'; +import { NgxPipeFunctionModule } from 'ngx-pipe-function'; import { CdTableSelection } from '~/app/shared/models/cd-table-selection'; import { SummaryService } from '~/app/shared/services/summary.service'; @@ -16,7 +17,13 @@ describe('ServiceDetailsComponent', () => { let fixture: ComponentFixture; configureTestBed({ - imports: [HttpClientTestingModule, RouterTestingModule, SharedModule, NgbNavModule], + imports: [ + HttpClientTestingModule, + RouterTestingModule, + SharedModule, + NgbNavModule, + NgxPipeFunctionModule + ], declarations: [ServiceDetailsComponent, ServiceDaemonListComponent], providers: [{ provide: SummaryService, useValue: { subscribeOnce: jest.fn() } }] }); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.ts index bf4c206e2f4e1..c1b6ae5db835d 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.ts @@ -484,7 +484,7 @@ export class PoolFormComponent extends CdForm implements OnInit { return (ecpControl.valid || ecpControl.disabled) && ecp ? pgs / (ecp.k + ecp.m) : 0; } - private alignPgs(pgs = this.form.getValue('pgNum')) { + alignPgs(pgs = this.form.getValue('pgNum')) { this.setPgs(Math.round(this.calculatePgPower(pgs < 1 ? 1 : pgs))); } diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-form/rgw-user-form.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-form/rgw-user-form.component.html index 164f6c2b3e8f9..acd6c02fd60a0 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-form/rgw-user-form.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-form/rgw-user-form.component.html @@ -414,10 +414,10 @@