reordering authors

This commit is contained in:
lotte
2019-12-02 15:37:59 +01:00
parent 0048a97181
commit bc8e7d8fe6
16 changed files with 291 additions and 126 deletions

View File

@@ -75,6 +75,7 @@
}, },
"dependencies": { "dependencies": {
"@angular/animations": "^6.1.4", "@angular/animations": "^6.1.4",
"@angular/cdk": "^7.3.7",
"@angular/cli": "^6.1.5", "@angular/cli": "^6.1.5",
"@angular/common": "^6.1.4", "@angular/common": "^6.1.4",
"@angular/core": "^6.1.4", "@angular/core": "^6.1.4",

View File

@@ -70,5 +70,4 @@ export class EditRelationshipComponent implements OnChanges {
canUndo(): boolean { canUndo(): boolean {
return this.fieldUpdate.changeType >= 0; return this.fieldUpdate.changeType >= 0;
} }
} }

View File

@@ -20,7 +20,7 @@ import { Operation } from 'fast-json-patch';
import { ObjectCacheService } from '../cache/object-cache.service'; import { ObjectCacheService } from '../cache/object-cache.service';
import { DSpaceObject } from '../shared/dspace-object.model'; import { DSpaceObject } from '../shared/dspace-object.model';
import { NotificationsService } from '../../shared/notifications/notifications.service'; import { NotificationsService } from '../../shared/notifications/notifications.service';
import { configureRequest, getResponseFromEntry } from '../shared/operators'; import { configureRequest, getRemoteDataPayload, getResponseFromEntry, getSucceededRemoteData } from '../shared/operators';
import { ErrorResponse, RestResponse } from '../cache/response.models'; import { ErrorResponse, RestResponse } from '../cache/response.models';
import { NotificationOptions } from '../../shared/notifications/models/notification-options.model'; import { NotificationOptions } from '../../shared/notifications/models/notification-options.model';
import { DSpaceRESTv2Serializer } from '../dspace-rest-v2/dspace-rest-v2.serializer'; import { DSpaceRESTv2Serializer } from '../dspace-rest-v2/dspace-rest-v2.serializer';
@@ -228,8 +228,12 @@ export abstract class DataService<T extends CacheableObject> {
* @param {DSpaceObject} object The given object * @param {DSpaceObject} object The given object
*/ */
update(object: T): Observable<RemoteData<T>> { update(object: T): Observable<RemoteData<T>> {
const oldVersion$ = this.objectCache.getObjectBySelfLink(object.self); const oldVersion$ = this.findByHref(object.self);
return oldVersion$.pipe(take(1), mergeMap((oldVersion: T) => { return oldVersion$.pipe(
getSucceededRemoteData(),
getRemoteDataPayload(),
mergeMap((oldVersion: T) => {
console.log(oldVersion);
const operations = this.comparator.diff(oldVersion, object); const operations = this.comparator.diff(oldVersion, object);
if (isNotEmpty(operations)) { if (isNotEmpty(operations)) {
this.objectCache.addPatch(object.self, operations); this.objectCache.addPatch(object.self, operations);
@@ -237,7 +241,6 @@ export abstract class DataService<T extends CacheableObject> {
return this.findByHref(object.self); return this.findByHref(object.self);
} }
)); ));
} }
/** /**

View File

@@ -130,7 +130,7 @@ export class RelationshipService extends DataService<Relationship> {
private removeRelationshipItemsFromCache(item) { private removeRelationshipItemsFromCache(item) {
this.objectCache.remove(item.self); this.objectCache.remove(item.self);
this.requestService.removeByHrefSubstring(item.self); this.requestService.removeByHrefSubstring(item.uuid);
combineLatest( combineLatest(
this.objectCache.hasBySelfLinkObservable(item.self), this.objectCache.hasBySelfLinkObservable(item.self),
this.requestService.hasByHrefObservable(item.self) this.requestService.hasByHrefObservable(item.self)
@@ -327,7 +327,6 @@ export class RelationshipService extends DataService<Relationship> {
} }
return this.update(updatedRelationship); return this.update(updatedRelationship);
}), }),
// skipWhile((relationshipRD: RemoteData<Relationship>) => !relationshipRD.isSuccessful)
tap((relationshipRD: RemoteData<Relationship>) => { tap((relationshipRD: RemoteData<Relationship>) => {
if (relationshipRD.hasSucceeded) { if (relationshipRD.hasSucceeded) {
this.removeRelationshipItemsFromCache(item1); this.removeRelationshipItemsFromCache(item1);
@@ -337,4 +336,20 @@ export class RelationshipService extends DataService<Relationship> {
) )
} }
public updatePlace(relationship: Relationship, newIndex: number, left: boolean): Observable<RemoteData<Relationship>> {
let updatedRelationship;
if (left) {
updatedRelationship = Object.assign(new Relationship(), relationship, { leftPlace: newIndex });
} else {
updatedRelationship = Object.assign(new Relationship(), relationship, { rightPlace: newIndex });
}
return this.update(updatedRelationship).pipe(
tap((relationshipRD: RemoteData<Relationship>) => {
if (relationshipRD.hasSucceeded) {
this.removeRelationshipItemsFromCacheByRelationship(relationship.id);
}
})
);
}
} }

View File

@@ -1,6 +1,6 @@
<div class="d-flex"> <div class="d-flex">
<div class="person-thumbnail pr-2"> <div class="person-thumbnail pr-2">
<ds-thumbnail [thumbnail]="dso.getThumbnail() | async" [defaultImage]="'assets/images/orgunit-placeholder.svg'"></ds-thumbnail> <!-- <ds-thumbnail [thumbnail]="dso.getThumbnail() | async" [defaultImage]="'assets/images/orgunit-placeholder.svg'"></ds-thumbnail>-->
</div> </div>
<div class="flex-grow-1"> <div class="flex-grow-1">
<ds-org-unit-input-suggestions [suggestions]="allSuggestions" [(ngModel)]="selectedName" (clickSuggestion)="select($event)" <ds-org-unit-input-suggestions [suggestions]="allSuggestions" [(ngModel)]="selectedName" (clickSuggestion)="select($event)"

View File

@@ -1,6 +1,6 @@
<div class="d-flex"> <div class="d-flex">
<div class="person-thumbnail pr-2"> <div class="person-thumbnail pr-2">
<ds-thumbnail [thumbnail]="dso.getThumbnail() | async" [defaultImage]="'assets/images/person-placeholder.svg'"></ds-thumbnail> <!-- <ds-thumbnail [thumbnail]="dso.getThumbnail() | async" [defaultImage]="'assets/images/person-placeholder.svg'"></ds-thumbnail>-->
</div> </div>
<div class="flex-grow-1"> <div class="flex-grow-1">
<ds-person-input-suggestions [suggestions]="allSuggestions" [(ngModel)]="selectedName" (clickSuggestion)="select($event)" (submitSuggestion)="selectCustom($event)"></ds-person-input-suggestions> <ds-person-input-suggestions [suggestions]="allSuggestions" [(ngModel)]="selectedName" (clickSuggestion)="select($event)" (submitSuggestion)="selectCustom($event)"></ds-person-input-suggestions>

View File

@@ -53,16 +53,14 @@
<div *ngIf="hasRelationLookup" class="mt-3"> <div *ngIf="hasRelationLookup" class="mt-3">
<ul class="list-unstyled"> <ul class="list-unstyled" cdkDropList (cdkDropListDropped)="moveSelection($event)">
<li *ngFor="let value of ( selectedValues$ | async)"> <ds-existing-metadata-list-element cdkDrag [cdkDragData]="relationship" *ngFor="let relationship of relationships; trackBy: trackRelationship"
<button type="button" class="close float-left" aria-label="Close button" [relationship]="relationship"
(click)="removeSelection(value.selectedResult)"> [submissionItem]="item"
<span aria-hidden="true">&times;</span> [listId]="listId"
</button> [metadataFields]="model.metadataFields"
<span class="d-inline-block align-middle ml-1"> [relationshipOptions]="model.relationship">
<ds-metadata-representation-loader [mdRepresentation]="value.mdRep"></ds-metadata-representation-loader> </ds-existing-metadata-list-element>
</span>
</li>
</ul> </ul>
</div> </div>
</div> </div>

View File

@@ -6,7 +6,8 @@ import {
EventEmitter, EventEmitter,
Input, Input,
NgZone, NgZone,
OnChanges, OnDestroy, OnChanges,
OnDestroy,
OnInit, OnInit,
Output, Output,
QueryList, QueryList,
@@ -49,7 +50,6 @@ import {
DynamicNGBootstrapTimePickerComponent DynamicNGBootstrapTimePickerComponent
} from '@ng-dynamic-forms/ui-ng-bootstrap'; } from '@ng-dynamic-forms/ui-ng-bootstrap';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { MetadataRepresentation } from '../../../../core/shared/metadata-representation/metadata-representation.model';
import { DYNAMIC_FORM_CONTROL_TYPE_TYPEAHEAD } from './models/typeahead/dynamic-typeahead.model'; import { DYNAMIC_FORM_CONTROL_TYPE_TYPEAHEAD } from './models/typeahead/dynamic-typeahead.model';
import { DYNAMIC_FORM_CONTROL_TYPE_SCROLLABLE_DROPDOWN } from './models/scrollable-dropdown/dynamic-scrollable-dropdown.model'; import { DYNAMIC_FORM_CONTROL_TYPE_SCROLLABLE_DROPDOWN } from './models/scrollable-dropdown/dynamic-scrollable-dropdown.model';
@@ -71,9 +71,8 @@ import { DsDynamicFormArrayComponent } from './models/array-group/dynamic-form-a
import { DsDynamicRelationGroupComponent } from './models/relation-group/dynamic-relation-group.components'; import { DsDynamicRelationGroupComponent } from './models/relation-group/dynamic-relation-group.components';
import { DYNAMIC_FORM_CONTROL_TYPE_RELATION_GROUP } from './models/relation-group/dynamic-relation-group.model'; import { DYNAMIC_FORM_CONTROL_TYPE_RELATION_GROUP } from './models/relation-group/dynamic-relation-group.model';
import { DsDatePickerInlineComponent } from './models/date-picker-inline/dynamic-date-picker-inline.component'; import { DsDatePickerInlineComponent } from './models/date-picker-inline/dynamic-date-picker-inline.component';
import { map, switchMap, take, tap } from 'rxjs/operators'; import { map, startWith, switchMap } from 'rxjs/operators';
import { combineLatest as observableCombineLatest, Observable, Subscription } from 'rxjs'; import { combineLatest as observableCombineLatest, Observable, of as observableOf, Subscription } from 'rxjs';
import { SelectableListState } from '../../../object-list/selectable-list/selectable-list.reducer';
import { SearchResult } from '../../../search/search-result.model'; import { SearchResult } from '../../../search/search-result.model';
import { DSpaceObject } from '../../../../core/shared/dspace-object.model'; import { DSpaceObject } from '../../../../core/shared/dspace-object.model';
import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
@@ -82,25 +81,18 @@ import { SelectableListService } from '../../../object-list/selectable-list/sele
import { DsDynamicDisabledComponent } from './models/disabled/dynamic-disabled.component'; import { DsDynamicDisabledComponent } from './models/disabled/dynamic-disabled.component';
import { DYNAMIC_FORM_CONTROL_TYPE_DISABLED } from './models/disabled/dynamic-disabled.model'; import { DYNAMIC_FORM_CONTROL_TYPE_DISABLED } from './models/disabled/dynamic-disabled.model';
import { DsDynamicLookupRelationModalComponent } from './relation-lookup-modal/dynamic-lookup-relation-modal.component'; import { DsDynamicLookupRelationModalComponent } from './relation-lookup-modal/dynamic-lookup-relation-modal.component';
import { import { getAllSucceededRemoteData, getRemoteDataPayload, getSucceededRemoteData } from '../../../../core/shared/operators';
getAllSucceededRemoteData,
getRemoteDataPayload,
getSucceededRemoteData,
obsLog
} from '../../../../core/shared/operators';
import { RemoteData } from '../../../../core/data/remote-data'; import { RemoteData } from '../../../../core/data/remote-data';
import { Item } from '../../../../core/shared/item.model'; import { Item } from '../../../../core/shared/item.model';
import { ItemDataService } from '../../../../core/data/item-data.service'; import { ItemDataService } from '../../../../core/data/item-data.service';
import { RemoveRelationshipAction } from './relation-lookup-modal/relationship.actions';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppState } from '../../../../app.reducer'; import { AppState } from '../../../../app.reducer';
import { SubmissionObjectDataService } from '../../../../core/submission/submission-object-data.service'; import { SubmissionObjectDataService } from '../../../../core/submission/submission-object-data.service';
import { SubmissionObject } from '../../../../core/submission/models/submission-object.model'; import { SubmissionObject } from '../../../../core/submission/models/submission-object.model';
import { PaginatedList } from '../../../../core/data/paginated-list'; import { PaginatedList } from '../../../../core/data/paginated-list';
import { ItemSearchResult } from '../../../object-collection/shared/item-search-result.model'; import { ItemSearchResult } from '../../../object-collection/shared/item-search-result.model';
import { ItemMetadataRepresentation } from '../../../../core/shared/metadata-representation/item/item-metadata-representation.model'; import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
import { MetadataValue } from '../../../../core/shared/metadata.models'; import { Relationship } from '../../../../core/shared/item-relationships/relationship.model';
import * as uuidv4 from 'uuid/v4';
export function dsDynamicFormControlMapFn(model: DynamicFormControlModel): Type<DynamicFormControl> | null { export function dsDynamicFormControlMapFn(model: DynamicFormControlModel): Type<DynamicFormControl> | null {
switch (model.type) { switch (model.type) {
@@ -184,16 +176,15 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo
@Input() hasErrorMessaging = false; @Input() hasErrorMessaging = false;
@Input() layout = null as DynamicFormLayout; @Input() layout = null as DynamicFormLayout;
@Input() model: any; @Input() model: any;
relationships$: Observable<Array<SearchResult<Item>>>; relationships$: Observable<Relationship[]>;
relationships: Relationship[];
hasRelationLookup: boolean; hasRelationLookup: boolean;
modalRef: NgbModalRef; modalRef: NgbModalRef;
item: Item; item: Item;
listId: string; listId: string;
searchConfig: string; searchConfig: string;
selectedValues$: Observable<Array<{
selectedResult: SearchResult<Item>,
mdRep: MetadataRepresentation
}>>;
/** /**
* List of subscriptions to unsubscribe from * List of subscriptions to unsubscribe from
*/ */
@@ -238,38 +229,54 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo
.findById(this.model.submissionId).pipe( .findById(this.model.submissionId).pipe(
getAllSucceededRemoteData(), getAllSucceededRemoteData(),
getRemoteDataPayload(), getRemoteDataPayload(),
switchMap((submissionObject: SubmissionObject) => (submissionObject.item as Observable<RemoteData<Item>>).pipe(getAllSucceededRemoteData(), getRemoteDataPayload()))); switchMap((submissionObject: SubmissionObject) => (submissionObject.item as Observable<RemoteData<Item>>)
.pipe(
getAllSucceededRemoteData(),
getRemoteDataPayload()
)
)
);
this.subs.push(item$.subscribe((item) => this.item = item)); this.subs.push(item$.subscribe((item) => this.item = item));
this.relationships$ = item$.pipe(
switchMap((item) => this.relationService.getItemRelationshipsByLabel(item, this.model.relationship.relationshipType)
.pipe(
getAllSucceededRemoteData(),
getRemoteDataPayload(),
map((relationshipList: PaginatedList<Relationship>) => relationshipList.page),
startWith([]),
switchMap((relationships: Relationship[]) =>
observableCombineLatest(
relationships.map((relationship: Relationship) =>
relationship.leftItem.pipe(
getSucceededRemoteData(),
getRemoteDataPayload(),
map((item: Item) => {
return { relationship, left: item.uuid === this.item.uuid }
}),
)
))),
map((relationships: { relationship: Relationship, left: boolean }[]) =>
relationships
.sort((
a: { relationship: Relationship, left: boolean },
b: { relationship: Relationship, left: boolean }
) => {
const placeA: number = a.left ? a.relationship.leftPlace : a.relationship.rightPlace;
const placeB: number = b.left ? b.relationship.leftPlace : b.relationship.rightPlace;
return Math.sign(placeA - placeB);
})
.map((relationship) => relationship.relationship)
)
)
)
);
this.relationships$.subscribe((rels) => this.relationships = rels);
this.relationService.getRelatedItemsByLabel(this.item, this.model.relationship.relationshipType).pipe( this.relationService.getRelatedItemsByLabel(this.item, this.model.relationship.relationshipType).pipe(
map((items: RemoteData<PaginatedList<Item>>) => items.payload.page.map((item) => Object.assign(new ItemSearchResult(), { indexableObject: item }))), map((items: RemoteData<PaginatedList<Item>>) => items.payload.page.map((item) => Object.assign(new ItemSearchResult(), { indexableObject: item }))),
).subscribe((relatedItems: Array<SearchResult<Item>>) => this.selectableListService.select(this.listId, relatedItems)); ).subscribe((relatedItems: Array<SearchResult<Item>>) => this.selectableListService.select(this.listId, relatedItems));
this.relationships$ = this.selectableListService.getSelectableList(this.listId).pipe(
map((listState: SelectableListState) => hasValue(listState) && hasValue(listState.selection) ? listState.selection : []),
) as Observable<Array<SearchResult<Item>>>;
this.selectedValues$ =
observableCombineLatest(item$, this.relationships$).pipe(
map(([item, relatedItems]: [Item, Array<SearchResult<DSpaceObject>>]) => {
return relatedItems
.map((element: SearchResult<Item>) => {
const relationMD: MetadataValue = item.firstMetadata(this.model.relationship.metadataField, { value: element.indexableObject.uuid });
if (hasValue(relationMD)) {
const metadataRepresentationMD: MetadataValue = item.firstMetadata(this.model.metadataFields, { authority: relationMD.authority });
return {
selectedResult: element,
mdRep: Object.assign(
new ItemMetadataRepresentation(metadataRepresentationMD),
element.indexableObject
)
};
}
}).filter(hasValue)
}
)
);
} }
} }
@@ -327,12 +334,39 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo
modalComp.item = this.item; modalComp.item = this.item;
} }
removeSelection(object: SearchResult<Item>) {
this.selectableListService.deselectSingle(this.listId, object);
this.store.dispatch(new RemoveRelationshipAction(this.item, object.indexableObject, this.model.relationship.relationshipType))
// this.zone.runOutsideAngular( moveSelection(event: CdkDragDrop<Relationship>) {
// () => ); moveItemInArray(this.relationships, event.previousIndex, event.currentIndex);
this.zone.runOutsideAngular(() => {
observableCombineLatest(
this.relationships.map((relationship: Relationship, index: number) =>
relationship.leftItem.pipe(
getSucceededRemoteData(),
getRemoteDataPayload(),
map((item: Item) => {
const left: boolean = item.uuid === this.item.uuid;
if (left) {
return { relationship, left: item.uuid === this.item.uuid, oldIndex: relationship.leftPlace, newIndex: index }
} else {
return { relationship, left: item.uuid === this.item.uuid, oldIndex: relationship.rightPlace, newIndex: index }
}
}),
)
)
).pipe(
switchMap((relationships: { relationship: Relationship, left: boolean, oldIndex: number, newIndex: number }[]) =>
observableCombineLatest(relationships.map((rel: { relationship: Relationship, left: boolean, oldIndex: number, newIndex: number }) => {
if (rel.oldIndex !== rel.newIndex) {
return this.relationshipService.updatePlace(rel.relationship, rel.newIndex, rel.left);
} else {
observableOf(undefined);
}
}
)
)
)
).subscribe();
})
} }
/** /**
@@ -343,4 +377,11 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo
.filter((sub) => hasValue(sub)) .filter((sub) => hasValue(sub))
.forEach((sub) => sub.unsubscribe()); .forEach((sub) => sub.unsubscribe());
} }
/**
* Prevent unnecessary rerendering so fields don't lose focus
*/
trackRelationship(index, relationship: Relationship) {
return hasValue(relationship) ? relationship.id : undefined;
}
} }

