mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 18:14:17 +00:00
fixed file upload, styling, boolean/date/output inputs
This commit is contained in:
@@ -1614,6 +1614,24 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
"process.new.select-parameters": "Parameters",
|
||||||
|
|
||||||
|
"process.new.submit": "Submit",
|
||||||
|
|
||||||
|
"process.new.select-script": "Script",
|
||||||
|
|
||||||
|
"process.new.select-script.placeholder": "Choose a script...",
|
||||||
|
|
||||||
|
"process.new.select-script.required": "Script is required",
|
||||||
|
|
||||||
|
"process.new.parameter.file.upload-button": "Select file...",
|
||||||
|
|
||||||
|
"process.new.parameter.file.required": "Please select a file",
|
||||||
|
|
||||||
|
"process.new.parameter.string.required": "Parameter value is required",
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"publication.listelement.badge": "Publication",
|
"publication.listelement.badge": "Publication",
|
||||||
|
|
||||||
"publication.page.description": "Description",
|
"publication.page.description": "Description",
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { DataService } from '../data.service';
|
import { DataService } from '../data.service';
|
||||||
import { RequestService } from '../request.service';
|
|
||||||
import { RemoteDataBuildService } from '../../cache/builders/remote-data-build.service';
|
import { RemoteDataBuildService } from '../../cache/builders/remote-data-build.service';
|
||||||
import { Store } from '@ngrx/store';
|
import { Store } from '@ngrx/store';
|
||||||
import { CoreState } from '../../core.reducers';
|
import { CoreState } from '../../core.reducers';
|
||||||
@@ -10,6 +9,11 @@ import { NotificationsService } from '../../../shared/notifications/notification
|
|||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { DefaultChangeAnalyzer } from '../default-change-analyzer.service';
|
import { DefaultChangeAnalyzer } from '../default-change-analyzer.service';
|
||||||
import { Script } from '../../../process-page/scripts/script.model';
|
import { Script } from '../../../process-page/scripts/script.model';
|
||||||
|
import { ProcessParameter } from '../../../process-page/processes/process-parameter.model';
|
||||||
|
import { map } from 'rxjs/operators';
|
||||||
|
import { URLCombiner } from '../../url-combiner/url-combiner';
|
||||||
|
import { MultipartPostRequest, RestRequest } from '../request.models';
|
||||||
|
import { RequestService } from '../request.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ScriptDataService extends DataService<Script> {
|
export class ScriptDataService extends DataService<Script> {
|
||||||
@@ -26,4 +30,24 @@ export class ScriptDataService extends DataService<Script> {
|
|||||||
protected comparator: DefaultChangeAnalyzer<Script>) {
|
protected comparator: DefaultChangeAnalyzer<Script>) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public invocate(scriptName: string, parameters: ProcessParameter[], files: File[]) {
|
||||||
|
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)
|
||||||
|
}),
|
||||||
|
map((request: RestRequest) => this.requestService.configure(request))
|
||||||
|
).subscribe();
|
||||||
|
}
|
||||||
|
|
||||||
|
private getInvocationFormData(parameters: ProcessParameter[], files: File[]): FormData {
|
||||||
|
const form: FormData = new FormData();
|
||||||
|
form.set('properties', JSON.stringify(parameters));
|
||||||
|
files.forEach((file: File) => {
|
||||||
|
form.append('file', file);
|
||||||
|
});
|
||||||
|
return form;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -12,12 +12,7 @@ import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.
|
|||||||
|
|
||||||
import { DSpaceRESTv2Service } from '../dspace-rest-v2/dspace-rest-v2.service';
|
import { DSpaceRESTv2Service } from '../dspace-rest-v2/dspace-rest-v2.service';
|
||||||
import { DSpaceSerializer } from '../dspace-rest-v2/dspace.serializer';
|
import { DSpaceSerializer } from '../dspace-rest-v2/dspace.serializer';
|
||||||
import {
|
import { RequestActionTypes, RequestCompleteAction, RequestExecuteAction, ResetResponseTimestampsAction } from './request.actions';
|
||||||
RequestActionTypes,
|
|
||||||
RequestCompleteAction,
|
|
||||||
RequestExecuteAction,
|
|
||||||
ResetResponseTimestampsAction
|
|
||||||
} from './request.actions';
|
|
||||||
import { RequestError, RestRequest } from './request.models';
|
import { RequestError, RestRequest } from './request.models';
|
||||||
import { RequestEntry } from './request.reducer';
|
import { RequestEntry } from './request.reducer';
|
||||||
import { RequestService } from './request.service';
|
import { RequestService } from './request.service';
|
||||||
@@ -43,12 +38,12 @@ export class RequestEffects {
|
|||||||
filter((entry: RequestEntry) => hasValue(entry)),
|
filter((entry: RequestEntry) => hasValue(entry)),
|
||||||
map((entry: RequestEntry) => entry.request),
|
map((entry: RequestEntry) => entry.request),
|
||||||
flatMap((request: RestRequest) => {
|
flatMap((request: RestRequest) => {
|
||||||
let body;
|
let body = request.body;
|
||||||
if (isNotEmpty(request.body)) {
|
if (isNotEmpty(request.body) && !request.isMultipart) {
|
||||||
const serializer = new DSpaceSerializer(getClassForType(request.body.type));
|
const serializer = new DSpaceSerializer(getClassForType(request.body.type));
|
||||||
body = serializer.serialize(request.body);
|
body = serializer.serialize(request.body);
|
||||||
}
|
}
|
||||||
return this.restApi.request(request.method, request.href, body, request.options).pipe(
|
return this.restApi.request(request.method, request.href, body, request.options, request.isMultipart).pipe(
|
||||||
map((data: DSpaceRESTV2Response) => this.injector.get(request.getResponseParser()).parse(request, data)),
|
map((data: DSpaceRESTV2Response) => this.injector.get(request.getResponseParser()).parse(request, data)),
|
||||||
addToResponseCacheAndCompleteAction(request, this.EnvConfig),
|
addToResponseCacheAndCompleteAction(request, this.EnvConfig),
|
||||||
catchError((error: RequestError) => observableOf(new ErrorResponse(error)).pipe(
|
catchError((error: RequestError) => observableOf(new ErrorResponse(error)).pipe(
|
||||||
|
@@ -32,6 +32,8 @@ export enum IdentifierType {
|
|||||||
export abstract class RestRequest {
|
export abstract class RestRequest {
|
||||||
public responseMsToLive = 10 * 1000;
|
public responseMsToLive = 10 * 1000;
|
||||||
public forceBypassCache = false;
|
public forceBypassCache = false;
|
||||||
|
public isMultipart = false;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public uuid: string,
|
public uuid: string,
|
||||||
public href: string,
|
public href: string,
|
||||||
@@ -74,6 +76,18 @@ export class PostRequest extends RestRequest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class MultipartPostRequest extends RestRequest {
|
||||||
|
public isMultipart = true;
|
||||||
|
constructor(
|
||||||
|
public uuid: string,
|
||||||
|
public href: string,
|
||||||
|
public body?: any,
|
||||||
|
public options?: HttpOptions
|
||||||
|
) {
|
||||||
|
super(uuid, href, RestRequestMethod.POST, body)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class PutRequest extends RestRequest {
|
export class PutRequest extends RestRequest {
|
||||||
constructor(
|
constructor(
|
||||||
public uuid: string,
|
public uuid: string,
|
||||||
|
@@ -72,7 +72,7 @@ export class DSpaceRESTv2Service {
|
|||||||
* @return {Observable<string>}
|
* @return {Observable<string>}
|
||||||
* An Observable<string> containing the response from the server
|
* An Observable<string> containing the response from the server
|
||||||
*/
|
*/
|
||||||
request(method: RestRequestMethod, url: string, body?: any, options?: HttpOptions): Observable<DSpaceRESTV2Response> {
|
request(method: RestRequestMethod, url: string, body?: any, options?: HttpOptions, isMultipart?: boolean): Observable<DSpaceRESTV2Response> {
|
||||||
const requestOptions: HttpOptions = {};
|
const requestOptions: HttpOptions = {};
|
||||||
requestOptions.body = body;
|
requestOptions.body = body;
|
||||||
if (method === RestRequestMethod.POST && isNotEmpty(body) && isNotEmpty(body.name)) {
|
if (method === RestRequestMethod.POST && isNotEmpty(body) && isNotEmpty(body.name)) {
|
||||||
@@ -98,7 +98,7 @@ export class DSpaceRESTv2Service {
|
|||||||
requestOptions.withCredentials = options.withCredentials;
|
requestOptions.withCredentials = options.withCredentials;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!requestOptions.headers.has('Content-Type')) {
|
if (!requestOptions.headers.has('Content-Type') && !isMultipart) {
|
||||||
// Because HttpHeaders is immutable, the set method returns a new object instead of updating the existing headers
|
// Because HttpHeaders is immutable, the set method returns a new object instead of updating the existing headers
|
||||||
requestOptions.headers = requestOptions.headers.set('Content-Type', DEFAULT_CONTENT_TYPE);
|
requestOptions.headers = requestOptions.headers.set('Content-Type', DEFAULT_CONTENT_TYPE);
|
||||||
}
|
}
|
||||||
|
@@ -1,14 +1,16 @@
|
|||||||
|
<script src="process-parameters/parameter-value-input/value-input.component.ts"></script>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12 col-md-6">
|
<div class="col-12 col-md-6">
|
||||||
<form>
|
<form #form="ngForm" (ngSubmit)="submitForm()">
|
||||||
<ds-scripts-select (select)="selectScript($event)"></ds-scripts-select>
|
<ds-scripts-select (select)="selectedScript = $event"></ds-scripts-select>
|
||||||
<ds-process-parameters [script]="selectedScript"></ds-process-parameters>
|
<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>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 col-md-6">
|
<div class="col-12 col-md-6">
|
||||||
<ds-script-help [script]="selectedScript"></ds-script-help>
|
<ds-script-help [script]="selectedScript"></ds-script-help>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@@ -1,6 +1,8 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { Script } from '../scripts/script.model';
|
import { Script } from '../scripts/script.model';
|
||||||
import { Process } from '../processes/process.model';
|
import { Process } from '../processes/process.model';
|
||||||
|
import { ProcessParameter } from '../processes/process-parameter.model';
|
||||||
|
import { ScriptDataService } from '../../core/data/processes/script-data.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-new-process',
|
selector: 'ds-new-process',
|
||||||
@@ -10,13 +12,32 @@ import { Process } from '../processes/process.model';
|
|||||||
export class NewProcessComponent implements OnInit {
|
export class NewProcessComponent implements OnInit {
|
||||||
public selectedScript: Script;
|
public selectedScript: Script;
|
||||||
public process: Process;
|
public process: Process;
|
||||||
|
public parameters: ProcessParameter[];
|
||||||
|
public files: File[] = [];
|
||||||
|
|
||||||
|
constructor(private scriptService: ScriptDataService) {
|
||||||
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.process = new Process();
|
this.process = new Process();
|
||||||
}
|
}
|
||||||
|
|
||||||
selectScript(script: Script) {
|
submitForm() {
|
||||||
this.selectedScript = script;
|
const stringParameters: ProcessParameter[] = this.parameters.map((parameter: ProcessParameter) => {
|
||||||
console.log('selected script: ', script);
|
return {
|
||||||
|
name: parameter.name,
|
||||||
|
value: this.checkValue(parameter)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
this.scriptService.invocate(this.selectedScript.id, stringParameters, this.files)
|
||||||
|
}
|
||||||
|
|
||||||
|
checkValue(processParameter: ProcessParameter): string {
|
||||||
|
if (typeof processParameter.value === 'object') {
|
||||||
|
this.files = [...this.files, processParameter.value];
|
||||||
|
return processParameter.value.name;
|
||||||
|
}
|
||||||
|
return processParameter.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
{{param.nameLong || param.name}}
|
{{param.nameLong || param.name}}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<ds-parameter-value-input [parameter]="selectedScriptParameter" class="d-block col"></ds-parameter-value-input>
|
<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" (click)="removeParameter.emit(parameterValue);"><span class="fas fa-trash"></span></button>
|
||||||
<span *ngIf="!removable" class="col-1"></span>
|
<span *ngIf="!removable" class="col-1"></span>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -31,6 +31,7 @@ export class ParameterSelectComponent implements OnInit {
|
|||||||
|
|
||||||
set selectedParameter(value: string) {
|
set selectedParameter(value: string) {
|
||||||
this.parameterValue.name = value;
|
this.parameterValue.name = value;
|
||||||
|
this.selectedParameterValue = undefined;
|
||||||
this.changeParameter.emit(this.parameterValue);
|
this.changeParameter.emit(this.parameterValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -0,0 +1 @@
|
|||||||
|
<input type="hidden" value="true"/>
|
@@ -0,0 +1,25 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { BooleanValueInputComponent } from './boolean-value-input.component';
|
||||||
|
|
||||||
|
describe('StringValueInputComponent', () => {
|
||||||
|
let component: BooleanValueInputComponent;
|
||||||
|
let fixture: ComponentFixture<BooleanValueInputComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ BooleanValueInputComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(BooleanValueInputComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@@ -0,0 +1,13 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { ValueInputComponent } from '../value-input.component';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ds-boolean-value-input',
|
||||||
|
templateUrl: './boolean-value-input.component.html',
|
||||||
|
styleUrls: ['./boolean-value-input.component.scss']
|
||||||
|
})
|
||||||
|
export class BooleanValueInputComponent extends ValueInputComponent<boolean> implements OnInit {
|
||||||
|
ngOnInit() {
|
||||||
|
this.updateValue.emit(true)
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,7 @@
|
|||||||
|
<input required #string="ngModel" type="date" class="form-control" id="string-value-input" [ngModel]="value" (ngModelChange)="setValue($event)"/>
|
||||||
|
<div *ngIf="string.invalid && (string.dirty || string.touched)"
|
||||||
|
class="alert alert-danger">
|
||||||
|
<div *ngIf="string.errors.required">
|
||||||
|
{{'process.new.parameter.string.required' | translate}}
|
||||||
|
</div>
|
||||||
|
</div>
|
@@ -0,0 +1,25 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { DateValueInputComponent } from './date-value-input.component';
|
||||||
|
|
||||||
|
describe('StringValueInputComponent', () => {
|
||||||
|
let component: DateValueInputComponent;
|
||||||
|
let fixture: ComponentFixture<DateValueInputComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ DateValueInputComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(DateValueInputComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@@ -0,0 +1,16 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { ValueInputComponent } from '../value-input.component';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ds-date-value-input',
|
||||||
|
templateUrl: './date-value-input.component.html',
|
||||||
|
styleUrls: ['./date-value-input.component.scss']
|
||||||
|
})
|
||||||
|
export class DateValueInputComponent extends ValueInputComponent<string> {
|
||||||
|
value: string;
|
||||||
|
|
||||||
|
setValue(value) {
|
||||||
|
this.value = value;
|
||||||
|
this.updateValue.emit(value)
|
||||||
|
}
|
||||||
|
}
|
@@ -1,6 +1,10 @@
|
|||||||
<ds-uploader dropMsg="process.parameter.file-upload"
|
<label for="file-upload" class="btn btn-light">
|
||||||
dropOverDocumentMsg="process.parameter.file-upload"
|
{{'process.new.parameter.file.upload-button' | translate}}
|
||||||
[enableDragOverDocument]="true"
|
</label>
|
||||||
[uploadFilesOptions]="uploadFilesOptions"
|
<input requireFile #file="ngModel" type="file" id="file-upload" class="form-control-file d-none" [ngModel]="file" (ngModelChange)="setFile($event)"/>
|
||||||
(onCompleteItem)="onCompleteItem()"
|
<div *ngIf="file.invalid && (file.dirty || file.touched)"
|
||||||
(onUploadError)="onUploadError()"></ds-uploader>
|
class="alert alert-danger">
|
||||||
|
<div *ngIf="file.errors.required">
|
||||||
|
{{'process.new.parameter.file.required' | translate}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@@ -1,33 +1,16 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { FileUploaderOptions } from 'ng2-file-upload';
|
import { ValueInputComponent } from '../value-input.component';
|
||||||
import { UploaderOptions } from '../../../../../shared/uploader/uploader-options.model';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-file-value-input',
|
selector: 'ds-file-value-input',
|
||||||
templateUrl: './file-value-input.component.html',
|
templateUrl: './file-value-input.component.html',
|
||||||
styleUrls: ['./file-value-input.component.scss']
|
styleUrls: ['./file-value-input.component.scss']
|
||||||
})
|
})
|
||||||
export class FileValueInputComponent implements OnInit {
|
export class FileValueInputComponent extends ValueInputComponent<File> {
|
||||||
uploadFilesOptions: FileUploaderOptions;
|
file: File;
|
||||||
|
setFile(files) {
|
||||||
constructor() {
|
this.file = files.length > 0 ? files[0] : undefined;
|
||||||
}
|
console.log(this.file);
|
||||||
|
this.updateValue.emit(this.file);
|
||||||
ngOnInit() {
|
|
||||||
this.uploadFilesOptions = new UploaderOptions();
|
|
||||||
this.uploadFilesOptions.autoUpload = false;
|
|
||||||
this.uploadFilesOptions.url = 'bladibla';
|
|
||||||
this.uploadFilesOptions.authToken = 'bladibla';
|
|
||||||
this.uploadFilesOptions.disableMultipart = true;
|
|
||||||
this.uploadFilesOptions.formatDataFunctionIsAsync = false;
|
|
||||||
this.uploadFilesOptions.formatDataFunction((t) => console.log(t));
|
|
||||||
}
|
|
||||||
|
|
||||||
onCompleteItem() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
onUploadError() {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,7 @@
|
|||||||
<div [ngSwitch]="parameter?.type">
|
<div [ngSwitch]="parameter?.type">
|
||||||
<ds-string-value-input *ngSwitchCase="parameterTypes.STRING"></ds-string-value-input>
|
<ds-string-value-input *ngSwitchCase="parameterTypes.STRING" (updateValue)="updateValue.emit($event)"></ds-string-value-input>
|
||||||
<ds-file-value-input *ngSwitchCase="parameterTypes.FILE"></ds-file-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>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { Component, Input, OnChanges, OnInit } from '@angular/core';
|
import { Component, EventEmitter, Input, OnChanges, OnInit, Output } from '@angular/core';
|
||||||
import { ScriptParameterType } from '../../../scripts/script-parameter-type.model';
|
import { ScriptParameterType } from '../../../scripts/script-parameter-type.model';
|
||||||
import { ScriptParameter } from '../../../scripts/script-parameter.model';
|
import { ScriptParameter } from '../../../scripts/script-parameter.model';
|
||||||
|
|
||||||
@@ -9,5 +9,6 @@ import { ScriptParameter } from '../../../scripts/script-parameter.model';
|
|||||||
})
|
})
|
||||||
export class ParameterValueInputComponent {
|
export class ParameterValueInputComponent {
|
||||||
@Input() parameter: ScriptParameter;
|
@Input() parameter: ScriptParameter;
|
||||||
|
@Output() updateValue: EventEmitter<any> = new EventEmitter();
|
||||||
parameterTypes = ScriptParameterType;
|
parameterTypes = ScriptParameterType;
|
||||||
}
|
}
|
||||||
|
@@ -1 +1,7 @@
|
|||||||
<input type="input" class="form-control" id="string-value-input">
|
<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">
|
||||||
|
<div *ngIf="string.errors.required">
|
||||||
|
{{'process.new.parameter.string.required' | translate}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@@ -1,15 +1,16 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { ValueInputComponent } from '../value-input.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-string-value-input',
|
selector: 'ds-string-value-input',
|
||||||
templateUrl: './string-value-input.component.html',
|
templateUrl: './string-value-input.component.html',
|
||||||
styleUrls: ['./string-value-input.component.scss']
|
styleUrls: ['./string-value-input.component.scss']
|
||||||
})
|
})
|
||||||
export class StringValueInputComponent implements OnInit {
|
export class StringValueInputComponent extends ValueInputComponent<string> {
|
||||||
|
value: string;
|
||||||
|
|
||||||
constructor() { }
|
setValue(value) {
|
||||||
|
this.value = value;
|
||||||
ngOnInit() {
|
this.updateValue.emit(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,5 @@
|
|||||||
|
import { EventEmitter, Output } from '@angular/core';
|
||||||
|
|
||||||
|
export abstract class ValueInputComponent<T> {
|
||||||
|
@Output() updateValue: EventEmitter<T> = new EventEmitter<T>()
|
||||||
|
}
|
@@ -1,5 +1,5 @@
|
|||||||
<div class="form-group" *ngIf="script">
|
<div class="form-group" *ngIf="script">
|
||||||
<label>Parameters</label>
|
<label>{{'process.new.select-parameters' | translate}}</label>
|
||||||
<ds-parameter-select
|
<ds-parameter-select
|
||||||
*ngFor="let value of parameterValues; let i = index; let last = last"
|
*ngFor="let value of parameterValues; let i = index; let last = last"
|
||||||
[parameters]="script.parameters"
|
[parameters]="script.parameters"
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core';
|
import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core';
|
||||||
import { Script } from '../../scripts/script.model';
|
import { Script } from '../../scripts/script.model';
|
||||||
import { ProcessParameter } from '../../processes/process-parameter.model';
|
import { ProcessParameter } from '../../processes/process-parameter.model';
|
||||||
|
import { hasValue } from '../../../shared/empty.util';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-process-parameters',
|
selector: 'ds-process-parameters',
|
||||||
@@ -9,6 +10,7 @@ import { ProcessParameter } from '../../processes/process-parameter.model';
|
|||||||
})
|
})
|
||||||
export class ProcessParametersComponent implements OnChanges {
|
export class ProcessParametersComponent implements OnChanges {
|
||||||
@Input() script: Script;
|
@Input() script: Script;
|
||||||
|
@Output() updateParameters: EventEmitter<ProcessParameter[]> = new EventEmitter();
|
||||||
parameterValues: ProcessParameter[];
|
parameterValues: ProcessParameter[];
|
||||||
|
|
||||||
ngOnChanges(changes: SimpleChanges): void {
|
ngOnChanges(changes: SimpleChanges): void {
|
||||||
@@ -27,6 +29,7 @@ export class ProcessParametersComponent implements OnChanges {
|
|||||||
if (index === this.parameterValues.length - 1) {
|
if (index === this.parameterValues.length - 1) {
|
||||||
this.addParameter();
|
this.addParameter();
|
||||||
}
|
}
|
||||||
|
this.updateParameters.emit(this.parameterValues.filter((param: ProcessParameter) => hasValue(param.name)));
|
||||||
}
|
}
|
||||||
|
|
||||||
removeParameter(index: number) {
|
removeParameter(index: number) {
|
||||||
|
@@ -1,11 +1,11 @@
|
|||||||
<div class="form-group" *ngIf="scripts$ | async">
|
<div class="form-group" *ngIf="scripts$ | async">
|
||||||
<label for="process-script">Script</label>
|
<label for="process-script"><label>{{'process.new.select-script' | translate}}</label></label>
|
||||||
<select required id="process-script"
|
<select required id="process-script"
|
||||||
class="form-control"
|
class="form-control"
|
||||||
name="script"
|
name="script"
|
||||||
[(ngModel)]="selectedScript"
|
[(ngModel)]="selectedScript"
|
||||||
#script="ngModel">
|
#script="ngModel">
|
||||||
<option [ngValue]="undefined">Choose a script...</option>
|
<option [ngValue]="undefined">{{'process.new.select-script.placeholder' | translate}}</option>
|
||||||
<option *ngFor="let script of scripts$ | async" [ngValue]="script.id">
|
<option *ngFor="let script of scripts$ | async" [ngValue]="script.id">
|
||||||
{{script.name}}
|
{{script.name}}
|
||||||
</option>
|
</option>
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
<div *ngIf="script.invalid && (script.dirty || script.touched)"
|
<div *ngIf="script.invalid && (script.dirty || script.touched)"
|
||||||
class="alert alert-danger">
|
class="alert alert-danger">
|
||||||
<div *ngIf="script.errors.required">
|
<div *ngIf="script.errors.required">
|
||||||
Script is required.
|
{{'process.new.select-script.required' | translate}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -9,6 +9,8 @@ import { ProcessParametersComponent } from './new/process-parameters/process-par
|
|||||||
import { StringValueInputComponent } from './new/process-parameters/parameter-value-input/string-value-input/string-value-input.component';
|
import { StringValueInputComponent } from './new/process-parameters/parameter-value-input/string-value-input/string-value-input.component';
|
||||||
import { ParameterValueInputComponent } from './new/process-parameters/parameter-value-input/parameter-value-input.component';
|
import { ParameterValueInputComponent } from './new/process-parameters/parameter-value-input/parameter-value-input.component';
|
||||||
import { FileValueInputComponent } from './new/process-parameters/parameter-value-input/file-value-input/file-value-input.component';
|
import { FileValueInputComponent } from './new/process-parameters/parameter-value-input/file-value-input/file-value-input.component';
|
||||||
|
import { BooleanValueInputComponent } from './new/process-parameters/parameter-value-input/boolean-value-input/boolean-value-input.component';
|
||||||
|
import { DateValueInputComponent } from './new/process-parameters/parameter-value-input/date-value-input/date-value-input.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -24,6 +26,8 @@ import { FileValueInputComponent } from './new/process-parameters/parameter-valu
|
|||||||
StringValueInputComponent,
|
StringValueInputComponent,
|
||||||
ParameterValueInputComponent,
|
ParameterValueInputComponent,
|
||||||
FileValueInputComponent,
|
FileValueInputComponent,
|
||||||
|
BooleanValueInputComponent,
|
||||||
|
DateValueInputComponent,
|
||||||
],
|
],
|
||||||
entryComponents: []
|
entryComponents: []
|
||||||
})
|
})
|
||||||
|
@@ -6,8 +6,9 @@ export class ProcessParameter {
|
|||||||
* The name of the parameter Eg. '-d', '-f' etc.
|
* The name of the parameter Eg. '-d', '-f' etc.
|
||||||
*/
|
*/
|
||||||
name: string;
|
name: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The value of the parameter
|
* The value of the parameter
|
||||||
*/
|
*/
|
||||||
value: string;
|
value: any;
|
||||||
}
|
}
|
||||||
|
@@ -63,10 +63,10 @@ export class EndpointMockingRestService extends DSpaceRESTv2Service {
|
|||||||
* @return Observable<DSpaceRESTV2Response>
|
* @return Observable<DSpaceRESTV2Response>
|
||||||
* An Observable<DSpaceRESTV2Response> containing the response from the server
|
* An Observable<DSpaceRESTV2Response> containing the response from the server
|
||||||
*/
|
*/
|
||||||
request(method: RestRequestMethod, url: string, body?: any, options?: HttpOptions): Observable<DSpaceRESTV2Response> {
|
request(method: RestRequestMethod, url: string, body?: any, options?: HttpOptions, isMultipart?: boolean): Observable<DSpaceRESTV2Response> {
|
||||||
const mockData = this.getMockData(url);
|
const mockData = this.getMockData(url);
|
||||||
if (isEmpty(mockData)) {
|
if (isEmpty(mockData)) {
|
||||||
return super.request(method, url, body, options);
|
return super.request(method, url, body, options, isMultipart);
|
||||||
} else {
|
} else {
|
||||||
return this.toMockResponse$(mockData);
|
return this.toMockResponse$(mockData);
|
||||||
}
|
}
|
||||||
|
@@ -186,6 +186,8 @@ import { LogInPasswordComponent } from './log-in/methods/password/log-in-passwor
|
|||||||
import { LogInComponent } from './log-in/log-in.component';
|
import { LogInComponent } from './log-in/log-in.component';
|
||||||
import { MissingTranslationHelper } from './translate/missing-translation.helper';
|
import { MissingTranslationHelper } from './translate/missing-translation.helper';
|
||||||
import { ItemVersionsNoticeComponent } from './item/item-versions/notice/item-versions-notice.component';
|
import { ItemVersionsNoticeComponent } from './item/item-versions/notice/item-versions-notice.component';
|
||||||
|
import { FileValidator } from './utils/require-file.validator';
|
||||||
|
import { FileValueAccessorDirective } from './utils/file-value-accessor.directive';
|
||||||
|
|
||||||
const MODULES = [
|
const MODULES = [
|
||||||
// Do NOT include UniversalModule, HttpModule, or JsonpModule here
|
// Do NOT include UniversalModule, HttpModule, or JsonpModule here
|
||||||
@@ -452,7 +454,9 @@ const DIRECTIVES = [
|
|||||||
AutoFocusDirective,
|
AutoFocusDirective,
|
||||||
RoleDirective,
|
RoleDirective,
|
||||||
MetadataRepresentationDirective,
|
MetadataRepresentationDirective,
|
||||||
ListableObjectDirective
|
ListableObjectDirective,
|
||||||
|
FileValueAccessorDirective,
|
||||||
|
FileValidator
|
||||||
];
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
@@ -146,6 +146,8 @@ export class UploaderComponent {
|
|||||||
};
|
};
|
||||||
this.uploader.onProgressAll = () => this.onProgress();
|
this.uploader.onProgressAll = () => this.onProgress();
|
||||||
this.uploader.onProgressItem = () => this.onProgress();
|
this.uploader.onProgressItem = () => this.onProgress();
|
||||||
|
|
||||||
|
console.log(this.uploader.options.formatDataFunction());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
24
src/app/shared/utils/file-value-accessor.directive.ts
Normal file
24
src/app/shared/utils/file-value-accessor.directive.ts
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import {Directive} from '@angular/core';
|
||||||
|
import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/forms';
|
||||||
|
|
||||||
|
@Directive({
|
||||||
|
// tslint:disable-next-line:directive-selector
|
||||||
|
selector: 'input[type=file]',
|
||||||
|
// tslint:disable-next-line:no-host-metadata-property
|
||||||
|
host : {
|
||||||
|
'(change)' : 'onChange($event.target.files)',
|
||||||
|
'(blur)': 'onTouched()'
|
||||||
|
},
|
||||||
|
providers: [
|
||||||
|
{ provide: NG_VALUE_ACCESSOR, useExisting: FileValueAccessorDirective, multi: true }
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class FileValueAccessorDirective implements ControlValueAccessor {
|
||||||
|
value: any;
|
||||||
|
onChange = (_) => { /* empty */ };
|
||||||
|
onTouched = () => { /* empty */};
|
||||||
|
|
||||||
|
writeValue(value) { /* empty */}
|
||||||
|
registerOnChange(fn: any) { this.onChange = fn; }
|
||||||
|
registerOnTouched(fn: any) { this.onTouched = fn; }
|
||||||
|
}
|
19
src/app/shared/utils/require-file.validator.ts
Normal file
19
src/app/shared/utils/require-file.validator.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import {Directive} from '@angular/core';
|
||||||
|
import {NG_VALIDATORS, Validator, FormControl} from '@angular/forms';
|
||||||
|
|
||||||
|
@Directive({
|
||||||
|
// tslint:disable-next-line:directive-selector
|
||||||
|
selector: '[requireFile]',
|
||||||
|
providers: [
|
||||||
|
{ provide: NG_VALIDATORS, useExisting: FileValidator, multi: true },
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class FileValidator implements Validator {
|
||||||
|
static validate(c: FormControl): {[key: string]: any} {
|
||||||
|
return c.value == null || c.value.length === 0 ? { required : true} : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
validate(c: FormControl): {[key: string]: any} {
|
||||||
|
return FileValidator.validate(c);
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user