Skip to content

Commit

Permalink
Feature: VM Sizes picker show basic input when unable to get vm sizes…
Browse files Browse the repository at this point in the history
…(Local account) (#1811)
  • Loading branch information
timotheeguerin authored Dec 3, 2018
1 parent ecb91ab commit ce53342
Show file tree
Hide file tree
Showing 13 changed files with 422 additions and 323 deletions.
6 changes: 0 additions & 6 deletions src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
AutoscaleFormulaService,
BatchAccountService,
CommandService,
GithubDataService,
NavigatorService,
NcjTemplateService,
PoolOsService,
Expand All @@ -24,7 +23,6 @@ import {
SettingsService,
SubscriptionService,
ThemeService,
VmSizeService,
} from "app/services";
import { filter, first, takeUntil } from "rxjs/operators";

Expand All @@ -50,12 +48,10 @@ export class AppComponent implements OnInit, OnDestroy {
private accountService: BatchAccountService,
private navigatorService: NavigatorService,
private subscriptionService: SubscriptionService,
private githubDataService: GithubDataService,
private poolOsService: PoolOsService,
private sshKeyService: SSHKeyService,
remote: ElectronRemote,
pythonRpcService: PythonRpcService,
private vmSizeService: VmSizeService,
themeService: ThemeService,
private route: ActivatedRoute,
permissionService: PermissionService,
Expand All @@ -71,12 +67,10 @@ export class AppComponent implements OnInit, OnDestroy {
this.autoscaleFormulaService.init();
this.settingsService.init();
this._initWorkspaces();
this.githubDataService.init();
this.sshKeyService.init();
this.commandService.init();
this.pricingService.init();
this.navigatorService.init();
this.vmSizeService.init();
this.accountService.loadInitialData();
this.ncjTemplateService.init();
pythonRpcService.init();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
import { Component, DebugElement, NO_ERRORS_SCHEMA } from "@angular/core";
import { ComponentFixture, TestBed } from "@angular/core/testing";
import { FormsModule } from "@angular/forms";
import { By } from "@angular/platform-browser";
import { FormsModule, ReactiveFormsModule } from "@angular/forms";
import { BrowserModule, By } from "@angular/platform-browser";
import { NoopAnimationsModule } from "@angular/platform-browser/animations";
import { List } from "immutable";

import { RouterTestingModule } from "@angular/router/testing";
import { ElectronModule } from "@batch-flask/ui";
import { ElectronModule, FormModule } from "@batch-flask/ui";
import { BreadcrumbService } from "@batch-flask/ui/breadcrumbs";
import { TableTestingModule } from "@batch-flask/ui/testing";
import { VmSizePickerComponent } from "app/components/pool/action/add";
import { ArmBatchAccount, VmSize } from "app/models";
import { PoolOsSources } from "app/models/forms";
import { BatchAccountService, PricingService, VmSizeService } from "app/services";
import { OSPricing } from "app/services/pricing";
import { of } from "rxjs";
import { BehaviorSubject, of } from "rxjs";
import { updateInput } from "test/utils/helpers";

@Component({
template: `<bl-vm-size-picker [(ngModel)]="vmSize" [osSource]="osSource"></bl-vm-size-picker>`,
Expand Down Expand Up @@ -57,7 +58,7 @@ describe("VmSizePickerComponent", () => {
"^standard_m",
],
}),
virtualMachineSizes: of(List([
virtualMachineSizes: new BehaviorSubject(List([
new VmSize({ name: "Standard_A1" } as any),
new VmSize({ name: "Standard_A2" } as any),
new VmSize({ name: "Standard_A3" } as any),
Expand All @@ -72,7 +73,7 @@ describe("VmSizePickerComponent", () => {
new VmSize({ name: "Standard_C2" } as any),
new VmSize({ name: "Standard_O1" } as any),
])),
cloudServiceSizes: of(List([
cloudServiceSizes: new BehaviorSubject(List([
new VmSize({ name: "Standard_A1" } as any),
new VmSize({ name: "Standard_A2" } as any),
new VmSize({ name: "Standard_A3" } as any),
Expand All @@ -85,7 +86,10 @@ describe("VmSizePickerComponent", () => {
};

TestBed.configureTestingModule({
imports: [FormsModule, TableTestingModule, NoopAnimationsModule, ElectronModule, RouterTestingModule],
imports: [
BrowserModule, FormsModule, ReactiveFormsModule, TableTestingModule,
NoopAnimationsModule, ElectronModule, RouterTestingModule, FormModule,
],
declarations: [VmSizePickerComponent, TestComponent],
providers: [
{ provide: BatchAccountService, useValue: accountServiceSpy },
Expand Down Expand Up @@ -152,4 +156,23 @@ describe("VmSizePickerComponent", () => {
const searchResult = de.queryAll(By.css("bl-table bl-row-render")).map(t => t.nativeElement.textContent);
expect(searchResult.length).toEqual(13);
});

describe("when it fails to load the vm sizes", () => {
let plainInputEl: DebugElement;

beforeEach(() => {
vmSizeServiceSpy.virtualMachineSizes.next(null);
fixture.detectChanges();
plainInputEl = de.query(By.css(".no-vm-sizes-basic-input input"));
});

it("shows a plain input when its unable to load the vm sizes", () => {
expect(plainInputEl).not.toBeFalsy();
});

it("propagate the changes when updating the input", () => {
updateInput(plainInputEl, "Standard_D4_V2");
expect(testComponent.vmSize).toEqual("Standard_D4_V2");
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ import { PoolOsSources } from "app/models/forms";
import { PricingService, VmSizeService } from "app/services";
import { OSPricing } from "app/services/pricing";
import { List } from "immutable";
import { Subscription } from "rxjs";
import { Subject, Subscription } from "rxjs";

import { TableConfig } from "@batch-flask/ui/table";
import { distinctUntilChanged, takeUntil } from "rxjs/operators";
import { VmSizeFilterValue } from "./vm-size-picker-filter.component";
import "./vm-size-picker.scss";

Expand Down Expand Up @@ -69,6 +70,8 @@ export class VmSizeDecorator {
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class VmSizePickerComponent implements ControlValueAccessor, OnInit, OnChanges, OnDestroy {
public LoadingStatus = LoadingStatus;

@Input() public osSource: PoolOsSources;

@Input() public osType: "linux" | "windows";
Expand All @@ -79,6 +82,7 @@ export class VmSizePickerComponent implements ControlValueAccessor, OnInit, OnCh
public filteredCategories: VmSizeDecorator[];
public prices: OSPricing = null;
public categoriesDisplayName = categoriesDisplayName;
public basicInput = new FormControl();

public tableConfig: TableConfig = {
sorting: {
Expand All @@ -94,17 +98,28 @@ export class VmSizePickerComponent implements ControlValueAccessor, OnInit, OnCh
private _categoryRegex: StringMap<string[]>;
private _vmSizes: List<VmSize> = List([]);
private _sizeSub: Subscription;
private _categorySub: Subscription;
private _destroy = new Subject();
private _currentFilter: VmSizeFilterValue = { category: "all" };

constructor(
public vmSizeService: VmSizeService,
private changeDetector: ChangeDetectorRef,
private pricingService: PricingService) {

this.basicInput.valueChanges.pipe(
takeUntil(this._destroy),
distinctUntilChanged(),
).subscribe((value) => {
if (this._propagateChange) {
this._propagateChange(value);
}
});
}

public ngOnInit() {
this._categorySub = this.vmSizeService.vmSizeCategories.subscribe((categories) => {
this.vmSizeService.vmSizeCategories.pipe(
takeUntil(this._destroy),
).subscribe((categories) => {
this._categoryRegex = categories;
this._categorizeSizes();
});
Expand All @@ -123,7 +138,7 @@ export class VmSizePickerComponent implements ControlValueAccessor, OnInit, OnCh
sizes = this.vmSizeService.cloudServiceSizes;
}
this.loadingStatus = LoadingStatus.Loading;
this._sizeSub = sizes.subscribe(x => {
this._sizeSub = sizes.subscribe((x) => {
this._vmSizes = x;
this._categorizeSizes();
});
Expand All @@ -135,17 +150,16 @@ export class VmSizePickerComponent implements ControlValueAccessor, OnInit, OnCh
}

public ngOnDestroy() {
if (this._sizeSub) {
this._sizeSub.unsubscribe();
}
this._categorySub.unsubscribe();
this._destroy.next();
this._destroy.unsubscribe();
}

public writeValue(value: any) {
public writeValue(value: string) {
this.pickedSize = value;
this.basicInput.setValue(value);
}

public registerOnChange(fn) {
public registerOnChange(fn: (value: string) => void) {
this._propagateChange = fn;
}

Expand Down Expand Up @@ -175,8 +189,12 @@ export class VmSizePickerComponent implements ControlValueAccessor, OnInit, OnCh
}

private _categorizeSizes() {
if (!this._vmSizes) { return; }
this.loadingStatus = LoadingStatus.Ready;
if (!this._vmSizes) {
this.filteredCategories = null;
this.changeDetector.markForCheck();
return;
}
let vmSizes = this._vmSizes.toArray();
if (this._currentFilter && this._categoryRegex) {
if (this._currentFilter.category && (this._currentFilter.category in this._categoryRegex)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,40 +1,48 @@
<bl-loading [status]="loadingStatus">
<bl-vm-size-picker-filter
[categoriesDisplayName]="categoriesDisplayName"
(filterChange)="onFilterChange($event)">
</bl-vm-size-picker-filter>
<div class="vm-size-list">
<bl-table [data]="filteredCategories" [activeItem]="pickedSize" (activeItemChange)="pickSize($event)" [config]="tableConfig">
<bl-column name="title" [sortable]="true">
<div *blHeadCellDef>Name</div>
<div *blCellDef="let size">{{size.title}}</div>
</bl-column>
<div class="no-vm-sizes-basic-input" *ngIf="loadingStatus !== LoadingStatus.Loading && !filteredCategories">
<bl-form-field>
<input blInput placeholder="VM size" [formControl]="basicInput">
<bl-hint>Cannot load VM sizes. You can enter it instead.</bl-hint>
</bl-form-field>
</div>
<ng-container *ngIf="loadingStatus === LoadingStatus.Loading || filteredCategories">
<bl-vm-size-picker-filter
[categoriesDisplayName]="categoriesDisplayName"
(filterChange)="onFilterChange($event)">
</bl-vm-size-picker-filter>
<div class="vm-size-list">
<bl-table [data]="filteredCategories" [activeItem]="pickedSize" (activeItemChange)="pickSize($event)" [config]="tableConfig">
<bl-column name="title" [sortable]="true">
<div *blHeadCellDef>Name</div>
<div *blCellDef="let size">{{size.title}}</div>
</bl-column>

<bl-column name="price" [sortable]="true">
<div *blHeadCellDef>Price per node (hourly)</div>
<div *blCellDef="let size">{{size.prettyPrice}}</div>
</bl-column>
<bl-column name="price" [sortable]="true">
<div *blHeadCellDef>Price per node (hourly)</div>
<div *blCellDef="let size">{{size.prettyPrice}}</div>
</bl-column>

<bl-column name="cores" [sortable]="true" [defaultWidth]="60">
<div *blHeadCellDef>Cores</div>
<div *blCellDef="let size">{{size.vmSize.numberOfCores}}</div>
</bl-column>
<bl-column name="cores" [sortable]="true" [defaultWidth]="60">
<div *blHeadCellDef>Cores</div>
<div *blCellDef="let size">{{size.vmSize.numberOfCores}}</div>
</bl-column>

<bl-column name="ram" [sortable]="true" [defaultWidth]="60">
<div *blHeadCellDef>Ram</div>
<div *blCellDef="let size">{{size.prettyRAM}}</div>
</bl-column>
<bl-column name="ram" [sortable]="true" [defaultWidth]="60">
<div *blHeadCellDef>Ram</div>
<div *blCellDef="let size">{{size.prettyRAM}}</div>
</bl-column>

<bl-column name="osdisk" [sortable]="true" [defaultWidth]="70">
<div *blHeadCellDef>OS Disk</div>
<div *blCellDef="let size">{{size.prettyOSDiskSize}}</div>
</bl-column>
<bl-column name="osdisk" [sortable]="true" [defaultWidth]="70">
<div *blHeadCellDef>OS Disk</div>
<div *blCellDef="let size">{{size.prettyOSDiskSize}}</div>
</bl-column>

<bl-column name="resourcedisk" [sortable]="true">
<div *blHeadCellDef>Resource/Temp disk</div>
<div *blCellDef="let size">{{size.prettyResourceDiskSize}}</div>
</bl-column>
</bl-table>
</div>
<bl-column name="resourcedisk" [sortable]="true">
<div *blHeadCellDef>Resource/Temp disk</div>
<div *blCellDef="let size">{{size.prettyResourceDiskSize}}</div>
</bl-column>
</bl-table>
</div>
<p>Note: Per-month pricing for listed nodes is an approximation only and based on estimated usage.</p>
</ng-container>
</bl-loading>
<p>Note: Per-month pricing for listed nodes is an approximation only and based on estimated usage.</p>
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

bl-vm-size-picker {
display: block;
position: relative;

.vm-size-list {
height: 400px;
border: 1px solid $border-color;
Expand Down
1 change: 1 addition & 0 deletions src/app/services/compute/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./vm-size.service";
Loading

0 comments on commit ce53342

Please sign in to comment.