View File

@@ -0,0 +1,11 @@
<li *ngIf="metadataRepresentation$ | async">
<button type="button" class="close float-left" aria-label="Move button" cdkDragHandle>
<i aria-hidden="true" class="fas fa-arrows-alt fa-xs"></i>
</button>
<button type="button" class="close float-left" aria-label="Close button" (click)="removeSelection()">
<span aria-hidden="true">&times;</span>
</button>
<span class="d-inline-block align-middle ml-1">
<ds-metadata-representation-loader [mdRepresentation]="metadataRepresentation$ | async"></ds-metadata-representation-loader>
</span>
</li>

View File

@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ExistingMetadataListElementComponent } from './existing-metadata-list-element.component';
describe('ExistingMetadataListElementComponent', () => {
let component: ExistingMetadataListElementComponent;
let fixture: ComponentFixture<ExistingMetadataListElementComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ExistingMetadataListElementComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ExistingMetadataListElementComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,82 @@
import { Component, Input, OnChanges, OnInit } from '@angular/core';
import { Item } from '../../../../../core/shared/item.model';
import { getRemoteDataPayload, getSucceededRemoteData } from '../../../../../core/shared/operators';
import { hasValue, isNotEmpty } from '../../../../empty.util';
import { filter, map, take } from 'rxjs/operators';
import { Relationship } from '../../../../../core/shared/item-relationships/relationship.model';
import { combineLatest as observableCombineLatest } from 'rxjs';
import { MetadataValue } from '../../../../../core/shared/metadata.models';
import { ItemMetadataRepresentation } from '../../../../../core/shared/metadata-representation/item/item-metadata-representation.model';
import { RelationshipOptions } from '../../models/relationship-options.model';
import { RemoveRelationshipAction } from '../relation-lookup-modal/relationship.actions';
import { SelectableListService } from '../../../../object-list/selectable-list/selectable-list.service';
import { Store } from '@ngrx/store';
import { AppState } from '../../../../../app.reducer';
import { ItemSearchResult } from '../../../../object-collection/shared/item-search-result.model';
@Component({
selector: 'ds-existing-metadata-list-element',
templateUrl: './existing-metadata-list-element.component.html',
styleUrls: ['./existing-metadata-list-element.component.scss']
})
export class ExistingMetadataListElementComponent implements OnChanges {
@Input() listId: string;
@Input() submissionItem: Item;
@Input() relationship: Relationship;
@Input() metadataFields: string[];
@Input() relationshipOptions: RelationshipOptions;
metadataRepresentation$;
relatedItem$;
constructor(
private selectableListService: SelectableListService,
private store: Store<AppState>
) {
}
ngOnChanges() {
const leftItem$ = this.relationship.leftItem.pipe(
getSucceededRemoteData(),
getRemoteDataPayload(),
filter((item: Item) => hasValue(item) && isNotEmpty(item.uuid))
);
const rightItem$ = this.relationship.rightItem.pipe(
getSucceededRemoteData(),
getRemoteDataPayload(),
filter((item: Item) => hasValue(item) && isNotEmpty(item.uuid))
);
this.relatedItem$ = observableCombineLatest(
leftItem$,
rightItem$,
).pipe(
map((items: Item[]) =>
items.find((item) => item.uuid !== this.submissionItem.uuid)
)
);
this.metadataRepresentation$ = this.relatedItem$.pipe(
map((relatedItem: Item) => {
console.log(relatedItem);
const relationMD: MetadataValue = this.submissionItem.firstMetadata(this.relationshipOptions.metadataField, { value: relatedItem.uuid });
console.log(relationMD);
if (hasValue(relationMD)) {
const metadataRepresentationMD: MetadataValue = this.submissionItem.firstMetadata(this.metadataFields, { authority: relationMD.authority });
return Object.assign(
new ItemMetadataRepresentation(metadataRepresentationMD),
relatedItem
)
}
}
)
);
}
removeSelection() {
this.relatedItem$.pipe(take(1)).subscribe((relatedItem: Item) => {
this.selectableListService.deselectSingle(this.listId, Object.assign(new ItemSearchResult(), { indexableObject: relatedItem }));
this.store.dispatch(new RemoveRelationshipAction(this.submissionItem, relatedItem, this.relationshipOptions.relationshipType))
})
}
}

View File

@@ -2,7 +2,7 @@ import { Component, NgZone, OnDestroy, OnInit } from '@angular/core';
import { combineLatest, Observable, Subscription } from 'rxjs'; import { combineLatest, Observable, Subscription } from 'rxjs';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
import { hasValue } from '../../../../empty.util'; import { hasValue } from '../../../../empty.util';
import { map, skip, switchMap, take } from 'rxjs/operators'; import { map, skip, take } from 'rxjs/operators';
import { SEARCH_CONFIG_SERVICE } from '../../../../../+my-dspace-page/my-dspace-page.component'; import { SEARCH_CONFIG_SERVICE } from '../../../../../+my-dspace-page/my-dspace-page.component';
import { SearchConfigurationService } from '../../../../../core/shared/search/search-configuration.service'; import { SearchConfigurationService } from '../../../../../core/shared/search/search-configuration.service';
import { SelectableListService } from '../../../../object-list/selectable-list/selectable-list.service'; import { SelectableListService } from '../../../../object-list/selectable-list/selectable-list.service';
@@ -11,15 +11,12 @@ import { ListableObject } from '../../../../object-collection/shared/listable-ob
import { RelationshipOptions } from '../../models/relationship-options.model'; import { RelationshipOptions } from '../../models/relationship-options.model';
import { SearchResult } from '../../../../search/search-result.model'; import { SearchResult } from '../../../../search/search-result.model';
import { Item } from '../../../../../core/shared/item.model'; import { Item } from '../../../../../core/shared/item.model';
import { getRemoteDataPayload, getSucceededRemoteData } from '../../../../../core/shared/operators';
import { AddRelationshipAction, RemoveRelationshipAction, UpdateRelationshipAction } from './relationship.actions'; import { AddRelationshipAction, RemoveRelationshipAction, UpdateRelationshipAction } from './relationship.actions';
import { RelationshipService } from '../../../../../core/data/relationship.service'; import { RelationshipService } from '../../../../../core/data/relationship.service';
import { RelationshipTypeService } from '../../../../../core/data/relationship-type.service'; import { RelationshipTypeService } from '../../../../../core/data/relationship-type.service';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppState } from '../../../../../app.reducer'; import { AppState } from '../../../../../app.reducer';
import { Context } from '../../../../../core/shared/context.model'; import { Context } from '../../../../../core/shared/context.model';
import { Relationship } from '../../../../../core/shared/item-relationships/relationship.model';
import { MetadataValue } from '../../../../../core/shared/metadata.models';
@Component({ @Component({
selector: 'ds-dynamic-lookup-relation-modal', selector: 'ds-dynamic-lookup-relation-modal',
@@ -66,8 +63,6 @@ export class DsDynamicLookupRelationModalComponent implements OnInit, OnDestroy
if (this.relationshipOptions.nameVariants) { if (this.relationshipOptions.nameVariants) {
this.context = Context.SubmissionModal; this.context = Context.SubmissionModal;
} }
// this.setExistingNameVariants();
} }
close() { close() {
@@ -117,37 +112,6 @@ export class DsDynamicLookupRelationModalComponent implements OnInit, OnDestroy
); );
} }
private setExistingNameVariants() {
const virtualMDs: MetadataValue[] = this.item.allMetadata(this.metadataFields).filter((mdValue) => mdValue.isVirtual);
const relatedItemPairs$: Observable<Array<[Item, Item]>> =
combineLatest(virtualMDs.map((md: MetadataValue) => this.relationshipService.findById(md.virtualValue).pipe(getSucceededRemoteData(), getRemoteDataPayload())))
.pipe(
switchMap((relationships: Relationship[]) => combineLatest(relationships.map((relationship: Relationship) =>
combineLatest(
relationship.leftItem.pipe(getSucceededRemoteData(), getRemoteDataPayload()),
relationship.rightItem.pipe(getSucceededRemoteData(), getRemoteDataPayload())
))
)
)
);
const relatedItems$: Observable<Item[]> = relatedItemPairs$.pipe(
map(([relatedItemPairs,]: [Array<[Item, Item]>]) => relatedItemPairs.map(([left, right]: [Item, Item]) => left.uuid === this.item.uuid ? left : right))
);
relatedItems$.pipe(take(1)).subscribe((relatedItems) => {
let index = 0;
virtualMDs.forEach(
(md: MetadataValue) => {
this.relationshipService.setNameVariant(this.listId, relatedItems[index].uuid, md.value);
index++;
}
);
}
)
}
ngOnDestroy() { ngOnDestroy() {
Object.values(this.subMap).forEach((subscription) => subscription.unsubscribe()); Object.values(this.subMap).forEach((subscription) => subscription.unsubscribe());
} }

View File

@@ -174,6 +174,8 @@ import { SidebarFilterComponent } from './sidebar/filter/sidebar-filter.componen
import { SidebarFilterSelectedOptionComponent } from './sidebar/filter/sidebar-filter-selected-option.component'; import { SidebarFilterSelectedOptionComponent } from './sidebar/filter/sidebar-filter-selected-option.component';
import { MetadataRepresentationListComponent } from '../+item-page/simple/metadata-representation-list/metadata-representation-list.component'; import { MetadataRepresentationListComponent } from '../+item-page/simple/metadata-representation-list/metadata-representation-list.component';
import { SelectableListItemControlComponent } from './object-collection/shared/selectable-list-item-control/selectable-list-item-control.component'; import { SelectableListItemControlComponent } from './object-collection/shared/selectable-list-item-control/selectable-list-item-control.component';
import { DragDropModule } from '@angular/cdk/drag-drop';
import { ExistingMetadataListElementComponent } from './form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component';
const MODULES = [ const MODULES = [
// Do NOT include UniversalModule, HttpModule, or JsonpModule here // Do NOT include UniversalModule, HttpModule, or JsonpModule here
@@ -196,6 +198,7 @@ const MODULES = [
MomentModule, MomentModule,
TextMaskModule, TextMaskModule,
MenuModule, MenuModule,
DragDropModule
]; ];
const ROOT_MODULES = [ const ROOT_MODULES = [
@@ -330,7 +333,8 @@ const COMPONENTS = [
ItemSelectComponent, ItemSelectComponent,
CollectionSelectComponent, CollectionSelectComponent,
MetadataRepresentationLoaderComponent, MetadataRepresentationLoaderComponent,
SelectableListItemControlComponent SelectableListItemControlComponent,
ExistingMetadataListElementComponent
]; ];
const ENTRY_COMPONENTS = [ const ENTRY_COMPONENTS = [
@@ -432,7 +436,8 @@ const DIRECTIVES = [
...DIRECTIVES, ...DIRECTIVES,
...ENTRY_COMPONENTS, ...ENTRY_COMPONENTS,
...SHARED_ITEM_PAGE_COMPONENTS, ...SHARED_ITEM_PAGE_COMPONENTS,
PublicationSearchResultListElementComponent PublicationSearchResultListElementComponent,
ExistingMetadataListElementComponent
], ],
providers: [ providers: [
...PROVIDERS ...PROVIDERS

View File

@@ -197,21 +197,23 @@ export class SubmissionFormCollectionComponent implements OnChanges, OnInit {
find((communities: RemoteData<PaginatedList<Community>>) => isNotEmpty(communities.payload)), find((communities: RemoteData<PaginatedList<Community>>) => isNotEmpty(communities.payload)),
mergeMap((communities: RemoteData<PaginatedList<Community>>) => communities.payload.page)); mergeMap((communities: RemoteData<PaginatedList<Community>>) => communities.payload.page));
const listCollection$ = communities$.pipe( const listCollection$ = observableOf([]);
flatMap((communityData: Community) => {
return this.collectionDataService.getAuthorizedCollectionByCommunity(communityData.uuid, findOptions).pipe( // const listCollection$ = communities$.pipe(
find((collections: RemoteData<PaginatedList<Collection>>) => !collections.isResponsePending && collections.hasSucceeded), // flatMap((communityData: Community) => {
mergeMap((collections: RemoteData<PaginatedList<Collection>>) => collections.payload.page), // return this.collectionDataService.getAuthorizedCollectionByCommunity(communityData.uuid, findOptions).pipe(
filter((collectionData: Collection) => isNotEmpty(collectionData)), // find((collections: RemoteData<PaginatedList<Collection>>) => !collections.isResponsePending && collections.hasSucceeded),
map((collectionData: Collection) => ({ // mergeMap((collections: RemoteData<PaginatedList<Collection>>) => collections.payload.page),
communities: [{ id: communityData.id, name: communityData.name }], // filter((collectionData: Collection) => isNotEmpty(collectionData)),
collection: { id: collectionData.id, name: collectionData.name } // map((collectionData: Collection) => ({
})) // communities: [{ id: communityData.id, name: communityData.name }],
); // collection: { id: collectionData.id, name: collectionData.name }
}), // }))
reduce((acc: any, value: any) => [...acc, ...value], []), // );
startWith([]) // }),
); // reduce((acc: any, value: any) => [...acc, ...value], []),
// startWith([])
// );
const searchTerm$ = this.searchField.valueChanges.pipe( const searchTerm$ = this.searchField.valueChanges.pipe(
debounceTime(200), debounceTime(200),
@@ -227,8 +229,8 @@ export class SubmissionFormCollectionComponent implements OnChanges, OnInit {
} else { } else {
return listCollection.filter((v) => v.collection.name.toLowerCase().indexOf(searchTerm.toLowerCase()) > -1).slice(0, 5); return listCollection.filter((v) => v.collection.name.toLowerCase().indexOf(searchTerm.toLowerCase()) > -1).slice(0, 5);
} }
}) })
); );
} }
} }
} }

