mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 10:04:11 +00:00
working on fixes for OrgUnit field in submission
This commit is contained in:
@@ -6,6 +6,12 @@ import { excludeFromEquals } from '../../utilities/equals.decorators';
|
||||
|
||||
export abstract class ConfigObject implements CacheableObject {
|
||||
|
||||
/**
|
||||
* The name for this configuration
|
||||
*/
|
||||
@autoserialize
|
||||
public id: string;
|
||||
|
||||
/**
|
||||
* The name for this configuration
|
||||
*/
|
||||
|
@@ -16,6 +16,10 @@ import { FormFieldMetadataValueObject } from '../../shared/form/builder/models/f
|
||||
import { SubmissionObject } from './models/submission-object.model';
|
||||
import { WorkflowItem } from './models/workflowitem.model';
|
||||
import { WorkspaceItem } from './models/workspaceitem.model';
|
||||
import { SubmissionDefinitionsModel } from '../config/models/config-submission-definitions.model';
|
||||
import { SubmissionSectionModel } from '../config/models/config-submission-section.model';
|
||||
import { SectionsType } from '../../submission/sections/sections-type';
|
||||
import { SectionDataModel } from '../../submission/sections/models/section.model';
|
||||
|
||||
/**
|
||||
* Export a function to check if object has same properties of FormFieldMetadataValueObject
|
||||
@@ -136,24 +140,29 @@ export class SubmissionResponseParsingService extends BaseResponseParsingService
|
||||
|
||||
processedList.forEach((item) => {
|
||||
|
||||
item = Object.assign({}, item);
|
||||
// In case data is an Instance of WorkspaceItem normalize field value of all the section of type form
|
||||
if (item instanceof WorkspaceItem
|
||||
|| item instanceof WorkflowItem) {
|
||||
if (item.sections) {
|
||||
const sectionConfigs = (item.submissionDefinition as SubmissionDefinitionsModel).sections.page;
|
||||
const precessedSection = Object.create({});
|
||||
// Iterate over all workspaceitem's sections
|
||||
Object.keys(item.sections)
|
||||
.forEach((sectionId) => {
|
||||
if (typeof item.sections[sectionId] === 'object' && (isNotEmpty(item.sections[sectionId]) &&
|
||||
const sectionConfig: SubmissionSectionModel = sectionConfigs.find((config) => config.id === sectionId);
|
||||
let sectionData = item.sections[sectionId];
|
||||
if (sectionConfig && sectionConfig.sectionType === SectionsType.SubmissionForm) {
|
||||
sectionData = item.item.metadata;
|
||||
}
|
||||
if (typeof sectionData === 'object' && (isNotEmpty(sectionData) &&
|
||||
// When Upload section is disabled, add to submission only if there are files
|
||||
(!item.sections[sectionId].hasOwnProperty('files') || isNotEmpty((item.sections[sectionId] as any).files)))) {
|
||||
(!sectionData.hasOwnProperty('files') || isNotEmpty((sectionData as any).files)))) {
|
||||
|
||||
const sectiondata = Object.create({});
|
||||
// Iterate over all sections property
|
||||
Object.keys(item.sections[sectionId])
|
||||
Object.keys(sectionData)
|
||||
.forEach((metdadataId) => {
|
||||
const entry = item.sections[sectionId][metdadataId];
|
||||
const entry = sectionData[metdadataId];
|
||||
// If entry is not an array, for sure is not a section of type form
|
||||
if (Array.isArray(entry)) {
|
||||
sectiondata[metdadataId] = [];
|
||||
|
@@ -1 +1 @@
|
||||
<ds-journal-issue-search-result-grid-element [object]="{ indexableObject: object, hitHighlights: {} }" [linkType]="linkType"></ds-journal-issue-search-result-grid-element>
|
||||
<ds-journal-issue-search-result-grid-element [showLabel]="showLabel" [object]="{ indexableObject: object, hitHighlights: {} }" [linkType]="linkType"></ds-journal-issue-search-result-grid-element>
|
||||
|
@@ -1 +1 @@
|
||||
<ds-journal-volume-search-result-grid-element [object]="{ indexableObject: object, hitHighlights: {} }" [linkType]="linkType"></ds-journal-volume-search-result-grid-element>
|
||||
<ds-journal-volume-search-result-grid-element [showLabel]="showLabel" [object]="{ indexableObject: object, hitHighlights: {} }" [linkType]="linkType"></ds-journal-volume-search-result-grid-element>
|
||||
|
@@ -1 +1 @@
|
||||
<ds-journal-search-result-grid-element [object]="{ indexableObject: object, hitHighlights: {} }" [linkType]="linkType"></ds-journal-search-result-grid-element>
|
||||
<ds-journal-search-result-grid-element [showLabel]="showLabel" [object]="{ indexableObject: object, hitHighlights: {} }" [linkType]="linkType"></ds-journal-search-result-grid-element>
|
||||
|
@@ -17,7 +17,7 @@
|
||||
</div>
|
||||
</span>
|
||||
<div class="card-body">
|
||||
<ds-item-type-badge [object]="dso"></ds-item-type-badge>
|
||||
<ds-item-type-badge *ngIf="showLabel" [object]="dso"></ds-item-type-badge>
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="3" type="h4">
|
||||
<h4 class="card-title" [innerHTML]="firstMetadataValue('dc.title')"></h4>
|
||||
</ds-truncatable-part>
|
||||
|
@@ -17,7 +17,7 @@
|
||||
</div>
|
||||
</span>
|
||||
<div class="card-body">
|
||||
<ds-item-type-badge [object]="dso"></ds-item-type-badge>
|
||||
<ds-item-type-badge *ngIf="showLabel" [object]="dso"></ds-item-type-badge>
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="3" type="h4">
|
||||
<h4 class="card-title" [innerHTML]="dso.firstMetadataValue('dc.title')"></h4>
|
||||
</ds-truncatable-part>
|
||||
|
@@ -17,7 +17,7 @@
|
||||
</div>
|
||||
</span>
|
||||
<div class="card-body">
|
||||
<ds-item-type-badge [object]="dso"></ds-item-type-badge>
|
||||
<ds-item-type-badge *ngIf="showLabel" [object]="dso"></ds-item-type-badge>
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="3" type="h4">
|
||||
<h4 class="card-title" [innerHTML]="firstMetadataValue('dc.title')"></h4>
|
||||
</ds-truncatable-part>
|
||||
|
@@ -1 +1 @@
|
||||
<ds-journal-issue-search-result-list-element [object]="{ indexableObject: object, hitHighlights: {} }" [linkType]="linkType"></ds-journal-issue-search-result-list-element>
|
||||
<ds-journal-issue-search-result-list-element [showLabel]="showLabel" [object]="{ indexableObject: object, hitHighlights: {} }" [linkType]="linkType"></ds-journal-issue-search-result-list-element>
|
||||
|
@@ -1 +1 @@
|
||||
<ds-journal-volume-search-result-list-element [object]="{ indexableObject: object, hitHighlights: {} }" [linkType]="linkType"></ds-journal-volume-search-result-list-element>
|
||||
<ds-journal-volume-search-result-list-element [showLabel]="showLabel" [object]="{ indexableObject: object, hitHighlights: {} }" [linkType]="linkType"></ds-journal-volume-search-result-list-element>
|
||||
|
@@ -1 +1 @@
|
||||
<ds-journal-search-result-list-element [object]="{ indexableObject: object, hitHighlights: {} }" [linkType]="linkType"></ds-journal-search-result-list-element>
|
||||
<ds-journal-search-result-list-element [showLabel]="showLabel" [object]="{ indexableObject: object, hitHighlights: {} }" [linkType]="linkType"></ds-journal-search-result-list-element>
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<ds-item-type-badge [object]="dso"></ds-item-type-badge>
|
||||
<ds-item-type-badge *ngIf="showLabel" [object]="dso"></ds-item-type-badge>
|
||||
<ds-truncatable [id]="dso.id">
|
||||
<a *ngIf="linkType != linkTypes.None" [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer"
|
||||
[routerLink]="['/items/' + dso.id]" class="lead"
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<ds-item-type-badge [object]="dso"></ds-item-type-badge>
|
||||
<ds-item-type-badge *ngIf="showLabel" [object]="dso"></ds-item-type-badge>
|
||||
<ds-truncatable [id]="dso.id">
|
||||
<a *ngIf="linkType != linkTypes.None" [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer"
|
||||
[routerLink]="['/items/' + dso.id]" class="lead"
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<ds-item-type-badge [object]="dso"></ds-item-type-badge>
|
||||
<ds-item-type-badge *ngIf="showLabel" [object]="dso"></ds-item-type-badge>
|
||||
<ds-truncatable [id]="dso.id">
|
||||
<a *ngIf="linkType != linkTypes.None" [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer"
|
||||
[routerLink]="['/items/' + dso.id]" class="lead"
|
||||
|
@@ -1 +1 @@
|
||||
<ds-org-unit-search-result-grid-element [object]="{ indexableObject: object, hitHighlights: {} }" [linkType]="linkType"></ds-org-unit-search-result-grid-element>
|
||||
<ds-org-unit-search-result-grid-element [showLabel]="showLabel" [object]="{ indexableObject: object, hitHighlights: {} }" [linkType]="linkType"></ds-org-unit-search-result-grid-element>
|
||||
|
@@ -1 +1 @@
|
||||
<ds-person-search-result-grid-element [object]="{ indexableObject: object, hitHighlights: {} }" [linkType]="linkType"></ds-person-search-result-grid-element>
|
||||
<ds-person-search-result-grid-element [showLabel]="showLabel" [object]="{ indexableObject: object, hitHighlights: {} }" [linkType]="linkType"></ds-person-search-result-grid-element>
|
||||
|
@@ -1 +1 @@
|
||||
<ds-project-search-result-grid-element [object]="{ indexableObject: object, hitHighlights: {} }" [linkType]="linkType"></ds-project-search-result-grid-element>
|
||||
<ds-project-search-result-grid-element [showLabel]="showLabel" [object]="{ indexableObject: object, hitHighlights: {} }" [linkType]="linkType"></ds-project-search-result-grid-element>
|
||||
|
@@ -17,7 +17,7 @@
|
||||
</div>
|
||||
</span>
|
||||
<div class="card-body">
|
||||
<ds-item-type-badge [object]="dso"></ds-item-type-badge>
|
||||
<ds-item-type-badge *ngIf="showLabel" [object]="dso"></ds-item-type-badge>
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="3" type="h4">
|
||||
<h4 class="card-title" [innerHTML]="firstMetadataValue('organization.legalName')"></h4>
|
||||
</ds-truncatable-part>
|
||||
|
@@ -17,7 +17,7 @@
|
||||
</div>
|
||||
</span>
|
||||
<div class="card-body">
|
||||
<ds-item-type-badge [object]="dso"></ds-item-type-badge>
|
||||
<ds-item-type-badge *ngIf="showLabel" [object]="dso"></ds-item-type-badge>
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="3" type="h4">
|
||||
<h4 class="card-title"
|
||||
[innerHTML]="firstMetadataValue('person.familyName') + ', ' + firstMetadataValue('person.givenName')"></h4>
|
||||
|
@@ -17,7 +17,7 @@
|
||||
</div>
|
||||
</span>
|
||||
<div class="card-body">
|
||||
<ds-item-type-badge [object]="dso"></ds-item-type-badge>
|
||||
<ds-item-type-badge *ngIf="showLabel" [object]="dso"></ds-item-type-badge>
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="3" type="h4">
|
||||
<h4 class="card-title" [innerHTML]="firstMetadataValue('dc.title')"></h4>
|
||||
</ds-truncatable-part>
|
||||
|
@@ -1 +1 @@
|
||||
<ds-org-unit-search-result-list-element [object]="{ indexableObject: object, hitHighlights: {} }" [linkType]="linkType"></ds-org-unit-search-result-list-element>
|
||||
<ds-org-unit-search-result-list-element [showLabel]="showLabel" [object]="{ indexableObject: object, hitHighlights: {} }" [linkType]="linkType"></ds-org-unit-search-result-list-element>
|
||||
|
@@ -1 +1 @@
|
||||
<ds-person-search-result-list-element [object]="{ indexableObject: object, hitHighlights: {} }" [linkType]="linkType"></ds-person-search-result-list-element>
|
||||
<ds-person-search-result-list-element [showLabel]="showLabel" [object]="{ indexableObject: object, hitHighlights: {} }" [linkType]="linkType"></ds-person-search-result-list-element>
|
||||
|
@@ -1 +1 @@
|
||||
<ds-project-search-result-list-element [object]="{ indexableObject: object, hitHighlights: {} }" [linkType]="linkType"></ds-project-search-result-list-element>
|
||||
<ds-project-search-result-list-element [showLabel]="showLabel" [object]="{ indexableObject: object, hitHighlights: {} }" [linkType]="linkType"></ds-project-search-result-list-element>
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<ds-item-type-badge [object]="dso"></ds-item-type-badge>
|
||||
<ds-item-type-badge *ngIf="showLabel" [object]="dso"></ds-item-type-badge>
|
||||
<ds-truncatable [id]="dso.id">
|
||||
<a *ngIf="linkType != linkTypes.None" [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer"
|
||||
[routerLink]="['/items/' + dso.id]" class="lead"
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<ds-item-type-badge [object]="dso"></ds-item-type-badge>
|
||||
<ds-item-type-badge *ngIf="showLabel" [object]="dso"></ds-item-type-badge>
|
||||
<ds-truncatable [id]="dso.id">
|
||||
<a *ngIf="linkType != linkTypes.None" [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer"
|
||||
[routerLink]="['/items/' + dso.id]" class="lead"
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<ds-truncatable [id]="dso.id">
|
||||
<ds-item-type-badge [object]="dso"></ds-item-type-badge>
|
||||
<ds-item-type-badge *ngIf="showLabel" [object]="dso"></ds-item-type-badge>
|
||||
<a *ngIf="linkType != linkTypes.None" [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer"
|
||||
[routerLink]="['/items/' + dso.id]" class="lead"
|
||||
[innerHTML]="firstMetadataValue('dc.title')"></a>
|
||||
|
@@ -43,6 +43,7 @@
|
||||
<ng-container *ngTemplateOutlet="endTemplate?.templateRef; context: model"></ng-container>
|
||||
<ng-container *ngIf="value?.isVirtual">
|
||||
<ds-existing-metadata-list-element
|
||||
*ngIf="model.hasSelectableMetadata"
|
||||
[reoRel]="relationshipValue$ | async"
|
||||
[submissionItem]="item$ | async"
|
||||
[listId]="listId"
|
||||
@@ -50,6 +51,15 @@
|
||||
[submissionId]="model.submissionId"
|
||||
[relationshipOptions]="model.relationship">
|
||||
</ds-existing-metadata-list-element>
|
||||
<ds-existing-relation-list-element
|
||||
*ngIf="!model.hasSelectableMetadata"
|
||||
[reoRel]="relationshipValue$ | async"
|
||||
[submissionItem]="item$ | async"
|
||||
[listId]="listId"
|
||||
[metadataFields]="model.metadataFields"
|
||||
[submissionId]="model.submissionId"
|
||||
[relationshipOptions]="model.relationship">
|
||||
</ds-existing-relation-list-element>
|
||||
</ng-container>
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
|
@@ -256,7 +256,7 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo
|
||||
this.relationshipValue$ = observableCombineLatest([this.item$.pipe(take(1)), relationship$]).pipe(
|
||||
switchMap(([item, relationship]: [Item, Relationship]) =>
|
||||
relationship.leftItem.pipe(
|
||||
getSucceededRemoteData(),
|
||||
getAllSucceededRemoteData(),
|
||||
getRemoteDataPayload(),
|
||||
map((leftItem: Item) => {
|
||||
return new ReorderableRelationship(relationship, leftItem.uuid !== item.uuid, this.relationshipService, this.store, this.model.submissionId)
|
||||
@@ -267,16 +267,17 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo
|
||||
);
|
||||
}
|
||||
}
|
||||
if (this.model.relationshipConfig) {
|
||||
const relationshipOptions = Object.assign(new RelationshipOptions(), this.model.relationshipConfig);
|
||||
this.listId = 'list-' + this.model.relationshipConfig.relationshipType;
|
||||
if (this.model.relationshipConfig || (this.isRelationship && !this.model.repeatable)) {
|
||||
const config = this.model.relationshipConfig || this.model.relationship;
|
||||
const relationshipOptions = Object.assign(new RelationshipOptions(), config);
|
||||
this.listId = 'list-' + relationshipOptions.relationshipType;
|
||||
this.setItem();
|
||||
const subscription = this.selectableListService.getSelectableList(this.listId).pipe(
|
||||
find((list: SelectableListState) => hasNoValue(list)),
|
||||
switchMap(() => this.item$.pipe(take(1))),
|
||||
switchMap((item) => {
|
||||
const relationshipsRD$ = this.relationshipService.getItemRelationshipsByLabel(item,
|
||||
this.model.relationshipConfig.relationshipType,
|
||||
relationshipOptions.relationshipType,
|
||||
undefined,
|
||||
followLink('leftItem'),
|
||||
followLink('rightItem'),
|
||||
|
@@ -145,9 +145,9 @@ export class ReorderableRelationship extends Reorderable {
|
||||
* Update the Reorderable
|
||||
*/
|
||||
update(): Observable<RemoteData<Relationship>> {
|
||||
this.store.dispatch(new UpdateRelationshipAction(this.relationship, this.submissionID))
|
||||
this.store.dispatch(new UpdateRelationshipAction(this.relationship, this.submissionID));
|
||||
const updatedRelationship$ = this.relationshipService.updatePlace(this).pipe(
|
||||
getSucceededRemoteData(),
|
||||
getSucceededRemoteData()
|
||||
);
|
||||
|
||||
updatedRelationship$.subscribe(() => {
|
||||
@@ -208,7 +208,6 @@ export class ExistingMetadataListElementComponent implements OnInit, OnChanges,
|
||||
const relationMD: MetadataValue = this.submissionItem.firstMetadata(this.relationshipOptions.metadataField, { value: this.relatedItem.uuid });
|
||||
if (hasValue(relationMD)) {
|
||||
const metadataRepresentationMD: MetadataValue = this.submissionItem.firstMetadata(this.metadataFields, { authority: relationMD.authority });
|
||||
|
||||
const nextValue = Object.assign(
|
||||
new ItemMetadataRepresentation(metadataRepresentationMD),
|
||||
this.relatedItem
|
||||
|
@@ -0,0 +1,14 @@
|
||||
<div class="d-flex">
|
||||
<span class="mr-auto text-contents">
|
||||
<ng-container *ngIf="!relatedItem">
|
||||
<ds-loading [showMessage]="false"></ds-loading>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="relatedItem">
|
||||
<ds-listable-object-component-loader [showLabel]="false" [viewMode]="viewType" [object]="relatedItem"></ds-listable-object-component-loader>
|
||||
</ng-container>
|
||||
</span>
|
||||
<button type="button" class="btn btn-secondary"
|
||||
(click)="removeSelection()">
|
||||
<i class="fas fa-trash" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
@@ -0,0 +1,3 @@
|
||||
span.text-contents{
|
||||
padding: $btn-padding-y 0;
|
||||
}
|
@@ -0,0 +1,100 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ExistingRelationListElementComponent } from './existing-relation-list-element.component';
|
||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import { SelectableListService } from '../../../../object-list/selectable-list/selectable-list.service';
|
||||
import { select, Store } from '@ngrx/store';
|
||||
import { Item } from '../../../../../core/shared/item.model';
|
||||
import { Relationship } from '../../../../../core/shared/item-relationships/relationship.model';
|
||||
import { RelationshipOptions } from '../../models/relationship-options.model';
|
||||
import { createSuccessfulRemoteDataObject$ } from '../../../../testing/utils';
|
||||
import { RemoveRelationshipAction } from '../relation-lookup-modal/relationship.actions';
|
||||
import { ItemSearchResult } from '../../../../object-collection/shared/item-search-result.model';
|
||||
import { of as observableOf } from 'rxjs';
|
||||
import { ReorderableRelationship } from '../existing-metadata-list-element/existing-metadata-list-element.component';
|
||||
|
||||
describe('ExistingRelationListElementComponent', () => {
|
||||
let component: ExistingRelationListElementComponent;
|
||||
let fixture: ComponentFixture<ExistingRelationListElementComponent>;
|
||||
let selectionService;
|
||||
let store;
|
||||
let listID;
|
||||
let submissionItem;
|
||||
let relationship;
|
||||
let reoRel;
|
||||
let metadataFields;
|
||||
let relationshipOptions;
|
||||
let uuid1;
|
||||
let uuid2;
|
||||
let relatedItem;
|
||||
let leftItemRD$;
|
||||
let rightItemRD$;
|
||||
let relatedSearchResult;
|
||||
let submissionId;
|
||||
let relationshipService;
|
||||
|
||||
function init() {
|
||||
uuid1 = '91ce578d-2e63-4093-8c73-3faafd716000';
|
||||
uuid2 = '0e9dba1c-e1c3-4e05-a539-446f08ef57a7';
|
||||
selectionService = jasmine.createSpyObj('selectionService', ['deselectSingle']);
|
||||
store = jasmine.createSpyObj('store', ['dispatch']);
|
||||
listID = '1234-listID';
|
||||
submissionItem = Object.assign(new Item(), { uuid: uuid1 });
|
||||
metadataFields = ['dc.contributor.author'];
|
||||
relationshipOptions = Object.assign(new RelationshipOptions(), { relationshipType: 'isPublicationOfAuthor', filter: 'test.filter', searchConfiguration: 'personConfiguration', nameVariants: true })
|
||||
relatedItem = Object.assign(new Item(), { uuid: uuid2 });
|
||||
leftItemRD$ = createSuccessfulRemoteDataObject$(relatedItem);
|
||||
rightItemRD$ = createSuccessfulRemoteDataObject$(submissionItem);
|
||||
relatedSearchResult = Object.assign(new ItemSearchResult(), { indexableObject: relatedItem });
|
||||
relationshipService = {
|
||||
updatePlace:() => observableOf({})
|
||||
} as any;
|
||||
|
||||
relationship = Object.assign(new Relationship(), { leftItem: leftItemRD$, rightItem: rightItemRD$ });
|
||||
submissionId = '1234';
|
||||
reoRel = new ReorderableRelationship(relationship, true, relationshipService, {} as any, submissionId);
|
||||
}
|
||||
|
||||
beforeEach(async(() => {
|
||||
init();
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ExistingRelationListElementComponent],
|
||||
providers: [
|
||||
{ provide: SelectableListService, useValue: selectionService },
|
||||
{ provide: Store, useValue: store },
|
||||
],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ExistingRelationListElementComponent);
|
||||
component = fixture.componentInstance;
|
||||
component.listId = listID;
|
||||
component.submissionItem = submissionItem;
|
||||
component.reoRel = reoRel;
|
||||
component.metadataFields = metadataFields;
|
||||
component.relationshipOptions = relationshipOptions;
|
||||
component.submissionId = submissionId;
|
||||
fixture.detectChanges();
|
||||
component.ngOnChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
describe('removeSelection', () => {
|
||||
it('should deselect the object in the selectable list service', () => {
|
||||
component.removeSelection();
|
||||
expect(selectionService.deselectSingle).toHaveBeenCalledWith(listID, relatedSearchResult);
|
||||
});
|
||||
|
||||
it('should dispatch a RemoveRelationshipAction', () => {
|
||||
component.removeSelection();
|
||||
const action = new RemoveRelationshipAction(submissionItem, relatedItem, relationshipOptions.relationshipType, submissionId);
|
||||
expect(store.dispatch).toHaveBeenCalledWith(action);
|
||||
});
|
||||
})
|
||||
});
|
@@ -0,0 +1,168 @@
|
||||
import { Component, Input, OnChanges, OnDestroy, OnInit } from '@angular/core';
|
||||
import { FormControl } from '@angular/forms';
|
||||
import { DynamicFormArrayGroupModel } from '@ng-dynamic-forms/core';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { Observable, of as observableOf, Subscription } from 'rxjs';
|
||||
import { filter } from 'rxjs/operators';
|
||||
import { AppState } from '../../../../../app.reducer';
|
||||
import { Item } from '../../../../../core/shared/item.model';
|
||||
import { getAllSucceededRemoteData, getRemoteDataPayload } from '../../../../../core/shared/operators';
|
||||
import { hasValue, isNotEmpty } from '../../../../empty.util';
|
||||
import { ItemSearchResult } from '../../../../object-collection/shared/item-search-result.model';
|
||||
import { SelectableListService } from '../../../../object-list/selectable-list/selectable-list.service';
|
||||
import { FormFieldMetadataValueObject } from '../../models/form-field-metadata-value.model';
|
||||
import { RelationshipOptions } from '../../models/relationship-options.model';
|
||||
import { DynamicConcatModel } from '../models/ds-dynamic-concat.model';
|
||||
import { RemoveRelationshipAction } from '../relation-lookup-modal/relationship.actions';
|
||||
import { ViewMode } from '../../../../../core/shared/view-mode.model';
|
||||
import { ReorderableRelationship } from '../existing-metadata-list-element/existing-metadata-list-element.component';
|
||||
|
||||
// tslint:disable:max-classes-per-file
|
||||
/**
|
||||
* Abstract class that defines objects that can be reordered
|
||||
*/
|
||||
export abstract class Reorderable {
|
||||
|
||||
constructor(public oldIndex?: number, public newIndex?: number) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the id for this Reorderable
|
||||
*/
|
||||
abstract getId(): string;
|
||||
|
||||
/**
|
||||
* Return the place metadata for this Reorderable
|
||||
*/
|
||||
abstract getPlace(): number;
|
||||
|
||||
/**
|
||||
* Update the Reorderable
|
||||
*/
|
||||
abstract update(): Observable<any>;
|
||||
|
||||
/**
|
||||
* Returns true if the oldIndex of this Reorderable
|
||||
* differs from the newIndex
|
||||
*/
|
||||
get hasMoved(): boolean {
|
||||
return this.oldIndex !== this.newIndex
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A Reorderable representation of a FormFieldMetadataValue
|
||||
*/
|
||||
export class ReorderableFormFieldMetadataValue extends Reorderable {
|
||||
|
||||
constructor(
|
||||
public metadataValue: FormFieldMetadataValueObject,
|
||||
public model: DynamicConcatModel,
|
||||
public control: FormControl,
|
||||
public group: DynamicFormArrayGroupModel,
|
||||
oldIndex?: number,
|
||||
newIndex?: number
|
||||
) {
|
||||
super(oldIndex, newIndex);
|
||||
this.metadataValue = metadataValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the id for this Reorderable
|
||||
*/
|
||||
getId(): string {
|
||||
if (hasValue(this.metadataValue.authority)) {
|
||||
return this.metadataValue.authority;
|
||||
} else {
|
||||
// can't use UUIDs, they're generated client side
|
||||
return this.metadataValue.value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the place metadata for this Reorderable
|
||||
*/
|
||||
getPlace(): number {
|
||||
return this.metadataValue.place;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the Reorderable
|
||||
*/
|
||||
update(): Observable<FormFieldMetadataValueObject> {
|
||||
this.oldIndex = this.newIndex;
|
||||
return observableOf(this.metadataValue);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a single existing relationship value as metadata in submission
|
||||
*/
|
||||
@Component({
|
||||
selector: 'ds-existing-relation-list-element',
|
||||
templateUrl: './existing-relation-list-element.component.html',
|
||||
styleUrls: ['./existing-relation-list-element.component.scss']
|
||||
})
|
||||
export class ExistingRelationListElementComponent implements OnInit, OnChanges, OnDestroy {
|
||||
@Input() listId: string;
|
||||
@Input() submissionItem: Item;
|
||||
@Input() reoRel: ReorderableRelationship;
|
||||
@Input() metadataFields: string[];
|
||||
@Input() relationshipOptions: RelationshipOptions;
|
||||
@Input() submissionId: string;
|
||||
relatedItem: Item;
|
||||
viewType = ViewMode.ListElement;
|
||||
|
||||
/**
|
||||
* List of subscriptions to unsubscribe from
|
||||
*/
|
||||
private subs: Subscription[] = [];
|
||||
|
||||
constructor(
|
||||
private selectableListService: SelectableListService,
|
||||
private store: Store<AppState>
|
||||
) {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.ngOnChanges();
|
||||
}
|
||||
|
||||
/**
|
||||
* Change callback for the component
|
||||
*/
|
||||
ngOnChanges() {
|
||||
if (hasValue(this.reoRel)) {
|
||||
const item$ = this.reoRel.useLeftItem ?
|
||||
this.reoRel.relationship.leftItem : this.reoRel.relationship.rightItem;
|
||||
this.subs.push(item$.pipe(
|
||||
getAllSucceededRemoteData(),
|
||||
getRemoteDataPayload(),
|
||||
filter((item: Item) => hasValue(item) && isNotEmpty(item.uuid))
|
||||
).subscribe((item: Item) => {
|
||||
this.relatedItem = item;
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the selected relationship from the list
|
||||
*/
|
||||
removeSelection() {
|
||||
this.selectableListService.deselectSingle(this.listId, Object.assign(new ItemSearchResult(), { indexableObject: this.relatedItem }));
|
||||
this.store.dispatch(new RemoveRelationshipAction(this.submissionItem, this.relatedItem, this.relationshipOptions.relationshipType, this.submissionId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsubscribe from all subscriptions
|
||||
*/
|
||||
ngOnDestroy(): void {
|
||||
this.subs
|
||||
.filter((sub) => hasValue(sub))
|
||||
.forEach((sub) => sub.unsubscribe());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// tslint:enable:max-classes-per-file
|
@@ -5,6 +5,7 @@ export const DYNAMIC_FORM_CONTROL_TYPE_DISABLED = 'EMPTY';
|
||||
|
||||
export interface DsDynamicDisabledModelConfig extends DsDynamicInputModelConfig {
|
||||
value?: any;
|
||||
hasSelectableMetadata: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -14,11 +15,14 @@ export class DynamicDisabledModel extends DsDynamicInputModel {
|
||||
|
||||
@serializable() readonly type: string = DYNAMIC_FORM_CONTROL_TYPE_DISABLED;
|
||||
@serializable() value: any;
|
||||
@serializable() hasSelectableMetadata: boolean;
|
||||
|
||||
constructor(config: DsDynamicDisabledModelConfig, layout?: DynamicFormControlLayout) {
|
||||
super(config, layout);
|
||||
this.readOnly = true;
|
||||
this.disabled = true;
|
||||
this.hasSelectableMetadata = config.hasSelectableMetadata;
|
||||
|
||||
this.valueUpdates.next(config.value);
|
||||
}
|
||||
}
|
||||
|
@@ -20,6 +20,7 @@ export interface DynamicConcatModelConfig extends DynamicFormGroupModelConfig {
|
||||
required: boolean;
|
||||
metadataFields: string[];
|
||||
submissionId: string;
|
||||
hasSelectableMetadata: boolean;
|
||||
}
|
||||
|
||||
export class DynamicConcatModel extends DynamicFormGroupModel {
|
||||
@@ -32,6 +33,7 @@ export class DynamicConcatModel extends DynamicFormGroupModel {
|
||||
@serializable() hint?: string;
|
||||
@serializable() metadataFields: string[];
|
||||
@serializable() submissionId: string;
|
||||
@serializable() hasSelectableMetadata: boolean;
|
||||
|
||||
isCustomGroup = true;
|
||||
valueUpdates: Subject<string>;
|
||||
@@ -46,6 +48,7 @@ export class DynamicConcatModel extends DynamicFormGroupModel {
|
||||
this.hint = config.hint;
|
||||
this.metadataFields = config.metadataFields;
|
||||
this.submissionId = config.submissionId;
|
||||
this.hasSelectableMetadata = config.hasSelectableMetadata;
|
||||
this.valueUpdates = new Subject<string>();
|
||||
this.valueUpdates.subscribe((value: string) => this.value = value);
|
||||
}
|
||||
|
@@ -17,6 +17,8 @@ export interface DsDynamicInputModelConfig extends DynamicInputModelConfig {
|
||||
repeatable: boolean;
|
||||
metadataFields: string[];
|
||||
submissionId: string;
|
||||
hasSelectableMetadata: boolean;
|
||||
|
||||
}
|
||||
|
||||
export class DsDynamicInputModel extends DynamicInputModel {
|
||||
@@ -29,6 +31,7 @@ export class DsDynamicInputModel extends DynamicInputModel {
|
||||
@serializable() repeatable?: boolean;
|
||||
@serializable() metadataFields: string[];
|
||||
@serializable() submissionId: string;
|
||||
@serializable() hasSelectableMetadata: boolean;
|
||||
|
||||
constructor(config: DsDynamicInputModelConfig, layout?: DynamicFormControlLayout) {
|
||||
super(config, layout);
|
||||
@@ -39,6 +42,7 @@ export class DsDynamicInputModel extends DynamicInputModel {
|
||||
this.value = config.value;
|
||||
this.relationship = config.relationship;
|
||||
this.submissionId = config.submissionId;
|
||||
this.hasSelectableMetadata = config.hasSelectableMetadata;
|
||||
|
||||
this.language = config.language;
|
||||
if (!this.language) {
|
||||
|
@@ -8,6 +8,7 @@ export interface DynamicRowArrayModelConfig extends DynamicFormArrayModelConfig
|
||||
relationshipConfig: RelationshipOptions;
|
||||
metadataKey: string;
|
||||
metadataFields: string[];
|
||||
hasSelectableMetadata: boolean;
|
||||
}
|
||||
|
||||
export class DynamicRowArrayModel extends DynamicFormArrayModel {
|
||||
@@ -17,6 +18,7 @@ export class DynamicRowArrayModel extends DynamicFormArrayModel {
|
||||
@serializable() relationshipConfig: RelationshipOptions;
|
||||
@serializable() metadataKey: string;
|
||||
@serializable() metadataFields: string[];
|
||||
@serializable() hasSelectableMetadata: boolean;
|
||||
isRowArray = true;
|
||||
|
||||
constructor(config: DynamicRowArrayModelConfig, layout?: DynamicFormControlLayout) {
|
||||
@@ -27,5 +29,6 @@ export class DynamicRowArrayModel extends DynamicFormArrayModel {
|
||||
this.relationshipConfig = config.relationshipConfig;
|
||||
this.metadataKey = config.metadataKey;
|
||||
this.metadataFields = config.metadataFields;
|
||||
this.hasSelectableMetadata = config.hasSelectableMetadata;
|
||||
}
|
||||
}
|
||||
|
@@ -51,7 +51,7 @@ describe('DisabledFieldParser test suite', () => {
|
||||
it('should set init value properly', () => {
|
||||
initFormValues = {
|
||||
description: [
|
||||
new FormFieldMetadataValueObject('test description'),
|
||||
'test description',
|
||||
],
|
||||
};
|
||||
const expectedValue ='test description';
|
||||
@@ -59,7 +59,7 @@ describe('DisabledFieldParser test suite', () => {
|
||||
const parser = new DisabledFieldParser(submissionId, field, initFormValues, parserOptions);
|
||||
|
||||
const fieldModel = parser.parse();
|
||||
expect(fieldModel.value).toEqual(expectedValue);
|
||||
expect(fieldModel.value.value).toEqual(expectedValue);
|
||||
});
|
||||
|
||||
});
|
||||
|
@@ -9,7 +9,7 @@ export class DisabledFieldParser extends FieldParser {
|
||||
|
||||
public modelFactory(fieldValue?: FormFieldMetadataValueObject | any, label?: boolean): any {
|
||||
const emptyModelConfig: DsDynamicDisabledModelConfig = this.initModel(null, label);
|
||||
this.setValues(emptyModelConfig, fieldValue);
|
||||
this.setValues(emptyModelConfig, fieldValue, true);
|
||||
return new DynamicDisabledModel(emptyModelConfig)
|
||||
}
|
||||
}
|
||||
|
@@ -45,7 +45,6 @@ export abstract class FieldParser {
|
||||
if (Array.isArray(this.configData.selectableMetadata) && this.configData.selectableMetadata.length === 1) {
|
||||
metadataKey = this.configData.selectableMetadata[0].metadata;
|
||||
}
|
||||
|
||||
const config = {
|
||||
id: uniqueId() + '_array',
|
||||
label: this.configData.label,
|
||||
@@ -56,6 +55,7 @@ export abstract class FieldParser {
|
||||
submissionId: this.submissionId,
|
||||
metadataKey,
|
||||
metadataFields: this.getAllFieldIds(),
|
||||
hasSelectableMetadata: isNotEmpty(this.configData.selectableMetadata),
|
||||
groupFactory: () => {
|
||||
let model;
|
||||
let isFirstModelInArray = true;
|
||||
@@ -192,7 +192,7 @@ export abstract class FieldParser {
|
||||
return ids;
|
||||
}
|
||||
} else {
|
||||
return [this.configData.selectableRelationship.relationshipType];
|
||||
return ['relation.' + this.configData.selectableRelationship.relationshipType];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,7 +216,8 @@ export abstract class FieldParser {
|
||||
controlModel.relationship = Object.assign(new RelationshipOptions(), this.configData.selectableRelationship);
|
||||
}
|
||||
controlModel.repeatable = this.configData.repeatable;
|
||||
controlModel.metadataFields = isNotEmpty(this.configData.selectableMetadata) ? this.configData.selectableMetadata.map((metadataObject) => metadataObject.metadata) : [];
|
||||
controlModel.metadataFields = this.getAllFieldIds() || [];
|
||||
controlModel.hasSelectableMetadata = isNotEmpty(this.configData.selectableMetadata);
|
||||
controlModel.submissionId = this.submissionId;
|
||||
|
||||
// Set label
|
||||
|
@@ -55,7 +55,8 @@ export const qualdropInputConfig = {
|
||||
repeatable: false,
|
||||
value: 'test',
|
||||
submissionId: '1234',
|
||||
metadataFields: []
|
||||
metadataFields: [],
|
||||
hasSelectableMetadata: false
|
||||
};
|
||||
|
||||
export const mockQualdropSelectModel = new DynamicSelectModel(qualdropSelectConfig);
|
||||
@@ -82,7 +83,8 @@ const rowArrayQualdropConfig = {
|
||||
required: false,
|
||||
submissionId: '1234',
|
||||
metadataKey: 'dc.some.key',
|
||||
metadataFields: ['dc.some.key']
|
||||
metadataFields: ['dc.some.key'],
|
||||
hasSelectableMetadata: false
|
||||
} as DynamicRowArrayModelConfig;
|
||||
|
||||
export const MockRowArrayQualdropModel: DynamicRowArrayModel = new DynamicRowArrayModel(rowArrayQualdropConfig);
|
||||
@@ -139,7 +141,8 @@ const relationGroupConfig = {
|
||||
'issue test 2'
|
||||
],
|
||||
},
|
||||
metadataFields: []
|
||||
metadataFields: [],
|
||||
hasSelectableMetadata: false
|
||||
};
|
||||
|
||||
export const MockRelationModel: DynamicRelationGroupModel = new DynamicRelationGroupModel(relationGroupConfig);
|
||||
@@ -168,7 +171,8 @@ export const inputWithLanguageAndAuthorityConfig = {
|
||||
id: 'testWithLanguageAndAuthority',
|
||||
},
|
||||
submissionId: '1234',
|
||||
metadataFields: []
|
||||
metadataFields: [],
|
||||
hasSelectableMetadata: false
|
||||
};
|
||||
|
||||
export const mockInputWithLanguageAndAuthorityModel = new DsDynamicInputModel(inputWithLanguageAndAuthorityConfig);
|
||||
@@ -192,7 +196,8 @@ export const inputWithLanguageConfig = {
|
||||
repeatable: false,
|
||||
value: 'testWithLanguage',
|
||||
submissionId: '1234',
|
||||
metadataFields: []
|
||||
metadataFields: [],
|
||||
hasSelectableMetadata: false
|
||||
};
|
||||
|
||||
export const mockInputWithLanguageModel = new DsDynamicInputModel(inputWithLanguageConfig);
|
||||
@@ -221,7 +226,8 @@ export const inputWithLanguageAndAuthorityArrayConfig = {
|
||||
id: 'testLanguageAndAuthorityArray',
|
||||
}],
|
||||
submissionId: '1234',
|
||||
metadataFields: []
|
||||
metadataFields: [],
|
||||
hasSelectableMetadata: false
|
||||
};
|
||||
|
||||
export const mockInputWithLanguageAndAuthorityArrayModel = new DsDynamicInputModel(inputWithLanguageAndAuthorityArrayConfig);
|
||||
@@ -234,7 +240,8 @@ export const inputWithFormFieldValueConfig = {
|
||||
repeatable: false,
|
||||
value: new FormFieldMetadataValueObject('testWithFormFieldValue'),
|
||||
submissionId: '1234',
|
||||
metadataFields: []
|
||||
metadataFields: [],
|
||||
hasSelectableMetadata: false
|
||||
};
|
||||
|
||||
export const mockInputWithFormFieldValueModel = new DsDynamicInputModel(inputWithFormFieldValueConfig);
|
||||
@@ -247,7 +254,8 @@ export const inputWithAuthorityValueConfig = {
|
||||
repeatable: false,
|
||||
value: Object.assign({}, new AuthorityValue(), { value: 'testWithAuthorityValue', id: 'testWithAuthorityValue', display: 'testWithAuthorityValue' }),
|
||||
submissionId: '1234',
|
||||
metadataFields: []
|
||||
metadataFields: [],
|
||||
hasSelectableMetadata: false
|
||||
};
|
||||
|
||||
export const mockInputWithAuthorityValueModel = new DsDynamicInputModel(inputWithAuthorityValueConfig);
|
||||
@@ -260,7 +268,8 @@ export const inputWithObjectValueConfig = {
|
||||
repeatable: false,
|
||||
value: { value: 'testWithObjectValue', id: 'testWithObjectValue', display: 'testWithObjectValue' },
|
||||
submissionId: '1234',
|
||||
metadataFields: []
|
||||
metadataFields: [],
|
||||
hasSelectableMetadata: false
|
||||
};
|
||||
|
||||
export const mockInputWithObjectValueModel = new DsDynamicInputModel(inputWithObjectValueConfig);
|
||||
@@ -277,7 +286,8 @@ export const fileFormEditInputConfig = {
|
||||
disabled: false,
|
||||
repeatable: false,
|
||||
submissionId: '1234',
|
||||
metadataFields: []
|
||||
metadataFields: [],
|
||||
hasSelectableMetadata: false
|
||||
};
|
||||
|
||||
export const mockFileFormEditInputModel = new DsDynamicInputModel(fileFormEditInputConfig);
|
||||
|
@@ -46,6 +46,11 @@ export class ListableObjectComponentLoaderComponent implements OnInit {
|
||||
*/
|
||||
@Input() listID: string;
|
||||
|
||||
/**
|
||||
* Whether to show the badge label or not
|
||||
*/
|
||||
@Input() showLabel: boolean = true;
|
||||
|
||||
/**
|
||||
* Directive hook used to place the dynamic child component
|
||||
*/
|
||||
@@ -68,6 +73,7 @@ export class ListableObjectComponentLoaderComponent implements OnInit {
|
||||
(componentRef.instance as any).index = this.index;
|
||||
(componentRef.instance as any).linkType = this.linkType;
|
||||
(componentRef.instance as any).listID = this.listID;
|
||||
(componentRef.instance as any).showLabel = this.showLabel;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -29,6 +29,11 @@ export class AbstractListableElementComponent<T extends ListableObject> {
|
||||
*/
|
||||
@Input() index: number;
|
||||
|
||||
/**
|
||||
* Whether to show the badge label or not
|
||||
*/
|
||||
@Input() showLabel: boolean = true;
|
||||
|
||||
/**
|
||||
* The available link types
|
||||
*/
|
||||
|
@@ -1 +1 @@
|
||||
<ds-publication-search-result-grid-element [object]="{ indexableObject: object, hitHighlights: {} }" [linkType]="linkType"></ds-publication-search-result-grid-element>
|
||||
<ds-publication-search-result-grid-element [showLabel]="showLabel" [object]="{ indexableObject: object, hitHighlights: {} }" [linkType]="linkType"></ds-publication-search-result-grid-element>
|
||||
|
@@ -15,7 +15,7 @@
|
||||
</div>
|
||||
</span>
|
||||
<div class="card-body">
|
||||
<ds-item-type-badge [object]="dso"></ds-item-type-badge>
|
||||
<ds-item-type-badge *ngIf="showLabel" [object]="dso"></ds-item-type-badge>
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="3" type="h4">
|
||||
<h4 class="card-title" [innerHTML]="firstMetadataValue('dc.title')"></h4>
|
||||
</ds-truncatable-part>
|
||||
|
@@ -1 +1 @@
|
||||
<ds-publication-search-result-list-element [object]="{ indexableObject: object, hitHighlights: {} }" [linkType]="linkType"></ds-publication-search-result-list-element>
|
||||
<ds-publication-search-result-list-element [showLabel]="showLabel" [object]="{ indexableObject: object, hitHighlights: {} }" [linkType]="linkType"></ds-publication-search-result-list-element>
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<ds-item-type-badge [object]="dso"></ds-item-type-badge>
|
||||
<ds-item-type-badge *ngIf="showLabel" [object]="dso"></ds-item-type-badge>
|
||||
|
||||
<ds-truncatable [id]="dso.id" *ngIf="object !== undefined && object !== null">
|
||||
<a *ngIf="linkType != linkTypes.None" [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer"
|
||||
|
@@ -186,6 +186,7 @@ import { LogInPasswordComponent } from './log-in/methods/password/log-in-passwor
|
||||
import { LogInComponent } from './log-in/log-in.component';
|
||||
import { MissingTranslationHelper } from './translate/missing-translation.helper';
|
||||
import { ItemVersionsNoticeComponent } from './item/item-versions/notice/item-versions-notice.component';
|
||||
import { ExistingRelationListElementComponent } from './form/builder/ds-dynamic-form-ui/existing-relation-list-element/existing-relation-list-element.component';
|
||||
|
||||
const MODULES = [
|
||||
// Do NOT include UniversalModule, HttpModule, or JsonpModule here
|
||||
@@ -352,6 +353,7 @@ const COMPONENTS = [
|
||||
ExternalSourceEntryImportModalComponent,
|
||||
ImportableListItemControlComponent,
|
||||
ExistingMetadataListElementComponent,
|
||||
ExistingRelationListElementComponent,
|
||||
LogInShibbolethComponent,
|
||||
LogInPasswordComponent,
|
||||
LogInContainerComponent,
|
||||
@@ -421,6 +423,7 @@ const ENTRY_COMPONENTS = [
|
||||
DsDynamicLookupRelationSelectionTabComponent,
|
||||
DsDynamicLookupRelationExternalSourceTabComponent,
|
||||
ExternalSourceEntryImportModalComponent,
|
||||
ExistingRelationListElementComponent,
|
||||
LogInPasswordComponent,
|
||||
LogInShibbolethComponent,
|
||||
ItemVersionsComponent,
|
||||
|
@@ -3,5 +3,6 @@
|
||||
[sections]="sections"
|
||||
[selfUrl]="selfUrl"
|
||||
[submissionDefinition]="submissionDefinition"
|
||||
[item]="item"
|
||||
[submissionId]="submissionId"></ds-submission-form>
|
||||
</div>
|
||||
|
@@ -13,6 +13,7 @@ import { NotificationsService } from '../../shared/notifications/notifications.s
|
||||
import { SubmissionObject } from '../../core/submission/models/submission-object.model';
|
||||
import { Collection } from '../../core/shared/collection.model';
|
||||
import { RemoteData } from '../../core/data/remote-data';
|
||||
import { Item } from '../../core/shared/item.model';
|
||||
|
||||
/**
|
||||
* This component allows to edit an existing workspaceitem/workflowitem.
|
||||
@@ -59,6 +60,7 @@ export class SubmissionEditComponent implements OnDestroy, OnInit {
|
||||
* @type {Array}
|
||||
*/
|
||||
private subs: Subscription[] = [];
|
||||
private item: Item;
|
||||
|
||||
/**
|
||||
* Initialize instance variables
|
||||
@@ -96,6 +98,7 @@ export class SubmissionEditComponent implements OnDestroy, OnInit {
|
||||
this.collectionId = (submissionObjectRD.payload.collection as Collection).id;
|
||||
this.selfUrl = submissionObjectRD.payload._links.self.href;
|
||||
this.sections = submissionObjectRD.payload.sections;
|
||||
this.item = submissionObjectRD.payload.item as Item;
|
||||
this.submissionDefinition = (submissionObjectRD.payload.submissionDefinition as SubmissionDefinitionsModel);
|
||||
this.changeDetectorRef.detectChanges();
|
||||
}
|
||||
|
@@ -20,6 +20,7 @@ import { AuthServiceStub } from '../../shared/testing/auth-service-stub';
|
||||
import { AuthService } from '../../core/auth/auth.service';
|
||||
import { HALEndpointServiceStub } from '../../shared/testing/hal-endpoint-service-stub';
|
||||
import { createTestComponent } from '../../shared/testing/utils';
|
||||
import { Item } from '../../core/shared/item.model';
|
||||
|
||||
describe('SubmissionFormComponent Component', () => {
|
||||
|
||||
@@ -66,7 +67,7 @@ describe('SubmissionFormComponent Component', () => {
|
||||
<ds-submission-form [collectionId]="collectionId"
|
||||
[selfUrl]="selfUrl"
|
||||
[submissionDefinition]="submissionDefinition"
|
||||
[submissionId]="submissionId"></ds-submission-form>`;
|
||||
[submissionId]="submissionId" [item]="item"></ds-submission-form>`;
|
||||
|
||||
testFixture = createTestComponent(html, TestComponent) as ComponentFixture<TestComponent>;
|
||||
testComp = testFixture.componentInstance;
|
||||
@@ -118,6 +119,7 @@ describe('SubmissionFormComponent Component', () => {
|
||||
comp.submissionDefinition = submissionDefinition;
|
||||
comp.selfUrl = selfUrl;
|
||||
comp.sections = sectionsData;
|
||||
comp.item = new Item();
|
||||
|
||||
submissionServiceStub.getSubmissionObject.and.returnValue(observableOf(submissionState));
|
||||
submissionServiceStub.getSubmissionSections.and.returnValue(observableOf(sectionsList));
|
||||
@@ -143,6 +145,7 @@ describe('SubmissionFormComponent Component', () => {
|
||||
selfUrl,
|
||||
submissionDefinition,
|
||||
sectionsData,
|
||||
comp.item,
|
||||
null);
|
||||
expect(submissionServiceStub.startAutoSave).toHaveBeenCalled();
|
||||
});
|
||||
@@ -153,6 +156,7 @@ describe('SubmissionFormComponent Component', () => {
|
||||
comp.submissionDefinition = submissionDefinition;
|
||||
comp.selfUrl = selfUrl;
|
||||
comp.sections = sectionsData;
|
||||
comp.item = new Item();
|
||||
|
||||
comp.onCollectionChange(submissionObjectNew);
|
||||
|
||||
@@ -168,7 +172,9 @@ describe('SubmissionFormComponent Component', () => {
|
||||
submissionId,
|
||||
selfUrl,
|
||||
submissionObjectNew.submissionDefinition,
|
||||
submissionObjectNew.sections);
|
||||
submissionObjectNew.sections,
|
||||
comp.item,
|
||||
);
|
||||
});
|
||||
|
||||
it('should update only collection id on collection change when submission definition is not changed', () => {
|
||||
@@ -178,6 +184,7 @@ describe('SubmissionFormComponent Component', () => {
|
||||
comp.submissionDefinition = submissionDefinition;
|
||||
comp.selfUrl = selfUrl;
|
||||
comp.sections = sectionsData;
|
||||
comp.item = new Item();
|
||||
|
||||
comp.onCollectionChange({
|
||||
collection: {
|
||||
|
@@ -14,6 +14,7 @@ import { UploaderOptions } from '../../shared/uploader/uploader-options.model';
|
||||
import { SubmissionObjectEntry } from '../objects/submission-objects.reducer';
|
||||
import { SectionDataObject } from '../sections/models/section-data.model';
|
||||
import { SubmissionService } from '../submission.service';
|
||||
import { Item } from '../../core/shared/item.model';
|
||||
|
||||
/**
|
||||
* This component represents the submission form.
|
||||
@@ -30,6 +31,7 @@ export class SubmissionFormComponent implements OnChanges, OnDestroy {
|
||||
* @type {string}
|
||||
*/
|
||||
@Input() collectionId: string;
|
||||
@Input() item: Item;
|
||||
|
||||
/**
|
||||
* The list of submission's sections
|
||||
@@ -150,6 +152,7 @@ export class SubmissionFormComponent implements OnChanges, OnDestroy {
|
||||
this.selfUrl,
|
||||
this.submissionDefinition,
|
||||
this.sections,
|
||||
this.item,
|
||||
null);
|
||||
this.changeDetectorRef.detectChanges();
|
||||
})
|
||||
@@ -191,7 +194,8 @@ export class SubmissionFormComponent implements OnChanges, OnDestroy {
|
||||
this.submissionId,
|
||||
submissionObject._links.self.href,
|
||||
this.submissionDefinition,
|
||||
this.sections);
|
||||
this.sections,
|
||||
this.item);
|
||||
} else {
|
||||
this.changeDetectorRef.detectChanges();
|
||||
}
|
||||
|
@@ -10,6 +10,7 @@ import {
|
||||
import { SubmissionObject } from '../../core/submission/models/submission-object.model';
|
||||
import { SubmissionDefinitionsModel } from '../../core/config/models/config-submission-definitions.model';
|
||||
import { SectionsType } from '../sections/sections-type';
|
||||
import { Item } from '../../core/shared/item.model';
|
||||
|
||||
/**
|
||||
* For each action type in an action group, make a simple
|
||||
@@ -273,6 +274,7 @@ export class InitSubmissionFormAction implements Action {
|
||||
selfUrl: string;
|
||||
submissionDefinition: SubmissionDefinitionsModel;
|
||||
sections: WorkspaceitemSectionsObject;
|
||||
item: Item;
|
||||
errors: SubmissionSectionError[];
|
||||
};
|
||||
|
||||
@@ -297,8 +299,9 @@ export class InitSubmissionFormAction implements Action {
|
||||
selfUrl: string,
|
||||
submissionDefinition: SubmissionDefinitionsModel,
|
||||
sections: WorkspaceitemSectionsObject,
|
||||
item: Item,
|
||||
errors: SubmissionSectionError[]) {
|
||||
this.payload = { collectionId, submissionId, selfUrl, submissionDefinition, sections, errors };
|
||||
this.payload = { collectionId, submissionId, selfUrl, submissionDefinition, sections, item, errors };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -477,6 +480,7 @@ export class ResetSubmissionFormAction implements Action {
|
||||
selfUrl: string;
|
||||
sections: WorkspaceitemSectionsObject;
|
||||
submissionDefinition: SubmissionDefinitionsModel;
|
||||
item: Item;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -493,8 +497,8 @@ export class ResetSubmissionFormAction implements Action {
|
||||
* @param submissionDefinition
|
||||
* the submission's form definition
|
||||
*/
|
||||
constructor(collectionId: string, submissionId: string, selfUrl: string, sections: WorkspaceitemSectionsObject, submissionDefinition: SubmissionDefinitionsModel) {
|
||||
this.payload = { collectionId, submissionId, selfUrl, sections, submissionDefinition };
|
||||
constructor(collectionId: string, submissionId: string, selfUrl: string, sections: WorkspaceitemSectionsObject, submissionDefinition: SubmissionDefinitionsModel, item: Item) {
|
||||
this.payload = { collectionId, submissionId, selfUrl, sections, submissionDefinition, item };
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -47,6 +47,7 @@ import { MockTranslateLoader } from '../../shared/mocks/mock-translate-loader';
|
||||
import { MockStore } from '../../shared/testing/mock-store';
|
||||
import { AppState } from '../../app.reducer';
|
||||
import parseSectionErrors from '../utils/parseSectionErrors';
|
||||
import { Item } from '../../core/shared/item.model';
|
||||
|
||||
describe('SubmissionObjectEffects test suite', () => {
|
||||
let submissionObjectEffects: SubmissionObjectEffects;
|
||||
@@ -101,6 +102,7 @@ describe('SubmissionObjectEffects test suite', () => {
|
||||
selfUrl: selfUrl,
|
||||
submissionDefinition: submissionDefinition,
|
||||
sections: {},
|
||||
item: {metadata: {}},
|
||||
errors: [],
|
||||
}
|
||||
}
|
||||
@@ -153,6 +155,7 @@ describe('SubmissionObjectEffects test suite', () => {
|
||||
selfUrl: selfUrl,
|
||||
submissionDefinition: submissionDefinition,
|
||||
sections: {},
|
||||
item: new Item(),
|
||||
errors: [],
|
||||
}
|
||||
}
|
||||
@@ -165,6 +168,7 @@ describe('SubmissionObjectEffects test suite', () => {
|
||||
selfUrl,
|
||||
submissionDefinition,
|
||||
{},
|
||||
new Item(),
|
||||
null
|
||||
)
|
||||
});
|
||||
|
@@ -4,8 +4,8 @@ import { Store } from '@ngrx/store';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { union } from 'lodash';
|
||||
|
||||
import { from as observableFrom, of as observableOf } from 'rxjs';
|
||||
import { catchError, map, mergeMap, switchMap, tap, withLatestFrom } from 'rxjs/operators';
|
||||
import { from as observableFrom, Observable, of as observableOf } from 'rxjs';
|
||||
import { catchError, map, mergeMap, switchMap, take, tap, withLatestFrom } from 'rxjs/operators';
|
||||
import { SubmissionObject } from '../../core/submission/models/submission-object.model';
|
||||
import { WorkflowItem } from '../../core/submission/models/workflowitem.model';
|
||||
import { WorkspaceitemSectionUploadObject } from '../../core/submission/models/workspaceitem-section-upload.model';
|
||||
@@ -44,6 +44,9 @@ import {
|
||||
UpdateSectionDataAction
|
||||
} from './submission-objects.actions';
|
||||
import { SubmissionObjectEntry } from './submission-objects.reducer';
|
||||
import { Item } from '../../core/shared/item.model';
|
||||
import { RemoteData } from '../../core/data/remote-data';
|
||||
import { getRemoteDataPayload, getSucceededRemoteData } from '../../core/shared/operators';
|
||||
|
||||
@Injectable()
|
||||
export class SubmissionObjectEffects {
|
||||
@@ -61,7 +64,12 @@ export class SubmissionObjectEffects {
|
||||
const sectionId = selfLink.substr(selfLink.lastIndexOf('/') + 1);
|
||||
const config = sectionDefinition._links.config ? (sectionDefinition._links.config.href || sectionDefinition._links.config) : '';
|
||||
const enabled = (sectionDefinition.mandatory) || (isNotEmpty(action.payload.sections) && action.payload.sections.hasOwnProperty(sectionId));
|
||||
const sectionData = (isNotUndefined(action.payload.sections) && isNotUndefined(action.payload.sections[sectionId])) ? action.payload.sections[sectionId] : Object.create(null);
|
||||
let sectionData;
|
||||
if (sectionDefinition.sectionType != SectionsType.SubmissionForm) {
|
||||
sectionData = (isNotUndefined(action.payload.sections) && isNotUndefined(action.payload.sections[sectionId])) ? action.payload.sections[sectionId] : Object.create(null);
|
||||
} else {
|
||||
sectionData = action.payload.item.metadata;
|
||||
}
|
||||
const sectionErrors = null;
|
||||
mappedActions.push(
|
||||
new InitSectionAction(
|
||||
@@ -99,6 +107,7 @@ export class SubmissionObjectEffects {
|
||||
action.payload.selfUrl,
|
||||
action.payload.submissionDefinition,
|
||||
action.payload.sections,
|
||||
action.payload.item,
|
||||
null
|
||||
)));
|
||||
|
||||
@@ -334,6 +343,7 @@ export class SubmissionObjectEffects {
|
||||
if (notify && !currentState.sections[sectionId].enabled) {
|
||||
this.submissionService.notifyNewSection(submissionId, sectionId, currentState.sections[sectionId].sectionType);
|
||||
}
|
||||
console.log(sectionId, sectionData);
|
||||
mappedActions.push(new UpdateSectionDataAction(submissionId, sectionId, sectionData, sectionErrors));
|
||||
}
|
||||
});
|
||||
|
@@ -46,6 +46,7 @@ import { RemoteDataError } from '../core/data/remote-data-error';
|
||||
import { createFailedRemoteDataObject$, createSuccessfulRemoteDataObject } from '../shared/testing/utils';
|
||||
import { RequestService } from '../core/data/request.service';
|
||||
import { SearchService } from '../core/shared/search/search.service';
|
||||
import { Item } from '../core/shared/item.model';
|
||||
|
||||
/**
|
||||
* A service that provides methods used in submission process.
|
||||
@@ -164,8 +165,9 @@ export class SubmissionService {
|
||||
selfUrl: string,
|
||||
submissionDefinition: SubmissionDefinitionsModel,
|
||||
sections: WorkspaceitemSectionsObject,
|
||||
item: Item,
|
||||
errors: SubmissionSectionError[]) {
|
||||
this.store.dispatch(new InitSubmissionFormAction(collectionId, submissionId, selfUrl, submissionDefinition, sections, errors));
|
||||
this.store.dispatch(new InitSubmissionFormAction(collectionId, submissionId, selfUrl, submissionDefinition, sections, item, errors));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -503,9 +505,10 @@ export class SubmissionService {
|
||||
submissionId: string,
|
||||
selfUrl: string,
|
||||
submissionDefinition: SubmissionDefinitionsModel,
|
||||
sections: WorkspaceitemSectionsObject
|
||||
sections: WorkspaceitemSectionsObject,
|
||||
item: Item
|
||||
) {
|
||||
this.store.dispatch(new ResetSubmissionFormAction(collectionId, submissionId, selfUrl, sections, submissionDefinition));
|
||||
this.store.dispatch(new ResetSubmissionFormAction(collectionId, submissionId, selfUrl, sections, submissionDefinition, item));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -3,6 +3,7 @@
|
||||
<ds-submission-form [collectionId]="collectionId"
|
||||
[selfUrl]="selfUrl"
|
||||
[submissionDefinition]="submissionDefinition"
|
||||
[item]="item"
|
||||
[submissionId]="submissionId"></ds-submission-form>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -10,6 +10,7 @@ import { NotificationsService } from '../../shared/notifications/notifications.s
|
||||
import { SubmissionService } from '../submission.service';
|
||||
import { SubmissionObject } from '../../core/submission/models/submission-object.model';
|
||||
import { Collection } from '../../core/shared/collection.model';
|
||||
import { Item } from '../../core/shared/item.model';
|
||||
|
||||
/**
|
||||
* This component allows to submit a new workspaceitem.
|
||||
@@ -26,6 +27,7 @@ export class SubmissionSubmitComponent implements OnDestroy, OnInit {
|
||||
* @type {string}
|
||||
*/
|
||||
public collectionId: string;
|
||||
public item: Item;
|
||||
|
||||
/**
|
||||
* The collection id input to create a new submission
|
||||
@@ -98,6 +100,7 @@ export class SubmissionSubmitComponent implements OnDestroy, OnInit {
|
||||
this.selfUrl = submissionObject._links.self.href;
|
||||
this.submissionDefinition = (submissionObject.submissionDefinition as SubmissionDefinitionsModel);
|
||||
this.submissionId = submissionObject.id;
|
||||
this.item = submissionObject.item as Item;
|
||||
this.changeDetectorRef.detectChanges();
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user