fixed tests and feedback

This commit is contained in:
lotte
2020-03-25 18:22:20 +01:00
committed by Art Lowel
parent ef3a235178
commit e7a5daad18
29 changed files with 248 additions and 57 deletions

View File

@@ -1616,6 +1616,8 @@
"process.new.select-parameters": "Parameters",
"process.new.cancel": "Cancel",
"process.new.submit": "Submit",
"process.new.select-script": "Script",
@@ -1630,6 +1632,24 @@
"process.new.parameter.string.required": "Parameter value is required",
"process.new.parameter.type.value": "value",
"process.new.parameter.type.file": "file",
"process.new.parameter.required.missing": "The following parameters are required but still missing:",
"process.new.notification.success.title": "Success",
"process.new.notification.success.content": "The process was successfully created",
"process.new.notification.error.title": "Error",
"process.new.notification.error.content": "An error occurred while creating this process",
"process.new.header": "Create a new process",
"process.new.title": "Create a new process",
"publication.listelement.badge": "Publication",

View File

@@ -10,10 +10,12 @@ import { HttpClient } from '@angular/common/http';
import { DefaultChangeAnalyzer } from '../default-change-analyzer.service';
import { Script } from '../../../process-page/scripts/script.model';
import { ProcessParameter } from '../../../process-page/processes/process-parameter.model';
import { map } from 'rxjs/operators';
import { find, map, switchMap, tap } from 'rxjs/operators';
import { URLCombiner } from '../../url-combiner/url-combiner';
import { MultipartPostRequest, RestRequest } from '../request.models';
import { RequestService } from '../request.service';
import { Observable } from 'rxjs';
import { RequestEntry } from '../request.reducer';
@Injectable()
export class ScriptDataService extends DataService<Script> {
@@ -31,15 +33,18 @@ export class ScriptDataService extends DataService<Script> {
super();
}
public invoke(scriptName: string, parameters: ProcessParameter[], files: File[]) {
this.getBrowseEndpoint().pipe(
public invoke(scriptName: string, parameters: ProcessParameter[], files: File[]): Observable<RequestEntry> {
const requestId = this.requestService.generateRequestId();
return this.getBrowseEndpoint().pipe(
map((endpoint: string) => new URLCombiner(endpoint, scriptName, 'processes').toString()),
map((endpoint: string) => {
const body = this.getInvocationFormData(parameters, files);
return new MultipartPostRequest(this.requestService.generateRequestId(), endpoint, body)
return new MultipartPostRequest(requestId, endpoint, body)
}),
map((request: RestRequest) => this.requestService.configure(request))
).subscribe();
map((request: RestRequest) => this.requestService.configure(request)),
switchMap(() => this.requestService.getByUUID(requestId)),
find((request: RequestEntry) => request.completed)
);
}
private getInvocationFormData(parameters: ProcessParameter[], files: File[]): FormData {

View File

@@ -1,14 +1,25 @@
<div class="container">
<div class="row">
<h2 class="col-12">
{{'process.new.header' | translate}}
</h2>
<div class="col-12 col-md-6">
<form #form="ngForm" (ngSubmit)="submitForm(form)">
<ds-scripts-select (select)="selectedScript = $event"></ds-scripts-select>
<ds-process-parameters [script]="selectedScript" (updateParameters)="parameters = $event"></ds-process-parameters>
<button [disabled]="form.invalid" type="submit" class="btn btn-light float-right">{{ 'process.new.submit' | translate }}</button>
<button [routerLink]="['/processes']" class="btn btn-light float-left">{{ 'process.new.cancel' | translate }}</button>
<button type="submit" class="btn btn-light float-right">{{ 'process.new.submit' | translate }}</button>
</form>
</div>
<div class="col-12 col-md-6">
<ds-script-help [script]="selectedScript"></ds-script-help>
</div>
</div>
<div *ngIf="missingParameters.length > 0" class="alert alert-danger validation-error">
{{'process.new.parameter.required.missing' | translate}}
<ul>
<li *ngFor="let missing of missingParameters">{{missing}}</li>
</ul>
</div>
</div>

View File

@@ -9,6 +9,9 @@ import { MockTranslateLoader } from '../../shared/testing/mock-translate-loader'
import { ScriptParameter } from '../scripts/script-parameter.model';
import { Script } from '../scripts/script.model';
import { ProcessParameter } from '../processes/process-parameter.model';
import { NotificationsService } from '../../shared/notifications/notifications.service';
import { NotificationsServiceStub } from '../../shared/testing/notifications-service-stub';
import { of as observableOf } from 'rxjs';
describe('NewProcessComponent', () => {
let component: NewProcessComponent;
@@ -26,7 +29,17 @@ describe('NewProcessComponent', () => {
Object.assign(new ProcessParameter(), { name: '-b', value: '123' }),
Object.assign(new ProcessParameter(), { name: '-c', value: 'value' }),
];
scriptService = jasmine.createSpyObj('scriptService', ['invoke'])
scriptService = jasmine.createSpyObj(
'scriptService',
{
invoke: observableOf({
response:
{
isSuccessful: true
}
})
}
)
}
beforeEach(async(() => {
@@ -43,6 +56,7 @@ describe('NewProcessComponent', () => {
declarations: [NewProcessComponent],
providers: [
{ provide: ScriptDataService, useValue: scriptService },
{ provide: NotificationsService, useValue: NotificationsServiceStub },
],
schemas: [NO_ERRORS_SCHEMA]
})
@@ -62,7 +76,7 @@ describe('NewProcessComponent', () => {
});
it('should call invoke on the scriptService on submit', () => {
component.submitForm({ invalid: false });
component.submitForm({ invalid: false } as any);
expect(scriptService.invoke).toHaveBeenCalled();
});
});

View File

@@ -3,7 +3,13 @@ import { Script } from '../scripts/script.model';
import { Process } from '../processes/process.model';
import { ProcessParameter } from '../processes/process-parameter.model';
import { ScriptDataService } from '../../core/data/processes/script-data.service';
import { NgForm } from '@angular/forms';
import { ControlContainer, NgForm } from '@angular/forms';
import { ScriptParameter } from '../scripts/script-parameter.model';
import { RequestEntry } from '../../core/data/request.reducer';
import { NotificationsService } from '../../shared/notifications/notifications.service';
import { TranslateService } from '@ngx-translate/core';
import { take } from 'rxjs/operators';
import { pipe } from 'rxjs';
/**
* Component to create a new script
@@ -27,14 +33,19 @@ export class NewProcessComponent implements OnInit {
/**
* The parameter values to use to start the process
*/
public parameters: ProcessParameter[];
public parameters: ProcessParameter[] = [];
/**
* Optional files that are used as parameter values
*/
public files: File[] = [];
constructor(private scriptService: ScriptDataService) {
/**
* Contains the missing parameters on submission
*/
public missingParameters = [];
constructor(private scriptService: ScriptDataService, private notificationsService: NotificationsService, private translationService: TranslateService) {
}
ngOnInit(): void {
@@ -46,7 +57,7 @@ export class NewProcessComponent implements OnInit {
* @param form
*/
submitForm(form: NgForm) {
if (!this.validateForm(form)) {
if (!this.validateForm(form) || this.isRequiredMissing()) {
return;
}
@@ -58,6 +69,18 @@ export class NewProcessComponent implements OnInit {
}
);
this.scriptService.invoke(this.selectedScript.id, stringParameters, this.files)
.pipe(take(1))
.subscribe((requestEntry: RequestEntry) => {
if (requestEntry.response.isSuccessful) {
const title = this.translationService.get('process.new.notification.success.title');
const content = this.translationService.get('process.new.notification.success.content');
this.notificationsService.success(title, content)
} else {
const title = this.translationService.get('process.new.notification.error.title');
const content = this.translationService.get('process.new.notification.error.content');
this.notificationsService.error(title, content)
}
})
}
/**
@@ -88,4 +111,20 @@ export class NewProcessComponent implements OnInit {
}
return true;
}
private isRequiredMissing() {
const setParams: string[] = this.parameters
.map((param) => param.name);
const requiredParams: ScriptParameter[] = this.selectedScript.parameters.filter((param) => param.mandatory)
for (const rp of requiredParams) {
if (!setParams.includes(rp.name)) {
this.missingParameters.push(rp.name);
}
}
return this.missingParameters.length > 0;
}
}
export function controlContainerFactory(controlContainer?: ControlContainer) {
return controlContainer;
}

View File

@@ -1,7 +1,7 @@
<div class="form-row mb-2">
<select required id="process-parameters"
<select id="process-parameters"
class="form-control col"
name="script"
name="parameter-{{index}}"
[(ngModel)]="selectedParameter"
#param="ngModel">
<option [ngValue]="undefined">Add a parameter...</option>
@@ -9,7 +9,7 @@
{{param.nameLong || param.name}}
</option>
</select>
<ds-parameter-value-input [parameter]="selectedScriptParameter" (updateValue)="selectedParameterValue = $event" class="d-block col"></ds-parameter-value-input>
<ds-parameter-value-input [parameter]="selectedScriptParameter" (updateValue)="selectedParameterValue = $event" class="d-block col" [index]="index"></ds-parameter-value-input>
<button *ngIf="removable" class="btn btn-light col-1 remove-button" (click)="removeParameter.emit(parameterValue);"><span class="fas fa-trash"></span></button>
<span *ngIf="!removable" class="col-1"></span>
</div>

View File

@@ -1,7 +1,9 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { Component, EventEmitter, Input, OnInit, Output, Optional } from '@angular/core';
import { ProcessParameter } from '../../../processes/process-parameter.model';
import { ScriptParameter } from '../../../scripts/script-parameter.model';
import { hasNoValue } from '../../../../shared/empty.util';
import { ControlContainer, NgForm } from '@angular/forms';
import { controlContainerFactory } from '../../new-process.component';
/**
* Component to select a single parameter for a process
@@ -9,13 +11,19 @@ import { hasNoValue } from '../../../../shared/empty.util';
@Component({
selector: 'ds-parameter-select',
templateUrl: './parameter-select.component.html',
styleUrls: ['./parameter-select.component.scss']
styleUrls: ['./parameter-select.component.scss'],
viewProviders: [ { provide: ControlContainer,
useFactory: controlContainerFactory,
deps: [[new Optional(), NgForm]] } ]
})
export class ParameterSelectComponent implements OnInit {
@Input() index: number;
/**
* The current parameter value of the selected parameter
*/
@Input() parameterValue: ProcessParameter;
/**
* The available script parameters for the script
*/

View File

@@ -1 +1 @@
<input type="hidden" value="true"/>
<input type="hidden" value="true" name="boolean-value-{{index}}" id="boolean-value-{{index}}"/>

View File

@@ -1,5 +1,7 @@
import { Component, OnInit } from '@angular/core';
import { Component, OnInit, Optional } from '@angular/core';
import { ValueInputComponent } from '../value-input.component';
import { ControlContainer, NgForm } from '@angular/forms';
import { controlContainerFactory } from '../../../new-process.component';
/**
* Represents the value of a boolean parameter
@@ -7,7 +9,10 @@ import { ValueInputComponent } from '../value-input.component';
@Component({
selector: 'ds-boolean-value-input',
templateUrl: './boolean-value-input.component.html',
styleUrls: ['./boolean-value-input.component.scss']
styleUrls: ['./boolean-value-input.component.scss'],
viewProviders: [ { provide: ControlContainer,
useFactory: controlContainerFactory,
deps: [[new Optional(), NgForm]] } ]
})
export class BooleanValueInputComponent extends ValueInputComponent<boolean> implements OnInit {
ngOnInit() {

View File

@@ -1,4 +1,4 @@
<input required #string="ngModel" type="text" class="form-control" id="string-value-input" [ngModel]="value" (ngModelChange)="setValue($event)"/>
<input required #string="ngModel" type="text" class="form-control" name="date-value-{{index}}" id="date-value-{{index}}" [ngModel]="value" (ngModelChange)="setValue($event)"/>
<div *ngIf="string.invalid && (string.dirty || string.touched)"
class="alert alert-danger validation-error">
<div *ngIf="string.errors.required">

View File

@@ -1,5 +1,7 @@
import { Component, OnInit } from '@angular/core';
import { Component, OnInit, Optional } from '@angular/core';
import { ValueInputComponent } from '../value-input.component';
import { ControlContainer, NgForm } from '@angular/forms';
import { controlContainerFactory } from '../../../new-process.component';
/**
* Represents the user inputted value of a date parameter
@@ -7,7 +9,10 @@ import { ValueInputComponent } from '../value-input.component';
@Component({
selector: 'ds-date-value-input',
templateUrl: './date-value-input.component.html',
styleUrls: ['./date-value-input.component.scss']
styleUrls: ['./date-value-input.component.scss'],
viewProviders: [ { provide: ControlContainer,
useFactory: controlContainerFactory,
deps: [[new Optional(), NgForm]] } ]
})
export class DateValueInputComponent extends ValueInputComponent<string> {
/**

View File

@@ -1,7 +1,10 @@
<label for="file-upload" class="btn btn-light">
<label for="file-upload-{{index}}" class="d-flex align-items-center">
<span class="btn btn-light">
{{'process.new.parameter.file.upload-button' | translate}}
</span>
<span class="file-name ml-1">{{fileObject?.name}}</span>
</label>
<input requireFile #file="ngModel" type="file" id="file-upload" class="form-control-file d-none" [ngModel]="file" (ngModelChange)="setFile($event)"/>
<input requireFile #file="ngModel" type="file" name="file-upload-{{index}}" id="file-upload-{{index}}" class="form-control-file d-none" [ngModel]="fileObject" (ngModelChange)="setFile($event)"/>
<div *ngIf="file.invalid && (file.dirty || file.touched)"
class="alert alert-danger validation-error">
<div *ngIf="file.errors.required">

View File

@@ -0,0 +1,6 @@
.file-name {
flex: 1;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}

View File

@@ -1,6 +1,6 @@
import { async, ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { FormsModule } from '@angular/forms';
import { FormsModule, NgForm, ReactiveFormsModule } from '@angular/forms';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { MockTranslateLoader } from '../../../../../shared/mocks/mock-translate-loader';
import { By } from '@angular/platform-browser';
@@ -9,7 +9,7 @@ import { NO_ERRORS_SCHEMA } from '@angular/core';
import { FileValueAccessorDirective } from '../../../../../shared/utils/file-value-accessor.directive';
import { FileValidator } from '../../../../../shared/utils/require-file.validator';
describe('FileValueInputComponent', () => {
describe('FileValueInputComponent', () => {
let component: FileValueInputComponent;
let fixture: ComponentFixture<FileValueInputComponent>;

View File

@@ -1,5 +1,7 @@
import { Component } from '@angular/core';
import { Component, Optional } from '@angular/core';
import { ValueInputComponent } from '../value-input.component';
import { ControlContainer, NgForm } from '@angular/forms';
import { controlContainerFactory } from '../../../new-process.component';
/**
* Represents the user inputted value of a file parameter
@@ -7,15 +9,18 @@ import { ValueInputComponent } from '../value-input.component';
@Component({
selector: 'ds-file-value-input',
templateUrl: './file-value-input.component.html',
styleUrls: ['./file-value-input.component.scss']
styleUrls: ['./file-value-input.component.scss'],
viewProviders: [ { provide: ControlContainer,
useFactory: controlContainerFactory,
deps: [[new Optional(), NgForm]] } ]
})
export class FileValueInputComponent extends ValueInputComponent<File> {
/**
* The current value of the file
*/
file: File;
fileObject: File;
setFile(files) {
this.file = files.length > 0 ? files[0] : undefined;
this.updateValue.emit(this.file);
this.fileObject = files.length > 0 ? files[0] : undefined;
this.updateValue.emit(this.fileObject);
}
}

View File

@@ -1,7 +1,7 @@
<div [ngSwitch]="parameter?.type">
<ds-string-value-input *ngSwitchCase="parameterTypes.STRING" (updateValue)="updateValue.emit($event)"></ds-string-value-input>
<ds-string-value-input *ngSwitchCase="parameterTypes.OUTPUT" (updateValue)="updateValue.emit($event)"></ds-string-value-input>
<ds-date-value-input *ngSwitchCase="parameterTypes.DATE" (updateValue)="updateValue.emit($event)"></ds-date-value-input>
<ds-file-value-input *ngSwitchCase="parameterTypes.FILE" (updateValue)="updateValue.emit($event)"></ds-file-value-input>
<ds-boolean-value-input *ngSwitchCase="parameterTypes.BOOLEAN" (updateValue)="updateValue.emit($event)"></ds-boolean-value-input>
<ds-string-value-input *ngSwitchCase="parameterTypes.STRING" (updateValue)="updateValue.emit($event)" [index]="index"></ds-string-value-input>
<ds-string-value-input *ngSwitchCase="parameterTypes.OUTPUT" (updateValue)="updateValue.emit($event)" [index]="index"></ds-string-value-input>
<ds-date-value-input *ngSwitchCase="parameterTypes.DATE" (updateValue)="updateValue.emit($event)" [index]="index"></ds-date-value-input>
<ds-file-value-input *ngSwitchCase="parameterTypes.FILE" (updateValue)="updateValue.emit($event)" [index]="index"></ds-file-value-input>
<ds-boolean-value-input *ngSwitchCase="parameterTypes.BOOLEAN" (updateValue)="updateValue.emit($event)" [index]="index"></ds-boolean-value-input>
</div>

View File

@@ -1,6 +1,8 @@
import { Component, EventEmitter, Input, OnChanges, OnInit, Output } from '@angular/core';
import { Component, EventEmitter, Input, OnChanges, OnInit, Optional, Output } from '@angular/core';
import { ScriptParameterType } from '../../../scripts/script-parameter-type.model';
import { ScriptParameter } from '../../../scripts/script-parameter.model';
import { ControlContainer, NgForm } from '@angular/forms';
import { controlContainerFactory } from '../../new-process.component';
/**
* Component that renders the correct parameter value input based the script parameter's type
@@ -8,9 +10,14 @@ import { ScriptParameter } from '../../../scripts/script-parameter.model';
@Component({
selector: 'ds-parameter-value-input',
templateUrl: './parameter-value-input.component.html',
styleUrls: ['./parameter-value-input.component.scss']
styleUrls: ['./parameter-value-input.component.scss'],
viewProviders: [ { provide: ControlContainer,
useFactory: controlContainerFactory,
deps: [[new Optional(), NgForm]] } ]
})
export class ParameterValueInputComponent {
@Input() index: number;
/**
* The current script parameter
*/

View File

@@ -1,4 +1,4 @@
<input required #string="ngModel" type="text" class="form-control" id="string-value-input" [ngModel]="value" (ngModelChange)="setValue($event)"/>
<input required #string="ngModel" type="text" name="string-value-{{index}}" class="form-control" id="string-value-{{index}}" [ngModel]="value" (ngModelChange)="setValue($event)"/>
<div *ngIf="string.invalid && (string.dirty || string.touched)"
class="alert alert-danger validation-error">
<div *ngIf="string.errors.required">

View File

@@ -1,6 +1,6 @@
import { async, ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { FormsModule } from '@angular/forms';
import { FormsModule, NgForm } from '@angular/forms';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { MockTranslateLoader } from '../../../../../shared/mocks/mock-translate-loader';
import { By } from '@angular/platform-browser';
@@ -20,7 +20,9 @@ describe('StringValueInputComponent', () => {
useClass: MockTranslateLoader
}
})],
declarations: [StringValueInputComponent]
declarations: [StringValueInputComponent],
providers: [
]
})
.compileComponents();
}));

View File

@@ -1,5 +1,7 @@
import { Component } from '@angular/core';
import { Component, Optional } from '@angular/core';
import { ValueInputComponent } from '../value-input.component';
import { ControlContainer, NgForm } from '@angular/forms';
import { controlContainerFactory } from '../../../new-process.component';
/**
* Represents the user inputted value of a string parameter
@@ -7,7 +9,10 @@ import { ValueInputComponent } from '../value-input.component';
@Component({
selector: 'ds-string-value-input',
templateUrl: './string-value-input.component.html',
styleUrls: ['./string-value-input.component.scss']
styleUrls: ['./string-value-input.component.scss'],
viewProviders: [ { provide: ControlContainer,
useFactory: controlContainerFactory,
deps: [[new Optional(), NgForm]] } ]
})
export class StringValueInputComponent extends ValueInputComponent<string> {
/**

View File

@@ -1,9 +1,10 @@
import { EventEmitter, Output } from '@angular/core';
import { EventEmitter, Input, Output } from '@angular/core';
/**
* Abstract class that represents value input components
*/
export abstract class ValueInputComponent<T> {
@Input() index: number;
/**
* Used by the subclasses to emit the value when it's updated
*/

View File

@@ -5,6 +5,7 @@
[parameters]="script.parameters"
[parameterValue]="value"
[removable]="!last"
[index]="i"
(removeParameter)="removeParameter(i)"
(changeParameter)="updateParameter($event, i)"></ds-parameter-select>
</div>

View File

@@ -1,7 +1,10 @@
import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core';
import { Component, EventEmitter, Input, OnChanges, Optional, Output, SimpleChanges } from '@angular/core';
import { Script } from '../../scripts/script.model';
import { ProcessParameter } from '../../processes/process-parameter.model';
import { hasValue } from '../../../shared/empty.util';
import { ControlContainer, NgForm } from '@angular/forms';
import { ScriptParameter } from '../../scripts/script-parameter.model';
import { controlContainerFactory } from '../new-process.component';
/**
* Component that represents the selected list of parameters for a script
@@ -9,7 +12,10 @@ import { hasValue } from '../../../shared/empty.util';
@Component({
selector: 'ds-process-parameters',
templateUrl: './process-parameters.component.html',
styleUrls: ['./process-parameters.component.scss']
styleUrls: ['./process-parameters.component.scss'],
viewProviders: [ { provide: ControlContainer,
useFactory: controlContainerFactory,
deps: [[new Optional(), NgForm]] } ]
})
export class ProcessParametersComponent implements OnChanges {
/**
@@ -42,7 +48,7 @@ export class ProcessParametersComponent implements OnChanges {
*/
initParameters() {
this.parameterValues = [];
this.addParameter();
this.initializeParameter();
}
/**
@@ -67,6 +73,20 @@ export class ProcessParametersComponent implements OnChanges {
this.parameterValues = this.parameterValues.filter((value, i) => i !== index);
}
/**
* Initializes parameter values based on the selected script
*/
initializeParameter() {
if (hasValue(this.script)) {
this.parameterValues = this.script.parameters
.filter((param) => param.mandatory)
.map(
(parameter: ScriptParameter) => Object.assign(new ProcessParameter(), { name: parameter.name })
);
}
this.addParameter();
}
/**
* Adds an empty parameter value to the end of the list
*/

View File

@@ -3,7 +3,16 @@
<table class="table-borderless mt-3 text-secondary">
<tr *ngFor="let param of script?.parameters">
<td>{{param.name}} {{param.nameLong}} {{param.type !== 'boolean' ? '<' + param.type + '>' : ''}}</td>
<td class="align-top text-nowrap">{{param.name}} {{param.nameLong}} <ng-container *ngTemplateOutlet="type; context: param"></ng-container></td>
<td>{{param.description}}</td>
</tr>
</table>
<ng-template #type let-type="type">
<ng-container [ngSwitch]="type">
<span *ngSwitchCase="parameterTypes.DATE"><{{'process.new.parameter.type.value' | translate}}></span>
<span *ngSwitchCase="parameterTypes.STRING"><{{'process.new.parameter.type.value' | translate}}></span>
<span *ngSwitchCase="parameterTypes.OUTPUT"><{{'process.new.parameter.type.value' | translate}}></span>
<span *ngSwitchCase="parameterTypes.FILE"><{{'process.new.parameter.type.file' | translate}}></span>
</ng-container>
</ng-template>

View File

@@ -5,6 +5,10 @@ import { ScriptParameter } from '../../scripts/script-parameter.model';
import { Script } from '../../scripts/script.model';
import { ScriptParameterType } from '../../scripts/script-parameter-type.model';
import { By } from '@angular/platform-browser';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { FormsModule } from '@angular/forms';
import { MockTranslateLoader } from '../../../shared/testing/mock-translate-loader';
describe('ScriptHelpComponent', () => {
let component: ScriptHelpComponent;
@@ -25,7 +29,16 @@ describe('ScriptHelpComponent', () => {
beforeEach(async(() => {
init();
TestBed.configureTestingModule({
declarations: [ ScriptHelpComponent ]
imports: [
FormsModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useClass: MockTranslateLoader
}
})],
declarations: [ ScriptHelpComponent ],
schemas: [NO_ERRORS_SCHEMA]
})
.compileComponents();
}));

View File

@@ -1,5 +1,6 @@
import { Component, Input } from '@angular/core';
import { Script } from '../../scripts/script.model';
import { ScriptParameterType } from '../../scripts/script-parameter-type.model';
/**
* Components that represents a help section for the script use and parameters
@@ -14,4 +15,9 @@ export class ScriptHelpComponent {
* The current script to show the help information for
*/
@Input() script: Script;
/**
* The available script parameter types
*/
parameterTypes = ScriptParameterType;
}

View File

@@ -1,5 +1,5 @@
<div class="form-group" *ngIf="scripts$ | async">
<label for="process-script"><label>{{'process.new.select-script' | translate}}</label></label>
<label for="process-script">{{'process.new.select-script' | translate}}</label>
<select required id="process-script"
class="form-control"
name="script"

View File

@@ -1,4 +1,4 @@
import { Component, EventEmitter, OnDestroy, OnInit, Output } from '@angular/core';
import { Component, EventEmitter, OnDestroy, OnInit, Optional, Output } from '@angular/core';
import { ScriptDataService } from '../../../core/data/processes/script-data.service';
import { Script } from '../../scripts/script.model';
import { Observable, Subscription } from 'rxjs';
@@ -7,6 +7,8 @@ import { PaginatedList } from '../../../core/data/paginated-list';
import { distinctUntilChanged, map, switchMap, take } from 'rxjs/operators';
import { ActivatedRoute, Params, Router } from '@angular/router';
import { hasValue } from '../../../shared/empty.util';
import { ControlContainer, FormControl, NgForm } from '@angular/forms';
import { controlContainerFactory } from '../new-process.component';
const SCRIPT_QUERY_PARAMETER = 'script';
@@ -16,7 +18,10 @@ const SCRIPT_QUERY_PARAMETER = 'script';
@Component({
selector: 'ds-scripts-select',
templateUrl: './scripts-select.component.html',
styleUrls: ['./scripts-select.component.scss']
styleUrls: ['./scripts-select.component.scss'],
viewProviders: [ { provide: ControlContainer,
useFactory: controlContainerFactory,
deps: [[new Optional(), NgForm]] } ]
})
export class ScriptsSelectComponent implements OnInit, OnDestroy {
@Output() select: EventEmitter<Script> = new EventEmitter<Script>();

View File

@@ -8,6 +8,7 @@ import { NewProcessComponent } from './new/new-process.component';
{
path: 'new',
component: NewProcessComponent,
data: { title: 'process.new.title' }
},
])
]