Skip to content

Commit

Permalink
Merge pull request #46 from Hydrospheredata/models-versioning
Browse files Browse the repository at this point in the history
Models filter + input for model testing
  • Loading branch information
esmeneev authored Nov 1, 2017
2 parents e577f59 + ab40770 commit b1ac7d9
Show file tree
Hide file tree
Showing 14 changed files with 182 additions and 69 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<div>
<h1 class="mdl-dialog__title mat-dialog-title">{{testTitle}}</h1>
<form [formGroup]="testForm" (ngSubmit)="submitTestForm(testForm)">
<form *ngIf="input" [formGroup]="testForm" (ngSubmit)="submitTestForm(testForm)">
<div class="mdl-dialog__content">
<div fxLayout="row" fxLayoutAlign="space-around stretch">
<div fxFlex="49%">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,11 @@
margin-top: 20px;
margin-bottom: 10px;
}

.input {
&-text {
&__input {
font-family: monospace;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import 'codemirror/addon/edit/matchbrackets.js';
import 'codemirror/addon/edit/closebrackets.js';
import 'codemirror/addon/display/placeholder.js';
import { Model, ModelService, Service } from '@shared/models/_index';
import { ServicesService, ModelServicesService } from '@shared/services/_index';
import { ServicesService, ModelServicesService, ModelRuntimesService } from '@shared/services/_index';
import { environment } from 'environments/environment';
import { Location } from '@angular/common';

Expand All @@ -26,6 +26,7 @@ export class DialogTestComponent implements OnInit {
public testForm: FormGroup;
public codeMirrorInputOptions: {};
public codeMirrorOutputOptions: {};
public input: {};
public output: {};
public testBtn: string;
public testTitle: string;
Expand All @@ -38,6 +39,7 @@ export class DialogTestComponent implements OnInit {
private fb: FormBuilder,
private mdlSnackbarService: MdlSnackbarService,
private modelServicesService: ModelServicesService,
private modelRuntimesService: ModelRuntimesService,
private location: Location,
private servicesService: ServicesService
) {
Expand All @@ -50,18 +52,6 @@ export class DialogTestComponent implements OnInit {


ngOnInit() {
if (!this.model.id || this.model instanceof Model) {
this.testTitle = `Test model "${this.model.modelRuntime.modelName}"`;
this.testBtn = 'Test model';
} else {
this.testTitle = `Test service "${this.model.serviceName}"`;
this.testBtn = `Test service`;
}
this.createTestForm();
this.requestBody = this.createCURLString(this.testForm);
this.testForm.valueChanges.subscribe(form => {
this.requestBody = this.createCURLString(this.testForm);
});
this.codeMirrorInputOptions = {
matchBrackets: true,
autoCloseBrackets: true,
Expand All @@ -79,8 +69,28 @@ export class DialogTestComponent implements OnInit {
scrollbarStyle: 'null'
};


if (this.model instanceof Service) {
this.input = [{}];
this.testTitle = `Test service "${this.model.serviceName}"`;
this.testBtn = `Test service`;
this.createTestForm();
} else {
// TODO: come up with better way of sending async data into formbuilder
this.modelRuntimesService.generateInputs(this.model.modelRuntime.id).first()
.subscribe(data => {
this.input = data;
this.testTitle = `Test model "${this.model.modelRuntime.modelName}"`;
this.testBtn = 'Test model';
this.createTestForm();
});
}


}



private createCURLString(form) {
let path = '';
let payload = '';
Expand All @@ -103,25 +113,17 @@ export class DialogTestComponent implements OnInit {

private createTestForm() {
this.testForm = this.fb.group({
data: [this.extractModelInputFields(this.model), [Validators.required, this.validateInput]],
data: [JSON.stringify(this.input, null, 2), [Validators.required, this.validateInput]],
path: ['/serve', [Validators.required]],
});
this.requestBody = this.createCURLString(this.testForm);
this.testForm.valueChanges.subscribe(form => {
this.requestBody = this.createCURLString(this.testForm);
});
}

private extractModelInputFields(model): string {
let inputFields;
if (model.inputFields) {
inputFields = model.inputFields;
} else if (model.modelRuntime && model.modelRuntime.inputFields) {
inputFields = model.modelRuntime.inputFields;
} else {
return JSON.stringify([{}]);
}
const reducedFields = inputFields.reduce((payload, field) => {
payload[field] = '';
return payload;
}, {});
return JSON.stringify([reducedFields], undefined, 2);
return '{}';
}

private validateInput(input) {
Expand Down
1 change: 1 addition & 0 deletions src/assets/images/copy.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 5 additions & 1 deletion src/assets/styles/_mdl-textfieled.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,8 @@
border-radius: 5px;
color: #04143c;
}
}
}
// hack for dialog-model-build
.runtime-select > .mdl-textfield {
width:60%;
}
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ <h5 class="model-details-grid-header">Versions</h5>
</div>
</td>
<td class="hydro-table-body__cell">
<div *ngIf="this.weightedServices && this.weightedServices.length > 0" class="cs-text-overflow-ellipsis">
<!-- todo: make more optimal -->
<div *ngIf="runtime && runtime.services[0] && runtime.services[0].weightedServices && runtime.services[0].weightedServices.length > 0" class="cs-text-overflow-ellipsis">
<span *ngFor="let weightedService of runtime.services[0].weightedServices; last as isLast">
<a class="hydro-table-link model-details-link" [routerLink]="['/services', weightedService.id]">
{{ weightedService.serviceName }}
Expand Down
86 changes: 50 additions & 36 deletions src/modules/shared/components/sidebar/sidebar.component.html
Original file line number Diff line number Diff line change
@@ -1,42 +1,56 @@
<aside class="sidebar">
<div class="sidebar-header">
<div class="sidebar-header__row">
<h3 class='sidebar-title'>{{sidebarTitle}}</h3>
<button class="btn btn-secondary" *ngIf="isAddBtnEnabled" (click)="addService($event)" title="Add new app">
<svg>
<use xlink:href="#icon-plus"></use>
</svg>
Add app
</button>
</div>
<div class="sidebar-header__row">
<hydro-input-text class="sidebar-search"
inputClass="sidebar-search"
placeholder="Search"
[(ngModel)]="searchQ"
iconName="search"
iconDirection="left"
></hydro-input-text>
</div>
<div class="sidebar-header">
<div class="sidebar-header__row">
<h3 class='sidebar-title'>{{sidebarTitle}}</h3>
<button class="btn btn-secondary" *ngIf="isAddBtnEnabled" (click)="addService($event)" title="Add new app">
<svg>
<use xlink:href="#icon-plus"></use>
</svg>
Add app
</button>
</div>
<div class="sidebar-header__row">
<hydro-input-text class="sidebar-search" inputClass="sidebar-search" placeholder="Search" [(ngModel)]="searchQ" iconName="search"
iconDirection="left"></hydro-input-text>
</div>


<div *ngIf="isModels" class="sidebar-filter">
<span class="sidebar-filter__label">Filter:</span>
<button (click)="toggleModelFilter('deployed')" class="sidebar-filter__button" [ngClass]="{'sidebar-filter__selected': !deployedFilter['deployed']}">
<svg class="icon sidebar-filter__button--icon deployed">
<use xlink:href="#icon-arrow" />
</svg>
<span class="sidebar-filter__button--label">Deployed</span>
</button>
<button (click)="toggleModelFilter('undeployed')" class="sidebar-filter__button" [ngClass]="{'sidebar-filter__selected': !deployedFilter['undeployed']}" >
<svg class="icon sidebar-filter__button--icon undeployed-filter">
<use xlink:href="#icon-arrow" />
</svg>
<span class="sidebar-filter__button--label">Undeployed</span>
</button>
</div>
</div>



<div class="sidebar-body">
<ul class='sidebar-list'>
<li *ngFor="let item of sidebarList | search : (isModels ? 'name' : 'serviceName') : searchQ | sortBy: 'id'" class='sidebar-list__item' [routerLink]="[item.id]" routerLinkActive='__active'>
<span class="sidebar-list__item-name">{{ item.serviceName || item.source }}</span>
<span class='sidebar-list__item-status' *ngIf="item.currentServices && item.currentServices.length && this.dataType === 'services'" [mdl-badge]="item.currentServices.length"></span>
<div *ngIf="isModels" class="sidebar-list__item-details">
<span class="sidebar-list__item--version"
[ngClass]="{
<div class="sidebar-body">
<ul class='sidebar-list'>
<li *ngFor="let item of sidebarList | modelFilter:deployedFilter | search : (isModels ? 'name' : 'serviceName') : searchQ | sortBy: 'id'"
class='sidebar-list__item' [routerLink]="[item.id]" routerLinkActive='__active'>
<span class="sidebar-list__item-name">{{ item.serviceName || item.source }}</span>
<span class='sidebar-list__item-status' *ngIf="item.currentServices && item.currentServices.length && this.dataType === 'services'"
[mdl-badge]="item.currentServices.length"></span>
<div *ngIf="isModels" class="sidebar-list__item-details">
<span class="sidebar-list__item--version" [ngClass]="{
'version-new': isDeployable(item),
'version-failed': item.lastModelBuild.status === 'FAILED'
}"
>{{getLatestVersion(item)}}</span>
<svg class="icon sidebar-list__item--deploy" [ngClass]="item?.currentServices?.length > 0 ? 'deployed' : 'undeployed'">
<use xlink:href="#icon-arrow" />
</svg>
</div>
</li>
</ul>
</div>
}">{{getLatestVersion(item)}}</span>
<svg class="icon sidebar-list__item--deploy" [ngClass]="item?.currentServices?.length > 0 ? 'deployed' : 'undeployed'">
<use xlink:href="#icon-arrow" />
</svg>
</div>
</li>
</ul>
</div>
</aside>
45 changes: 44 additions & 1 deletion src/modules/shared/components/sidebar/sidebar.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
.sidebar {
height: 100%;
&-header {
padding: 45px 32px 42px;
padding: 45px 32px 26px;
border-bottom: 2px solid #d4d7d9;
&__row {
display: flex;
Expand Down Expand Up @@ -35,6 +35,7 @@
margin: 0;
padding: 0;
&__item {
height: 0px;
line-height: 15px;
border-bottom: 1px solid $secondary-color;
padding: 23px 36px;
Expand Down Expand Up @@ -76,6 +77,44 @@
}
}
}
&-filter {
display: flex;
flex-direction: row;
align-items: center;
&__label {
color: #818994;
font-size: 12px;
font-weight: 400;
line-height: 24px;
text-transform: uppercase;
letter-spacing: 1.2px;
padding-right: 10px;
}
&__button {
height: 33px;
border-radius: 5px;
background-color: #e6e9ed;
border: none;
cursor: pointer;
margin-right: 10px;
display: inline-flex;
&--label {
font-family: $main-font-family;
color: #818994;
font-size: 14px;
font-weight: 400;
line-height: 24px;
letter-spacing: 0.35px;
}
&--icon {
margin-top: 5px;
margin-right: 5px;
}
}
&__selected {
background: none;
}
}
}

::-webkit-scrollbar {
Expand All @@ -99,6 +138,10 @@ svg {
fill: #e1e4eb;
}

.undeployed-filter {
fill: #d2d5d9;
}

.version-new {
padding-right: 26px!important;
color: #f28a03;
Expand Down
6 changes: 5 additions & 1 deletion src/modules/shared/components/sidebar/sidebar.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export class SidebarComponent implements OnInit, OnChanges, OnDestroy {
private title = '';
public searchQ: string;
private needsToGo = false;

public deployedFilter = {'deployed': true, 'undeployed': true};
@Input() isAddBtnEnabled: boolean;
@Input() isModels: boolean;
@Input() sidebarTitle: string;
Expand Down Expand Up @@ -97,6 +97,10 @@ export class SidebarComponent implements OnInit, OnChanges, OnDestroy {

}

toggleModelFilter(option) {
this.deployedFilter[option] = !this.deployedFilter[option];
}

public isDeployable(model) {
if (!model || !model.lastModelRuntime.created) {
return true;
Expand Down
3 changes: 2 additions & 1 deletion src/modules/shared/pipes/_index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
export * from './model-filter.pipe';
export * from './model-status.pipe';
export * from './positive-numbers.pipe';
export * from './search.pipe';
export * from './sort-by.pipe';
export * from './utc-to-local.pipe';
export * from './iterate-as-array.pipe';
export * from './remove-dublicates.pipe';
export * from './remove-dublicates.pipe';
8 changes: 8 additions & 0 deletions src/modules/shared/pipes/model-filter.pipe.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { ModelFilterPipe } from './model-filter.pipe';

describe('ModelFilterPipe', () => {
it('create an instance', () => {
const pipe = new ModelFilterPipe();
expect(true).toBeTruthy();
});
});
18 changes: 18 additions & 0 deletions src/modules/shared/pipes/model-filter.pipe.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
name: 'modelFilter',
pure: false
})
export class ModelFilterPipe implements PipeTransform {

transform(models: any, filterStatus: any): any {
return models.filter(model => {
let result = false;
result = result || filterStatus['deployed'] && model.currentServices && model.currentServices.length > 0;
result = result || filterStatus['undeployed'] && (!model.currentServices || model.currentServices.length < 1);
return result;
});
}

}
6 changes: 6 additions & 0 deletions src/modules/shared/services/model-runtimes.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ export class ModelRuntimesService {
return res.json();
});
}
generateInputs(id: number): Observable<any>{
const url = `${this.baseAPIUrl}/generateInputs/${id}`;
return this.http.get(url).map((res: Response) => {
return res.json();
})
}
createModelRuntime() {}
removeModelRuntime() {}
updateModelRuntime() {}
Expand Down
Loading

0 comments on commit b1ac7d9

Please sign in to comment.