Skip to content
This repository has been archived by the owner on Mar 25, 2023. It is now read-only.

Commit

Permalink
feat(sidebar): Show 'Entity not found' message if id in query params …
Browse files Browse the repository at this point in the history
…is invalid

Fixes #374
  • Loading branch information
wowshakhov authored Aug 28, 2017
1 parent 1aa83f5 commit 324eed6
Show file tree
Hide file tree
Showing 24 changed files with 322 additions and 242 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<div class="no-results">
{{ 'COMMON.NO_RESULTS' | translate }}
{{ text | translate }}
</div>
7 changes: 5 additions & 2 deletions src/app/shared/components/no-results/no-results.component.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { Component } from '@angular/core';
import { Component, Input } from '@angular/core';


@Component({
selector: 'cs-no-results',
templateUrl: 'no-results.component.html',
styleUrls: ['no-results.component.scss']
})
export class NoResultsComponent {}
export class NoResultsComponent {
@Input() public text = 'COMMON.NO_RESULTS';
}
2 changes: 1 addition & 1 deletion src/app/shared/components/sidebar/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export * from './sidebar.component';
export * from './sidebar-container/sidebar-container.component';
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@import '../../../../style/__variables';
@import '../../../../../style/_variables';

.sidebar {
height: 100%;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Component, HostBinding, Input, } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';


