mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
added tests and typedoc
This commit is contained in:
@@ -31,7 +31,7 @@ export class ScriptDataService extends DataService<Script> {
|
||||
super();
|
||||
}
|
||||
|
||||
public invocate(scriptName: string, parameters: ProcessParameter[], files: File[]) {
|
||||
public invoke(scriptName: string, parameters: ProcessParameter[], files: File[]) {
|
||||
this.getBrowseEndpoint().pipe(
|
||||
map((endpoint: string) => new URLCombiner(endpoint, scriptName, 'processes').toString()),
|
||||
map((endpoint: string) => {
|
||||
|
@@ -76,6 +76,9 @@ export class PostRequest extends RestRequest {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request representing a multipart post request
|
||||
*/
|
||||
export class MultipartPostRequest extends RestRequest {
|
||||
public isMultipart = true;
|
||||
constructor(
|
||||
|
@@ -69,6 +69,8 @@ export class DSpaceRESTv2Service {
|
||||
* an optional body for the request
|
||||
* @param options
|
||||
* the HttpOptions object
|
||||
* @param isMultipart
|
||||
* true when this concerns a multipart request
|
||||
* @return {Observable<string>}
|
||||
* An Observable<string> containing the response from the server
|
||||
*/
|
||||
|
@@ -1,8 +1,7 @@
|
||||
<script src="process-parameters/parameter-value-input/value-input.component.ts"></script>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-6">
|
||||
<form #form="ngForm" (ngSubmit)="submitForm()">
|
||||
<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>
|
||||
@@ -13,4 +12,3 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
68
src/app/process-page/new/new-process.component.spec.ts
Normal file
68
src/app/process-page/new/new-process.component.spec.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import { NewProcessComponent } from './new-process.component';
|
||||
import { ScriptDataService } from '../../core/data/processes/script-data.service';
|
||||
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';
|
||||
|
||||
describe('NewProcessComponent', () => {
|
||||
let component: NewProcessComponent;
|
||||
let fixture: ComponentFixture<NewProcessComponent>;
|
||||
let scriptService;
|
||||
let parameterValues;
|
||||
let script;
|
||||
|
||||
function init() {
|
||||
const param1 = new ScriptParameter();
|
||||
const param2 = new ScriptParameter();
|
||||
script = Object.assign(new Script(), { parameters: [param1, param2] });
|
||||
parameterValues = [
|
||||
Object.assign(new ProcessParameter(), { name: '-a', value: 'bla' }),
|
||||
Object.assign(new ProcessParameter(), { name: '-b', value: '123' }),
|
||||
Object.assign(new ProcessParameter(), { name: '-c', value: 'value' }),
|
||||
];
|
||||
scriptService = jasmine.createSpyObj('scriptService', ['invoke'])
|
||||
}
|
||||
|
||||
beforeEach(async(() => {
|
||||
init();
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
FormsModule,
|
||||
TranslateModule.forRoot({
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
useClass: MockTranslateLoader
|
||||
}
|
||||
})],
|
||||
declarations: [NewProcessComponent],
|
||||
providers: [
|
||||
{ provide: ScriptDataService, useValue: scriptService },
|
||||
],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(NewProcessComponent);
|
||||
component = fixture.componentInstance;
|
||||
component.parameters = parameterValues;
|
||||
component.selectedScript = script;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should call invoke on the scriptService on submit', () => {
|
||||
component.submitForm({ invalid: false });
|
||||
expect(scriptService.invoke).toHaveBeenCalled();
|
||||
});
|
||||
});
|
@@ -3,16 +3,35 @@ 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';
|
||||
|
||||
/**
|
||||
* Component to create a new script
|
||||
*/
|
||||
@Component({
|
||||
selector: 'ds-new-process',
|
||||
templateUrl: './new-process.component.html',
|
||||
styleUrls: ['./new-process.component.scss'],
|
||||
})
|
||||
export class NewProcessComponent implements OnInit {
|
||||
/**
|
||||
* The currently selected script
|
||||
*/
|
||||
public selectedScript: Script;
|
||||
|
||||
/**
|
||||
* The process to create
|
||||
*/
|
||||
public process: Process;
|
||||
|
||||
/**
|
||||
* The parameter values to use to start the process
|
||||
*/
|
||||
public parameters: ProcessParameter[];
|
||||
|
||||
/**
|
||||
* Optional files that are used as parameter values
|
||||
*/
|
||||
public files: File[] = [];
|
||||
|
||||
constructor(private scriptService: ScriptDataService) {
|
||||
@@ -22,7 +41,15 @@ export class NewProcessComponent implements OnInit {
|
||||
this.process = new Process();
|
||||
}
|
||||
|
||||
submitForm() {
|
||||
/**
|
||||
* Validates the form, sets the parameters to correct values and invokes the script with the correct parameters
|
||||
* @param form
|
||||
*/
|
||||
submitForm(form: NgForm) {
|
||||
if (!this.validateForm(form)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const stringParameters: ProcessParameter[] = this.parameters.map((parameter: ProcessParameter) => {
|
||||
return {
|
||||
name: parameter.name,
|
||||
@@ -30,14 +57,35 @@ export class NewProcessComponent implements OnInit {
|
||||
};
|
||||
}
|
||||
);
|
||||
this.scriptService.invocate(this.selectedScript.id, stringParameters, this.files)
|
||||
this.scriptService.invoke(this.selectedScript.id, stringParameters, this.files)
|
||||
}
|
||||
|
||||
checkValue(processParameter: ProcessParameter): string {
|
||||
/**
|
||||
* Checks whether the parameter values are files
|
||||
* Replaces file parameters by strings and stores the files in a separate list
|
||||
* @param processParameter The parameter value to check
|
||||
*/
|
||||
private checkValue(processParameter: ProcessParameter): string {
|
||||
if (typeof processParameter.value === 'object') {
|
||||
this.files = [...this.files, processParameter.value];
|
||||
return processParameter.value.name;
|
||||
}
|
||||
}
|
||||
return processParameter.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the form
|
||||
* Returns false if the form is invalid
|
||||
* Returns true if the form is valid
|
||||
* @param form The NgForm object to validate
|
||||
*/
|
||||
private validateForm(form: NgForm) {
|
||||
if (form.invalid) {
|
||||
Object.keys(form.controls).forEach((key) => {
|
||||
form.controls[key].markAsDirty();
|
||||
});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@@ -10,7 +10,7 @@
|
||||
</option>
|
||||
</select>
|
||||
<ds-parameter-value-input [parameter]="selectedScriptParameter" (updateValue)="selectedParameterValue = $event" class="d-block col"></ds-parameter-value-input>
|
||||
<button *ngIf="removable" class="btn btn-light col-1" (click)="removeParameter.emit(parameterValue);"><span class="fas fa-trash"></span></button>
|
||||
<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>
|
||||
|
||||
|
@@ -1,25 +1,71 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ParameterSelectComponent } from './parameter-select.component';
|
||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { ScriptParameter } from '../../../scripts/script-parameter.model';
|
||||
import { ScriptParameterType } from '../../../scripts/script-parameter-type.model';
|
||||
import { By } from '@angular/platform-browser';
|
||||
|
||||
describe('ParameterSelectComponent', () => {
|
||||
let component: ParameterSelectComponent;
|
||||
let fixture: ComponentFixture<ParameterSelectComponent>;
|
||||
let scriptParams: ScriptParameter[];
|
||||
|
||||
function init() {
|
||||
scriptParams = [
|
||||
Object.assign(
|
||||
new ScriptParameter(),
|
||||
{
|
||||
name: '-a',
|
||||
type: ScriptParameterType.BOOLEAN
|
||||
}
|
||||
),
|
||||
Object.assign(
|
||||
new ScriptParameter(),
|
||||
{
|
||||
name: '-f',
|
||||
type: ScriptParameterType.FILE
|
||||
}
|
||||
),
|
||||
]
|
||||
}
|
||||
beforeEach(async(() => {
|
||||
init();
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ ParameterSelectComponent ]
|
||||
imports: [FormsModule],
|
||||
declarations: [ParameterSelectComponent],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
})
|
||||
.compileComponents();
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ParameterSelectComponent);
|
||||
component = fixture.componentInstance;
|
||||
|
||||
component.parameters = scriptParams;
|
||||
component.removable = false;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should show the remove button when removable', () => {
|
||||
component.removable = true;
|
||||
fixture.detectChanges();
|
||||
|
||||
const button = fixture.debugElement.query(By.css('button.remove-button'));
|
||||
expect(button).not.toBeNull();
|
||||
});
|
||||
|
||||
it('should hide the remove button when not removable', () => {
|
||||
component.removable = false;
|
||||
fixture.detectChanges();
|
||||
|
||||
const button = fixture.debugElement.query(By.css('button.remove-button'));
|
||||
expect(button).toBeNull();
|
||||
});
|
||||
});
|
||||
|
@@ -3,16 +3,37 @@ import { ProcessParameter } from '../../../processes/process-parameter.model';
|
||||
import { ScriptParameter } from '../../../scripts/script-parameter.model';
|
||||
import { hasNoValue } from '../../../../shared/empty.util';
|
||||
|
||||
/**
|
||||
* Component to select a single parameter for a process
|
||||
*/
|
||||
@Component({
|
||||
selector: 'ds-parameter-select',
|
||||
templateUrl: './parameter-select.component.html',
|
||||
styleUrls: ['./parameter-select.component.scss']
|
||||
})
|
||||
export class ParameterSelectComponent implements OnInit {
|
||||
/**
|
||||
* The current parameter value of the selected parameter
|
||||
*/
|
||||
@Input() parameterValue: ProcessParameter;
|
||||
/**
|
||||
* The available script parameters for the script
|
||||
*/
|
||||
@Input() parameters: ScriptParameter[];
|
||||
|
||||
/**
|
||||
* Whether or not this selected parameter can be removed from the list
|
||||
*/
|
||||
@Input() removable: boolean;
|
||||
|
||||
/**
|
||||
* Emits the parameter value when it's removed
|
||||
*/
|
||||
@Output() removeParameter: EventEmitter<ProcessParameter> = new EventEmitter<ProcessParameter>();
|
||||
|
||||
/**
|
||||
* Emits the updated parameter value when it changes
|
||||
*/
|
||||
@Output() changeParameter: EventEmitter<ProcessParameter> = new EventEmitter<ProcessParameter>();
|
||||
|
||||
ngOnInit(): void {
|
||||
@@ -21,24 +42,43 @@ export class ParameterSelectComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the script parameter based on the currently selected name
|
||||
*/
|
||||
get selectedScriptParameter(): ScriptParameter {
|
||||
return this.parameters.find((parameter: ScriptParameter) => parameter.name === this.selectedParameter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the currently selected parameter name
|
||||
*/
|
||||
get selectedParameter(): string {
|
||||
return this.parameterValue ? this.parameterValue.name : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the currently selected parameter based on the provided parameter name
|
||||
* Emits the new value from the changeParameter output
|
||||
* @param value The parameter name to set
|
||||
*/
|
||||
set selectedParameter(value: string) {
|
||||
this.parameterValue.name = value;
|
||||
this.selectedParameterValue = undefined;
|
||||
this.changeParameter.emit(this.parameterValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently selected parameter value
|
||||
*/
|
||||
get selectedParameterValue(): any {
|
||||
return this.parameterValue ? this.parameterValue.value : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the currently selected value for the parameter
|
||||
* Emits the new value from the changeParameter output
|
||||
* @param value The parameter value to set
|
||||
*/
|
||||
set selectedParameterValue(value: any) {
|
||||
this.parameterValue.value = value;
|
||||
this.changeParameter.emit(this.parameterValue);
|
||||
|
@@ -1,25 +1,32 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { BooleanValueInputComponent } from './boolean-value-input.component';
|
||||
import { DebugElement } from '@angular/core';
|
||||
import { By } from '@angular/platform-browser';
|
||||
|
||||
describe('StringValueInputComponent', () => {
|
||||
describe('BooleanValueInputComponent', () => {
|
||||
let component: BooleanValueInputComponent;
|
||||
let fixture: ComponentFixture<BooleanValueInputComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ BooleanValueInputComponent ]
|
||||
declarations: [BooleanValueInputComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(BooleanValueInputComponent);
|
||||
component = fixture.componentInstance;
|
||||
spyOn(component.updateValue, 'emit');
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should emit true onInit', () => {
|
||||
expect(component.updateValue.emit).toHaveBeenCalledWith(true);
|
||||
});
|
||||
});
|
||||
|
@@ -1,6 +1,9 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { ValueInputComponent } from '../value-input.component';
|
||||
|
||||
/**
|
||||
* Represents the value of a boolean parameter
|
||||
*/
|
||||
@Component({
|
||||
selector: 'ds-boolean-value-input',
|
||||
templateUrl: './boolean-value-input.component.html',
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<input required #string="ngModel" type="date" class="form-control" id="string-value-input" [ngModel]="value" (ngModelChange)="setValue($event)"/>
|
||||
<input required #string="ngModel" type="text" class="form-control" id="string-value-input" [ngModel]="value" (ngModelChange)="setValue($event)"/>
|
||||
<div *ngIf="string.invalid && (string.dirty || string.touched)"
|
||||
class="alert alert-danger">
|
||||
class="alert alert-danger validation-error">
|
||||
<div *ngIf="string.errors.required">
|
||||
{{'process.new.parameter.string.required' | translate}}
|
||||
</div>
|
||||
|
@@ -1,16 +1,28 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { async, ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
|
||||
|
||||
import { DateValueInputComponent } from './date-value-input.component';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
||||
import { MockTranslateLoader } from '../../../../../shared/mocks/mock-translate-loader';
|
||||
import { By } from '@angular/platform-browser';
|
||||
|
||||
describe('StringValueInputComponent', () => {
|
||||
describe('DateValueInputComponent', () => {
|
||||
let component: DateValueInputComponent;
|
||||
let fixture: ComponentFixture<DateValueInputComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ DateValueInputComponent ]
|
||||
imports: [
|
||||
FormsModule,
|
||||
TranslateModule.forRoot({
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
useClass: MockTranslateLoader
|
||||
}
|
||||
})],
|
||||
declarations: [DateValueInputComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -22,4 +34,37 @@ describe('StringValueInputComponent', () => {
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should not show a validation error if the input field was left untouched but left empty', () => {
|
||||
const validationError = fixture.debugElement.query(By.css('.validation-error'));
|
||||
expect(validationError).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should show a validation error if the input field was touched but left empty', fakeAsync(() => {
|
||||
component.value = '';
|
||||
fixture.detectChanges();
|
||||
tick();
|
||||
|
||||
const input = fixture.debugElement.query(By.css('input'));
|
||||
input.triggerEventHandler('blur', null);
|
||||
|
||||
fixture.detectChanges();
|
||||
|
||||
const validationError = fixture.debugElement.query(By.css('.validation-error'));
|
||||
expect(validationError).toBeTruthy();
|
||||
}));
|
||||
|
||||
it('should not show a validation error if the input field was touched but not left empty', fakeAsync(() => {
|
||||
component.value = 'testValue';
|
||||
fixture.detectChanges();
|
||||
tick();
|
||||
|
||||
const input = fixture.debugElement.query(By.css('input'));
|
||||
input.triggerEventHandler('blur', null);
|
||||
|
||||
fixture.detectChanges();
|
||||
|
||||
const validationError = fixture.debugElement.query(By.css('.validation-error'));
|
||||
expect(validationError).toBeFalsy();
|
||||
}));
|
||||
});
|
||||
|
@@ -1,12 +1,18 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { ValueInputComponent } from '../value-input.component';
|
||||
|
||||
/**
|
||||
* Represents the user inputted value of a date parameter
|
||||
*/
|
||||
@Component({
|
||||
selector: 'ds-date-value-input',
|
||||
templateUrl: './date-value-input.component.html',
|
||||
styleUrls: ['./date-value-input.component.scss']
|
||||
})
|
||||
export class DateValueInputComponent extends ValueInputComponent<string> {
|
||||
/**
|
||||
* The current value of the date string
|
||||
*/
|
||||
value: string;
|
||||
|
||||
setValue(value) {
|
||||
|
@@ -3,7 +3,7 @@
|
||||
</label>
|
||||
<input requireFile #file="ngModel" type="file" id="file-upload" class="form-control-file d-none" [ngModel]="file" (ngModelChange)="setFile($event)"/>
|
||||
<div *ngIf="file.invalid && (file.dirty || file.touched)"
|
||||
class="alert alert-danger">
|
||||
class="alert alert-danger validation-error">
|
||||
<div *ngIf="file.errors.required">
|
||||
{{'process.new.parameter.file.required' | translate}}
|
||||
</div>
|
||||
|
@@ -1,6 +1,13 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { async, ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
|
||||
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
||||
import { MockTranslateLoader } from '../../../../../shared/mocks/mock-translate-loader';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { FileValueInputComponent } from './file-value-input.component';
|
||||
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', () => {
|
||||
let component: FileValueInputComponent;
|
||||
@@ -8,9 +15,19 @@ describe('FileValueInputComponent', () => {
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ FileValueInputComponent ]
|
||||
imports: [
|
||||
FormsModule,
|
||||
TranslateModule.forRoot({
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
useClass: MockTranslateLoader
|
||||
}
|
||||
})],
|
||||
declarations: [FileValueInputComponent, FileValueAccessorDirective, FileValidator],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
|
||||
})
|
||||
.compileComponents();
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -22,4 +39,19 @@ describe('FileValueInputComponent', () => {
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should not show a validation error if the input field was left untouched but left empty', () => {
|
||||
const validationError = fixture.debugElement.query(By.css('.validation-error'));
|
||||
expect(validationError).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should show a validation error if the input field was touched but left empty', () => {
|
||||
const input = fixture.debugElement.query(By.css('input'));
|
||||
input.triggerEventHandler('blur', null);
|
||||
|
||||
fixture.detectChanges();
|
||||
|
||||
const validationError = fixture.debugElement.query(By.css('.validation-error'));
|
||||
expect(validationError).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
@@ -1,16 +1,21 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { ValueInputComponent } from '../value-input.component';
|
||||
|
||||
/**
|
||||
* Represents the user inputted value of a file parameter
|
||||
*/
|
||||
@Component({
|
||||
selector: 'ds-file-value-input',
|
||||
templateUrl: './file-value-input.component.html',
|
||||
styleUrls: ['./file-value-input.component.scss']
|
||||
})
|
||||
export class FileValueInputComponent extends ValueInputComponent<File> {
|
||||
/**
|
||||
* The current value of the file
|
||||
*/
|
||||
file: File;
|
||||
setFile(files) {
|
||||
this.file = files.length > 0 ? files[0] : undefined;
|
||||
console.log(this.file);
|
||||
this.updateValue.emit(this.file);
|
||||
}
|
||||
}
|
||||
|
@@ -1,25 +1,105 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ParameterValueInputComponent } from './parameter-value-input.component';
|
||||
import { ScriptParameter } from '../../../scripts/script-parameter.model';
|
||||
import { ScriptParameterType } from '../../../scripts/script-parameter-type.model';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { BooleanValueInputComponent } from './boolean-value-input/boolean-value-input.component';
|
||||
import { StringValueInputComponent } from './string-value-input/string-value-input.component';
|
||||
import { FileValueInputComponent } from './file-value-input/file-value-input.component';
|
||||
import { DateValueInputComponent } from './date-value-input/date-value-input.component';
|
||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
||||
import { MockTranslateLoader } from '../../../../shared/testing/mock-translate-loader';
|
||||
import { FileValueAccessorDirective } from '../../../../shared/utils/file-value-accessor.directive';
|
||||
import { FileValidator } from '../../../../shared/utils/require-file.validator';
|
||||
|
||||
describe('ParameterValueInputComponent', () => {
|
||||
let component: ParameterValueInputComponent;
|
||||
let fixture: ComponentFixture<ParameterValueInputComponent>;
|
||||
let booleanParameter;
|
||||
let stringParameter;
|
||||
let fileParameter;
|
||||
let dateParameter;
|
||||
let outputParameter;
|
||||
|
||||
function init() {
|
||||
booleanParameter = Object.assign(new ScriptParameter(), { type: ScriptParameterType.BOOLEAN });
|
||||
stringParameter = Object.assign(new ScriptParameter(), { type: ScriptParameterType.STRING });
|
||||
fileParameter = Object.assign(new ScriptParameter(), { type: ScriptParameterType.FILE });
|
||||
dateParameter = Object.assign(new ScriptParameter(), { type: ScriptParameterType.DATE });
|
||||
outputParameter = Object.assign(new ScriptParameter(), { type: ScriptParameterType.OUTPUT });
|
||||
}
|
||||
|
||||
beforeEach(async(() => {
|
||||
init();
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ ParameterValueInputComponent ]
|
||||
imports: [
|
||||
FormsModule,
|
||||
TranslateModule.forRoot({
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
useClass: MockTranslateLoader
|
||||
}
|
||||
})],
|
||||
declarations: [
|
||||
ParameterValueInputComponent,
|
||||
BooleanValueInputComponent,
|
||||
StringValueInputComponent,
|
||||
FileValueInputComponent,
|
||||
DateValueInputComponent,
|
||||
FileValueAccessorDirective,
|
||||
FileValidator
|
||||
],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
})
|
||||
.compileComponents();
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ParameterValueInputComponent);
|
||||
component = fixture.componentInstance;
|
||||
component.parameter = stringParameter;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should show a BooleanValueInputComponent when the parameter type is boolean', () => {
|
||||
component.parameter = booleanParameter;
|
||||
fixture.detectChanges();
|
||||
const valueInput = fixture.debugElement.query(By.directive(BooleanValueInputComponent));
|
||||
expect(valueInput).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should show a StringValueInputComponent when the parameter type is string', () => {
|
||||
component.parameter = stringParameter;
|
||||
fixture.detectChanges();
|
||||
const valueInput = fixture.debugElement.query(By.directive(StringValueInputComponent));
|
||||
expect(valueInput).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should show a FileValueInputComponent when the parameter type is file', () => {
|
||||
component.parameter = fileParameter;
|
||||
fixture.detectChanges();
|
||||
const valueInput = fixture.debugElement.query(By.directive(FileValueInputComponent));
|
||||
expect(valueInput).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should show a DateValueInputComponent when the parameter type is date', () => {
|
||||
component.parameter = dateParameter;
|
||||
fixture.detectChanges();
|
||||
const valueInput = fixture.debugElement.query(By.directive(DateValueInputComponent));
|
||||
expect(valueInput).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should show a StringValueInputComponent when the parameter type is output', () => {
|
||||
component.parameter = outputParameter;
|
||||
fixture.detectChanges();
|
||||
const valueInput = fixture.debugElement.query(By.directive(StringValueInputComponent));
|
||||
expect(valueInput).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
@@ -2,13 +2,27 @@ import { Component, EventEmitter, Input, OnChanges, OnInit, Output } from '@angu
|
||||
import { ScriptParameterType } from '../../../scripts/script-parameter-type.model';
|
||||
import { ScriptParameter } from '../../../scripts/script-parameter.model';
|
||||
|
||||
/**
|
||||
* Component that renders the correct parameter value input based the script parameter's type
|
||||
*/
|
||||
@Component({
|
||||
selector: 'ds-parameter-value-input',
|
||||
templateUrl: './parameter-value-input.component.html',
|
||||
styleUrls: ['./parameter-value-input.component.scss']
|
||||
})
|
||||
export class ParameterValueInputComponent {
|
||||
/**
|
||||
* The current script parameter
|
||||
*/
|
||||
@Input() parameter: ScriptParameter;
|
||||
|
||||
/**
|
||||
* Emits the value of the input when its updated
|
||||
*/
|
||||
@Output() updateValue: EventEmitter<any> = new EventEmitter();
|
||||
|
||||
/**
|
||||
* The available script parameter types
|
||||
*/
|
||||
parameterTypes = ScriptParameterType;
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<input required #string="ngModel" type="text" class="form-control" id="string-value-input" [ngModel]="value" (ngModelChange)="setValue($event)"/>
|
||||
<div *ngIf="string.invalid && (string.dirty || string.touched)"
|
||||
class="alert alert-danger">
|
||||
class="alert alert-danger validation-error">
|
||||
<div *ngIf="string.errors.required">
|
||||
{{'process.new.parameter.string.required' | translate}}
|
||||
</div>
|
||||
|
@@ -1,5 +1,9 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { async, ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
|
||||
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
||||
import { MockTranslateLoader } from '../../../../../shared/mocks/mock-translate-loader';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { StringValueInputComponent } from './string-value-input.component';
|
||||
|
||||
describe('StringValueInputComponent', () => {
|
||||
@@ -8,9 +12,17 @@ describe('StringValueInputComponent', () => {
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ StringValueInputComponent ]
|
||||
imports: [
|
||||
FormsModule,
|
||||
TranslateModule.forRoot({
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
useClass: MockTranslateLoader
|
||||
}
|
||||
})],
|
||||
declarations: [StringValueInputComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -22,4 +34,37 @@ describe('StringValueInputComponent', () => {
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should not show a validation error if the input field was left untouched but left empty', () => {
|
||||
const validationError = fixture.debugElement.query(By.css('.validation-error'));
|
||||
expect(validationError).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should show a validation error if the input field was touched but left empty', fakeAsync(() => {
|
||||
component.value = '';
|
||||
fixture.detectChanges();
|
||||
tick();
|
||||
|
||||
const input = fixture.debugElement.query(By.css('input'));
|
||||
input.triggerEventHandler('blur', null);
|
||||
|
||||
fixture.detectChanges();
|
||||
|
||||
const validationError = fixture.debugElement.query(By.css('.validation-error'));
|
||||
expect(validationError).toBeTruthy();
|
||||
}));
|
||||
|
||||
it('should not show a validation error if the input field was touched but not left empty', fakeAsync(() => {
|
||||
component.value = 'testValue';
|
||||
fixture.detectChanges();
|
||||
tick();
|
||||
|
||||
const input = fixture.debugElement.query(By.css('input'));
|
||||
input.triggerEventHandler('blur', null);
|
||||
|
||||
fixture.detectChanges();
|
||||
|
||||
const validationError = fixture.debugElement.query(By.css('.validation-error'));
|
||||
expect(validationError).toBeFalsy();
|
||||
}));
|
||||
});
|
||||
|
@@ -1,12 +1,18 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Component } from '@angular/core';
|
||||
import { ValueInputComponent } from '../value-input.component';
|
||||
|
||||
/**
|
||||
* Represents the user inputted value of a string parameter
|
||||
*/
|
||||
@Component({
|
||||
selector: 'ds-string-value-input',
|
||||
templateUrl: './string-value-input.component.html',
|
||||
styleUrls: ['./string-value-input.component.scss']
|
||||
})
|
||||
export class StringValueInputComponent extends ValueInputComponent<string> {
|
||||
/**
|
||||
* The current value of the string
|
||||
*/
|
||||
value: string;
|
||||
|
||||
setValue(value) {
|
||||
|
@@ -1,5 +1,11 @@
|
||||
import { EventEmitter, Output } from '@angular/core';
|
||||
|
||||
/**
|
||||
* Abstract class that represents value input components
|
||||
*/
|
||||
export abstract class ValueInputComponent<T> {
|
||||
/**
|
||||
* Used by the subclasses to emit the value when it's updated
|
||||
*/
|
||||
@Output() updateValue: EventEmitter<T> = new EventEmitter<T>()
|
||||
}
|
||||
|
@@ -1,25 +1,64 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ProcessParametersComponent } from './process-parameters.component';
|
||||
import { ProcessParameter } from '../../processes/process-parameter.model';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { ParameterSelectComponent } from './parameter-select/parameter-select.component';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
||||
import { MockTranslateLoader } from '../../../shared/testing/mock-translate-loader';
|
||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import { Script } from '../../scripts/script.model';
|
||||
import { ScriptParameter } from '../../scripts/script-parameter.model';
|
||||
|
||||
describe('ProcessParametersComponent', () => {
|
||||
let component: ProcessParametersComponent;
|
||||
let fixture: ComponentFixture<ProcessParametersComponent>;
|
||||
let parameterValues;
|
||||
let script;
|
||||
|
||||
function init() {
|
||||
const param1 = new ScriptParameter();
|
||||
const param2 = new ScriptParameter();
|
||||
script = Object.assign(new Script(), { parameters: [param1, param2] });
|
||||
parameterValues = [
|
||||
Object.assign(new ProcessParameter(), { name: '-a', value: 'bla' }),
|
||||
Object.assign(new ProcessParameter(), { name: '-b', value: '123' }),
|
||||
Object.assign(new ProcessParameter(), { name: '-c', value: 'value' }),
|
||||
]
|
||||
}
|
||||
|
||||
beforeEach(async(() => {
|
||||
init();
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ ProcessParametersComponent ]
|
||||
imports: [
|
||||
FormsModule,
|
||||
TranslateModule.forRoot({
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
useClass: MockTranslateLoader
|
||||
}
|
||||
})],
|
||||
declarations: [ProcessParametersComponent, ParameterSelectComponent],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
})
|
||||
.compileComponents();
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ProcessParametersComponent);
|
||||
component = fixture.componentInstance;
|
||||
component.script = script;
|
||||
component.parameterValues = parameterValues;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render a ParameterSelectComponent for each parameter value of the component', () => {
|
||||
const selectComponents = fixture.debugElement.queryAll(By.directive(ParameterSelectComponent));
|
||||
expect(selectComponents.length).toBe(parameterValues.length);
|
||||
});
|
||||
});
|
||||
|
@@ -3,27 +3,54 @@ import { Script } from '../../scripts/script.model';
|
||||
import { ProcessParameter } from '../../processes/process-parameter.model';
|
||||
import { hasValue } from '../../../shared/empty.util';
|
||||
|
||||
/**
|
||||
* Component that represents the selected list of parameters for a script
|
||||
*/
|
||||
@Component({
|
||||
selector: 'ds-process-parameters',
|
||||
templateUrl: './process-parameters.component.html',
|
||||
styleUrls: ['./process-parameters.component.scss']
|
||||
})
|
||||
export class ProcessParametersComponent implements OnChanges {
|
||||
/**
|
||||
* The currently selected script
|
||||
*/
|
||||
@Input() script: Script;
|
||||
/**
|
||||
* Emits the parameter values when they're updated
|
||||
*/
|
||||
@Output() updateParameters: EventEmitter<ProcessParameter[]> = new EventEmitter();
|
||||
|
||||
/**
|
||||
* The current parameter values
|
||||
*/
|
||||
parameterValues: ProcessParameter[];
|
||||
|
||||
/**
|
||||
* Makes sure the parameters are reset when the script changes
|
||||
* @param changes
|
||||
*/
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
if (changes.script) {
|
||||
this.initParameters()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Empties the parameter values
|
||||
* Initializes the first parameter value
|
||||
*/
|
||||
initParameters() {
|
||||
this.parameterValues = [];
|
||||
this.addParameter();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a single parameter value using its new value and index
|
||||
* Adds a new parameter when the last of the parameter values is changed
|
||||
* @param processParameter The new value of the parameter
|
||||
* @param index The index of the parameter
|
||||
*/
|
||||
updateParameter(processParameter: ProcessParameter, index: number) {
|
||||
this.parameterValues[index] = processParameter;
|
||||
if (index === this.parameterValues.length - 1) {
|
||||
@@ -32,10 +59,17 @@ export class ProcessParametersComponent implements OnChanges {
|
||||
this.updateParameters.emit(this.parameterValues.filter((param: ProcessParameter) => hasValue(param.name)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a parameter value from the list
|
||||
* @param index The index of the parameter to remove
|
||||
*/
|
||||
removeParameter(index: number) {
|
||||
this.parameterValues = this.parameterValues.filter((value, i) => i !== index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an empty parameter value to the end of the list
|
||||
*/
|
||||
addParameter() {
|
||||
this.parameterValues = [...this.parameterValues, new ProcessParameter()];
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<h3>{{script?.name}}</h3>
|
||||
<span>{{script?.description}}</span>
|
||||
|
||||
<table class="table-border less mt-3">
|
||||
<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>{{param.description}}</td>
|
||||
|
@@ -1,12 +1,29 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ScriptHelpComponent } from './script-help.component';
|
||||
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';
|
||||
|
||||
describe('ScriptHelpComponent', () => {
|
||||
let component: ScriptHelpComponent;
|
||||
let fixture: ComponentFixture<ScriptHelpComponent>;
|
||||
let script;
|
||||
|
||||
function init() {
|
||||
const param1 = Object.assign(
|
||||
new ScriptParameter(),
|
||||
{name: '-d', description: 'Lorem ipsum dolor sit amet,', type: ScriptParameterType.DATE}
|
||||
);
|
||||
const param2 = Object.assign(
|
||||
new ScriptParameter(),
|
||||
{name: '-f', description: 'consetetur sadipscing elitr', type: ScriptParameterType.BOOLEAN}
|
||||
);
|
||||
script = Object.assign(new Script(), { parameters: [param1, param2] });
|
||||
}
|
||||
beforeEach(async(() => {
|
||||
init();
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ ScriptHelpComponent ]
|
||||
})
|
||||
@@ -16,10 +33,20 @@ describe('ScriptHelpComponent', () => {
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ScriptHelpComponent);
|
||||
component = fixture.componentInstance;
|
||||
component.script = script;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should show the name and description for each parameter of the script', () => {
|
||||
const rows = fixture.debugElement.queryAll(By.css('tr'));
|
||||
expect(rows.length).toBe(script.parameters.length);
|
||||
script.parameters.forEach((parameter, index) => {
|
||||
expect(rows[index].queryAll(By.css('td'))[0].nativeElement.textContent).toContain(parameter.name);
|
||||
expect(rows[index].queryAll(By.css('td'))[1].nativeElement.textContent.trim()).toEqual(parameter.description);
|
||||
})
|
||||
});
|
||||
});
|
||||
|
@@ -1,11 +1,17 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { Script } from '../../scripts/script.model';
|
||||
|
||||
/**
|
||||
* Components that represents a help section for the script use and parameters
|
||||
*/
|
||||
@Component({
|
||||
selector: 'ds-script-help',
|
||||
templateUrl: './script-help.component.html',
|
||||
styleUrls: ['./script-help.component.scss']
|
||||
})
|
||||
export class ScriptHelpComponent {
|
||||
/**
|
||||
* The current script to show the help information for
|
||||
*/
|
||||
@Input() script: Script;
|
||||
}
|
||||
|
@@ -12,7 +12,7 @@
|
||||
</select>
|
||||
|
||||
<div *ngIf="script.invalid && (script.dirty || script.touched)"
|
||||
class="alert alert-danger">
|
||||
class="alert alert-danger validation-error">
|
||||
<div *ngIf="script.errors.required">
|
||||
{{'process.new.select-script.required' | translate}}
|
||||
</div>
|
||||
|
@@ -1,25 +1,99 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { async, ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
|
||||
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { ScriptsSelectComponent } from './scripts-select.component';
|
||||
import { MockTranslateLoader } from '../../../shared/testing/mock-translate-loader';
|
||||
import { Script } from '../../scripts/script.model';
|
||||
import { ScriptDataService } from '../../../core/data/processes/script-data.service';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { RouterStub } from '../../../shared/testing/router-stub';
|
||||
import { ActivatedRouteStub } from '../../../shared/testing/active-router-stub';
|
||||
import { createSuccessfulRemoteDataObject$ } from '../../../shared/testing/utils';
|
||||
import { PaginatedList } from '../../../core/data/paginated-list';
|
||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
|
||||
describe('ScriptsSelectComponent', () => {
|
||||
let component: ScriptsSelectComponent;
|
||||
let fixture: ComponentFixture<ScriptsSelectComponent>;
|
||||
let scriptService;
|
||||
let script1;
|
||||
let script2;
|
||||
|
||||
function init() {
|
||||
script1 = new Script();
|
||||
script2 = new Script();
|
||||
scriptService = jasmine.createSpyObj('scriptService',
|
||||
{
|
||||
findAll: createSuccessfulRemoteDataObject$(new PaginatedList(undefined, [script1, script2]))
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
beforeEach(async(() => {
|
||||
init();
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ ScriptsSelectComponent ]
|
||||
imports: [
|
||||
FormsModule,
|
||||
TranslateModule.forRoot({
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
useClass: MockTranslateLoader
|
||||
}
|
||||
})],
|
||||
declarations: [ScriptsSelectComponent],
|
||||
providers: [
|
||||
{ provide: ScriptDataService, useValue: scriptService },
|
||||
{ provide: Router, useClass: RouterStub },
|
||||
{ provide: ActivatedRoute, useValue: new ActivatedRouteStub() },
|
||||
],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
})
|
||||
.compileComponents();
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ScriptsSelectComponent);
|
||||
component = fixture.componentInstance;
|
||||
(component as any)._selectedScript = new Script();
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should not show a validation error if the input field was left untouched but left empty', () => {
|
||||
const validationError = fixture.debugElement.query(By.css('.validation-error'));
|
||||
expect(validationError).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should show a validation error if the input field was touched but left empty', fakeAsync(() => {
|
||||
(component as any)._selectedScript.id = '';
|
||||
fixture.detectChanges();
|
||||
tick();
|
||||
|
||||
const select = fixture.debugElement.query(By.css('select'));
|
||||
select.triggerEventHandler('blur', null);
|
||||
|
||||
fixture.detectChanges();
|
||||
|
||||
const validationError = fixture.debugElement.query(By.css('.validation-error'));
|
||||
expect(validationError).toBeTruthy();
|
||||
}));
|
||||
|
||||
it('should not show a validation error if the input field was touched but not left empty', fakeAsync(() => {
|
||||
(component as any)._selectedScript.id = 'testValue';
|
||||
fixture.detectChanges();
|
||||
tick();
|
||||
|
||||
const select = fixture.debugElement.query(By.css('select'));
|
||||
select.triggerEventHandler('blur', null);
|
||||
|
||||
fixture.detectChanges();
|
||||
|
||||
const validationError = fixture.debugElement.query(By.css('.validation-error'));
|
||||
expect(validationError).toBeFalsy();
|
||||
}));
|
||||
});
|
||||
|
@@ -6,10 +6,13 @@ import { getRemoteDataPayload, getSucceededRemoteData } from '../../../core/shar
|
||||
import { PaginatedList } from '../../../core/data/paginated-list';
|
||||
import { distinctUntilChanged, map, switchMap, take } from 'rxjs/operators';
|
||||
import { ActivatedRoute, Params, Router } from '@angular/router';
|
||||
import { hasValue, hasValueOperator } from '../../../shared/empty.util';
|
||||
import { hasValue } from '../../../shared/empty.util';
|
||||
|
||||
const SCRIPT_QUERY_PARAMETER = 'script';
|
||||
|
||||
/**
|
||||
* Component used to select a script
|
||||
*/
|
||||
@Component({
|
||||
selector: 'ds-scripts-select',
|
||||
templateUrl: './scripts-select.component.html',
|
||||
@@ -28,6 +31,10 @@ export class ScriptsSelectComponent implements OnInit, OnDestroy {
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets all available scripts
|
||||
* Checks if the route contains a script ID and auto selects this scripts
|
||||
*/
|
||||
ngOnInit() {
|
||||
this.scripts$ = this.scriptService.findAll({ elementsPerPage: Number.MAX_SAFE_INTEGER })
|
||||
.pipe(
|
||||
@@ -55,10 +62,17 @@ export class ScriptsSelectComponent implements OnInit, OnDestroy {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the identifier of the selected script
|
||||
*/
|
||||
get selectedScript(): string {
|
||||
return this._selectedScript ? this._selectedScript.id : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the currently selected script by navigating to the correct route using the scripts ID
|
||||
* @param value The identifier of the script
|
||||
*/
|
||||
set selectedScript(value: string) {
|
||||
this.router.navigate([],
|
||||
{
|
||||
|
@@ -8,6 +8,9 @@ import { excludeFromEquals } from '../../core/utilities/equals.decorators';
|
||||
import { ResourceType } from '../../core/shared/resource-type';
|
||||
import { typedObject } from '../../core/cache/builders/build-decorators';
|
||||
|
||||
/**
|
||||
* Object representing a process
|
||||
*/
|
||||
@typedObject
|
||||
export class Process implements CacheableObject {
|
||||
static type = PROCESS;
|
||||
|
@@ -7,6 +7,9 @@ import { typedObject } from '../../core/cache/builders/build-decorators';
|
||||
import { excludeFromEquals } from '../../core/utilities/equals.decorators';
|
||||
import { ResourceType } from '../../core/shared/resource-type';
|
||||
|
||||
/**
|
||||
* Object representing a script
|
||||
*/
|
||||
@typedObject
|
||||
export class Script implements CacheableObject {
|
||||
static type = SCRIPT;
|
||||
|
@@ -113,15 +113,12 @@ export class UploaderComponent {
|
||||
ngAfterViewInit() {
|
||||
// Maybe to remove: needed to avoid CORS issue with our temp upload server
|
||||
this.uploader.onAfterAddingFile = ((item) => {
|
||||
console.log(item);
|
||||
|
||||
item.withCredentials = false;
|
||||
});
|
||||
if (isUndefined(this.onBeforeUpload)) {
|
||||
this.onBeforeUpload = () => {return};
|
||||
}
|
||||
this.uploader.onBeforeUploadItem = (item) => {
|
||||
|
||||
if (item.url !== this.uploader.options.url) {
|
||||
item.url = this.uploader.options.url;
|
||||
}
|
||||
@@ -146,8 +143,6 @@ export class UploaderComponent {
|
||||
};
|
||||
this.uploader.onProgressAll = () => this.onProgress();
|
||||
this.uploader.onProgressItem = () => this.onProgress();
|
||||
|
||||
console.log(this.uploader.options.formatDataFunction());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -13,6 +13,9 @@ import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/forms';
|
||||
{ provide: NG_VALUE_ACCESSOR, useExisting: FileValueAccessorDirective, multi: true }
|
||||
]
|
||||
})
|
||||
/**
|
||||
* Value accessor directive for inputs of type 'file'
|
||||
*/
|
||||
export class FileValueAccessorDirective implements ControlValueAccessor {
|
||||
value: any;
|
||||
onChange = (_) => { /* empty */ };
|
||||
|
@@ -8,9 +8,12 @@ import {NG_VALIDATORS, Validator, FormControl} from '@angular/forms';
|
||||
{ provide: NG_VALIDATORS, useExisting: FileValidator, multi: true },
|
||||
]
|
||||
})
|
||||
/**
|
||||
* Validator directive to validate if a file is selected
|
||||
*/
|
||||
export class FileValidator implements Validator {
|
||||
static validate(c: FormControl): {[key: string]: any} {
|
||||
return c.value == null || c.value.length === 0 ? { required : true} : null;
|
||||
return c.value == null || c.value.length === 0 ? { required : true } : null;
|
||||
}
|
||||
|
||||
validate(c: FormControl): {[key: string]: any} {
|
||||
|
Reference in New Issue
Block a user