Merge branch 'refactor-submission-parsers' into clean-relationships-in-submission

This commit is contained in:
lotte
2019-11-08 08:49:12 +01:00
49 changed files with 757 additions and 271 deletions

View File

@@ -1,6 +1,6 @@
dspace.dir=/dspace dspace.dir=/dspace
db.url=jdbc:postgresql://dspacedb:5432/dspace db.url=jdbc:postgresql://dspacedb:5432/dspace
dspace.hostname=dspace dspace.hostname=dspace
dspace.baseUrl=http://localhost:8080 dspace.baseUrl=http://localhost:8080/server
dspace.name=DSpace Started with Docker Compose dspace.name=DSpace Started with Docker Compose
solr.server=http://dspacesolr:8983/solr solr.server=http://dspacesolr:8983/solr

View File

@@ -161,6 +161,7 @@
"collection.page.browse.recent.head": "Recent Submissions", "collection.page.browse.recent.head": "Recent Submissions",
"collection.page.browse.recent.empty": "No items to show", "collection.page.browse.recent.empty": "No items to show",
"collection.page.handle": "Permanent URI for this collection",
"collection.page.license": "License", "collection.page.license": "License",
"collection.page.news": "News", "collection.page.news": "News",
@@ -184,8 +185,10 @@
"community.form.rights": "Copyright text (HTML)", "community.form.rights": "Copyright text (HTML)",
"community.form.tableofcontents": "News (HTML)", "community.form.tableofcontents": "News (HTML)",
"community.form.title": "Name", "community.form.title": "Name",
"community.page.handle": "Permanent URI for this community",
"community.page.license": "License", "community.page.license": "License",
"community.page.news": "News", "community.page.news": "News",
"community.all-lists.head": "Subcommunities and Collections",
"community.sub-collection-list.head": "Collections of this Community", "community.sub-collection-list.head": "Collections of this Community",
"community.sub-community-list.head": "Communities of this Community", "community.sub-community-list.head": "Communities of this Community",

View File

