Skip to content

Commit

Permalink
Feature/do sizes (#438)
Browse files Browse the repository at this point in the history
* adjust digitalocean sizes

* hide 'Please add a Digital Ocean Token first!' if sizes are available

* some small adjustments

* Revert "some small adjustments"

This reverts commit a770c8f.

* adjust route due to changes in the backend

* get do token from header
  • Loading branch information
kgroschoff authored and j3ank committed Feb 15, 2018
1 parent caa89fa commit ef20857
Show file tree
Hide file tree
Showing 3 changed files with 290 additions and 273 deletions.
Original file line number Diff line number Diff line change
@@ -1,25 +1,32 @@
<kubermatic-add-node-form [connect]="connect" [formGroup]="doNodeForm" (change)="onChange()">
<mat-form-field fxFlex>
<input id="node_count_do" [errorStateMatcher]="inputValidationService" matInput formControlName="node_count" min="1"
max="20" type="number" placeholder="Quantity of Nodes*:">
<mat-error *ngIf="doNodeForm.controls.node_count.hasError('min') && !doNodeForm.controls.node_count.hasError('required')">
Quantity of Nodes must be minimum <strong>1</strong>
</mat-error>
<mat-error *ngIf="doNodeForm.controls.node_count.hasError('required')">
Quantity of Nodes is <strong>required</strong>
</mat-error>
</mat-form-field>
<div fxFlex class="mat-select-content">
<mat-form-field>
<mat-select class="mat-select" [errorStateMatcher]="inputValidationService" placeholder="Node Size*:" id="node_size" name="node_size" formControlName="node_size" (change)="onChange()">
<mat-option *ngIf="!nodeSize.length" [value]="">Please add a Digital Ocean Token first!</mat-option>
<mat-option *ngFor="let size of nodeSize; let i = index;" [value]="size.slug">
{{ size.memory / 1024 }} GB RAM, {{ size.vcpus }} CPU{{ (size.vcpus!=1) ? 's' : '' }}, ${{ size.price_monthly }} per month
</mat-option>
</mat-select>
<mat-error *ngIf="doNodeForm.controls.node_size.hasError('required')">
Node size is <strong>required</strong>
</mat-error>
</mat-form-field>
</div>
<kubermatic-add-node-form [connect]="connect" [formGroup]="doNodeForm" (change)="onChange()">
<mat-form-field fxFlex>
<input id="node_count_do" [errorStateMatcher]="inputValidationService" matInput formControlName="node_count" min="1"
max="20" type="number" placeholder="Quantity of Nodes*:">
<mat-error *ngIf="doNodeForm.controls.node_count.hasError('min') && !doNodeForm.controls.node_count.hasError('required')">
Quantity of Nodes must be minimum <strong>1</strong>
</mat-error>
<mat-error *ngIf="doNodeForm.controls.node_count.hasError('required')">
Quantity of Nodes is <strong>required</strong>
</mat-error>
</mat-form-field>
<div fxFlex class="mat-select-content">
<mat-form-field>
<mat-select class="mat-select" [errorStateMatcher]="inputValidationService" placeholder="Node Size*:" id="node_size" name="node_size" formControlName="node_size" (change)="onChange()">
<mat-option *ngIf="!nodeSizeAvailable" [value]="">Please add a Digital Ocean Token first!</mat-option>
<mat-optgroup *ngIf="nodeSizeAvailable" label="Standard Droplets">
<mat-option *ngFor="let size of nodeSize.standard; let i = index;" [value]="size.slug">
{{ size.memory / 1024 }} GB RAM, {{ size.vcpus }} CPU{{ (size.vcpus!=1) ? 's' : '' }}, ${{ size.price_monthly }} per month
</mat-option>
</mat-optgroup>
<mat-optgroup *ngIf="nodeSizeAvailable" label="Optimized Droplets">
<mat-option *ngFor="let size of nodeSize.optimized; let i = index;" [value]="size.slug">
{{ size.memory / 1024 }} GB RAM, {{ size.vcpus }} CPU{{ (size.vcpus!=1) ? 's' : '' }}, ${{ size.price_monthly }} per month
</mat-option>
</mat-optgroup>
</mat-select>
<mat-error *ngIf="doNodeForm.controls.node_size.hasError('required')">
Node size is <strong>required</strong>
</mat-error>
</mat-form-field>
</div>
</kubermatic-add-node-form>
277 changes: 143 additions & 134 deletions src/app/add-node/digitalocean-add-node/digitalocean-add-node.component.ts
Original file line number Diff line number Diff line change
@@ -1,134 +1,143 @@
import { NgRedux } from '@angular-redux/store/lib/src/components/ng-redux';
import { CreateNodeModel } from 'app/shared/model/CreateNodeModel';
import { NodeInstanceFlavors } from 'app/shared/model/NodeProviderConstants';
import { ApiService } from 'app/core/services/api/api.service';
import { Input, EventEmitter, Output, AfterContentInit, OnChanges, OnDestroy, OnInit, Component } from '@angular/core';
import { CustomValidators } from 'ng2-validation';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { NodeCreateSpec } from 'app/shared/entity/NodeEntity';
import { DigitaloceanNodeSpec } from 'app/shared/entity/node/DigitialoceanNodeSpec';
import { InputValidationService } from 'app/core/services/input-validation/input-validation.service';
import { WizardActions } from 'app/redux/actions/wizard.actions';
import { select } from '@angular-redux/store';
import { Observable } from 'rxjs/Observable';
import { Subscription } from 'rxjs/Subscription';

@Component({
selector: 'kubermatic-digitalocean-add-node',
templateUrl: './digitalocean-add-node.component.html',
styleUrls: ['./digitalocean-add-node.component.scss']
})

export class DigitaloceanAddNodeComponent implements OnInit, AfterContentInit, OnChanges, OnDestroy {

@Input() public token: string = '';
@Input() public connect: string[] = [];
@Output() public nodeSpecChanges: EventEmitter<{nodeSpec: NodeCreateSpec, count: number}> = new EventEmitter();
@Output() public formChanges: EventEmitter<FormGroup> = new EventEmitter();

public doNodeForm: FormGroup;
public nodeSize: any[] = NodeInstanceFlavors.VOID;
private subscriptions: Subscription[] = [];

@select(['wizard', 'isCheckedForm']) isChecked$: Observable<boolean>;

constructor(private fb: FormBuilder,
private api: ApiService,
public inputValidationService: InputValidationService,
private ngRedux: NgRedux<any>) { }

ngOnInit() {
const sub = this.isChecked$.subscribe(isChecked => {
isChecked && this.showRequiredFields();
});
this.subscriptions.push(sub);

this.doNodeForm = this.fb.group({
node_count: [3, [<any>Validators.required, CustomValidators.min(1)]],
node_size: ['', [<any>Validators.required]]
});

if (Array.isArray(this.connect) && this.connect.length) {
const reduxStore = this.ngRedux.getState();
const nodeForm = reduxStore.wizard.nodeForm;

if (nodeForm) {
const formValue = {
node_count: nodeForm.node_count,
node_size: nodeForm.node_size
};

this.doNodeForm.setValue(formValue);
}
}

this.onChange();
}

public getNodeSize(token: string): void {
const selectedNodeSize = null;

if (token) {
this.api.getDigitaloceanSizes(token).subscribe(result => {
this.nodeSize = result.sizes;
if (this.nodeSize.length > 0 && this.doNodeForm.controls['node_size'].value === '') {
const nodeSize = selectedNodeSize ? selectedNodeSize : '4gb';
this.doNodeForm.patchValue({node_size: nodeSize});
this.onChange();
}
}
);
}
}

public showRequiredFields() {
if (this.doNodeForm.invalid) {
for (const i in this.doNodeForm.controls) {
if (this.doNodeForm.controls.hasOwnProperty(i)) {
this.doNodeForm.get(i).markAsTouched();
}
}
}
}

public ngAfterContentInit(): void {
this.getNodeSize(this.token);
}

public ngOnChanges(): void {
this.getNodeSize(this.token);
}

public onChange() {
WizardActions.formChanged(
['wizard', 'nodeForm'],
{
node_size: this.doNodeForm.controls['node_size'].value,
node_count: this.doNodeForm.controls['node_count'].value,
},
this.doNodeForm.valid
);

const nodeInfo = this.ngRedux.getState().wizard.nodeForm;

const nodeSpec = new NodeCreateSpec(
new DigitaloceanNodeSpec(nodeInfo.node_size),
null,
null,
null,
);

this.nodeSpecChanges.emit({
nodeSpec,
count: nodeInfo.node_count
});

this.formChanges.emit(this.doNodeForm);
}

public ngOnDestroy(): void {
this.subscriptions.forEach(sub => {
sub.unsubscribe();
});
}
}
import { NgRedux } from '@angular-redux/store/lib/src/components/ng-redux';
import { CreateNodeModel } from 'app/shared/model/CreateNodeModel';
import { NodeInstanceFlavors } from 'app/shared/model/NodeProviderConstants';
import { ApiService } from 'app/core/services/api/api.service';

import { Input, EventEmitter, Output, AfterContentInit, OnChanges, OnDestroy, OnInit, Component } from '@angular/core';
import { CustomValidators } from 'ng2-validation';

import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { NodeCreateSpec } from 'app/shared/entity/NodeEntity';
import { DigitaloceanNodeSpec } from 'app/shared/entity/node/DigitialoceanNodeSpec';
import { InputValidationService } from 'app/core/services/input-validation/input-validation.service';
import { WizardActions } from 'app/redux/actions/wizard.actions';
import { select } from '@angular-redux/store';
import { Observable } from 'rxjs/Observable';
import { Subscription } from 'rxjs/Subscription';


@Component({
selector: 'kubermatic-digitalocean-add-node',
templateUrl: './digitalocean-add-node.component.html',
styleUrls: ['./digitalocean-add-node.component.scss']
})

export class DigitaloceanAddNodeComponent implements OnInit, AfterContentInit, OnChanges, OnDestroy {

@Input() public token: string = '';
@Input() public connect: string[] = [];
@Output() public nodeSpecChanges: EventEmitter<{nodeSpec: NodeCreateSpec, count: number}> = new EventEmitter();
@Output() public formChanges: EventEmitter<FormGroup> = new EventEmitter();

public doNodeForm: FormGroup;
public nodeSize: any[] = NodeInstanceFlavors.VOID;
private subscriptions: Subscription[] = [];
public nodeSizeAvailable: boolean;

@select(['wizard', 'isCheckedForm']) isChecked$: Observable<boolean>;

constructor(private fb: FormBuilder,
private api: ApiService,
public inputValidationService: InputValidationService,
private ngRedux: NgRedux<any>) { }

ngOnInit() {
const sub = this.isChecked$.subscribe(isChecked => {
isChecked && this.showRequiredFields();
});
this.subscriptions.push(sub);

this.doNodeForm = this.fb.group({
node_count: [3, [<any>Validators.required, CustomValidators.min(1)]],
node_size: ['', [<any>Validators.required]]
});

if (Array.isArray(this.connect) && this.connect.length) {
const reduxStore = this.ngRedux.getState();
const nodeForm = reduxStore.wizard.nodeForm;

if (nodeForm) {
const formValue = {
node_count: nodeForm.node_count,
node_size: nodeForm.node_size
};

this.doNodeForm.setValue(formValue);
}
}

this.onChange();
}

public getNodeSize(token: string): void {
const selectedNodeSize = null;

if (token) {
this.api.getDigitaloceanSizes(token).subscribe(result => {
this.nodeSize = result;
if (result.standard.length > 0 && result.optimized.length > 0 && this.doNodeForm.controls['node_size'].value === '') {
const nodeSize = selectedNodeSize ? selectedNodeSize : 's-2vcpu-4gb';
this.doNodeForm.patchValue({node_size: nodeSize});
this.onChange();
}

if (result.standard.length > 0 && result.optimized.length > 0) {
this.nodeSizeAvailable = true;
} else if (result.standard.length === 0 && result.optimized.length === 0) {
this.nodeSizeAvailable = false;
}
});
}
}

public showRequiredFields() {
if (this.doNodeForm.invalid) {
for (const i in this.doNodeForm.controls) {
if (this.doNodeForm.controls.hasOwnProperty(i)) {
this.doNodeForm.get(i).markAsTouched();
}
}
}
}

public ngAfterContentInit(): void {
this.getNodeSize(this.token);
}

public ngOnChanges(): void {
this.getNodeSize(this.token);
}

public onChange() {
WizardActions.formChanged(
['wizard', 'nodeForm'],
{
node_size: this.doNodeForm.controls['node_size'].value,
node_count: this.doNodeForm.controls['node_count'].value,
},
this.doNodeForm.valid
);

const nodeInfo = this.ngRedux.getState().wizard.nodeForm;

const nodeSpec = new NodeCreateSpec(
new DigitaloceanNodeSpec(nodeInfo.node_size),
null,
null,
null,
);

this.nodeSpecChanges.emit({
nodeSpec,
count: nodeInfo.node_count
});

this.formChanges.emit(this.doNodeForm);
}

public ngOnDestroy(): void {
this.subscriptions.forEach(sub => {
sub.unsubscribe();
});
}
}
Loading

0 comments on commit ef20857

Please sign in to comment.