Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 46 additions & 32 deletions app/components/base/editor/editor.component.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { AfterViewInit, Component, EventEmitter, Input, Output, ViewChild, forwardRef } from "@angular/core";
import {
AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter,
HostListener, Input, Output, ViewChild, forwardRef,
} from "@angular/core";
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from "@angular/forms";
import "app/utils/autoscale";
import * as CodeMirror from "codemirror";
Expand All @@ -9,18 +12,20 @@ import "codemirror/addon/hint/show-hint";
@Component({
selector: "bl-editor",
providers: [
{
provide: NG_VALUE_ACCESSOR,
// tslint:disable-next-line:no-forward-ref
useExisting: forwardRef(() => EditorComponent),
multi: true,
}],
{
provide: NG_VALUE_ACCESSOR,
// tslint:disable-next-line:no-forward-ref
useExisting: forwardRef(() => EditorComponent),
multi: true,
}],
template: `
<textarea #host placeholder="enter autoscale formula" placeholder="Please enter {{label}}"></textarea>
<div class="mat-input-underline" [class.mat-focused]="isFocused">
<span class="mat-input-ripple"></span>
<textarea #host placeholder="enter autoscale formula" placeholder="Please enter {{label}}">
</textarea>
<div class="mat-input-underline">
<span class="mat-input-ripple" [class.mat-focused]="isFocused"></span>
</div>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})

export class EditorComponent implements ControlValueAccessor, AfterViewInit {
Expand Down Expand Up @@ -52,6 +57,8 @@ export class EditorComponent implements ControlValueAccessor, AfterViewInit {
}
}

constructor(private changeDetector: ChangeDetectorRef) { }

public ngAfterViewInit() {
this.config = this.config || {};
this.codemirrorInit(this.config);
Expand All @@ -61,43 +68,50 @@ export class EditorComponent implements ControlValueAccessor, AfterViewInit {
this.instance = CodeMirror.fromTextArea(this.host.nativeElement, config);
this.instance.setValue(this._value);

this.instance.on("change", () => {
this.instance.on("change", (editor, change) => {
this.updateValue(this.instance.getValue());

if (change.origin !== "complete" && change.origin !== "setValue") {
this.instance.showHint({ hint: CodeMirror.hint.autoscale, completeSingle: false });
}
});

this.instance.on("focus", () => {
this.isFocused = true;
this.focus.emit();
this.onTouched();
this.changeDetector.markForCheck();
});

this.instance.on("blur", () => {
this.isFocused = false;
this.blur.emit();
this.changeDetector.markForCheck();
});
}

this.instance.on("change", (editor, change) => {
if (change.origin !== "complete" && change.origin !== "setValue") {
this.instance.showHint({ hint: CodeMirror.hint.autoscale, completeSingle: false });
}
});
public updateValue(value) {
this.value = value;
this.change.emit(value);
}

public updateValue(value) {
this.value = value;
this.onTouched();
this.change.emit(value);
}
public writeValue(value) {
this._value = value || "";
if (this.instance) {
this.instance.setValue(this._value);
}
}

public writeValue(value) {
this._value = value || "";
if (this.instance) {
this.instance.setValue(this._value);
@HostListener("keyup.enter", ["$event"])
public onEnter(event: KeyboardEvent) {
// Prevent forms from being submitted when focussed in editor and pressing enter.
event.stopPropagation();
}
}
// tslint:disable-next-line:no-empty
public onChange(_) { }
// tslint:disable-next-line:no-empty
public onTouched() { }
public registerOnChange(fn) { this.onChange = fn; }
public registerOnTouched(fn) { this.onTouched = fn; }

public onChange: Function = () => null;

// tslint:disable-next-line:no-empty
public onTouched() { }
public registerOnChange(fn) { this.onChange = fn; }
public registerOnTouched(fn) { this.onTouched = fn; }
}
1 change: 0 additions & 1 deletion app/components/pool/action/add/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
export * from "./autoscale-formula-picker.component";
export * from "./pool-create-basic-dialog.component";
export * from "./pool-os-picker.component";
export * from "./os-offer-tile.component";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,7 @@ export class PoolCreateBasicDialogComponent extends DynamicForm<Pool, PoolCreate
Validators.pattern("^[\\w\\_-]+$"),
]],
displayName: "",
targetDedicated: [0, this.invalidTargetDedicated()],
enableAutoScale: false,
autoScaleFormula: [null, this.invalidAutoscaleFormula()],
autoScaleEvaluationInterval: null,
scale: [null],
os: this._osControl,
vmSize: ["Standard_D1", Validators.required],
maxTasksPerNode: 1,
Expand Down Expand Up @@ -85,31 +82,4 @@ export class PoolCreateBasicDialogComponent extends DynamicForm<Pool, PoolCreate
public get startTask() {
return this.form.controls.startTask.value;
}

public changeScaleModeTab(event) {
if (event.index === 0) {
this.form.controls.enableAutoScale.setValue(false);
} else if (event.index === 1) {
this.form.controls.enableAutoScale.setValue(true);
}
this.form.controls.autoScaleFormula.updateValueAndValidity();
}

private invalidAutoscaleFormula() {
return (control: FormControl): { [key: string]: any } => {
if (!this.form || !this.form.controls.enableAutoScale.value) {
return null;
}
return control.value ? null : { invalidAutoscaleFormula: true };
};
}

private invalidTargetDedicated() {
return (control: FormControl): { [key: string]: any } => {
if (!this.form || this.form.controls.enableAutoScale.value) {
return null;
}
return control.value !== null ? null : { invalidTargetDedicated: true };
};
}
}
16 changes: 1 addition & 15 deletions app/components/pool/action/add/pool-create-basic-dialog.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,7 @@

<bl-form-section title="Scale" subtitle="Number of nodes in your pool using a fix number or a auto scaling forumla">
<div class="form-element">
<md-tab-group class="form-tabs" (selectChange)="changeScaleModeTab($event)">
<md-tab label="Fixed" class="banana">
<md-input-container>
<input mdInput formControlName="targetDedicated" placeholder="Number of virtual machines in pool" type="number" />
</md-input-container>
<bl-error controlName="targetDedicated" code="invalidTargetDedicated">Target size is a required field</bl-error>
</md-tab>
<md-tab label="Auto Scale" class="banana">
<bl-autoscale-formula-picker formControlName="autoScaleFormula"></bl-autoscale-formula-picker>
<bl-error controlName="autoScaleFormula" code="invalidAutoscaleFormula">Auto scale formula is a required field</bl-error>
<md-input-container>
<input mdInput formControlName="autoScaleEvaluationInterval" placeholder="Evaluation interval" type="number" />
</md-input-container>
</md-tab>
</md-tab-group>
<bl-pool-scale-picker formControlName="scale"></bl-pool-scale-picker>
</div>
</bl-form-section>

Expand Down
1 change: 1 addition & 0 deletions app/components/pool/action/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from "./add";
export * from "./delete";
export * from "./scale";
export * from "./resize/pool-resize-dialog.component";
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, ElementRef, OnDestroy, OnInit, ViewChild, forwardRef } from "@angular/core";
import { Component, ElementRef, OnDestroy, OnInit, ViewChild, ViewEncapsulation, forwardRef } from "@angular/core";
import { ControlValueAccessor, FormControl, NG_VALIDATORS, NG_VALUE_ACCESSOR } from "@angular/forms";
import { AutoscaleFormula } from "app/models";
import { AutoscaleFormulaService } from "app/services";
Expand All @@ -13,7 +13,8 @@ import { Subscription } from "rxjs";
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => AutoscaleFormulaPickerComponent), multi: true },
{ provide: NG_VALIDATORS, useExisting: forwardRef(() => AutoscaleFormulaPickerComponent), multi: true },
],
styleUrls: [ "autoscale-formula-picker" ],
styleUrls: ["autoscale-formula-picker"],
encapsulation: ViewEncapsulation.None,
})
export class AutoscaleFormulaPickerComponent implements OnInit, OnDestroy, ControlValueAccessor {
public savedAutoscaleFormulas: List<AutoscaleFormula>;
Expand All @@ -40,7 +41,7 @@ export class AutoscaleFormulaPickerComponent implements OnInit, OnDestroy, Contr
this.autoscaleFormulaName = new FormControl("");
this.showSaveForm = false;
this.savedAutoscaleFormulas = List([]);
this._subs = [];
this._subs = [];
this._propagateChange = null;
this._propagateTouch = null;
this._subs.push(this.autoscaleFormulaService.formulas.subscribe((formulas) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<div class="form-element autoscale-formula-picker">
<div class="bl-textarea">
<div class="autoscale-formula-picker">
<div class="editor">
<bl-editor [(ngModel)]="autoscaleFormulaValue"
[label]="'Autoscale Formula'"
[config]="config"
(change)="textEditorOnChange()"
(blur)="textEditorOnBlur()"></bl-editor>
</div>
<div class="saved-formulas">
<div *ngIf="!showSaveForm">
<div *ngIf="!showSaveForm" class="saved-formulas-container">
<div class="saved-formulas-btns">
<button md-raised-button color="primary" class="small add-formula-btn" (click)="addFormula()">
<i class="fa fa-save"></i> Save Autoscale Formula
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,42 @@
.CodeMirror {
display:block;
width:100%;
height:195px;
}

.ng-invalid.ng-touched .mat-input-underline {
border-color: #aa3939;
border-width: 2px;
border-right: 1px solid $altoGray;
}

.autoscale-formula-picker {
display: flex;
> div {
width: 100%;
max-width: 100%;
overflow: hidden;

> .editor {
flex: 1;
min-width: 100px;
}

.mat-input-underline {
position: relative;
margin-top: 0;
}

> .saved-formulas {
width: 210px;
flex: 0 0 170px;
padding: 1em 0;
border-bottom: 1px solid $altoGray;

> .saved-formulas-container {
height: 100%;
}

.saved-formulas-btns {
height: 28px;
padding: 2px 5px;
}

.saved-formulas-wrapper {
height: 120px;
height: 100%;
overflow: auto;
border-top: 1px solid #d5d5d5;
border-bottom: 1px solid #d5d5d5;
Expand Down
2 changes: 2 additions & 0 deletions app/components/pool/action/scale/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./autoscale-formula-picker.component";
export * from "./pool-scale-picker.component";
91 changes: 91 additions & 0 deletions app/components/pool/action/scale/pool-scale-picker.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { Component, OnDestroy, forwardRef } from "@angular/core";
import {
ControlValueAccessor, FormBuilder, FormControl, FormGroup, NG_VALIDATORS, NG_VALUE_ACCESSOR,
} from "@angular/forms";
import { Subscription } from "rxjs";

@Component({
selector: "bl-pool-scale-picker",
templateUrl: "pool-scale-picker.html",
providers: [
// tslint:disable:no-forward-ref
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => PoolScalePickerComponent), multi: true },
{ provide: NG_VALIDATORS, useExisting: forwardRef(() => PoolScalePickerComponent), multi: true },
],
styleUrls: ["autoscale-formula-picker"],
})
export class PoolScalePickerComponent implements OnDestroy, ControlValueAccessor {
public form: FormGroup;

private _propagateChange: Function;
private _sub: Subscription;

constructor(formBuilder: FormBuilder) {
this.form = formBuilder.group({
enableAutoScale: false,
autoScaleFormula: ["", this._invalidAutoscaleFormula()],
targetDedicated: [0, this._invalidTargetDedicated()],
autoScaleEvaluationInterval: [15],
});

this._sub = this.form.valueChanges.distinctUntilChanged().subscribe((value) => {
if (this._propagateChange) {
this._propagateChange(value);
}
});
}

public ngOnDestroy() {
this._sub.unsubscribe();
}

public writeValue(value: any) {
this.form.patchValue(value || {});
}

public registerOnChange(fn) {
this._propagateChange = fn;
}

public registerOnTouched(fn) {
// Nothing to do
}

public validate(c: FormControl) {
const valid = this.form.valid;
if (valid) {
return null;
}

return {
scalePicker: this.form.errors,
};
}

public changeScaleModeTab(event) {
if (event.index === 0) {
this.form.patchValue({ enableAutoScale: false });
} else if (event.index === 1) {
this.form.patchValue({ enableAutoScale: true });
}
this.form.controls.autoScaleFormula.updateValueAndValidity();
}

private _invalidAutoscaleFormula() {
return (control: FormControl): { [key: string]: any } => {
if (!this.form || !this.form.controls.enableAutoScale.value) {
return null;
}
return control.value ? null : { required: true };
};
}

private _invalidTargetDedicated() {
return (control: FormControl): { [key: string]: any } => {
if (!this.form || this.form.controls.enableAutoScale.value) {
return null;
}
return control.value !== null ? null : { required: true };
};
}
}
Loading