@Component({
selector: 'cs-sidebar',
templateUrl: 'sidebar-container.component.html',
styleUrls: ['sidebar-container.component.scss']
})
export class SidebarContainerComponent {
@Input() @HostBinding('class.open') public isOpen;

constructor(
private route: ActivatedRoute,
private router: Router
) {}

public onDetailsHide(): void {
this.router.navigate([this.route.parent.snapshot.url], {
queryParamsHandling: 'preserve'
});
}
}
68 changes: 40 additions & 28 deletions src/app/shared/components/sidebar/sidebar.component.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,50 @@
import {
Component, Input
} from '@angular/core';
import { DialogService } from '../../../dialog/dialog-module/dialog.service';
import { OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import { BaseModel } from '../../models/base.model';
import { BaseBackendService } from '../../services/base-backend.service';
import { NotificationService } from '../../services/notification.service';


@Component({
selector: 'cs-sidebar',
templateUrl: 'sidebar.component.html',
styleUrls: ['sidebar.component.scss']
})
export class SidebarComponent {
@Input() public isOpen = false;

private dialogsOpen: boolean; // true if any mdl dialog is open
private dialogWasOpen: boolean; // true if last dialog was closed
export abstract class SidebarComponent<M extends BaseModel> implements OnInit {
public entity: M;
public notFound: boolean;

constructor(
private router: Router,
private route: ActivatedRoute,
private dialogService: DialogService
) {
this.dialogService.onDialogsOpenChanged
.subscribe(dialogsOpen => {
this.dialogsOpen = dialogsOpen;
if (dialogsOpen) {
this.dialogWasOpen = true;
protected entityService: BaseBackendService<M>,
protected notificationService: NotificationService,
protected route: ActivatedRoute,
protected router: Router
) {}

public ngOnInit(): void {
this.pluckId()
.switchMap(id => this.loadEntity(id))
.subscribe(
entity => this.entity = entity,
error => {
if (error === 'ENTITY_DOES_NOT_EXIST') {
this.onEntityDoesNotExist();
} else {
this.onError(error);
}
}
});
);
}

private pluckId(): Observable<string> {
return this.route.params.pluck('id').filter(id => !!id) as Observable<string>;
}

protected loadEntity(id: string): Observable<M> {
return this.entityService.get(id);
}

private onEntityDoesNotExist(): void {
this.notFound = true;
}

public onDetailsHide(): void {
this.router.navigate([this.route.parent.snapshot.url], {
queryParamsHandling: 'preserve'
});
private onError(error: any): void {
this.notificationService.error(error.message);
}
}
3 changes: 2 additions & 1 deletion src/app/shared/models/volume.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,10 @@ export class Volume extends BaseModel {
public tags: Array<Tag>;
public type: VolumeType;
public zoneId: string;

public zoneName: string;

public description: string;

constructor(json) {
super(json);
this.created = moment(json.created).toDate();
Expand Down
4 changes: 2 additions & 2 deletions src/app/shared/services/base-backend.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ export abstract class BaseBackendService<M extends BaseModel> {
throw Error('BaseBackendService.get id not specified!');
}

return this.getList({ id })
.map(res => res[0] as M);
return this.getList()
.map(res => res.find(entity => entity.id === id));
}

public getList(params?: {}, customApiFormat?: ApiFormat): Observable<Array<M>> {
Expand Down
28 changes: 8 additions & 20 deletions src/app/shared/services/volume.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,34 +44,22 @@ export class VolumeService extends BaseBackendService<Volume> {
this.onVolumeAttached = new Subject<Volume>();
}

public get(id: string): Observable<Volume> {
const snapshotsRequest = this.snapshotService.getList(id);
const volumeRequest = super.get(id);

return Observable.forkJoin(
volumeRequest,
snapshotsRequest
).map(([volume, snapshots]) => {
volume.snapshots = snapshots;
return volume;
});
}

public getList(params?: {}): Observable<Array<Volume>> {
const volumesRequest = super.getList(params);
const snapshotsRequest = this.snapshotService.getList();

return Observable.forkJoin(
volumesRequest,
snapshotsRequest
).map(([volumes, snapshots]) => {
volumes.forEach(volume => {
volume.snapshots = snapshots.filter(
(snapshot: Snapshot) => snapshot.volumeId === volume.id
);
)
.map(([volumes, snapshots]) => {
volumes.forEach(volume => {
volume.snapshots = snapshots.filter(
(snapshot: Snapshot) => snapshot.volumeId === volume.id
);
});
return volumes;
});
return volumes;
});
}

public getSpareList(params?: {}): Observable<Array<Volume>> {
Expand Down
6 changes: 3 additions & 3 deletions src/app/shared/shared.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import {
NotificationBoxComponent,
NotificationBoxItemComponent,
SgRulesManagerComponent,
SidebarComponent,
SidebarContainerComponent,
SliderComponent,
TopBarComponent,
VmStatisticsComponent
Expand Down Expand Up @@ -154,7 +154,7 @@ import { ZoneService } from './services/zone.service';
OverlayLoadingComponent,
SearchComponent,
SgRulesManagerComponent,
SidebarComponent,
SidebarContainerComponent,
TableComponent,
TopBarComponent,
VmStatisticsComponent,
Expand Down Expand Up @@ -206,7 +206,7 @@ import { ZoneService } from './services/zone.service';
ReloadComponent,
SearchComponent,
SgRulesManagerComponent,
SidebarComponent,
SidebarContainerComponent,
TableComponent,
TopBarComponent,
VmStatisticsComponent,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<div *ngIf="volume">
<cs-spare-drive-sidebar-volume [volume]="volume"></cs-spare-drive-sidebar-volume>
<div *ngIf="entity">
<cs-spare-drive-sidebar-volume [volume]="entity"></cs-spare-drive-sidebar-volume>

<cs-description
[description]="description"
[description]="entity.description"
(descriptionChange)="changeDescription($event)"
></cs-description>

<md-card *ngIf="volume.diskOffering">
<md-card *ngIf="entity.diskOffering">
<md-card-header>
<md-card-title>
<h2 class="md-card-title-text">
Expand All @@ -16,39 +16,44 @@ <h2 class="md-card-title-text">
</md-card-header>
<md-card-content>
<div class="grid grid-right">
<div class="row" *ngIf="volume.diskOffering.name">
<div class="row" *ngIf="entity.diskOffering.name">
<div>{{ 'SPARE_DRIVE_PAGE.DETAILS.DISK_OFFERING_NAME' | translate }}</div>
<div>{{ volume.diskOffering.name }}</div>
<div>{{ entity.diskOffering.name }}</div>
</div>
<div class="row" *ngIf="volume.diskOffering.displayText">
<div class="row" *ngIf="entity.diskOffering.displayText">
<div>{{ 'SPARE_DRIVE_PAGE.DETAILS.DESCRIPTION' | translate }}</div>
<div>{{ volume.diskOffering.displayText }}</div>
<div>{{ entity.diskOffering.displayText }}</div>
</div>
<div class="row" *ngIf="volume.diskOffering.minIops">
<div class="row" *ngIf="entity.diskOffering.minIops">
<div>{{ 'SPARE_DRIVE_PAGE.DETAILS.MIN_IO' | translate }}</div>
<div>{{ volume.diskOffering.minIops }}</div>
<div>{{ entity.diskOffering.minIops }}</div>
</div>
<div class="row" *ngIf="volume.diskOffering.maxIops">
<div class="row" *ngIf="entity.diskOffering.maxIops">
<div>{{ 'SPARE_DRIVE_PAGE.DETAILS.MAX_IO' | translate }}</div>
<div>{{ volume.diskOffering.maxIops }}</div>
<div>{{ entity.diskOffering.maxIops }}</div>
</div>
<div class="row" *ngIf="volume.diskOffering.diskBytesReadRate">
<div class="row" *ngIf="entity.diskOffering.diskBytesReadRate">
<div>{{ 'SPARE_DRIVE_PAGE.DETAILS.READ_RATE_MB' | translate }}</div>
<div>{{ 'UNITS.MBPS' | translate:{ value: volume.diskOffering.diskBytesReadRate | division:10:6 } }}</div>
<div>{{ 'UNITS.MBPS' | translate:{ value: entity.diskOffering.diskBytesReadRate | division:10:6 } }}</div>
</div>
<div class="row" *ngIf="volume.diskOffering.diskBytesWriteRate">
<div class="row" *ngIf="entity.diskOffering.diskBytesWriteRate">
<div>{{ 'SPARE_DRIVE_PAGE.DETAILS.WRITE_RATE_MB' | translate }}</div>
<div>{{ 'UNITS.MBPS' | translate:{ value: volume.diskOffering.diskBytesWriteRate | division:10:6 } }}</div>
<div>{{ 'UNITS.MBPS' | translate:{ value: entity.diskOffering.diskBytesWriteRate | division:10:6 } }}</div>
</div>
<div class="row" *ngIf="volume.diskOffering.diskIopsReadRate">
<div class="row" *ngIf="entity.diskOffering.diskIopsReadRate">
<div>{{ 'SPARE_DRIVE_PAGE.DETAILS.READ_RATE_IOPS' | translate }}</div>
<div>{{ 'UNITS.IOPS' | translate:{ value: volume.diskOffering.diskIopsReadRate } }}</div>
<div>{{ 'UNITS.IOPS' | translate:{ value: entity.diskOffering.diskIopsReadRate } }}</div>
</div>
<div class="row" *ngIf="volume.diskOffering.diskIopsWriteRate">
<div class="row" *ngIf="entity.diskOffering.diskIopsWriteRate">
<div>{{ 'SPARE_DRIVE_PAGE.DETAILS.WRITE_RATE_IOPS' | translate }}</div>
<div>{{ 'UNITS.IOPS' | translate:{ value: volume.diskOffering.diskIopsWriteRate } }}</div>
<div>{{ 'UNITS.IOPS' | translate:{ value: entity.diskOffering.diskIopsWriteRate } }}</div>
</div>
</div>
</md-card-content>
</md-card>
</div>

<cs-no-results *ngIf="notFound" [text]="'VOLUME_NOT_FOUND'"></cs-no-results>

<cs-overlay-loading [active]="!entity && !notFound"></cs-overlay-loading>

Original file line number Diff line number Diff line change
@@ -1,57 +1,61 @@
import { Component, HostBinding, Input } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Component, HostBinding } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import { SidebarComponent } from '../../shared/components/sidebar/sidebar.component';
import { Volume } from '../../shared/models';
import { VolumeType } from '../../shared/models/volume.model';
import { DateTimeFormatterService } from '../../shared/services/date-time-formatter.service';
import { DiskOfferingService } from '../../shared/services/disk-offering.service';
import { VolumeTagService } from '../../shared/services/tags/volume-tag.service';
import { NotificationService } from '../../shared/services/notification.service';
import { VolumeService } from '../../shared/services/volume.service';
import { VolumeTagService } from '../../shared/services/tags/volume-tag.service';


@Component({
selector: 'cs-spare-drive-sidebar',
templateUrl: 'spare-drive-sidebar.component.html'
})
export class SpareDriveSidebarComponent {
public description: string;

@Input() public volume: Volume;
export class SpareDriveSidebarComponent extends SidebarComponent<Volume> {
@HostBinding('class.grid') public grid = true;

constructor(
public dateTimeFormatterService: DateTimeFormatterService,
private diskOfferingService: DiskOfferingService,
private route: ActivatedRoute,
private volumeService: VolumeService,
private volumeTagService: VolumeTagService,
protected notificationService: NotificationService,
protected route: ActivatedRoute,
protected router: Router,
protected volumeService: VolumeService,
protected volumeTagService: VolumeTagService,
private diskOfferingService: DiskOfferingService
) {
this.route.params.pluck('id')
.subscribe((id: string) => {
if (!id) {
return;
}

Observable.forkJoin(
this.diskOfferingService.getList({ type: VolumeType.DATADISK }),
this.volumeService.get(id)
)
.subscribe(([diskOfferings, volume]) => {
this.volumeTagService.getDescription(volume)
.subscribe(description => {
volume.diskOffering = diskOfferings.find(
offering => offering.id === volume.diskOfferingId
);
this.volume = volume;
this.description = description;
});
});
});
super(volumeService, notificationService, route, router);
}

public changeDescription(newDescription: string): void {
this.volumeTagService.setDescription(this.volume, newDescription)
this.volumeTagService.setDescription(this.entity, newDescription)
.onErrorResumeNext()
.subscribe();
}

protected loadEntity(id: string): Observable<Volume> {
return this.volumeService.get(id)
.switchMap(volume => {
if (volume) {
return Observable.of(volume);
} else {
return Observable.throw('ENTITY_DOES_NOT_EXIST');
}
})
.switchMap(volume => {
return Observable.forkJoin(
Observable.of(volume),
this.diskOfferingService.getList({ type: VolumeType.DATADISK }),
this.volumeTagService.getDescription(volume)
);
})
.map(([volume, diskOfferings, description]) => {
volume.diskOffering = diskOfferings.find(_ => _.id === volume.diskOfferingId);
volume.description = description;
return volume;
});
}
}
Loading

0 comments on commit 324eed6

Please sign in to comment.