@@ -19,6 +19,7 @@ import { ENV_CONFIG, GLOBAL_CONFIG } from '../../../config';
import { BrowseEntrySearchOptions } from '../../core/browse/browse-entry-search-options.model'; import { BrowseEntrySearchOptions } from '../../core/browse/browse-entry-search-options.model';
import { toRemoteData } from '../+browse-by-metadata-page/browse-by-metadata-page.component.spec'; import { toRemoteData } from '../+browse-by-metadata-page/browse-by-metadata-page.component.spec';
import { createSuccessfulRemoteDataObject$ } from '../../shared/testing/utils'; import { createSuccessfulRemoteDataObject$ } from '../../shared/testing/utils';
import { VarDirective } from '../../shared/utils/var.directive';
describe('BrowseByDatePageComponent', () => { describe('BrowseByDatePageComponent', () => {
let comp: BrowseByDatePageComponent; let comp: BrowseByDatePageComponent;
@@ -69,7 +70,7 @@ describe('BrowseByDatePageComponent', () => {
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule.forRoot()], imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule.forRoot()],
declarations: [BrowseByDatePageComponent, EnumKeysPipe], declarations: [BrowseByDatePageComponent, EnumKeysPipe, VarDirective],
providers: [ providers: [
{ provide: GLOBAL_CONFIG, useValue: ENV_CONFIG }, { provide: GLOBAL_CONFIG, useValue: ENV_CONFIG },
{ provide: ActivatedRoute, useValue: activatedRouteStub }, { provide: ActivatedRoute, useValue: activatedRouteStub },

View File

@@ -1,7 +1,31 @@
<div class="container"> <div class="container">
<ng-container *ngVar="(parent$ | async) as parent">
<ng-container *ngIf="parent?.payload as parentContext">
<header class="comcol-header border-bottom mb-4 pb-4">
<!-- Parent Name -->
<ds-comcol-page-header [name]="parentContext.name">
</ds-comcol-page-header>
<!-- Handle -->
<ds-comcol-page-handle
[content]="parentContext.handle"
[title]="parentContext.type+'.page.handle'" >
</ds-comcol-page-handle>
<!-- Introductory text -->
<ds-comcol-page-content [content]="parentContext.introductoryText" [hasInnerHtml]="true">
</ds-comcol-page-content>
<!-- News -->
<ds-comcol-page-content [content]="parentContext.sidebarText" [hasInnerHtml]="true" [title]="'community.page.news'">
</ds-comcol-page-content>
</header>
<!-- Browse-By Links -->
<ds-comcol-page-browse-by [id]="parentContext.id" [contentType]="parentContext.type"></ds-comcol-page-browse-by>
</ng-container></ng-container>
<section class="comcol-page-browse-section">
<div class="browse-by-metadata w-100"> <div class="browse-by-metadata w-100">
<ds-browse-by *ngIf="startsWithOptions" class="col-xs-12 w-100" <ds-browse-by *ngIf="startsWithOptions" class="col-xs-12 w-100"
title="{{'browse.title' | translate:{collection: (parent$ | async)?.payload?.name || '', field: 'browse.metadata.' + browseId | translate, value: (value)? '&quot;' + value + '&quot;': ''} }}" title="{{'browse.title' | translate:{collection: (parent$ | async)?.payload?.name || '', field: 'browse.metadata.' + browseId | translate, value: (value)? '&quot;' + value + '&quot;': ''} }}"
parentname="{{(parent$ | async)?.payload?.name || ''}}"
[objects$]="(items$ !== undefined)? items$ : browseEntries$" [objects$]="(items$ !== undefined)? items$ : browseEntries$"
[paginationConfig]="paginationConfig" [paginationConfig]="paginationConfig"
[sortConfig]="sortConfig" [sortConfig]="sortConfig"
@@ -15,4 +39,17 @@
</ds-browse-by> </ds-browse-by>
<ds-loading *ngIf="!startsWithOptions" message="{{'loading.browse-by-page' | translate}}"></ds-loading> <ds-loading *ngIf="!startsWithOptions" message="{{'loading.browse-by-page' | translate}}"></ds-loading>
</div> </div>
</section>
<ng-container *ngVar="(parent$ | async) as parent">
<ng-container *ngIf="parent?.payload as parentContext">
<footer *ngIf="parentContext.copyrightText" class="border-top my-5 pt-4">
<div >
<!-- Copyright -->
<ds-comcol-page-content [content]="parentContext.copyrightText" [hasInnerHtml]="true">
</ds-comcol-page-content>
</div>
</footer>
</ng-container>
</ng-container>
</div> </div>

View File

@@ -23,6 +23,7 @@ import { MockRouter } from '../../shared/mocks/mock-router';
import { ResourceType } from '../../core/shared/resource-type'; import { ResourceType } from '../../core/shared/resource-type';
import { createSuccessfulRemoteDataObject$ } from '../../shared/testing/utils'; import { createSuccessfulRemoteDataObject$ } from '../../shared/testing/utils';
import { BrowseEntry } from '../../core/shared/browse-entry.model'; import { BrowseEntry } from '../../core/shared/browse-entry.model';
import { VarDirective } from '../../shared/utils/var.directive';
describe('BrowseByMetadataPageComponent', () => { describe('BrowseByMetadataPageComponent', () => {
let comp: BrowseByMetadataPageComponent; let comp: BrowseByMetadataPageComponent;
@@ -86,7 +87,7 @@ describe('BrowseByMetadataPageComponent', () => {
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule.forRoot()], imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule.forRoot()],
declarations: [BrowseByMetadataPageComponent, EnumKeysPipe], declarations: [BrowseByMetadataPageComponent, EnumKeysPipe, VarDirective],
providers: [ providers: [
{ provide: ActivatedRoute, useValue: activatedRouteStub }, { provide: ActivatedRoute, useValue: activatedRouteStub },
{ provide: BrowseService, useValue: mockBrowseService }, { provide: BrowseService, useValue: mockBrowseService },

View File

@@ -18,6 +18,7 @@ import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.serv
import { BrowseService } from '../../core/browse/browse.service'; import { BrowseService } from '../../core/browse/browse.service';
import { MockRouter } from '../../shared/mocks/mock-router'; import { MockRouter } from '../../shared/mocks/mock-router';
import { createSuccessfulRemoteDataObject$ } from '../../shared/testing/utils'; import { createSuccessfulRemoteDataObject$ } from '../../shared/testing/utils';
import { VarDirective } from '../../shared/utils/var.directive';
describe('BrowseByTitlePageComponent', () => { describe('BrowseByTitlePageComponent', () => {
let comp: BrowseByTitlePageComponent; let comp: BrowseByTitlePageComponent;
@@ -64,7 +65,7 @@ describe('BrowseByTitlePageComponent', () => {
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule.forRoot()], imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule.forRoot()],
declarations: [BrowseByTitlePageComponent, EnumKeysPipe], declarations: [BrowseByTitlePageComponent, EnumKeysPipe, VarDirective],
providers: [ providers: [
{ provide: ActivatedRoute, useValue: activatedRouteStub }, { provide: ActivatedRoute, useValue: activatedRouteStub },
{ provide: BrowseService, useValue: mockBrowseService }, { provide: BrowseService, useValue: mockBrowseService },

View File

@@ -3,18 +3,22 @@
*ngVar="(collectionRD$ | async) as collectionRD"> *ngVar="(collectionRD$ | async) as collectionRD">
<div *ngIf="collectionRD?.hasSucceeded" @fadeInOut> <div *ngIf="collectionRD?.hasSucceeded" @fadeInOut>
<div *ngIf="collectionRD?.payload as collection"> <div *ngIf="collectionRD?.payload as collection">
<header class="comcol-header border-bottom mb-4 pb-4">
<!-- Collection logo -->
<ds-comcol-page-logo *ngIf="logoRD$"
[logo]="(logoRD$ | async)?.payload" [alternateText]="'Collection Logo'">
[alternateText]="'Collection Logo'">
</ds-comcol-page-logo>
<!-- Collection Name --> <!-- Collection Name -->
<ds-comcol-page-header <ds-comcol-page-header
[name]="collection.name"> [name]="collection.name">
</ds-comcol-page-header> </ds-comcol-page-header>
<!-- Browse-By Links --> <!-- Handle -->
<ds-comcol-page-browse-by [id]="collection.id"></ds-comcol-page-browse-by> <ds-comcol-page-handle
<!-- Collection logo --> [content]="collection.handle"
<ds-comcol-page-logo *ngIf="logoRD$" [title]="'collection.page.handle'" >
[logo]="(logoRD$ | async)?.payload" </ds-comcol-page-handle>
[alternateText]="'Collection Logo'"> <!-- Introductory text -->
</ds-comcol-page-logo>
<!-- Introductionary text -->
<ds-comcol-page-content <ds-comcol-page-content
[content]="collection.introductoryText" [content]="collection.introductoryText"
[hasInnerHtml]="true"> [hasInnerHtml]="true">
@@ -23,23 +27,20 @@
<ds-comcol-page-content <ds-comcol-page-content
[content]="collection.sidebarText" [content]="collection.sidebarText"
[hasInnerHtml]="true" [hasInnerHtml]="true"
[title]="'community.page.news'"> [title]="'collection.page.news'">
</ds-comcol-page-content> </ds-comcol-page-content>
<!-- Copyright -->
<ds-comcol-page-content </header>
[content]="collection.copyrightText" <section class="comcol-page-browse-section">
[hasInnerHtml]="true"> <!-- Browse-By Links -->
</ds-comcol-page-content> <ds-comcol-page-browse-by
<!-- Licence --> [id]="collection.id"
<ds-comcol-page-content [contentType]="collection.type">
[content]="collection.dcLicense" </ds-comcol-page-browse-by>
[title]="'collection.page.license'">
</ds-comcol-page-content>
</div>
<br>
<ng-container *ngVar="(itemRD$ | async) as itemRD"> <ng-container *ngVar="(itemRD$ | async) as itemRD">
<div *ngIf="itemRD?.hasSucceeded" @fadeIn> <div class="mt-4" *ngIf="itemRD?.hasSucceeded" @fadeIn>
<h2>{{'collection.page.browse.recent.head' | translate}}</h2> <h3 class="sr-only">{{'collection.page.browse.recent.head' | translate}}</h3>
<ds-viewable-collection <ds-viewable-collection
[config]="paginationConfig" [config]="paginationConfig"
[sortConfig]="sortConfig" [sortConfig]="sortConfig"
@@ -56,6 +57,15 @@
{{'collection.page.browse.recent.empty' | translate}} {{'collection.page.browse.recent.empty' | translate}}
</div> </div>
</ng-container> </ng-container>
</section>
<footer *ngIf="collection.copyrightText" class="border-top my-5 pt-4">
<!-- Copyright -->
<ds-comcol-page-content
[content]="collection.copyrightText"
[hasInnerHtml]="true">
</ds-comcol-page-content>
</footer>
</div>
</div> </div>
<ds-error *ngIf="collectionRD?.hasFailed" <ds-error *ngIf="collectionRD?.hasFailed"
message="{{'error.collection' | translate}}"></ds-error> message="{{'error.collection' | translate}}"></ds-error>

View File

@@ -1,33 +1,38 @@
<div class="container" *ngVar="(communityRD$ | async) as communityRD"> <div class="container" *ngVar="(communityRD$ | async) as communityRD">
<div class="community-page" *ngIf="communityRD?.hasSucceeded" @fadeInOut> <div class="community-page" *ngIf="communityRD?.hasSucceeded" @fadeInOut>
<div *ngIf="communityRD?.payload; let communityPayload"> <div *ngIf="communityRD?.payload; let communityPayload">
<header class="comcol-header border-bottom mb-4 pb-4">
<!-- Community logo -->
<ds-comcol-page-logo *ngIf="logoRD$" [logo]="(logoRD$ | async)?.payload" [alternateText]="'Community Logo'">
</ds-comcol-page-logo>
<!-- Community name --> <!-- Community name -->
<ds-comcol-page-header [name]="communityPayload.name"></ds-comcol-page-header> <ds-comcol-page-header [name]="communityPayload.name"></ds-comcol-page-header>
<!-- Browse-By Links --> <!-- Handle -->
<ds-comcol-page-browse-by [id]="communityPayload.id"></ds-comcol-page-browse-by> <ds-comcol-page-handle [content]="communityPayload.handle" [title]="'community.page.handle'">
<!-- Community logo --> </ds-comcol-page-handle>
<ds-comcol-page-logo *ngIf="logoRD$"
[logo]="(logoRD$ | async)?.payload"
[alternateText]="'Community Logo'">
</ds-comcol-page-logo>
<!-- Introductory text --> <!-- Introductory text -->
<ds-comcol-page-content <ds-comcol-page-content [content]="communityPayload.introductoryText" [hasInnerHtml]="true">
[content]="communityPayload.introductoryText"
[hasInnerHtml]="true">
</ds-comcol-page-content> </ds-comcol-page-content>
<!-- News --> <!-- News -->
<ds-comcol-page-content <ds-comcol-page-content [content]="communityPayload.sidebarText" [hasInnerHtml]="true"
[content]="communityPayload.sidebarText"
[hasInnerHtml]="true"
[title]="'community.page.news'"> [title]="'community.page.news'">
</ds-comcol-page-content> </ds-comcol-page-content>
<!-- Copyright -->
<ds-comcol-page-content </header>
[content]="communityPayload.copyrightText" <section class="comcol-page-browse-section">
[hasInnerHtml]="true"> <!-- Browse-By Links -->
</ds-comcol-page-content> <ds-comcol-page-browse-by [id]="communityPayload.id" [contentType]="communityPayload.type">
</ds-comcol-page-browse-by>
<ds-community-page-sub-community-list [community]="communityPayload"></ds-community-page-sub-community-list> <ds-community-page-sub-community-list [community]="communityPayload"></ds-community-page-sub-community-list>
<ds-community-page-sub-collection-list [community]="communityPayload"></ds-community-page-sub-collection-list> <ds-community-page-sub-collection-list [community]="communityPayload"></ds-community-page-sub-collection-list>
</section>
<footer *ngIf="communityPayload.copyrightText" class="border-top my-5 pt-4">
<!-- Copyright -->
<ds-comcol-page-content [content]="communityPayload.copyrightText" [hasInnerHtml]="true">
</ds-comcol-page-content>
</footer>
</div> </div>
</div> </div>

View File

@@ -0,0 +1,95 @@
import { Observable } from 'rxjs';
import { SubmissionService } from '../../submission/submission.service';
import { RemoteData } from '../data/remote-data';
import { SubmissionObject } from './models/submission-object.model';
import { WorkspaceItem } from './models/workspaceitem.model';
import { SubmissionObjectDataService } from './submission-object-data.service';
import { SubmissionScopeType } from './submission-scope-type';
import { WorkflowItemDataService } from './workflowitem-data.service';
import { WorkspaceitemDataService } from './workspaceitem-data.service';
describe('SubmissionObjectDataService', () => {
let service: SubmissionObjectDataService;
let submissionService: SubmissionService;
let workspaceitemDataService: WorkspaceitemDataService;
let workflowItemDataService: WorkflowItemDataService;
const submissionId = '1234';
const wsiResult = 'wsiResult' as any;
const wfiResult = 'wfiResult' as any;
beforeEach(() => {
workspaceitemDataService = jasmine.createSpyObj('WorkspaceitemDataService', {
findById: wsiResult
});
workflowItemDataService = jasmine.createSpyObj('WorkflowItemDataService', {
findById: wfiResult
});
});
describe('findById', () => {
it('should call SubmissionService.getSubmissionScope to determine the type of submission object', () => {
submissionService = jasmine.createSpyObj('SubmissionService', {
getSubmissionScope: {}
});
service = new SubmissionObjectDataService(workspaceitemDataService, workflowItemDataService, submissionService);
service.findById(submissionId);
expect(submissionService.getSubmissionScope).toHaveBeenCalled();
});
describe('when the submission ID refers to a WorkspaceItem', () => {
beforeEach(() => {
submissionService = jasmine.createSpyObj('SubmissionService', {
getSubmissionScope: SubmissionScopeType.WorkspaceItem
});
service = new SubmissionObjectDataService(workspaceitemDataService, workflowItemDataService, submissionService);
});
it('should forward the result of WorkspaceitemDataService.findById()', () => {
const result = service.findById(submissionId);
expect(workspaceitemDataService.findById).toHaveBeenCalledWith(submissionId);
expect(result).toBe(wsiResult);
});
});
describe('when the submission ID refers to a WorkflowItem', () => {
beforeEach(() => {
submissionService = jasmine.createSpyObj('SubmissionService', {
getSubmissionScope: SubmissionScopeType.WorkflowItem
});
service = new SubmissionObjectDataService(workspaceitemDataService, workflowItemDataService, submissionService);
});
it('should forward the result of WorkflowItemDataService.findById()', () => {
const result = service.findById(submissionId);
expect(workflowItemDataService.findById).toHaveBeenCalledWith(submissionId);
expect(result).toBe(wfiResult);
});
});
describe('when the type of submission object is unknown', () => {
beforeEach(() => {
submissionService = jasmine.createSpyObj('SubmissionService', {
getSubmissionScope: 'Something else'
});
service = new SubmissionObjectDataService(workspaceitemDataService, workflowItemDataService, submissionService);
});
it('shouldn\'t call any data service methods', () => {
service.findById(submissionId);
expect(workspaceitemDataService.findById).not.toHaveBeenCalled();
expect(workflowItemDataService.findById).not.toHaveBeenCalled();
});
it('should return a RemoteData containing an error', (done) => {
const result = service.findById(submissionId);
result.subscribe((rd: RemoteData<SubmissionObject>) => {
expect(rd.hasFailed).toBe(true);
expect(rd.error).toBeDefined();
done();
})
});
});
});
});

View File

@@ -0,0 +1,46 @@
import { Injectable } from '@angular/core';
import { of as observableOf, Observable } from 'rxjs';
import { SubmissionService } from '../../submission/submission.service';
import { RemoteData } from '../data/remote-data';
import { RemoteDataError } from '../data/remote-data-error';
import { SubmissionObject } from './models/submission-object.model';
import { SubmissionScopeType } from './submission-scope-type';
import { WorkflowItemDataService } from './workflowitem-data.service';
import { WorkspaceitemDataService } from './workspaceitem-data.service';
/**
* A service to retrieve submission objects (WorkspaceItem/WorkflowItem)
* without knowing their type
*/
@Injectable({
providedIn: 'root'
})
export class SubmissionObjectDataService {
constructor(
private workspaceitemDataService: WorkspaceitemDataService,
private workflowItemDataService: WorkflowItemDataService,
private submissionService: SubmissionService
) {
}
/**
* Retrieve a submission object based on its ID.
*
* @param id The identifier of a submission object
*/
findById(id: string): Observable<RemoteData<SubmissionObject>> {
switch (this.submissionService.getSubmissionScope()) {
case SubmissionScopeType.WorkspaceItem:
return this.workspaceitemDataService.findById(id);
case SubmissionScopeType.WorkflowItem:
return this.workflowItemDataService.findById(id);
default:
const error = new RemoteDataError(
undefined,
undefined,
'The request couldn\'t be sent. Unable to determine the type of submission object'
);
return observableOf(new RemoteData(false, false, false, error, undefined));
}
}
}

View File

@@ -1,5 +1,5 @@
<ng-container *ngVar="(objects$ | async) as objects"> <ng-container *ngVar="(objects$ | async) as objects">
<h2 class="w-100">{{title | translate}}</h2> <h3 [ngClass]="{'sr-only': parentname }" >{{title | translate}}</h3>
<ng-container *ngComponentOutlet="getStartsWithComponent(); injector: objectInjector;"></ng-container> <ng-container *ngComponentOutlet="getStartsWithComponent(); injector: objectInjector;"></ng-container>
<div *ngIf="objects?.hasSucceeded && !objects?.isLoading && objects?.payload?.page.length > 0" @fadeIn> <div *ngIf="objects?.hasSucceeded && !objects?.isLoading && objects?.payload?.page.length > 0" @fadeIn>
<div *ngIf="!enableArrows"> <div *ngIf="!enableArrows">

View File

@@ -26,6 +26,10 @@ export class BrowseByComponent implements OnInit {
*/ */
@Input() title: string; @Input() title: string;
/**
* The parent name
*/
@Input() parentname: string;
/** /**
* The list of objects to display * The list of objects to display
*/ */

View File

@@ -1,6 +1,24 @@
<h3>{{'browse.comcol.head' | translate}}</h3> <h2 class="comcol-browse-label h5">{{'browse.comcol.head' | translate}}</h2>
<ul> <nav class="comcol-browse mb-4" aria-label="Browse Community or Collection">
<li *ngFor="let config of types"> <div class="d-none d-sm-block">
<a [routerLink]="['/browse/' + config.id]" [queryParams]="{scope: id}">{{'browse.comcol.by.' + config.id | translate}}</a>
</li> <div class="list-group list-group-horizontal">
</ul> <a *ngFor="let option of allOptions"
class="list-group-item"
[routerLink]="option.routerLink"
[queryParams]="option.params"
routerLinkActive="active">{{ option.label | translate }}</a>
</div>
</div>
<div class="d-block d-sm-none">
<select name="browse-type"
class="form-control"
aria-label="Browse Community or Collection"
(ngModelChange)="onSelectChange($event)" [ngModel]="currentOptionId$ | async">
<option *ngFor="let option of allOptions"
[ngValue]="option.id"
[attr.selected]="(currentOptionId$ | async) === option.id ? 'selected' : null">{{ option.label | translate }}</option>
</select>
</div>
</nav>

View File

@@ -1,6 +1,27 @@
import { Component, Inject, Input, OnInit } from '@angular/core'; import {
ChangeDetectionStrategy,
Component,
Inject,
Input, NgZone,
OnDestroy,
OnInit
} from '@angular/core';
import { Observable } from 'rxjs/internal/Observable';
import { Subscription } from 'rxjs/internal/Subscription';
import { filter, map, startWith, tap } from 'rxjs/operators';
import { getCollectionPageRoute } from '../../+collection-page/collection-page-routing.module';
import { getCommunityPageRoute } from '../../+community-page/community-page-routing.module';
import { GLOBAL_CONFIG, GlobalConfig } from '../../../config'; import { GLOBAL_CONFIG, GlobalConfig } from '../../../config';
import { Router, ActivatedRoute, RouterModule, UrlSegment } from '@angular/router';
import { BrowseByTypeConfig } from '../../../config/browse-by-type-config.interface'; import { BrowseByTypeConfig } from '../../../config/browse-by-type-config.interface';
import { hasValue } from '../empty.util';
export interface ComColPageNavOption {
id: string;
label: string,
routerLink: string
params?: any;
};
/** /**
* A component to display the "Browse By" section of a Community or Collection page * A component to display the "Browse By" section of a Community or Collection page
@@ -8,24 +29,63 @@ import { BrowseByTypeConfig } from '../../../config/browse-by-type-config.interf
*/ */
@Component({ @Component({
selector: 'ds-comcol-page-browse-by', selector: 'ds-comcol-page-browse-by',
templateUrl: './comcol-page-browse-by.component.html', styleUrls: ['./comcol-page-browse-by.component.scss'],
templateUrl: './comcol-page-browse-by.component.html'
}) })
export class ComcolPageBrowseByComponent implements OnInit { export class ComcolPageBrowseByComponent implements OnInit {
/** /**
* The ID of the Community or Collection * The ID of the Community or Collection
*/ */
@Input() id: string; @Input() id: string;
@Input() contentType: string;
/** /**
* List of currently active browse configurations * List of currently active browse configurations
*/ */
types: BrowseByTypeConfig[]; types: BrowseByTypeConfig[];
constructor(@Inject(GLOBAL_CONFIG) public config: GlobalConfig) { allOptions: ComColPageNavOption[];
currentOptionId$: Observable<string>;
constructor(
@Inject(GLOBAL_CONFIG) public config: GlobalConfig,
private route: ActivatedRoute,
private router: Router) {
} }
ngOnInit(): void { ngOnInit(): void {
this.types = this.config.browseBy.types; this.allOptions = this.config.browseBy.types
.map((config: BrowseByTypeConfig) => ({
id: config.id,
label: `browse.comcol.by.${config.id}`,
routerLink: `/browse/${config.id}`,
params: { scope: this.id }
}));
if (this.contentType === 'collection') {
this.allOptions = [ {
id: this.id,
label: 'collection.page.browse.recent.head',
routerLink: getCollectionPageRoute(this.id)
}, ...this.allOptions ];
} else if (this.contentType === 'community') {
this.allOptions = [{
id: this.id,
label: 'community.all-lists.head',
routerLink: getCommunityPageRoute(this.id)
}, ...this.allOptions ];
} }
this.currentOptionId$ = this.route.url.pipe(
filter((urlSegments: UrlSegment[]) => hasValue(urlSegments)),
map((urlSegments: UrlSegment[]) => urlSegments[urlSegments.length - 1].path)
);
}
onSelectChange(newId: string) {
const selectedOption = this.allOptions
.find((option: ComColPageNavOption) => option.id === newId);
this.router.navigate([selectedOption.routerLink], { queryParams: selectedOption.params });
}
} }

View File

@@ -0,0 +1,4 @@
<div *ngIf="content" class="content-with-optional-title mb-2">
<h2 class="d-inline-block h6" *ngIf="title">{{ title | translate }}</h2>
<div class="d-inline-block "><a href="{{getHandle()}}">{{getHandle()}}</a></div>
</div>

View File

@@ -0,0 +1,5 @@
div {
word-break: break-word;
word-wrap: break-word;
overflow-wrap: break-word;
}

View File

@@ -0,0 +1,29 @@
import { Component, Input, Inject, Injectable } from '@angular/core';
import { GlobalConfig } from '../../../config/global-config.interface';
import { GLOBAL_CONFIG } from '../../../config';
import { UIURLCombiner } from '../../core/url-combiner/ui-url-combiner';
/**
* This component builds a URL from the value of "handle"
*/
@Component({
selector: 'ds-comcol-page-handle',
styleUrls: ['./comcol-page-handle.component.scss'],
templateUrl: './comcol-page-handle.component.html'
})
@Injectable()
export class ComcolPageHandleComponent {
// Optional title
@Input() title: string;
// The value of "handle"
@Input() content: string;
constructor(@Inject(GLOBAL_CONFIG) private EnvConfig: GlobalConfig) {
}
public getHandle(): string {
return new UIURLCombiner(this.EnvConfig, '/handle/', this.content).toString();
}
}

View File

@@ -115,6 +115,7 @@ describe('DsDynamicFormControlContainerComponent test suite', () => {
repeatable: false repeatable: false
}), }),
new DynamicRelationGroupModel({ new DynamicRelationGroupModel({
submissionId: '1234',
id: 'relationGroup', id: 'relationGroup',
formConfiguration: [], formConfiguration: [],
mandatoryField: '', mandatoryField: '',

View File

@@ -26,7 +26,6 @@ import { MOCK_SUBMISSION_CONFIG } from '../../../../../testing/mock-submission-c
import { Store, StoreModule } from '@ngrx/store'; import { Store, StoreModule } from '@ngrx/store';
import { MockStore } from '../../../../../testing/mock-store'; import { MockStore } from '../../../../../testing/mock-store';
import { FormRowModel } from '../../../../../../core/config/models/config-submission-form.model'; import { FormRowModel } from '../../../../../../core/config/models/config-submission-form.model';
import { WorkspaceItem } from '../../../../../../core/submission/models/workspaceitem.model';
export let FORM_GROUP_TEST_MODEL_CONFIG; export let FORM_GROUP_TEST_MODEL_CONFIG;
@@ -34,6 +33,8 @@ export let FORM_GROUP_TEST_GROUP;
const config: GlobalConfig = MOCK_SUBMISSION_CONFIG; const config: GlobalConfig = MOCK_SUBMISSION_CONFIG;
const submissionId = '1234';
function init() { function init() {
FORM_GROUP_TEST_MODEL_CONFIG = { FORM_GROUP_TEST_MODEL_CONFIG = {
disabled: false, disabled: false,
@@ -68,6 +69,7 @@ function init() {
}] }]
} as FormFieldModel] } as FormFieldModel]
} as FormRowModel], } as FormRowModel],
submissionId,
id: 'dc_contributor_author', id: 'dc_contributor_author',
label: 'Authors', label: 'Authors',
mandatoryField: 'dc.contributor.author', mandatoryField: 'dc.contributor.author',
@@ -79,7 +81,6 @@ function init() {
scopeUUID: '43fe1f8c-09a6-4fcf-9c78-5d4fed8f2c8f', scopeUUID: '43fe1f8c-09a6-4fcf-9c78-5d4fed8f2c8f',
submissionScope: undefined, submissionScope: undefined,
validators: { required: null }, validators: { required: null },
workspaceItem: new WorkspaceItem(),
repeatable: false repeatable: false
} as DynamicRelationGroupModelConfig; } as DynamicRelationGroupModelConfig;
@@ -186,7 +187,7 @@ describe('DsDynamicRelationGroupComponent test suite', () => {
it('should init component properly', inject([FormBuilderService], (service: FormBuilderService) => { it('should init component properly', inject([FormBuilderService], (service: FormBuilderService) => {
const formConfig = { rows: groupComp.model.formConfiguration } as SubmissionFormsModel; const formConfig = { rows: groupComp.model.formConfiguration } as SubmissionFormsModel;
const formModel = service.modelFromConfiguration(formConfig, groupComp.model.scopeUUID, {}, new WorkspaceItem(), groupComp.model.submissionScope, groupComp.model.readOnly); const formModel = service.modelFromConfiguration(submissionId, formConfig, groupComp.model.scopeUUID, {}, groupComp.model.submissionScope, groupComp.model.readOnly);
const chips = new Chips([], 'value', 'dc.contributor.author'); const chips = new Chips([], 'value', 'dc.contributor.author');
groupComp.formCollapsed.subscribe((value) => { groupComp.formCollapsed.subscribe((value) => {
expect(value).toEqual(false); expect(value).toEqual(false);
@@ -260,7 +261,7 @@ describe('DsDynamicRelationGroupComponent test suite', () => {
it('should init component properly', inject([FormBuilderService], (service: FormBuilderService) => { it('should init component properly', inject([FormBuilderService], (service: FormBuilderService) => {
const formConfig = { rows: groupComp.model.formConfiguration } as SubmissionFormsModel; const formConfig = { rows: groupComp.model.formConfiguration } as SubmissionFormsModel;
const formModel = service.modelFromConfiguration(formConfig, groupComp.model.scopeUUID, {}, new WorkspaceItem(), groupComp.model.submissionScope, groupComp.model.readOnly); const formModel = service.modelFromConfiguration(submissionId, formConfig, groupComp.model.scopeUUID, {}, groupComp.model.submissionScope, groupComp.model.readOnly);
const chips = new Chips(modelValue, 'value', 'dc.contributor.author'); const chips = new Chips(modelValue, 'value', 'dc.contributor.author');
groupComp.formCollapsed.subscribe((value) => { groupComp.formCollapsed.subscribe((value) => {
expect(value).toEqual(true); expect(value).toEqual(true);

View File

@@ -93,6 +93,7 @@ export class DsDynamicRelationGroupComponent extends DynamicFormControlComponent
this.formId = this.formService.getUniqueId(this.model.id); this.formId = this.formService.getUniqueId(this.model.id);
this.formModel = this.formBuilderService.modelFromConfiguration( this.formModel = this.formBuilderService.modelFromConfiguration(
this.model.submissionId,
config, config,
this.model.scopeUUID, this.model.scopeUUID,
{}, {},

View File

@@ -10,6 +10,7 @@ export const PLACEHOLDER_PARENT_METADATA = '#PLACEHOLDER_PARENT_METADATA_VALUE#'
* Dynamic Group Model configuration interface * Dynamic Group Model configuration interface
*/ */
export interface DynamicRelationGroupModelConfig extends DsDynamicInputModelConfig { export interface DynamicRelationGroupModelConfig extends DsDynamicInputModelConfig {
submissionId: string,
formConfiguration: FormRowModel[], formConfiguration: FormRowModel[],
mandatoryField: string, mandatoryField: string,
relationFields: string[], relationFields: string[],
@@ -21,6 +22,7 @@ export interface DynamicRelationGroupModelConfig extends DsDynamicInputModelConf
* Dynamic Group Model class * Dynamic Group Model class
*/ */
export class DynamicRelationGroupModel extends DsDynamicInputModel { export class DynamicRelationGroupModel extends DsDynamicInputModel {
@serializable() submissionId: string;
@serializable() formConfiguration: FormRowModel[]; @serializable() formConfiguration: FormRowModel[];
@serializable() mandatoryField: string; @serializable() mandatoryField: string;
@serializable() relationFields: string[]; @serializable() relationFields: string[];
@@ -32,6 +34,7 @@ export class DynamicRelationGroupModel extends DsDynamicInputModel {
constructor(config: DynamicRelationGroupModelConfig, layout?: DynamicFormControlLayout) { constructor(config: DynamicRelationGroupModelConfig, layout?: DynamicFormControlLayout) {
super(config, layout); super(config, layout);
this.submissionId = config.submissionId;
this.formConfiguration = config.formConfiguration; this.formConfiguration = config.formConfiguration;
this.mandatoryField = config.mandatoryField; this.mandatoryField = config.mandatoryField;
this.relationFields = config.relationFields; this.relationFields = config.relationFields;

View File

@@ -49,7 +49,6 @@ import { DynamicConcatModel } from './ds-dynamic-form-ui/models/ds-dynamic-conca
import { DynamicLookupNameModel } from './ds-dynamic-form-ui/models/lookup/dynamic-lookup-name.model'; import { DynamicLookupNameModel } from './ds-dynamic-form-ui/models/lookup/dynamic-lookup-name.model';
import { DynamicRowArrayModel } from './ds-dynamic-form-ui/models/ds-dynamic-row-array-model'; import { DynamicRowArrayModel } from './ds-dynamic-form-ui/models/ds-dynamic-row-array-model';
import { FormRowModel } from '../../../core/config/models/config-submission-form.model'; import { FormRowModel } from '../../../core/config/models/config-submission-form.model';
import { WorkspaceItem } from '../../../core/submission/models/workspaceitem.model';
describe('FormBuilderService test suite', () => { describe('FormBuilderService test suite', () => {
@@ -57,6 +56,8 @@ describe('FormBuilderService test suite', () => {
let testFormConfiguration: SubmissionFormsModel; let testFormConfiguration: SubmissionFormsModel;
let service: FormBuilderService; let service: FormBuilderService;
const submissionId = '1234';
function testValidator() { function testValidator() {
return {testValidator: {valid: true}}; return {testValidator: {valid: true}};
} }
@@ -194,17 +195,18 @@ describe('FormBuilderService test suite', () => {
new DynamicColorPickerModel({id: 'testColorPicker'}), new DynamicColorPickerModel({id: 'testColorPicker'}),
new DynamicTypeaheadModel({id: 'testTypeahead', workspaceItem: new WorkspaceItem(), repeatable: false}), new DynamicTypeaheadModel({id: 'testTypeahead', repeatable: false}),
new DynamicScrollableDropdownModel({id: 'testScrollableDropdown', authorityOptions: authorityOptions, workspaceItem: new WorkspaceItem(), repeatable: false}), new DynamicScrollableDropdownModel({id: 'testScrollableDropdown', authorityOptions: authorityOptions, repeatable: false}),
new DynamicTagModel({id: 'testTag', workspaceItem: new WorkspaceItem(), repeatable: false}), new DynamicTagModel({id: 'testTag', repeatable: false}),
new DynamicListCheckboxGroupModel({id: 'testCheckboxList', authorityOptions: authorityOptions, repeatable: true}), new DynamicListCheckboxGroupModel({id: 'testCheckboxList', authorityOptions: authorityOptions, repeatable: true}),
new DynamicListRadioGroupModel({id: 'testRadioList', authorityOptions: authorityOptions, repeatable: false}), new DynamicListRadioGroupModel({id: 'testRadioList', authorityOptions: authorityOptions, repeatable: false}),
new DynamicRelationGroupModel({ new DynamicRelationGroupModel({
submissionId,
id: 'testRelationGroup', id: 'testRelationGroup',
formConfiguration: [{ formConfiguration: [{
fields: [{ fields: [{
@@ -241,15 +243,14 @@ describe('FormBuilderService test suite', () => {
relationFields: [], relationFields: [],
scopeUUID: '', scopeUUID: '',
submissionScope: '', submissionScope: '',
workspaceItem: new WorkspaceItem(),
repeatable: false repeatable: false
}), }),
new DynamicDsDatePickerModel({id: 'testDate'}), new DynamicDsDatePickerModel({id: 'testDate'}),
new DynamicLookupModel({id: 'testLookup', workspaceItem: new WorkspaceItem(), repeatable: false}), new DynamicLookupModel({id: 'testLookup', repeatable: false}),
new DynamicLookupNameModel({id: 'testLookupName', workspaceItem: new WorkspaceItem(), repeatable: false}), new DynamicLookupNameModel({id: 'testLookupName', repeatable: false}),
new DynamicQualdropModel({id: 'testCombobox', readOnly: false, required: false}), new DynamicQualdropModel({id: 'testCombobox', readOnly: false, required: false}),
@@ -410,7 +411,7 @@ describe('FormBuilderService test suite', () => {
}); });
it('should create an array of form models', () => { it('should create an array of form models', () => {
const formModel = service.modelFromConfiguration(testFormConfiguration, 'testScopeUUID', {}, new WorkspaceItem()); const formModel = service.modelFromConfiguration(submissionId, testFormConfiguration, 'testScopeUUID');
expect(formModel[0] instanceof DynamicRowGroupModel).toBe(true); expect(formModel[0] instanceof DynamicRowGroupModel).toBe(true);
expect((formModel[0] as DynamicRowGroupModel).group.length).toBe(3); expect((formModel[0] as DynamicRowGroupModel).group.length).toBe(3);
@@ -431,7 +432,7 @@ describe('FormBuilderService test suite', () => {
}); });
it('should return form\'s fields value from form model', () => { it('should return form\'s fields value from form model', () => {
const formModel = service.modelFromConfiguration(testFormConfiguration, 'testScopeUUID', {}, new WorkspaceItem()); const formModel = service.modelFromConfiguration(submissionId, testFormConfiguration, 'testScopeUUID');
let value = {} as any; let value = {} as any;
expect(service.getValueFromModel(formModel)).toEqual(value); expect(service.getValueFromModel(formModel)).toEqual(value);
@@ -452,7 +453,7 @@ describe('FormBuilderService test suite', () => {
}); });
it('should clear all form\'s fields value', () => { it('should clear all form\'s fields value', () => {
const formModel = service.modelFromConfiguration(testFormConfiguration, 'testScopeUUID', {}, new WorkspaceItem()); const formModel = service.modelFromConfiguration(submissionId, testFormConfiguration, 'testScopeUUID');
const value = {} as any; const value = {} as any;
((formModel[0] as DynamicRowGroupModel).get(1) as DsDynamicInputModel).valueUpdates.next('test'); ((formModel[0] as DynamicRowGroupModel).get(1) as DsDynamicInputModel).valueUpdates.next('test');
@@ -464,7 +465,7 @@ describe('FormBuilderService test suite', () => {
}); });
it('should return true when model has a custom group model as parent', () => { it('should return true when model has a custom group model as parent', () => {
const formModel = service.modelFromConfiguration(testFormConfiguration, 'testScopeUUID', {}, new WorkspaceItem()); const formModel = service.modelFromConfiguration(submissionId, testFormConfiguration, 'testScopeUUID');
let model = service.findById('dc_identifier_QUALDROP_VALUE', formModel); let model = service.findById('dc_identifier_QUALDROP_VALUE', formModel);
let modelParent = service.findById('dc_identifier_QUALDROP_GROUP', formModel); let modelParent = service.findById('dc_identifier_QUALDROP_GROUP', formModel);
model.parent = modelParent; model.parent = modelParent;
@@ -493,7 +494,7 @@ describe('FormBuilderService test suite', () => {
}); });
it('should return true when model value is a map', () => { it('should return true when model value is a map', () => {
const formModel = service.modelFromConfiguration(testFormConfiguration, 'testScopeUUID', {}, new WorkspaceItem()); const formModel = service.modelFromConfiguration(submissionId, testFormConfiguration, 'testScopeUUID');
const model = service.findById('dc_identifier_QUALDROP_VALUE', formModel); const model = service.findById('dc_identifier_QUALDROP_VALUE', formModel);
const modelParent = service.findById('dc_identifier_QUALDROP_GROUP', formModel); const modelParent = service.findById('dc_identifier_QUALDROP_GROUP', formModel);
model.parent = modelParent; model.parent = modelParent;
@@ -502,7 +503,7 @@ describe('FormBuilderService test suite', () => {
}); });
it('should return true when model is a Qualdrop Group', () => { it('should return true when model is a Qualdrop Group', () => {
const formModel = service.modelFromConfiguration(testFormConfiguration, 'testScopeUUID', {}, new WorkspaceItem()); const formModel = service.modelFromConfiguration(submissionId, testFormConfiguration, 'testScopeUUID');
let model = service.findById('dc_identifier_QUALDROP_GROUP', formModel); let model = service.findById('dc_identifier_QUALDROP_GROUP', formModel);
expect(service.isQualdropGroup(model)).toBe(true); expect(service.isQualdropGroup(model)).toBe(true);
@@ -513,7 +514,7 @@ describe('FormBuilderService test suite', () => {
}); });
it('should return true when model is a Custom or List Group', () => { it('should return true when model is a Custom or List Group', () => {
const formModel = service.modelFromConfiguration(testFormConfiguration, 'testScopeUUID', {}, new WorkspaceItem()); const formModel = service.modelFromConfiguration(submissionId, testFormConfiguration, 'testScopeUUID');
let model = service.findById('dc_identifier_QUALDROP_GROUP', formModel); let model = service.findById('dc_identifier_QUALDROP_GROUP', formModel);
expect(service.isCustomOrListGroup(model)).toBe(true); expect(service.isCustomOrListGroup(model)).toBe(true);
@@ -532,7 +533,7 @@ describe('FormBuilderService test suite', () => {
}); });
it('should return true when model is a Custom Group', () => { it('should return true when model is a Custom Group', () => {
const formModel = service.modelFromConfiguration(testFormConfiguration, 'testScopeUUID', {}, new WorkspaceItem()); const formModel = service.modelFromConfiguration(submissionId, testFormConfiguration, 'testScopeUUID');
let model = service.findById('dc_identifier_QUALDROP_GROUP', formModel); let model = service.findById('dc_identifier_QUALDROP_GROUP', formModel);
expect(service.isCustomGroup(model)).toBe(true); expect(service.isCustomGroup(model)).toBe(true);

View File

@@ -11,6 +11,7 @@ import {
DynamicFormControlModel, DynamicFormControlModel,
DynamicFormGroupModel, DynamicFormGroupModel,
DynamicFormService, DynamicFormService,
DynamicFormValidationService,
DynamicPathable, DynamicPathable,
JSONUtils, JSONUtils,
} from '@ng-dynamic-forms/core'; } from '@ng-dynamic-forms/core';
@@ -26,11 +27,17 @@ import { DynamicRowArrayModel } from './ds-dynamic-form-ui/models/ds-dynamic-row
import { DsDynamicInputModel } from './ds-dynamic-form-ui/models/ds-dynamic-input.model'; import { DsDynamicInputModel } from './ds-dynamic-form-ui/models/ds-dynamic-input.model';
import { FormFieldMetadataValueObject } from './models/form-field-metadata-value.model'; import { FormFieldMetadataValueObject } from './models/form-field-metadata-value.model';
import { isNgbDateStruct } from '../../date.util'; import { isNgbDateStruct } from '../../date.util';
import { WorkspaceItem } from '../../../core/submission/models/workspaceitem.model';
@Injectable() @Injectable()
export class FormBuilderService extends DynamicFormService { export class FormBuilderService extends DynamicFormService {
constructor(
validationService: DynamicFormValidationService,
protected rowParser: RowParser
) {
super(validationService);
}
findById(id: string, groupModel: DynamicFormControlModel[], arrayIndex = null): DynamicFormControlModel | null { findById(id: string, groupModel: DynamicFormControlModel[], arrayIndex = null): DynamicFormControlModel | null {
let result = null; let result = null;
@@ -196,13 +203,13 @@ export class FormBuilderService extends DynamicFormService {
return result; return result;
} }
modelFromConfiguration(json: string | SubmissionFormsModel, scopeUUID: string, initFormValues: any = {}, wsi: WorkspaceItem, submissionScope?: string, readOnly = false): DynamicFormControlModel[] | never { modelFromConfiguration(submissionId: string, json: string | SubmissionFormsModel, scopeUUID: string, sectionData: any = {}, submissionScope?: string, readOnly = false): DynamicFormControlModel[] | never {
let rows: DynamicFormControlModel[] = []; let rows: DynamicFormControlModel[] = [];
const rawData = typeof json === 'string' ? JSON.parse(json, JSONUtils.parseReviver) : json; const rawData = typeof json === 'string' ? JSON.parse(json, JSONUtils.parseReviver) : json;
if (rawData.rows && !isEmpty(rawData.rows)) { if (rawData.rows && !isEmpty(rawData.rows)) {
rawData.rows.forEach((currentRow) => { rawData.rows.forEach((currentRow) => {
const rowParsed = new RowParser(currentRow, scopeUUID, initFormValues, wsi, submissionScope, readOnly).parse(); const rowParsed = this.rowParser.parse(submissionId, currentRow, scopeUUID, sectionData, submissionScope, readOnly);
if (isNotNull(rowParsed)) { if (isNotNull(rowParsed)) {
if (Array.isArray(rowParsed)) { if (Array.isArray(rowParsed)) {
rows = rows.concat(rowParsed); rows = rows.concat(rowParsed);

View File

@@ -1,4 +1,4 @@
import { FieldParser } from './field-parser'; import { Inject } from '@angular/core';
import { FormFieldModel } from '../models/form-field.model'; import { FormFieldModel } from '../models/form-field.model';
import { FormFieldMetadataValueObject } from '../models/form-field-metadata-value.model'; import { FormFieldMetadataValueObject } from '../models/form-field-metadata-value.model';
import { import {
@@ -15,18 +15,25 @@ import {
} from '../ds-dynamic-form-ui/models/ds-dynamic-concat.model'; } from '../ds-dynamic-form-ui/models/ds-dynamic-concat.model';
import { isNotEmpty } from '../../../empty.util'; import { isNotEmpty } from '../../../empty.util';
import { ParserOptions } from './parser-options'; import { ParserOptions } from './parser-options';
import { WorkspaceItem } from '../../../../core/submission/models/workspaceitem.model'; import {
CONFIG_DATA,
FieldParser,
INIT_FORM_VALUES,
PARSER_OPTIONS,
SUBMISSION_ID
} from './field-parser';
export class ConcatFieldParser extends FieldParser { export class ConcatFieldParser extends FieldParser {
constructor(protected configData: FormFieldModel, constructor(
protected initFormValues, @Inject(SUBMISSION_ID) submissionId: string,
protected parserOptions: ParserOptions, @Inject(CONFIG_DATA) configData: FormFieldModel,
@Inject(INIT_FORM_VALUES) initFormValues,
@Inject(PARSER_OPTIONS) parserOptions: ParserOptions,
protected separator: string, protected separator: string,
protected workspaceItem: WorkspaceItem,
protected firstPlaceholder: string = null, protected firstPlaceholder: string = null,
protected secondPlaceholder: string = null) { protected secondPlaceholder: string = null) {
super(configData, initFormValues, parserOptions, workspaceItem); super(submissionId, configData, initFormValues, parserOptions);
this.separator = separator; this.separator = separator;
this.firstPlaceholder = firstPlaceholder; this.firstPlaceholder = firstPlaceholder;

View File

@@ -3,12 +3,12 @@ import { DateFieldParser } from './date-field-parser';
import { DynamicDsDatePickerModel } from '../ds-dynamic-form-ui/models/date-picker/date-picker.model'; import { DynamicDsDatePickerModel } from '../ds-dynamic-form-ui/models/date-picker/date-picker.model';
import { FormFieldMetadataValueObject } from '../models/form-field-metadata-value.model'; import { FormFieldMetadataValueObject } from '../models/form-field-metadata-value.model';
import { ParserOptions } from './parser-options'; import { ParserOptions } from './parser-options';
import { WorkspaceItem } from '../../../../core/submission/models/workspaceitem.model';
describe('DateFieldParser test suite', () => { describe('DateFieldParser test suite', () => {
let field: FormFieldModel; let field: FormFieldModel;
let initFormValues: any = {}; let initFormValues: any = {};
const submissionId = '1234';
const parserOptions: ParserOptions = { const parserOptions: ParserOptions = {
readOnly: false, readOnly: false,
submissionScope: null, submissionScope: null,
@@ -36,13 +36,13 @@ describe('DateFieldParser test suite', () => {
}); });
it('should init parser properly', () => { it('should init parser properly', () => {
const parser = new DateFieldParser(field, initFormValues, parserOptions, new WorkspaceItem()); const parser = new DateFieldParser(submissionId, field, initFormValues, parserOptions);
expect(parser instanceof DateFieldParser).toBe(true); expect(parser instanceof DateFieldParser).toBe(true);
}); });
it('should return a DynamicDsDatePickerModel object when repeatable option is false', () => { it('should return a DynamicDsDatePickerModel object when repeatable option is false', () => {
const parser = new DateFieldParser(field, initFormValues, parserOptions, new WorkspaceItem()); const parser = new DateFieldParser(submissionId, field, initFormValues, parserOptions);
const fieldModel = parser.parse(); const fieldModel = parser.parse();
@@ -55,7 +55,7 @@ describe('DateFieldParser test suite', () => {
}; };
const expectedValue = '1983-11-18'; const expectedValue = '1983-11-18';
const parser = new DateFieldParser(field, initFormValues, parserOptions, new WorkspaceItem()); const parser = new DateFieldParser(submissionId, field, initFormValues, parserOptions);
const fieldModel = parser.parse(); const fieldModel = parser.parse();

View File

@@ -2,11 +2,11 @@ import { FormFieldModel } from '../models/form-field.model';
import { DropdownFieldParser } from './dropdown-field-parser'; import { DropdownFieldParser } from './dropdown-field-parser';
import { DynamicScrollableDropdownModel } from '../ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.model'; import { DynamicScrollableDropdownModel } from '../ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.model';
import { ParserOptions } from './parser-options'; import { ParserOptions } from './parser-options';
import { WorkspaceItem } from '../../../../core/submission/models/workspaceitem.model';
describe('DropdownFieldParser test suite', () => { describe('DropdownFieldParser test suite', () => {
let field: FormFieldModel; let field: FormFieldModel;
const submissionId = '1234';
const initFormValues = {}; const initFormValues = {};
const parserOptions: ParserOptions = { const parserOptions: ParserOptions = {
readOnly: false, readOnly: false,
@@ -36,13 +36,13 @@ describe('DropdownFieldParser test suite', () => {
}); });
it('should init parser properly', () => { it('should init parser properly', () => {
const parser = new DropdownFieldParser(field, initFormValues, parserOptions, new WorkspaceItem()); const parser = new DropdownFieldParser(submissionId, field, initFormValues, parserOptions);
expect(parser instanceof DropdownFieldParser).toBe(true); expect(parser instanceof DropdownFieldParser).toBe(true);
}); });
it('should return a DynamicScrollableDropdownModel object when repeatable option is false', () => { it('should return a DynamicScrollableDropdownModel object when repeatable option is false', () => {
const parser = new DropdownFieldParser(field, initFormValues, parserOptions, new WorkspaceItem()); const parser = new DropdownFieldParser(submissionId, field, initFormValues, parserOptions);
const fieldModel = parser.parse(); const fieldModel = parser.parse();
@@ -51,7 +51,7 @@ describe('DropdownFieldParser test suite', () => {
it('should throw when authority is not passed', () => { it('should throw when authority is not passed', () => {
field.selectableMetadata[0].authority = null; field.selectableMetadata[0].authority = null;
const parser = new DropdownFieldParser(field, initFormValues, parserOptions, new WorkspaceItem()); const parser = new DropdownFieldParser(submissionId, field, initFormValues, parserOptions);
expect(() => parser.parse()) expect(() => parser.parse())
.toThrow(); .toThrow();

View File

@@ -1,4 +1,12 @@
import { FieldParser } from './field-parser'; import { Inject } from '@angular/core';
import { FormFieldModel } from '../models/form-field.model';
import {
CONFIG_DATA,
FieldParser,
INIT_FORM_VALUES,
PARSER_OPTIONS,
SUBMISSION_ID
} from './field-parser';
import { DynamicFormControlLayout, } from '@ng-dynamic-forms/core'; import { DynamicFormControlLayout, } from '@ng-dynamic-forms/core';
import { import {
DynamicScrollableDropdownModel, DynamicScrollableDropdownModel,
@@ -6,9 +14,19 @@ import {
} from '../ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.model'; } from '../ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.model';
import { isNotEmpty } from '../../../empty.util'; import { isNotEmpty } from '../../../empty.util';
import { FormFieldMetadataValueObject } from '../models/form-field-metadata-value.model'; import { FormFieldMetadataValueObject } from '../models/form-field-metadata-value.model';
import { ParserOptions } from './parser-options';
export class DropdownFieldParser extends FieldParser { export class DropdownFieldParser extends FieldParser {
constructor(
@Inject(SUBMISSION_ID) submissionId: string,
@Inject(CONFIG_DATA) configData: FormFieldModel,
@Inject(INIT_FORM_VALUES) initFormValues,
@Inject(PARSER_OPTIONS) parserOptions: ParserOptions
) {
super(submissionId, configData, initFormValues, parserOptions)
}
public modelFactory(fieldValue?: FormFieldMetadataValueObject | any, label?: boolean): any { public modelFactory(fieldValue?: FormFieldMetadataValueObject | any, label?: boolean): any {
const dropdownModelConfig: DynamicScrollableDropdownModelConfig = this.initModel(null, label); const dropdownModelConfig: DynamicScrollableDropdownModelConfig = this.initModel(null, label);
let layout: DynamicFormControlLayout; let layout: DynamicFormControlLayout;

View File

@@ -1,4 +1,5 @@
import { hasValue, isEmpty, isNotEmpty, isNotNull, isNotUndefined } from '../../../empty.util'; import { Inject, InjectionToken } from '@angular/core';
import { hasValue, isNotEmpty, isNotNull, isNotUndefined, isEmpty } from '../../../empty.util';
import { FormFieldModel } from '../models/form-field.model'; import { FormFieldModel } from '../models/form-field.model';
import { uniqueId } from 'lodash'; import { uniqueId } from 'lodash';
@@ -12,13 +13,22 @@ import { DynamicFormControlLayout } from '@ng-dynamic-forms/core';
import { setLayout } from './parser.utils'; import { setLayout } from './parser.utils';
import { AuthorityOptions } from '../../../../core/integration/models/authority-options.model'; import { AuthorityOptions } from '../../../../core/integration/models/authority-options.model';
import { ParserOptions } from './parser-options'; import { ParserOptions } from './parser-options';
import { WorkspaceItem } from '../../../../core/submission/models/workspaceitem.model';
export const SUBMISSION_ID: InjectionToken<string> = new InjectionToken<string>('submissionId');
export const CONFIG_DATA: InjectionToken<FormFieldModel> = new InjectionToken<FormFieldModel>('configData');
export const INIT_FORM_VALUES:InjectionToken<any> = new InjectionToken<any>('initFormValues');
export const PARSER_OPTIONS: InjectionToken<ParserOptions> = new InjectionToken<ParserOptions>('parserOptions');
export abstract class FieldParser { export abstract class FieldParser {
protected fieldId: string; protected fieldId: string;
constructor(protected configData: FormFieldModel, protected initFormValues, protected parserOptions: ParserOptions, protected workspaceItem: WorkspaceItem) {
} constructor(
@Inject(SUBMISSION_ID) protected submissionId: string,
@Inject(CONFIG_DATA) protected configData: FormFieldModel,
@Inject(INIT_FORM_VALUES) protected initFormValues: any,
@Inject(PARSER_OPTIONS) protected parserOptions: ParserOptions
) {}
public abstract modelFactory(fieldValue?: FormFieldMetadataValueObject, label?: boolean): any; public abstract modelFactory(fieldValue?: FormFieldMetadataValueObject, label?: boolean): any;
@@ -31,11 +41,12 @@ export abstract class FieldParser {
) { ) {
let arrayCounter = 0; let arrayCounter = 0;
let fieldArrayCounter = 0; let fieldArrayCounter = 0;
const config = { const config = {
id: uniqueId() + '_array', id: uniqueId() + '_array',
label: this.configData.label,
initialCount: this.getInitArrayIndex(), initialCount: this.getInitArrayIndex(),
notRepeatable: !this.configData.repeatable, notRepeatable: !this.configData.repeatable,
label: this.configData.label,
required: isNotEmpty(this.configData.mandatory), required: isNotEmpty(this.configData.mandatory),
groupFactory: () => { groupFactory: () => {
let model; let model;
@@ -185,7 +196,6 @@ export abstract class FieldParser {
// Set read only option // Set read only option
controlModel.readOnly = this.parserOptions.readOnly; controlModel.readOnly = this.parserOptions.readOnly;
controlModel.disabled = this.parserOptions.readOnly; controlModel.disabled = this.parserOptions.readOnly;
controlModel.workspaceItem = this.workspaceItem;
controlModel.relationship = this.configData.selectableRelationship; controlModel.relationship = this.configData.selectableRelationship;
controlModel.repeatable = this.configData.repeatable; controlModel.repeatable = this.configData.repeatable;
controlModel.metadataFields = isNotEmpty(this.configData.selectableMetadata) ? this.configData.selectableMetadata.map((metadataObject) => metadataObject.metadata) : []; controlModel.metadataFields = isNotEmpty(this.configData.selectableMetadata) ? this.configData.selectableMetadata.map((metadataObject) => metadataObject.metadata) : [];

View File

@@ -4,12 +4,12 @@ import { ListFieldParser } from './list-field-parser';
import { DynamicListCheckboxGroupModel } from '../ds-dynamic-form-ui/models/list/dynamic-list-checkbox-group.model'; import { DynamicListCheckboxGroupModel } from '../ds-dynamic-form-ui/models/list/dynamic-list-checkbox-group.model';
import { DynamicListRadioGroupModel } from '../ds-dynamic-form-ui/models/list/dynamic-list-radio-group.model'; import { DynamicListRadioGroupModel } from '../ds-dynamic-form-ui/models/list/dynamic-list-radio-group.model';
import { ParserOptions } from './parser-options'; import { ParserOptions } from './parser-options';
import { WorkspaceItem } from '../../../../core/submission/models/workspaceitem.model';
describe('ListFieldParser test suite', () => { describe('ListFieldParser test suite', () => {
let field: FormFieldModel; let field: FormFieldModel;
let initFormValues = {}; let initFormValues = {};
const submissionId = '1234';
const parserOptions: ParserOptions = { const parserOptions: ParserOptions = {
readOnly: false, readOnly: false,
submissionScope: 'testScopeUUID', submissionScope: 'testScopeUUID',
@@ -38,13 +38,13 @@ describe('ListFieldParser test suite', () => {
}); });
it('should init parser properly', () => { it('should init parser properly', () => {
const parser = new ListFieldParser(field, initFormValues, parserOptions, new WorkspaceItem()); const parser = new ListFieldParser(submissionId, field, initFormValues, parserOptions);
expect(parser instanceof ListFieldParser).toBe(true); expect(parser instanceof ListFieldParser).toBe(true);
}); });
it('should return a DynamicListCheckboxGroupModel object when repeatable option is true', () => { it('should return a DynamicListCheckboxGroupModel object when repeatable option is true', () => {
const parser = new ListFieldParser(field, initFormValues, parserOptions, new WorkspaceItem()); const parser = new ListFieldParser(submissionId, field, initFormValues, parserOptions);
const fieldModel = parser.parse(); const fieldModel = parser.parse();
@@ -53,7 +53,7 @@ describe('ListFieldParser test suite', () => {
it('should return a DynamicListRadioGroupModel object when repeatable option is false', () => { it('should return a DynamicListRadioGroupModel object when repeatable option is false', () => {
field.repeatable = false; field.repeatable = false;
const parser = new ListFieldParser(field, initFormValues, parserOptions, new WorkspaceItem()); const parser = new ListFieldParser(submissionId, field, initFormValues, parserOptions);
const fieldModel = parser.parse(); const fieldModel = parser.parse();
@@ -66,7 +66,7 @@ describe('ListFieldParser test suite', () => {
}; };
const expectedValue = [new FormFieldMetadataValueObject('test type')]; const expectedValue = [new FormFieldMetadataValueObject('test type')];
const parser = new ListFieldParser(field, initFormValues, parserOptions, new WorkspaceItem()); const parser = new ListFieldParser(submissionId, field, initFormValues, parserOptions);
const fieldModel = parser.parse(); const fieldModel = parser.parse();

View File

@@ -3,12 +3,12 @@ import { FormFieldMetadataValueObject } from '../models/form-field-metadata-valu
import { LookupFieldParser } from './lookup-field-parser'; import { LookupFieldParser } from './lookup-field-parser';
import { DynamicLookupModel } from '../ds-dynamic-form-ui/models/lookup/dynamic-lookup.model'; import { DynamicLookupModel } from '../ds-dynamic-form-ui/models/lookup/dynamic-lookup.model';
import { ParserOptions } from './parser-options'; import { ParserOptions } from './parser-options';
import { WorkspaceItem } from '../../../../core/submission/models/workspaceitem.model';
describe('LookupFieldParser test suite', () => { describe('LookupFieldParser test suite', () => {
let field: FormFieldModel; let field: FormFieldModel;
let initFormValues = {}; let initFormValues = {};
const submissionId = '1234';
const parserOptions: ParserOptions = { const parserOptions: ParserOptions = {
readOnly: false, readOnly: false,
submissionScope: 'testScopeUUID', submissionScope: 'testScopeUUID',
@@ -37,13 +37,13 @@ describe('LookupFieldParser test suite', () => {
}); });
it('should init parser properly', () => { it('should init parser properly', () => {
const parser = new LookupFieldParser(field, initFormValues, parserOptions, new WorkspaceItem()); const parser = new LookupFieldParser(submissionId, field, initFormValues, parserOptions);
expect(parser instanceof LookupFieldParser).toBe(true); expect(parser instanceof LookupFieldParser).toBe(true);
}); });
it('should return a DynamicLookupModel object when repeatable option is false', () => { it('should return a DynamicLookupModel object when repeatable option is false', () => {
const parser = new LookupFieldParser(field, initFormValues, parserOptions, new WorkspaceItem()); const parser = new LookupFieldParser(submissionId, field, initFormValues, parserOptions);
const fieldModel = parser.parse(); const fieldModel = parser.parse();
@@ -56,7 +56,7 @@ describe('LookupFieldParser test suite', () => {
}; };
const expectedValue = new FormFieldMetadataValueObject('test journal'); const expectedValue = new FormFieldMetadataValueObject('test journal');
const parser = new LookupFieldParser(field, initFormValues, parserOptions, new WorkspaceItem()); const parser = new LookupFieldParser(submissionId, field, initFormValues, parserOptions);
const fieldModel = parser.parse(); const fieldModel = parser.parse();

View File

@@ -1,16 +1,14 @@
import { FormFieldModel } from '../models/form-field.model'; import { FormFieldModel } from '../models/form-field.model';
import { FormFieldMetadataValueObject } from '../models/form-field-metadata-value.model'; import { FormFieldMetadataValueObject } from '../models/form-field-metadata-value.model';
import { LookupFieldParser } from './lookup-field-parser';
import { DynamicLookupModel } from '../ds-dynamic-form-ui/models/lookup/dynamic-lookup.model';
import { LookupNameFieldParser } from './lookup-name-field-parser'; import { LookupNameFieldParser } from './lookup-name-field-parser';
import { DynamicLookupNameModel } from '../ds-dynamic-form-ui/models/lookup/dynamic-lookup-name.model'; import { DynamicLookupNameModel } from '../ds-dynamic-form-ui/models/lookup/dynamic-lookup-name.model';
import { ParserOptions } from './parser-options'; import { ParserOptions } from './parser-options';
import { WorkspaceItem } from '../../../../core/submission/models/workspaceitem.model';
describe('LookupNameFieldParser test suite', () => { describe('LookupNameFieldParser test suite', () => {
let field: FormFieldModel; let field: FormFieldModel;
let initFormValues = {}; let initFormValues = {};
const submissionId = '1234';
const parserOptions: ParserOptions = { const parserOptions: ParserOptions = {
readOnly: false, readOnly: false,
submissionScope: 'testScopeUUID', submissionScope: 'testScopeUUID',
@@ -39,13 +37,13 @@ describe('LookupNameFieldParser test suite', () => {
}); });
it('should init parser properly', () => { it('should init parser properly', () => {
const parser = new LookupNameFieldParser(field, initFormValues, parserOptions, new WorkspaceItem()); const parser = new LookupNameFieldParser(submissionId, field, initFormValues, parserOptions);
expect(parser instanceof LookupNameFieldParser).toBe(true); expect(parser instanceof LookupNameFieldParser).toBe(true);
}); });
it('should return a DynamicLookupNameModel object when repeatable option is false', () => { it('should return a DynamicLookupNameModel object when repeatable option is false', () => {
const parser = new LookupNameFieldParser(field, initFormValues, parserOptions, new WorkspaceItem()); const parser = new LookupNameFieldParser(submissionId, field, initFormValues, parserOptions);
const fieldModel = parser.parse(); const fieldModel = parser.parse();
@@ -58,7 +56,7 @@ describe('LookupNameFieldParser test suite', () => {
}; };
const expectedValue = new FormFieldMetadataValueObject('test author'); const expectedValue = new FormFieldMetadataValueObject('test author');
const parser = new LookupNameFieldParser(field, initFormValues, parserOptions, new WorkspaceItem()); const parser = new LookupNameFieldParser(submissionId, field, initFormValues, parserOptions);
const fieldModel = parser.parse(); const fieldModel = parser.parse();

View File

@@ -3,7 +3,6 @@ import { NameFieldParser } from './name-field-parser';
import { DynamicConcatModel } from '../ds-dynamic-form-ui/models/ds-dynamic-concat.model'; import { DynamicConcatModel } from '../ds-dynamic-form-ui/models/ds-dynamic-concat.model';
import { FormFieldMetadataValueObject } from '../models/form-field-metadata-value.model'; import { FormFieldMetadataValueObject } from '../models/form-field-metadata-value.model';
import { ParserOptions } from './parser-options'; import { ParserOptions } from './parser-options';
import { WorkspaceItem } from '../../../../core/submission/models/workspaceitem.model';
describe('NameFieldParser test suite', () => { describe('NameFieldParser test suite', () => {
let field1: FormFieldModel; let field1: FormFieldModel;
@@ -11,6 +10,7 @@ describe('NameFieldParser test suite', () => {
let field3: FormFieldModel; let field3: FormFieldModel;
let initFormValues: any = {}; let initFormValues: any = {};
const submissionId = '1234';
const parserOptions: ParserOptions = { const parserOptions: ParserOptions = {
readOnly: false, readOnly: false,
submissionScope: 'testScopeUUID', submissionScope: 'testScopeUUID',
@@ -70,13 +70,13 @@ describe('NameFieldParser test suite', () => {
}); });
it('should init parser properly', () => { it('should init parser properly', () => {
const parser = new NameFieldParser(field1, initFormValues, parserOptions, new WorkspaceItem()); const parser = new NameFieldParser(submissionId, field1, initFormValues, parserOptions);
expect(parser instanceof NameFieldParser).toBe(true); expect(parser instanceof NameFieldParser).toBe(true);
}); });
it('should return a DynamicConcatModel object when repeatable option is false', () => { it('should return a DynamicConcatModel object when repeatable option is false', () => {
const parser = new NameFieldParser(field2, initFormValues, parserOptions, new WorkspaceItem()); const parser = new NameFieldParser(submissionId, field2, initFormValues, parserOptions);
const fieldModel = parser.parse(); const fieldModel = parser.parse();
@@ -84,7 +84,7 @@ describe('NameFieldParser test suite', () => {
}); });
it('should return a DynamicConcatModel object with the correct separator', () => { it('should return a DynamicConcatModel object with the correct separator', () => {
const parser = new NameFieldParser(field2, initFormValues, parserOptions, new WorkspaceItem()); const parser = new NameFieldParser(submissionId, field2, initFormValues, parserOptions);
const fieldModel = parser.parse(); const fieldModel = parser.parse();
@@ -97,7 +97,7 @@ describe('NameFieldParser test suite', () => {
}; };
const expectedValue = new FormFieldMetadataValueObject('test, name'); const expectedValue = new FormFieldMetadataValueObject('test, name');
const parser = new NameFieldParser(field1, initFormValues, parserOptions, new WorkspaceItem()); const parser = new NameFieldParser(submissionId, field1, initFormValues, parserOptions);
const fieldModel = parser.parse(); const fieldModel = parser.parse();

View File

@@ -1,11 +1,17 @@
import { Inject } from '@angular/core';
import { FormFieldModel } from '../models/form-field.model'; import { FormFieldModel } from '../models/form-field.model';
import { ConcatFieldParser } from './concat-field-parser'; import { ConcatFieldParser } from './concat-field-parser';
import { CONFIG_DATA, INIT_FORM_VALUES, PARSER_OPTIONS, SUBMISSION_ID } from './field-parser';
import { ParserOptions } from './parser-options'; import { ParserOptions } from './parser-options';
import { WorkspaceItem } from '../../../../core/submission/models/workspaceitem.model';
export class NameFieldParser extends ConcatFieldParser { export class NameFieldParser extends ConcatFieldParser {
constructor(protected configData: FormFieldModel, protected initFormValues, protected parserOptions: ParserOptions, wsi: WorkspaceItem) { constructor(
super(configData, initFormValues, parserOptions, ',', wsi, 'form.last-name', 'form.first-name'); @Inject(SUBMISSION_ID) submissionId: string,
@Inject(CONFIG_DATA) configData: FormFieldModel,
@Inject(INIT_FORM_VALUES) initFormValues,
@Inject(PARSER_OPTIONS) parserOptions: ParserOptions
) {
super(submissionId, configData, initFormValues, parserOptions, ',', 'form.last-name', 'form.first-name');
} }
} }

View File

@@ -4,13 +4,13 @@ import { DynamicQualdropModel } from '../ds-dynamic-form-ui/models/ds-dynamic-qu
import { DynamicTypeaheadModel } from '../ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.model'; import { DynamicTypeaheadModel } from '../ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.model';
import { DsDynamicInputModel } from '../ds-dynamic-form-ui/models/ds-dynamic-input.model'; import { DsDynamicInputModel } from '../ds-dynamic-form-ui/models/ds-dynamic-input.model';
import { ParserOptions } from './parser-options'; import { ParserOptions } from './parser-options';
import { WorkspaceItem } from '../../../../core/submission/models/workspaceitem.model';
describe('OneboxFieldParser test suite', () => { describe('OneboxFieldParser test suite', () => {
let field1: FormFieldModel; let field1: FormFieldModel;
let field2: FormFieldModel; let field2: FormFieldModel;
let field3: FormFieldModel; let field3: FormFieldModel;
const submissionId = '1234';
const initFormValues = {}; const initFormValues = {};
const parserOptions: ParserOptions = { const parserOptions: ParserOptions = {
readOnly: false, readOnly: false,
@@ -71,13 +71,13 @@ describe('OneboxFieldParser test suite', () => {
}); });
it('should init parser properly', () => { it('should init parser properly', () => {
const parser = new OneboxFieldParser(field1, initFormValues, parserOptions, new WorkspaceItem()); const parser = new OneboxFieldParser(submissionId, field1, initFormValues, parserOptions);
expect(parser instanceof OneboxFieldParser).toBe(true); expect(parser instanceof OneboxFieldParser).toBe(true);
}); });
it('should return a DynamicQualdropModel object when selectableMetadata is multiple', () => { it('should return a DynamicQualdropModel object when selectableMetadata is multiple', () => {
const parser = new OneboxFieldParser(field2, initFormValues, parserOptions, new WorkspaceItem()); const parser = new OneboxFieldParser(submissionId, field2, initFormValues, parserOptions);
const fieldModel = parser.parse(); const fieldModel = parser.parse();
@@ -85,7 +85,7 @@ describe('OneboxFieldParser test suite', () => {
}); });
it('should return a DsDynamicInputModel object when selectableMetadata is not multiple', () => { it('should return a DsDynamicInputModel object when selectableMetadata is not multiple', () => {
const parser = new OneboxFieldParser(field3, initFormValues, parserOptions, new WorkspaceItem()); const parser = new OneboxFieldParser(submissionId, field3, initFormValues, parserOptions);
const fieldModel = parser.parse(); const fieldModel = parser.parse();
@@ -93,7 +93,7 @@ describe('OneboxFieldParser test suite', () => {
}); });
it('should return a DynamicTypeaheadModel object when selectableMetadata has authority', () => { it('should return a DynamicTypeaheadModel object when selectableMetadata has authority', () => {
const parser = new OneboxFieldParser(field1, initFormValues, parserOptions, new WorkspaceItem()); const parser = new OneboxFieldParser(submissionId, field1, initFormValues, parserOptions);
const fieldModel = parser.parse(); const fieldModel = parser.parse();

View File

@@ -1,6 +1,12 @@
import { StaticProvider } from '@angular/core';
import { ParserType } from './parser-type'; import { ParserType } from './parser-type';
import { GenericConstructor } from '../../../../core/shared/generic-constructor'; import {
import { FieldParser } from './field-parser'; CONFIG_DATA,
FieldParser,
INIT_FORM_VALUES,
PARSER_OPTIONS,
SUBMISSION_ID
} from './field-parser';
import { DateFieldParser } from './date-field-parser'; import { DateFieldParser } from './date-field-parser';
import { DropdownFieldParser } from './dropdown-field-parser'; import { DropdownFieldParser } from './dropdown-field-parser';
import { RelationGroupFieldParser } from './relation-group-field-parser'; import { RelationGroupFieldParser } from './relation-group-field-parser';
@@ -14,41 +20,92 @@ import { TagFieldParser } from './tag-field-parser';
import { TextareaFieldParser } from './textarea-field-parser'; import { TextareaFieldParser } from './textarea-field-parser';
import { DisabledFieldParser } from './disabled-field-parser'; import { DisabledFieldParser } from './disabled-field-parser';
const fieldParserDeps = [
SUBMISSION_ID,
CONFIG_DATA,
INIT_FORM_VALUES,
PARSER_OPTIONS,
];
export class ParserFactory { export class ParserFactory {
public static getConstructor(type: ParserType): GenericConstructor<FieldParser> { public static getProvider(type: ParserType): StaticProvider {
switch (type) { switch (type) {
case ParserType.Date: { case ParserType.Date: {
return DateFieldParser return {
provide: FieldParser,
useClass: DateFieldParser,
deps: [...fieldParserDeps]
}
} }
case ParserType.Dropdown: { case ParserType.Dropdown: {
return DropdownFieldParser return {
provide: FieldParser,
useClass: DropdownFieldParser,
deps: [...fieldParserDeps]
}
} }
case ParserType.RelationGroup: { case ParserType.RelationGroup: {
return RelationGroupFieldParser return {
provide: FieldParser,
useClass: RelationGroupFieldParser,
deps: [...fieldParserDeps]
}
} }
case ParserType.List: { case ParserType.List: {
return ListFieldParser return {
provide: FieldParser,
useClass: ListFieldParser,
deps: [...fieldParserDeps]
}
} }
case ParserType.Lookup: { case ParserType.Lookup: {
return LookupFieldParser return {
provide: FieldParser,
useClass: LookupFieldParser,
deps: [...fieldParserDeps]
}
} }
case ParserType.LookupName: { case ParserType.LookupName: {
return LookupNameFieldParser return {
provide: FieldParser,
useClass: LookupNameFieldParser,
deps: [...fieldParserDeps]
}
} }
case ParserType.Onebox: { case ParserType.Onebox: {
return OneboxFieldParser return {
provide: FieldParser,
useClass: OneboxFieldParser,
deps: [...fieldParserDeps]
}
} }
case ParserType.Name: { case ParserType.Name: {
return NameFieldParser return {
provide: FieldParser,
useClass: NameFieldParser,
deps: [...fieldParserDeps]
}
} }
case ParserType.Series: { case ParserType.Series: {
return SeriesFieldParser return {
provide: FieldParser,
useClass: SeriesFieldParser,
deps: [...fieldParserDeps]
}
} }
case ParserType.Tag: { case ParserType.Tag: {
return TagFieldParser return {
provide: FieldParser,
useClass: TagFieldParser,
deps: [...fieldParserDeps]
}
} }
case ParserType.Textarea: { case ParserType.Textarea: {
return TextareaFieldParser return {
provide: FieldParser,
useClass: TextareaFieldParser,
deps: [...fieldParserDeps]
}
} }
case undefined: { case undefined: {
return DisabledFieldParser return DisabledFieldParser

View File

@@ -3,12 +3,12 @@ import { RelationGroupFieldParser } from './relation-group-field-parser';
import { DynamicRelationGroupModel } from '../ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.model'; import { DynamicRelationGroupModel } from '../ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.model';
import { FormFieldMetadataValueObject } from '../models/form-field-metadata-value.model'; import { FormFieldMetadataValueObject } from '../models/form-field-metadata-value.model';
import { ParserOptions } from './parser-options'; import { ParserOptions } from './parser-options';
import { WorkspaceItem } from '../../../../core/submission/models/workspaceitem.model';
describe('RelationGroupFieldParser test suite', () => { describe('RelationGroupFieldParser test suite', () => {
let field: FormFieldModel; let field: FormFieldModel;
let initFormValues = {}; let initFormValues = {};
const submissionId = '1234';
const parserOptions: ParserOptions = { const parserOptions: ParserOptions = {
readOnly: false, readOnly: false,
submissionScope: 'testScopeUUID', submissionScope: 'testScopeUUID',
@@ -72,13 +72,13 @@ describe('RelationGroupFieldParser test suite', () => {
}); });
it('should init parser properly', () => { it('should init parser properly', () => {
const parser = new RelationGroupFieldParser(field, initFormValues, parserOptions, new WorkspaceItem()); const parser = new RelationGroupFieldParser(submissionId, field, initFormValues, parserOptions);
expect(parser instanceof RelationGroupFieldParser).toBe(true); expect(parser instanceof RelationGroupFieldParser).toBe(true);
}); });
it('should return a DynamicRelationGroupModel object', () => { it('should return a DynamicRelationGroupModel object', () => {
const parser = new RelationGroupFieldParser(field, initFormValues, parserOptions, new WorkspaceItem()); const parser = new RelationGroupFieldParser(submissionId, field, initFormValues, parserOptions);
const fieldModel = parser.parse(); const fieldModel = parser.parse();
@@ -87,7 +87,7 @@ describe('RelationGroupFieldParser test suite', () => {
it('should throw when rows configuration is empty', () => { it('should throw when rows configuration is empty', () => {
field.rows = null; field.rows = null;
const parser = new RelationGroupFieldParser(field, initFormValues, parserOptions, new WorkspaceItem()); const parser = new RelationGroupFieldParser(submissionId, field, initFormValues, parserOptions);
expect(() => parser.parse()) expect(() => parser.parse())
.toThrow(); .toThrow();
@@ -98,7 +98,7 @@ describe('RelationGroupFieldParser test suite', () => {
author: [new FormFieldMetadataValueObject('test author')], author: [new FormFieldMetadataValueObject('test author')],
affiliation: [new FormFieldMetadataValueObject('test affiliation')] affiliation: [new FormFieldMetadataValueObject('test affiliation')]
}; };
const parser = new RelationGroupFieldParser(field, initFormValues, parserOptions, new WorkspaceItem()); const parser = new RelationGroupFieldParser(submissionId, field, initFormValues, parserOptions);
const fieldModel = parser.parse(); const fieldModel = parser.parse();
const expectedValue = [{ const expectedValue = [{

View File

@@ -15,6 +15,7 @@ export class RelationGroupFieldParser extends FieldParser {
public modelFactory(fieldValue?: FormFieldMetadataValueObject | any, label?: boolean) { public modelFactory(fieldValue?: FormFieldMetadataValueObject | any, label?: boolean) {
const modelConfiguration: DynamicRelationGroupModelConfig = this.initModel(null, label); const modelConfiguration: DynamicRelationGroupModelConfig = this.initModel(null, label);
modelConfiguration.submissionId = this.submissionId;
modelConfiguration.scopeUUID = this.parserOptions.authorityUuid; modelConfiguration.scopeUUID = this.parserOptions.authorityUuid;
modelConfiguration.submissionScope = this.parserOptions.submissionScope; modelConfiguration.submissionScope = this.parserOptions.submissionScope;
if (this.configData && this.configData.rows && this.configData.rows.length > 0) { if (this.configData && this.configData.rows && this.configData.rows.length > 0) {

View File

@@ -3,7 +3,6 @@ import { RowParser } from './row-parser';
import { DynamicRowGroupModel } from '../ds-dynamic-form-ui/models/ds-dynamic-row-group-model'; import { DynamicRowGroupModel } from '../ds-dynamic-form-ui/models/ds-dynamic-row-group-model';
import { DynamicRowArrayModel } from '../ds-dynamic-form-ui/models/ds-dynamic-row-array-model'; import { DynamicRowArrayModel } from '../ds-dynamic-form-ui/models/ds-dynamic-row-array-model';
import { FormRowModel } from '../../../../core/config/models/config-submission-form.model'; import { FormRowModel } from '../../../../core/config/models/config-submission-form.model';
import { WorkspaceItem } from '../../../../core/submission/models/workspaceitem.model';
describe('RowParser test suite', () => { describe('RowParser test suite', () => {
@@ -18,6 +17,7 @@ describe('RowParser test suite', () => {
let row9: FormRowModel; let row9: FormRowModel;
let row10: FormRowModel; let row10: FormRowModel;
const submissionId = '1234';
const scopeUUID = 'testScopeUUID'; const scopeUUID = 'testScopeUUID';
const initFormValues = {}; const initFormValues = {};
const submissionScope = 'WORKSPACE'; const submissionScope = 'WORKSPACE';
@@ -329,76 +329,98 @@ describe('RowParser test suite', () => {
}); });
it('should init parser properly', () => { it('should init parser properly', () => {
let parser = new RowParser(row1, scopeUUID, initFormValues, new WorkspaceItem(), submissionScope, readOnly); const parser = new RowParser(undefined);
expect(parser instanceof RowParser).toBe(true);
parser = new RowParser(row2, scopeUUID, initFormValues, new WorkspaceItem(), submissionScope, readOnly);
expect(parser instanceof RowParser).toBe(true);
parser = new RowParser(row3, scopeUUID, initFormValues, new WorkspaceItem(), submissionScope, readOnly);
expect(parser instanceof RowParser).toBe(true);
parser = new RowParser(row4, scopeUUID, initFormValues, new WorkspaceItem(), submissionScope, readOnly);
expect(parser instanceof RowParser).toBe(true);
parser = new RowParser(row5, scopeUUID, initFormValues, new WorkspaceItem(), submissionScope, readOnly);
expect(parser instanceof RowParser).toBe(true);
parser = new RowParser(row6, scopeUUID, initFormValues, new WorkspaceItem(), submissionScope, readOnly);
expect(parser instanceof RowParser).toBe(true);
parser = new RowParser(row7, scopeUUID, initFormValues, new WorkspaceItem(), submissionScope, readOnly);
expect(parser instanceof RowParser).toBe(true);
parser = new RowParser(row8, scopeUUID, initFormValues, new WorkspaceItem(), submissionScope, readOnly);
expect(parser instanceof RowParser).toBe(true);
parser = new RowParser(row9, scopeUUID, initFormValues, new WorkspaceItem(), submissionScope, readOnly);
expect(parser instanceof RowParser).toBe(true);
parser = new RowParser(row10, scopeUUID, initFormValues, new WorkspaceItem(), submissionScope, readOnly);
expect(parser instanceof RowParser).toBe(true); expect(parser instanceof RowParser).toBe(true);
}); });
describe('parse', () => {
it('should return a DynamicRowGroupModel object', () => { it('should return a DynamicRowGroupModel object', () => {
const parser = new RowParser(row1, scopeUUID, initFormValues, new WorkspaceItem(), submissionScope, readOnly); const parser = new RowParser(undefined);
const rowModel = parser.parse(); const rowModel = parser.parse(submissionId, row1, scopeUUID, initFormValues, submissionScope, readOnly);
expect(rowModel instanceof DynamicRowGroupModel).toBe(true); expect(rowModel instanceof DynamicRowGroupModel).toBe(true);
}); });
it('should return a row with three fields', () => { it('should return a row with three fields', () => {
const parser = new RowParser(row1, scopeUUID, initFormValues, new WorkspaceItem(), submissionScope, readOnly); const parser = new RowParser(undefined);
const rowModel = parser.parse(); const rowModel = parser.parse(submissionId, row1, scopeUUID, initFormValues, submissionScope, readOnly);
expect((rowModel as DynamicRowGroupModel).group.length).toBe(3); expect((rowModel as DynamicRowGroupModel).group.length).toBe(3);
}); });
it('should return a DynamicRowArrayModel object', () => { it('should return a DynamicRowArrayModel object', () => {
const parser = new RowParser(row2, scopeUUID, initFormValues, new WorkspaceItem(), submissionScope, readOnly); const parser = new RowParser(undefined);
const rowModel = parser.parse(); const rowModel = parser.parse(submissionId, row2, scopeUUID, initFormValues, submissionScope, readOnly);
expect(rowModel instanceof DynamicRowArrayModel).toBe(true); expect(rowModel instanceof DynamicRowArrayModel).toBe(true);
}); });
it('should return a row that contains only scoped fields', () => { it('should return a row that contains only scoped fields', () => {
const parser = new RowParser(row3, scopeUUID, initFormValues, new WorkspaceItem(), submissionScope, readOnly); const parser = new RowParser(undefined);
const rowModel = parser.parse(); const rowModel = parser.parse(submissionId, row3, scopeUUID, initFormValues, submissionScope, readOnly);
expect((rowModel as DynamicRowGroupModel).group.length).toBe(1); expect((rowModel as DynamicRowGroupModel).group.length).toBe(1);
}); });
it('should be able to parse a dropdown combo field', () => {
const parser = new RowParser(undefined);
const rowModel = parser.parse(submissionId, row4, scopeUUID, initFormValues, submissionScope, readOnly);
expect(rowModel).toBeDefined();
});
it('should be able to parse a lookup-name field', () => {
const parser = new RowParser(undefined);
const rowModel = parser.parse(submissionId, row5, scopeUUID, initFormValues, submissionScope, readOnly);
expect(rowModel).toBeDefined();
});
it('should be able to parse a list field', () => {
const parser = new RowParser(undefined);
const rowModel = parser.parse(submissionId, row6, scopeUUID, initFormValues, submissionScope, readOnly);
expect(rowModel).toBeDefined();
});
it('should be able to parse a date field', () => {
const parser = new RowParser(undefined);
const rowModel = parser.parse(submissionId, row7, scopeUUID, initFormValues, submissionScope, readOnly);
expect(rowModel).toBeDefined();
});
it('should be able to parse a tag field', () => {
const parser = new RowParser(undefined);
const rowModel = parser.parse(submissionId, row8, scopeUUID, initFormValues, submissionScope, readOnly);
expect(rowModel).toBeDefined();
});
it('should be able to parse a textarea field', () => {
const parser = new RowParser(undefined);
const rowModel = parser.parse(submissionId, row9, scopeUUID, initFormValues, submissionScope, readOnly);
expect(rowModel).toBeDefined();
});
it('should be able to parse a group field', () => {
const parser = new RowParser(undefined);
const rowModel = parser.parse(submissionId, row10, scopeUUID, initFormValues, submissionScope, readOnly);
expect(rowModel).toBeDefined();
});
});
}); });

View File

@@ -1,32 +1,42 @@
import { DYNAMIC_FORM_CONTROL_TYPE_ARRAY, DynamicFormGroupModelConfig } from '@ng-dynamic-forms/core'; import { Injectable, Injector } from '@angular/core';
import {
DYNAMIC_FORM_CONTROL_TYPE_ARRAY,
DynamicFormGroupModelConfig
} from '@ng-dynamic-forms/core';
import { uniqueId } from 'lodash'; import { uniqueId } from 'lodash';
import { IntegrationSearchOptions } from '../../../../core/integration/models/integration-options.model'; import { IntegrationSearchOptions } from '../../../../core/integration/models/integration-options.model';
import { DYNAMIC_FORM_CONTROL_TYPE_RELATION_GROUP } from '../ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.model';
import { DynamicRowGroupModel } from '../ds-dynamic-form-ui/models/ds-dynamic-row-group-model';
import { isEmpty } from '../../../empty.util'; import { isEmpty } from '../../../empty.util';
import { setLayout } from './parser.utils'; import { DynamicRowGroupModel } from '../ds-dynamic-form-ui/models/ds-dynamic-row-group-model';
import { DYNAMIC_FORM_CONTROL_TYPE_RELATION_GROUP } from '../ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.model';
import { FormFieldModel } from '../models/form-field.model'; import { FormFieldModel } from '../models/form-field.model';
import { ParserType } from './parser-type'; import {
import { ParserOptions } from './parser-options'; CONFIG_DATA,
FieldParser,
INIT_FORM_VALUES,
PARSER_OPTIONS,
SUBMISSION_ID
} from './field-parser';
import { ParserFactory } from './parser-factory'; import { ParserFactory } from './parser-factory';
import { WorkspaceItem } from '../../../../core/submission/models/workspaceitem.model'; import { ParserOptions } from './parser-options';
import { ParserType } from './parser-type';
import { setLayout } from './parser.utils';
export const ROW_ID_PREFIX = 'df-row-group-config-'; export const ROW_ID_PREFIX = 'df-row-group-config-';
@Injectable({
providedIn: 'root'
})
export class RowParser { export class RowParser {
protected authorityOptions: IntegrationSearchOptions; constructor(private parentInjector: Injector) {
constructor(protected rowData,
protected scopeUUID,
protected initFormValues: any,
protected wsi: WorkspaceItem,
protected submissionScope,
protected readOnly: boolean) {
this.authorityOptions = new IntegrationSearchOptions(scopeUUID);
} }
public parse(): DynamicRowGroupModel { public parse(submissionId: string,
rowData,
scopeUUID,
initFormValues: any,
submissionScope,
readOnly: boolean): DynamicRowGroupModel {
let fieldModel: any = null; let fieldModel: any = null;
let parsedResult = null; let parsedResult = null;
const config: DynamicFormGroupModelConfig = { const config: DynamicFormGroupModelConfig = {
@@ -34,31 +44,44 @@ export class RowParser {
group: [], group: [],
}; };
const scopedFields: FormFieldModel[] = this.filterScopedFields(this.rowData.fields); const authorityOptions = new IntegrationSearchOptions(scopeUUID);
const scopedFields: FormFieldModel[] = this.filterScopedFields(rowData.fields, submissionScope);
const layoutDefaultGridClass = ' col-sm-' + Math.trunc(12 / scopedFields.length); const layoutDefaultGridClass = ' col-sm-' + Math.trunc(12 / scopedFields.length);
const layoutClass = ' d-flex flex-column justify-content-start'; const layoutClass = ' d-flex flex-column justify-content-start';
const parserOptions: ParserOptions = { const parserOptions: ParserOptions = {
readOnly: this.readOnly, readOnly: readOnly,
submissionScope: this.submissionScope, submissionScope: submissionScope,
authorityUuid: this.authorityOptions.uuid authorityUuid: authorityOptions.uuid
}; };
// Iterate over row's fields // Iterate over row's fields
scopedFields.forEach((fieldData: FormFieldModel) => { scopedFields.forEach((fieldData: FormFieldModel) => {
const layoutFieldClass = (fieldData.style || layoutDefaultGridClass) + layoutClass; const layoutFieldClass = (fieldData.style || layoutDefaultGridClass) + layoutClass;
const parserCo = ParserFactory.getConstructor(fieldData.input.type as ParserType); const parserProvider = ParserFactory.getProvider(fieldData.input.type as ParserType);
if (parserCo) { if (parserProvider) {
fieldModel = new parserCo(fieldData, this.initFormValues, parserOptions, this.wsi).parse(); const fieldInjector = Injector.create({
providers: [
parserProvider,
{ provide: SUBMISSION_ID, useValue: submissionId },
{ provide: CONFIG_DATA, useValue: fieldData },
{ provide: INIT_FORM_VALUES, useValue: initFormValues },
{ provide: PARSER_OPTIONS, useValue: parserOptions }
],
parent: this.parentInjector
});
fieldModel = fieldInjector.get(FieldParser).parse();
} else { } else {
throw new Error(`unknown form control model type "${fieldData.input.type}" defined for Input field with label "${fieldData.label}".`,); throw new Error(`unknown form control model type "${fieldData.input.type}" defined for Input field with label "${fieldData.label}".`,);
} }
if (fieldModel) { if (fieldModel) {
if (fieldModel.type === DYNAMIC_FORM_CONTROL_TYPE_ARRAY || fieldModel.type === DYNAMIC_FORM_CONTROL_TYPE_RELATION_GROUP) { if (fieldModel.type === DYNAMIC_FORM_CONTROL_TYPE_ARRAY || fieldModel.type === DYNAMIC_FORM_CONTROL_TYPE_RELATION_GROUP) {
if (this.rowData.fields.length > 1) { if (rowData.fields.length > 1) {
setLayout(fieldModel, 'grid', 'host', layoutFieldClass); setLayout(fieldModel, 'grid', 'host', layoutFieldClass);
config.group.push(fieldModel); config.group.push(fieldModel);
// if (isEmpty(parsedResult)) { // if (isEmpty(parsedResult)) {
@@ -100,15 +123,15 @@ export class RowParser {
return parsedResult; return parsedResult;
} }
checksFieldScope(fieldScope) { checksFieldScope(fieldScope, submissionScope) {
return (isEmpty(fieldScope) || isEmpty(this.submissionScope) || fieldScope === this.submissionScope); return (isEmpty(fieldScope) || isEmpty(submissionScope) || fieldScope === submissionScope);
} }
filterScopedFields(fields: FormFieldModel[]): FormFieldModel[] { filterScopedFields(fields: FormFieldModel[], submissionScope): FormFieldModel[] {
const filteredFields: FormFieldModel[] = []; const filteredFields: FormFieldModel[] = [];
fields.forEach((field: FormFieldModel) => { fields.forEach((field: FormFieldModel) => {
// Whether field scope doesn't match the submission scope, skip it // Whether field scope doesn't match the submission scope, skip it
if (this.checksFieldScope(field.scope)) { if (this.checksFieldScope(field.scope, submissionScope)) {
filteredFields.push(field); filteredFields.push(field);
} }
}); });

View File

@@ -3,12 +3,12 @@ import { DynamicConcatModel } from '../ds-dynamic-form-ui/models/ds-dynamic-conc
import { SeriesFieldParser } from './series-field-parser'; import { SeriesFieldParser } from './series-field-parser';
import { FormFieldMetadataValueObject } from '../models/form-field-metadata-value.model'; import { FormFieldMetadataValueObject } from '../models/form-field-metadata-value.model';
import { ParserOptions } from './parser-options'; import { ParserOptions } from './parser-options';
import { WorkspaceItem } from '../../../../core/submission/models/workspaceitem.model';
describe('SeriesFieldParser test suite', () => { describe('SeriesFieldParser test suite', () => {
let field: FormFieldModel; let field: FormFieldModel;
let initFormValues: any = {}; let initFormValues: any = {};
const submissionId = '1234';
const parserOptions: ParserOptions = { const parserOptions: ParserOptions = {
readOnly: false, readOnly: false,
submissionScope: 'testScopeUUID', submissionScope: 'testScopeUUID',
@@ -33,13 +33,13 @@ describe('SeriesFieldParser test suite', () => {
}); });
it('should init parser properly', () => { it('should init parser properly', () => {
const parser = new SeriesFieldParser(field, initFormValues, parserOptions, new WorkspaceItem()); const parser = new SeriesFieldParser(submissionId, field, initFormValues, parserOptions);
expect(parser instanceof SeriesFieldParser).toBe(true); expect(parser instanceof SeriesFieldParser).toBe(true);
}); });
it('should return a DynamicConcatModel object when repeatable option is false', () => { it('should return a DynamicConcatModel object when repeatable option is false', () => {
const parser = new SeriesFieldParser(field, initFormValues, parserOptions, new WorkspaceItem()); const parser = new SeriesFieldParser(submissionId, field, initFormValues, parserOptions);
const fieldModel = parser.parse(); const fieldModel = parser.parse();
@@ -47,7 +47,7 @@ describe('SeriesFieldParser test suite', () => {
}); });
it('should return a DynamicConcatModel object with the correct separator', () => { it('should return a DynamicConcatModel object with the correct separator', () => {
const parser = new SeriesFieldParser(field, initFormValues, parserOptions, new WorkspaceItem()); const parser = new SeriesFieldParser(submissionId, field, initFormValues, parserOptions);
const fieldModel = parser.parse(); const fieldModel = parser.parse();
@@ -60,7 +60,7 @@ describe('SeriesFieldParser test suite', () => {
}; };
const expectedValue = new FormFieldMetadataValueObject('test; series'); const expectedValue = new FormFieldMetadataValueObject('test; series');
const parser = new SeriesFieldParser(field, initFormValues, parserOptions, new WorkspaceItem()); const parser = new SeriesFieldParser(submissionId, field, initFormValues, parserOptions);
const fieldModel = parser.parse(); const fieldModel = parser.parse();

View File

@@ -1,11 +1,17 @@
import { Inject } from '@angular/core';
import { FormFieldModel } from '../models/form-field.model'; import { FormFieldModel } from '../models/form-field.model';
import { ConcatFieldParser } from './concat-field-parser'; import { ConcatFieldParser } from './concat-field-parser';
import { CONFIG_DATA, INIT_FORM_VALUES, PARSER_OPTIONS, SUBMISSION_ID } from './field-parser';
import { ParserOptions } from './parser-options'; import { ParserOptions } from './parser-options';
import { WorkspaceItem } from '../../../../core/submission/models/workspaceitem.model';
export class SeriesFieldParser extends ConcatFieldParser { export class SeriesFieldParser extends ConcatFieldParser {
constructor(protected configData: FormFieldModel, protected initFormValues, protected parserOptions: ParserOptions, wsi: WorkspaceItem) { constructor(
super(configData, initFormValues, parserOptions, ';', wsi); @Inject(SUBMISSION_ID) submissionId: string,
@Inject(CONFIG_DATA) configData: FormFieldModel,
@Inject(INIT_FORM_VALUES) initFormValues,
@Inject(PARSER_OPTIONS) parserOptions: ParserOptions
) {
super(submissionId, configData, initFormValues, parserOptions, ';');
} }
} }

View File

@@ -3,12 +3,12 @@ import { FormFieldMetadataValueObject } from '../models/form-field-metadata-valu
import { TagFieldParser } from './tag-field-parser'; import { TagFieldParser } from './tag-field-parser';
import { DynamicTagModel } from '../ds-dynamic-form-ui/models/tag/dynamic-tag.model'; import { DynamicTagModel } from '../ds-dynamic-form-ui/models/tag/dynamic-tag.model';
import { ParserOptions } from './parser-options'; import { ParserOptions } from './parser-options';
import { WorkspaceItem } from '../../../../core/submission/models/workspaceitem.model';
describe('TagFieldParser test suite', () => { describe('TagFieldParser test suite', () => {
let field: FormFieldModel; let field: FormFieldModel;
let initFormValues: any = {}; let initFormValues: any = {};
const submissionId = '1234';
const parserOptions: ParserOptions = { const parserOptions: ParserOptions = {
readOnly: false, readOnly: false,
submissionScope: 'testScopeUUID', submissionScope: 'testScopeUUID',
@@ -37,13 +37,13 @@ describe('TagFieldParser test suite', () => {
}); });
it('should init parser properly', () => { it('should init parser properly', () => {
const parser = new TagFieldParser(field, initFormValues, parserOptions, new WorkspaceItem()); const parser = new TagFieldParser(submissionId, field, initFormValues, parserOptions);
expect(parser instanceof TagFieldParser).toBe(true); expect(parser instanceof TagFieldParser).toBe(true);
}); });
it('should return a DynamicTagModel object when repeatable option is false', () => { it('should return a DynamicTagModel object when repeatable option is false', () => {
const parser = new TagFieldParser(field, initFormValues, parserOptions, new WorkspaceItem()); const parser = new TagFieldParser(submissionId, field, initFormValues, parserOptions);
const fieldModel = parser.parse(); const fieldModel = parser.parse();
@@ -58,7 +58,7 @@ describe('TagFieldParser test suite', () => {
], ],
}; };
const parser = new TagFieldParser(field, initFormValues, parserOptions, new WorkspaceItem()); const parser = new TagFieldParser(submissionId, field, initFormValues, parserOptions);
const fieldModel = parser.parse(); const fieldModel = parser.parse();

View File

@@ -3,12 +3,12 @@ import { FormFieldMetadataValueObject } from '../models/form-field-metadata-valu
import { TextareaFieldParser } from './textarea-field-parser'; import { TextareaFieldParser } from './textarea-field-parser';
import { DsDynamicTextAreaModel } from '../ds-dynamic-form-ui/models/ds-dynamic-textarea.model'; import { DsDynamicTextAreaModel } from '../ds-dynamic-form-ui/models/ds-dynamic-textarea.model';
import { ParserOptions } from './parser-options'; import { ParserOptions } from './parser-options';
import { WorkspaceItem } from '../../../../core/submission/models/workspaceitem.model';
describe('TextareaFieldParser test suite', () => { describe('TextareaFieldParser test suite', () => {
let field: FormFieldModel; let field: FormFieldModel;
let initFormValues: any = {}; let initFormValues: any = {};
const submissionId = '1234';
const parserOptions: ParserOptions = { const parserOptions: ParserOptions = {
readOnly: false, readOnly: false,
submissionScope: null, submissionScope: null,
@@ -35,13 +35,13 @@ describe('TextareaFieldParser test suite', () => {
}); });
it('should init parser properly', () => { it('should init parser properly', () => {
const parser = new TextareaFieldParser(field, initFormValues, parserOptions, new WorkspaceItem()); const parser = new TextareaFieldParser(submissionId, field, initFormValues, parserOptions);
expect(parser instanceof TextareaFieldParser).toBe(true); expect(parser instanceof TextareaFieldParser).toBe(true);
}); });
it('should return a DsDynamicTextAreaModel object when repeatable option is false', () => { it('should return a DsDynamicTextAreaModel object when repeatable option is false', () => {
const parser = new TextareaFieldParser(field, initFormValues, parserOptions, new WorkspaceItem()); const parser = new TextareaFieldParser(submissionId, field, initFormValues, parserOptions);
const fieldModel = parser.parse(); const fieldModel = parser.parse();
@@ -56,7 +56,7 @@ describe('TextareaFieldParser test suite', () => {
}; };
const expectedValue ='test description'; const expectedValue ='test description';
const parser = new TextareaFieldParser(field, initFormValues, parserOptions, new WorkspaceItem()); const parser = new TextareaFieldParser(submissionId, field, initFormValues, parserOptions);
const fieldModel = parser.parse(); const fieldModel = parser.parse();

View File

@@ -118,6 +118,7 @@ const mockFormRowModel = {
} as FormRowModel; } as FormRowModel;
const relationGroupConfig = { const relationGroupConfig = {
submissionId: '1234',
id: 'relationGroup', id: 'relationGroup',
formConfiguration: [mockFormRowModel], formConfiguration: [mockFormRowModel],
mandatoryField: 'false', mandatoryField: 'false',

View File

@@ -30,6 +30,7 @@ import { AbstractListableElementComponent } from './object-collection/shared/obj
import { ObjectGridComponent } from './object-grid/object-grid.component'; import { ObjectGridComponent } from './object-grid/object-grid.component';
import { ObjectCollectionComponent } from './object-collection/object-collection.component'; import { ObjectCollectionComponent } from './object-collection/object-collection.component';
import { ComcolPageContentComponent } from './comcol-page-content/comcol-page-content.component'; import { ComcolPageContentComponent } from './comcol-page-content/comcol-page-content.component';
import { ComcolPageHandleComponent } from './comcol-page-handle/comcol-page-handle.component';
import { ComcolPageHeaderComponent } from './comcol-page-header/comcol-page-header.component'; import { ComcolPageHeaderComponent } from './comcol-page-header/comcol-page-header.component';
import { ComcolPageLogoComponent } from './comcol-page-logo/comcol-page-logo.component'; import { ComcolPageLogoComponent } from './comcol-page-logo/comcol-page-logo.component';
import { ErrorComponent } from './error/error.component'; import { ErrorComponent } from './error/error.component';
@@ -215,6 +216,7 @@ const COMPONENTS = [
UserMenuComponent, UserMenuComponent,
ChipsComponent, ChipsComponent,
ComcolPageContentComponent, ComcolPageContentComponent,
ComcolPageHandleComponent,
ComcolPageHeaderComponent, ComcolPageHeaderComponent,
ComcolPageLogoComponent, ComcolPageLogoComponent,
ComColFormComponent, ComColFormComponent,

View File

@@ -1,7 +1,7 @@
import { ChangeDetectorRef, Component, Input, OnChanges, OnDestroy, SimpleChanges } from '@angular/core'; import { ChangeDetectorRef, Component, Input, OnChanges, OnDestroy, SimpleChanges } from '@angular/core';
import { of as observableOf, Observable, Subscription } from 'rxjs'; import { of as observableOf, Observable, Subscription } from 'rxjs';
import { distinctUntilChanged, filter, flatMap, map } from 'rxjs/operators'; import { distinctUntilChanged, filter, flatMap, map, switchMap } from 'rxjs/operators';
import { hasValue, isNotEmpty } from '../../shared/empty.util'; import { hasValue, isNotEmpty } from '../../shared/empty.util';
import { SubmissionObjectEntry } from '../objects/submission-objects.reducer'; import { SubmissionObjectEntry } from '../objects/submission-objects.reducer';
@@ -125,7 +125,7 @@ export class SubmissionFormComponent implements OnChanges, OnDestroy {
map((submission: SubmissionObjectEntry) => submission.isLoading), map((submission: SubmissionObjectEntry) => submission.isLoading),
map((isLoading: boolean) => isLoading), map((isLoading: boolean) => isLoading),
distinctUntilChanged(), distinctUntilChanged(),
flatMap((isLoading: boolean) => { switchMap((isLoading: boolean) => {
if (!isLoading) { if (!isLoading) {
return this.getSectionsList(); return this.getSectionsList();
} else { } else {

View File

@@ -229,6 +229,7 @@ export class SubmissionSectionformComponent extends SectionModelComponent {
initForm(sectionData: WorkspaceitemSectionFormObject): void { initForm(sectionData: WorkspaceitemSectionFormObject): void {
try { try {
this.formModel = this.formBuilderService.modelFromConfiguration( this.formModel = this.formBuilderService.modelFromConfiguration(
this.submissionId,
this.formConfig, this.formConfig,
this.collectionId, this.collectionId,
sectionData, sectionData,

View File

@@ -166,6 +166,7 @@ export class SubmissionSectionUploadFileEditComponent implements OnChanges {
const formModel: DynamicFormControlModel[] = []; const formModel: DynamicFormControlModel[] = [];
const metadataGroupModelConfig = Object.assign({}, BITSTREAM_METADATA_FORM_GROUP_CONFIG); const metadataGroupModelConfig = Object.assign({}, BITSTREAM_METADATA_FORM_GROUP_CONFIG);
metadataGroupModelConfig.group = this.formBuilderService.modelFromConfiguration( metadataGroupModelConfig.group = this.formBuilderService.modelFromConfiguration(
this.submissionId,
configForm, configForm,
this.collectionId, this.collectionId,
this.fileData.metadata, this.fileData.metadata,