View File

@@ -35,6 +35,15 @@
dependencies: dependencies:
tslib "^1.9.0" tslib "^1.9.0"
"@angular/cdk@^7.3.7":
version "7.3.7"
resolved "https://registry.yarnpkg.com/@angular/cdk/-/cdk-7.3.7.tgz#ce1ad53ba04beb9c8e950acc5691ea0143753764"
integrity sha512-xbXxhHHKGkVuW6K7pzPmvpJXIwpl0ykBnvA2g+/7Sgy5Pd35wCC+UtHD9RYczDM/mkygNxMQtagyCErwFnDtQA==
dependencies:
tslib "^1.7.1"
optionalDependencies:
parse5 "^5.0.0"
"@angular/cli@^6.1.5": "@angular/cli@^6.1.5":
version "6.1.5" version "6.1.5"
resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-6.1.5.tgz#312c062631285ff06fd07ecde8afe22cdef5a0e1" resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-6.1.5.tgz#312c062631285ff06fd07ecde8afe22cdef5a0e1"
@@ -7775,6 +7784,11 @@ parse-passwd@^1.0.0:
resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6"
integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY= integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=
parse5@^5.0.0:
version "5.1.1"
resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178"
integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==
parseqs@0.0.5: parseqs@0.0.5:
version "0.0.5" version "0.0.5"
resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.5.tgz#d5208a3738e46766e291ba2ea173684921a8b89d" resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.5.tgz#d5208a3738e46766e291ba2ea173684921a8b89d"
@@ -10838,6 +10852,11 @@ tsickle@^0.32.1:
source-map "^0.6.0" source-map "^0.6.0"
source-map-support "^0.5.0" source-map-support "^0.5.0"
tslib@^1.7.1:
version "1.10.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a"
integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==
tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0: tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0:
version "1.9.3" version "1.9.3"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286"