Skip to content

Commit

Permalink
mgr/dashboard: Cluster Creation Workflow followups
Browse files Browse the repository at this point in the history
1. Fix bug in the modal where going forward one step on the wizard and coming back opens up the add host modal.
2. Rename Create Cluster to Expand Cluster as per the discussions
3. A skip confirmation modal to warn the user when he tries to skip the
   cluster creation
4. Adapted all the tests
5. Did some UI improvements like fixing and aligning the styles,
   colors..

Fixes: https://tracker.ceph.com/issues/51640
Signed-off-by: Nizamudeen A <nia@redhat.com>
  • Loading branch information
nizamial09 committed Jul 15, 2021
1 parent 5f8e0ba commit 4b86c90
Show file tree
Hide file tree
Showing 20 changed files with 141 additions and 86 deletions.
1 change: 1 addition & 0 deletions qa/suites/rados/dashboard/tasks/dashboard.yaml
Expand Up @@ -39,6 +39,7 @@ tasks:
- tasks.mgr.dashboard.test_auth
- tasks.mgr.dashboard.test_cephfs
- tasks.mgr.dashboard.test_cluster_configuration
- tasks.mgr.dashboard.test_cluster
- tasks.mgr.dashboard.test_crush_rule
- tasks.mgr.dashboard.test_erasure_code_profile
- tasks.mgr.dashboard.test_ganesha
Expand Down
2 changes: 1 addition & 1 deletion src/pybind/mgr/dashboard/controllers/host.py
Expand Up @@ -284,7 +284,7 @@ def list(self, sources=None):

@raise_if_no_orchestrator([OrchFeature.HOST_LIST, OrchFeature.HOST_CREATE])
@handle_orchestrator_error('host')
@host_task('create', {'hostname': '{hostname}'})
@host_task('add', {'hostname': '{hostname}'})
@EndpointDoc('',
parameters={
'hostname': (str, 'Hostname'),
Expand Down
Expand Up @@ -3,20 +3,21 @@ import { NotificationSidebarPageHelper } from '../ui/notification.po';

export class CreateClusterWelcomePageHelper extends PageHelper {
pages = {
index: { url: '#/create-cluster', id: 'cd-create-cluster' }
index: { url: '#/expand-cluster', id: 'cd-create-cluster' }
};

createCluster() {
cy.get('cd-create-cluster').should('contain.text', 'Welcome to Ceph');
cy.get('[name=create-cluster]').click();
cy.get('cd-create-cluster').should('contain.text', 'Please expand your cluster first');
cy.get('[name=expand-cluster]').click();
}

doSkip() {
cy.get('[name=skip-cluster-creation]').click();
cy.contains('cd-modal button', 'Continue').click();

cy.get('cd-dashboard').should('exist');
const notification = new NotificationSidebarPageHelper();
notification.open();
notification.getNotifications().should('contain', 'Cluster creation skipped by user');
notification.getNotifications().should('contain', 'Cluster expansion skipped by user');
}
}
Expand Up @@ -2,7 +2,7 @@ import { PageHelper } from '../page-helper.po';

export class CreateClusterReviewPageHelper extends PageHelper {
pages = {
index: { url: '#/create-cluster', id: 'cd-create-cluster-review' }
index: { url: '#/expand-cluster', id: 'cd-create-cluster-review' }
};

checkDefaultHostName() {
Expand Down
11 changes: 2 additions & 9 deletions src/pybind/mgr/dashboard/frontend/src/app/app-routing.module.ts
Expand Up @@ -91,23 +91,16 @@ const routes: Routes = [

// Cluster
{
path: 'create-cluster',
path: 'expand-cluster',
component: CreateClusterComponent,
canActivate: [ModuleStatusGuardService],
children: [
{
path: URLVerbs.ADD,
component: HostFormComponent,
outlet: 'modal'
}
],
data: {
moduleStatusGuardConfig: {
apiPath: 'orchestrator',
redirectTo: 'dashboard',
backend: 'cephadm'
},
breadcrumbs: 'Create Cluster'
breadcrumbs: 'Expand Cluster'
}
},
{
Expand Down
Expand Up @@ -5,6 +5,7 @@ import { RouterModule } from '@angular/router';

import { TreeModule } from '@circlon/angular-tree-component';
import {
NgbActiveModal,
NgbDatepickerModule,
NgbDropdownModule,
NgbNavModule,
Expand Down Expand Up @@ -114,6 +115,7 @@ import { TelemetryComponent } from './telemetry/telemetry.component';
OsdFlagsIndivModalComponent,
PlacementPipe,
CreateClusterComponent
]
],
providers: [NgbActiveModal]
})
export class ClusterModule {}
Expand Up @@ -11,12 +11,12 @@

<div class="m-4">
<h4 class="text-center"
i18n>Please proceed to complete the cluster creation</h4>
<div class="offset-md-3">
<button class="btn btn-accent m-3"
name="create-cluster"
i18n>Please expand your cluster first</h4>
<div class="offset-md-2">
<button class="btn btn-accent m-2"
name="expand-cluster"
(click)="createCluster()"
i18n>Create Cluster</button>
i18n>Expand Cluster</button>
<button class="btn btn-light"
name="skip-cluster-creation"
(click)="skipClusterCreation()"
Expand All @@ -30,7 +30,7 @@
<div class="card"
*ngIf="startClusterCreation">
<div class="card-header"
i18n>Create Cluster</div>
i18n>Expand Cluster</div>
<div class="container-fluid">
<cd-wizard [stepsTitle]="stepTitles"></cd-wizard>
<div class="card-body vertical-line">
Expand Down Expand Up @@ -63,3 +63,11 @@
[name]="showCancelButtonLabel()"></cd-back-button>
</div>
</div>

<ng-template #skipConfirmTpl>
<span i18n>You are about to skip the cluster expansion process.
You’ll need to <strong>navigate through the menu to add hosts and services</strong></span>
<br>
<br>
<ng-container i18n>Are you sure you want to continue?</ng-container>
</ng-template>
Expand Up @@ -3,17 +3,22 @@
.container-fluid {
align-items: flex-start;
display: flex;
padding-left: 0;
width: 100%;
}

.card-body {
max-width: 90%;
max-width: 85%;
}

.vertical-line {
border-left: 1px solid vv.$gray-400;
}

cd-wizard {
width: 15%;
}

cd-hosts {
::ng-deep .nav {
display: none;
Expand Down
Expand Up @@ -7,8 +7,10 @@ import { ToastrModule } from 'ngx-toastr';

import { CephModule } from '~/app/ceph/ceph.module';
import { CoreModule } from '~/app/core/core.module';
import { ClusterService } from '~/app/shared/api/cluster.service';
import { HostService } from '~/app/shared/api/host.service';
import { ConfirmationModalComponent } from '~/app/shared/components/confirmation-modal/confirmation-modal.component';
import { AppConstants } from '~/app/shared/constants/app.constants';
import { ModalService } from '~/app/shared/services/modal.service';
import { WizardStepsService } from '~/app/shared/services/wizard-steps.service';
import { SharedModule } from '~/app/shared/shared.module';
import { configureTestBed } from '~/testing/unit-test-helper';
Expand All @@ -17,9 +19,10 @@ import { CreateClusterComponent } from './create-cluster.component';
describe('CreateClusterComponent', () => {
let component: CreateClusterComponent;
let fixture: ComponentFixture<CreateClusterComponent>;
let clusterService: ClusterService;
let wizardStepService: WizardStepsService;
let hostService: HostService;
let modalServiceShowSpy: jasmine.Spy;
const projectConstants: typeof AppConstants = AppConstants;

configureTestBed({
imports: [
Expand All @@ -35,26 +38,28 @@ describe('CreateClusterComponent', () => {
beforeEach(() => {
fixture = TestBed.createComponent(CreateClusterComponent);
component = fixture.componentInstance;
clusterService = TestBed.inject(ClusterService);
wizardStepService = TestBed.inject(WizardStepsService);
hostService = TestBed.inject(HostService);
modalServiceShowSpy = spyOn(TestBed.inject(ModalService), 'show').and.returnValue({
// mock the close function, it might be called if there are async tests.
close: jest.fn()
});
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});

it('should have the heading "Welcome to Ceph Dashboard"', () => {
it('should have project name as heading in welcome screen', () => {
const heading = fixture.debugElement.query(By.css('h3')).nativeElement;
expect(heading.innerHTML).toBe('Welcome to Ceph Dashboard');
expect(heading.innerHTML).toBe(`Welcome to ${projectConstants.projectName}`);
});

it('should call updateStatus when cluster creation is skipped', () => {
const clusterServiceSpy = spyOn(clusterService, 'updateStatus').and.callThrough();
expect(clusterServiceSpy).not.toHaveBeenCalled();
it('should show confirmation modal when cluster creation is skipped', () => {
component.skipClusterCreation();
expect(clusterServiceSpy).toHaveBeenCalledTimes(1);
expect(modalServiceShowSpy.calls.any()).toBeTruthy();
expect(modalServiceShowSpy.calls.first().args[0]).toBe(ConfirmationModalComponent);
});

it('should show the wizard when cluster creation is started', () => {
Expand Down Expand Up @@ -103,7 +108,7 @@ describe('CreateClusterComponent', () => {
component.onNextStep();
fixture.detectChanges();
submitBtnLabel = component.showSubmitButtonLabel();
expect(submitBtnLabel).toEqual('Create Cluster');
expect(submitBtnLabel).toEqual('Expand Cluster');
cancelBtnLabel = component.showCancelButtonLabel();
expect(cancelBtnLabel).toEqual('Back');
});
Expand Down
@@ -1,16 +1,19 @@
import { Component, OnDestroy } from '@angular/core';
import { Component, OnDestroy, TemplateRef, ViewChild } from '@angular/core';
import { Router } from '@angular/router';

import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
import { forkJoin, Subscription } from 'rxjs';
import { finalize } from 'rxjs/operators';

import { ClusterService } from '~/app/shared/api/cluster.service';
import { HostService } from '~/app/shared/api/host.service';
import { ConfirmationModalComponent } from '~/app/shared/components/confirmation-modal/confirmation-modal.component';
import { ActionLabelsI18n, AppConstants } from '~/app/shared/constants/app.constants';
import { NotificationType } from '~/app/shared/enum/notification-type.enum';
import { Permissions } from '~/app/shared/models/permissions';
import { WizardStepModel } from '~/app/shared/models/wizard-steps';
import { AuthStorageService } from '~/app/shared/services/auth-storage.service';
import { ModalService } from '~/app/shared/services/modal.service';
import { NotificationService } from '~/app/shared/services/notification.service';
import { WizardStepsService } from '~/app/shared/services/wizard-steps.service';

Expand All @@ -20,14 +23,16 @@ import { WizardStepsService } from '~/app/shared/services/wizard-steps.service';
styleUrls: ['./create-cluster.component.scss']
})
export class CreateClusterComponent implements OnDestroy {
@ViewChild('skipConfirmTpl', { static: true })
skipConfirmTpl: TemplateRef<any>;
currentStep: WizardStepModel;
currentStepSub: Subscription;
permissions: Permissions;
projectConstants: typeof AppConstants = AppConstants;
hosts: Array<object> = [];
stepTitles = ['Add Hosts', 'Review'];
startClusterCreation = false;
observables: any = [];
modalRef: NgbModalRef;

constructor(
private authStorageService: AuthStorageService,
Expand All @@ -36,7 +41,8 @@ export class CreateClusterComponent implements OnDestroy {
private hostService: HostService,
private notificationService: NotificationService,
private actionLabels: ActionLabelsI18n,
private clusterService: ClusterService
private clusterService: ClusterService,
private modalService: ModalService
) {
this.permissions = this.authStorageService.getPermissions();
this.currentStepSub = this.stepsService.getCurrentStep().subscribe((step: WizardStepModel) => {
Expand All @@ -50,13 +56,27 @@ export class CreateClusterComponent implements OnDestroy {
}

skipClusterCreation() {
this.clusterService.updateStatus('POST_INSTALLED').subscribe(() => {
this.notificationService.show(
NotificationType.info,
$localize`Cluster creation skipped by user`
);
this.router.navigate(['/dashboard']);
});
const modalVarialbes = {
titleText: $localize`Warning`,
buttonText: $localize`Continue`,
warning: true,
bodyTpl: this.skipConfirmTpl,
showSubmit: true,
onSubmit: () => {
this.clusterService.updateStatus('POST_INSTALLED').subscribe({
error: () => this.modalRef.close(),
complete: () => {
this.notificationService.show(
NotificationType.info,
$localize`Cluster expansion skipped by user`
);
this.router.navigate(['/dashboard']);
this.modalRef.close();
}
});
}
};
this.modalRef = this.modalService.show(ConfirmationModalComponent, modalVarialbes);
}

onSubmit() {
Expand All @@ -66,7 +86,7 @@ export class CreateClusterComponent implements OnDestroy {
this.clusterService.updateStatus('POST_INSTALLED').subscribe(() => {
this.notificationService.show(
NotificationType.success,
$localize`Cluster creation was successful`
$localize`Cluster expansion was successful`
);
this.router.navigate(['/dashboard']);
})
Expand Down Expand Up @@ -101,7 +121,7 @@ export class CreateClusterComponent implements OnDestroy {
}

showSubmitButtonLabel() {
return !this.stepsService.isLastStep() ? this.actionLabels.NEXT : $localize`Create Cluster`;
return !this.stepsService.isLastStep() ? this.actionLabels.NEXT : $localize`Expand Cluster`;
}

showCancelButtonLabel() {
Expand Down
@@ -1,4 +1,5 @@
<cd-modal [pageURL]="pageURL">
<cd-modal [pageURL]="pageURL"
[modalRef]="activeModal">
<span class="modal-title"
i18n>{{ action | titlecase }} {{ resource | upperFirst }}</span>

Expand Down
Expand Up @@ -3,6 +3,7 @@ import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testin
import { ReactiveFormsModule } from '@angular/forms';
import { RouterTestingModule } from '@angular/router/testing';

import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
import { ToastrModule } from 'ngx-toastr';

import { LoadingPanelComponent } from '~/app/shared/components/loading-panel/loading-panel.component';
Expand All @@ -24,7 +25,8 @@ describe('HostFormComponent', () => {
ReactiveFormsModule,
ToastrModule.forRoot()
],
declarations: [HostFormComponent]
declarations: [HostFormComponent],
providers: [NgbActiveModal]
},
[LoadingPanelComponent]
);
Expand Down

0 comments on commit 4b86c90

Please sign in to comment.