From bc8e7d8fe6f7dd82ddc2dd03eca67ebf7b279f7d Mon Sep 17 00:00:00 2001 From: lotte Date: Mon, 2 Dec 2019 15:37:59 +0100 Subject: [PATCH 01/14] reordering authors --- package.json | 1 + .../edit-relationship.component.ts | 1 - src/app/core/data/data.service.ts | 11 +- src/app/core/data/relationship.service.ts | 19 ++- ...ult-list-submission-element.component.html | 2 +- ...ult-list-submission-element.component.html | 2 +- ...amic-form-control-container.component.html | 18 +-- ...ynamic-form-control-container.component.ts | 143 +++++++++++------- ...sting-metadata-list-element.component.html | 11 ++ ...sting-metadata-list-element.component.scss | 0 ...ng-metadata-list-element.component.spec.ts | 25 +++ ...xisting-metadata-list-element.component.ts | 82 ++++++++++ ...dynamic-lookup-relation-modal.component.ts | 38 +---- src/app/shared/shared.module.ts | 9 +- .../submission-form-collection.component.ts | 36 ++--- yarn.lock | 19 +++ 16 files changed, 291 insertions(+), 126 deletions(-) create mode 100644 src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.html create mode 100644 src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.scss create mode 100644 src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.spec.ts create mode 100644 src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.ts diff --git a/package.json b/package.json index 2a247f13ad..a664c8daa4 100644 --- a/package.json +++ b/package.json @@ -75,6 +75,7 @@ }, "dependencies": { "@angular/animations": "^6.1.4", + "@angular/cdk": "^7.3.7", "@angular/cli": "^6.1.5", "@angular/common": "^6.1.4", "@angular/core": "^6.1.4", diff --git a/src/app/+item-page/edit-item-page/item-relationships/edit-relationship/edit-relationship.component.ts b/src/app/+item-page/edit-item-page/item-relationships/edit-relationship/edit-relationship.component.ts index 302ebf68a7..ee9d2cda27 100644 --- a/src/app/+item-page/edit-item-page/item-relationships/edit-relationship/edit-relationship.component.ts +++ b/src/app/+item-page/edit-item-page/item-relationships/edit-relationship/edit-relationship.component.ts @@ -70,5 +70,4 @@ export class EditRelationshipComponent implements OnChanges { canUndo(): boolean { return this.fieldUpdate.changeType >= 0; } - } diff --git a/src/app/core/data/data.service.ts b/src/app/core/data/data.service.ts index 906249095e..b8e511524d 100644 --- a/src/app/core/data/data.service.ts +++ b/src/app/core/data/data.service.ts @@ -20,7 +20,7 @@ import { Operation } from 'fast-json-patch'; import { ObjectCacheService } from '../cache/object-cache.service'; import { DSpaceObject } from '../shared/dspace-object.model'; 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 { NotificationOptions } from '../../shared/notifications/models/notification-options.model'; import { DSpaceRESTv2Serializer } from '../dspace-rest-v2/dspace-rest-v2.serializer'; @@ -228,8 +228,12 @@ export abstract class DataService { * @param {DSpaceObject} object The given object */ update(object: T): Observable> { - const oldVersion$ = this.objectCache.getObjectBySelfLink(object.self); - return oldVersion$.pipe(take(1), mergeMap((oldVersion: T) => { + const oldVersion$ = this.findByHref(object.self); + return oldVersion$.pipe( + getSucceededRemoteData(), + getRemoteDataPayload(), + mergeMap((oldVersion: T) => { + console.log(oldVersion); const operations = this.comparator.diff(oldVersion, object); if (isNotEmpty(operations)) { this.objectCache.addPatch(object.self, operations); @@ -237,7 +241,6 @@ export abstract class DataService { return this.findByHref(object.self); } )); - } /** diff --git a/src/app/core/data/relationship.service.ts b/src/app/core/data/relationship.service.ts index 70b59b614e..fb9e75bd4d 100644 --- a/src/app/core/data/relationship.service.ts +++ b/src/app/core/data/relationship.service.ts @@ -130,7 +130,7 @@ export class RelationshipService extends DataService { private removeRelationshipItemsFromCache(item) { this.objectCache.remove(item.self); - this.requestService.removeByHrefSubstring(item.self); + this.requestService.removeByHrefSubstring(item.uuid); combineLatest( this.objectCache.hasBySelfLinkObservable(item.self), this.requestService.hasByHrefObservable(item.self) @@ -327,7 +327,6 @@ export class RelationshipService extends DataService { } return this.update(updatedRelationship); }), - // skipWhile((relationshipRD: RemoteData) => !relationshipRD.isSuccessful) tap((relationshipRD: RemoteData) => { if (relationshipRD.hasSucceeded) { this.removeRelationshipItemsFromCache(item1); @@ -337,4 +336,20 @@ export class RelationshipService extends DataService { ) } + public updatePlace(relationship: Relationship, newIndex: number, left: boolean): Observable> { + 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) => { + if (relationshipRD.hasSucceeded) { + this.removeRelationshipItemsFromCacheByRelationship(relationship.id); + } + }) + ); + } + } diff --git a/src/app/entity-groups/research-entities/submission/item-list-elements/org-unit/org-unit-search-result-list-submission-element.component.html b/src/app/entity-groups/research-entities/submission/item-list-elements/org-unit/org-unit-search-result-list-submission-element.component.html index b0fa714371..61bcbc9a4f 100644 --- a/src/app/entity-groups/research-entities/submission/item-list-elements/org-unit/org-unit-search-result-list-submission-element.component.html +++ b/src/app/entity-groups/research-entities/submission/item-list-elements/org-unit/org-unit-search-result-list-submission-element.component.html @@ -1,6 +1,6 @@
- +
- +
diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html index 144848b478..64f8315575 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html @@ -53,16 +53,14 @@
-
    -
  • - - - - -
  • +
      + +
diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts index b78385dc62..f34287fd48 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts @@ -6,7 +6,8 @@ import { EventEmitter, Input, NgZone, - OnChanges, OnDestroy, + OnChanges, + OnDestroy, OnInit, Output, QueryList, @@ -49,7 +50,6 @@ import { DynamicNGBootstrapTimePickerComponent } from '@ng-dynamic-forms/ui-ng-bootstrap'; 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_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 { 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 { map, switchMap, take, tap } from 'rxjs/operators'; -import { combineLatest as observableCombineLatest, Observable, Subscription } from 'rxjs'; -import { SelectableListState } from '../../../object-list/selectable-list/selectable-list.reducer'; +import { map, startWith, switchMap } from 'rxjs/operators'; +import { combineLatest as observableCombineLatest, Observable, of as observableOf, Subscription } from 'rxjs'; import { SearchResult } from '../../../search/search-result.model'; import { DSpaceObject } from '../../../../core/shared/dspace-object.model'; 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 { DYNAMIC_FORM_CONTROL_TYPE_DISABLED } from './models/disabled/dynamic-disabled.model'; import { DsDynamicLookupRelationModalComponent } from './relation-lookup-modal/dynamic-lookup-relation-modal.component'; -import { - getAllSucceededRemoteData, - getRemoteDataPayload, - getSucceededRemoteData, - obsLog -} from '../../../../core/shared/operators'; +import { getAllSucceededRemoteData, getRemoteDataPayload, getSucceededRemoteData } from '../../../../core/shared/operators'; import { RemoteData } from '../../../../core/data/remote-data'; import { Item } from '../../../../core/shared/item.model'; import { ItemDataService } from '../../../../core/data/item-data.service'; -import { RemoveRelationshipAction } from './relation-lookup-modal/relationship.actions'; import { Store } from '@ngrx/store'; import { AppState } from '../../../../app.reducer'; import { SubmissionObjectDataService } from '../../../../core/submission/submission-object-data.service'; import { SubmissionObject } from '../../../../core/submission/models/submission-object.model'; import { PaginatedList } from '../../../../core/data/paginated-list'; import { ItemSearchResult } from '../../../object-collection/shared/item-search-result.model'; -import { ItemMetadataRepresentation } from '../../../../core/shared/metadata-representation/item/item-metadata-representation.model'; -import { MetadataValue } from '../../../../core/shared/metadata.models'; -import * as uuidv4 from 'uuid/v4'; +import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop'; +import { Relationship } from '../../../../core/shared/item-relationships/relationship.model'; export function dsDynamicFormControlMapFn(model: DynamicFormControlModel): Type | null { switch (model.type) { @@ -184,16 +176,15 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo @Input() hasErrorMessaging = false; @Input() layout = null as DynamicFormLayout; @Input() model: any; - relationships$: Observable>>; + relationships$: Observable; + relationships: Relationship[]; hasRelationLookup: boolean; modalRef: NgbModalRef; item: Item; listId: string; searchConfig: string; - selectedValues$: Observable, - mdRep: MetadataRepresentation - }>>; + + /** * List of subscriptions to unsubscribe from */ @@ -238,38 +229,54 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo .findById(this.model.submissionId).pipe( getAllSucceededRemoteData(), getRemoteDataPayload(), - switchMap((submissionObject: SubmissionObject) => (submissionObject.item as Observable>).pipe(getAllSucceededRemoteData(), getRemoteDataPayload()))); + switchMap((submissionObject: SubmissionObject) => (submissionObject.item as Observable>) + .pipe( + getAllSucceededRemoteData(), + getRemoteDataPayload() + ) + ) + ); 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) => 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( map((items: RemoteData>) => items.payload.page.map((item) => Object.assign(new ItemSearchResult(), { indexableObject: item }))), ).subscribe((relatedItems: Array>) => 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>>; - this.selectedValues$ = - observableCombineLatest(item$, this.relationships$).pipe( - map(([item, relatedItems]: [Item, Array>]) => { - return relatedItems - .map((element: SearchResult) => { - 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; } - removeSelection(object: SearchResult) { - 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) { + 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)) .forEach((sub) => sub.unsubscribe()); } + + /** + * Prevent unnecessary rerendering so fields don't lose focus + */ + trackRelationship(index, relationship: Relationship) { + return hasValue(relationship) ? relationship.id : undefined; + } } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.html new file mode 100644 index 0000000000..ebda014e19 --- /dev/null +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.html @@ -0,0 +1,11 @@ +
  • + + + + + +
  • diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.scss b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.spec.ts new file mode 100644 index 0000000000..7172653557 --- /dev/null +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.spec.ts @@ -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; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ExistingMetadataListElementComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ExistingMetadataListElementComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.ts new file mode 100644 index 0000000000..4551a0a7d1 --- /dev/null +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.ts @@ -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 + ) { + } + + 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)) + }) + } +} diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.ts index 3421e6c5c9..9937fb6010 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.ts @@ -2,7 +2,7 @@ import { Component, NgZone, OnDestroy, OnInit } from '@angular/core'; import { combineLatest, Observable, Subscription } from 'rxjs'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; 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 { SearchConfigurationService } from '../../../../../core/shared/search/search-configuration.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 { SearchResult } from '../../../../search/search-result.model'; import { Item } from '../../../../../core/shared/item.model'; -import { getRemoteDataPayload, getSucceededRemoteData } from '../../../../../core/shared/operators'; import { AddRelationshipAction, RemoveRelationshipAction, UpdateRelationshipAction } from './relationship.actions'; import { RelationshipService } from '../../../../../core/data/relationship.service'; import { RelationshipTypeService } from '../../../../../core/data/relationship-type.service'; import { Store } from '@ngrx/store'; import { AppState } from '../../../../../app.reducer'; import { Context } from '../../../../../core/shared/context.model'; -import { Relationship } from '../../../../../core/shared/item-relationships/relationship.model'; -import { MetadataValue } from '../../../../../core/shared/metadata.models'; @Component({ selector: 'ds-dynamic-lookup-relation-modal', @@ -66,8 +63,6 @@ export class DsDynamicLookupRelationModalComponent implements OnInit, OnDestroy if (this.relationshipOptions.nameVariants) { this.context = Context.SubmissionModal; } - - // this.setExistingNameVariants(); } 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> = - 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 = 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() { Object.values(this.subMap).forEach((subscription) => subscription.unsubscribe()); } diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index 85d001286d..7e95d1c727 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -174,6 +174,8 @@ import { SidebarFilterComponent } from './sidebar/filter/sidebar-filter.componen import { SidebarFilterSelectedOptionComponent } from './sidebar/filter/sidebar-filter-selected-option.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 { 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 = [ // Do NOT include UniversalModule, HttpModule, or JsonpModule here @@ -196,6 +198,7 @@ const MODULES = [ MomentModule, TextMaskModule, MenuModule, + DragDropModule ]; const ROOT_MODULES = [ @@ -330,7 +333,8 @@ const COMPONENTS = [ ItemSelectComponent, CollectionSelectComponent, MetadataRepresentationLoaderComponent, - SelectableListItemControlComponent + SelectableListItemControlComponent, + ExistingMetadataListElementComponent ]; const ENTRY_COMPONENTS = [ @@ -432,7 +436,8 @@ const DIRECTIVES = [ ...DIRECTIVES, ...ENTRY_COMPONENTS, ...SHARED_ITEM_PAGE_COMPONENTS, - PublicationSearchResultListElementComponent + PublicationSearchResultListElementComponent, + ExistingMetadataListElementComponent ], providers: [ ...PROVIDERS diff --git a/src/app/submission/form/collection/submission-form-collection.component.ts b/src/app/submission/form/collection/submission-form-collection.component.ts index e40ea82163..0bd24cc304 100644 --- a/src/app/submission/form/collection/submission-form-collection.component.ts +++ b/src/app/submission/form/collection/submission-form-collection.component.ts @@ -197,21 +197,23 @@ export class SubmissionFormCollectionComponent implements OnChanges, OnInit { find((communities: RemoteData>) => isNotEmpty(communities.payload)), mergeMap((communities: RemoteData>) => communities.payload.page)); - const listCollection$ = communities$.pipe( - flatMap((communityData: Community) => { - return this.collectionDataService.getAuthorizedCollectionByCommunity(communityData.uuid, findOptions).pipe( - find((collections: RemoteData>) => !collections.isResponsePending && collections.hasSucceeded), - mergeMap((collections: RemoteData>) => collections.payload.page), - filter((collectionData: Collection) => isNotEmpty(collectionData)), - 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([]) - ); + const listCollection$ = observableOf([]); + + // const listCollection$ = communities$.pipe( + // flatMap((communityData: Community) => { + // return this.collectionDataService.getAuthorizedCollectionByCommunity(communityData.uuid, findOptions).pipe( + // find((collections: RemoteData>) => !collections.isResponsePending && collections.hasSucceeded), + // mergeMap((collections: RemoteData>) => collections.payload.page), + // filter((collectionData: Collection) => isNotEmpty(collectionData)), + // 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([]) + // ); const searchTerm$ = this.searchField.valueChanges.pipe( debounceTime(200), @@ -227,8 +229,8 @@ export class SubmissionFormCollectionComponent implements OnChanges, OnInit { } else { return listCollection.filter((v) => v.collection.name.toLowerCase().indexOf(searchTerm.toLowerCase()) > -1).slice(0, 5); } - }) - ); + }) + ); } } } diff --git a/yarn.lock b/yarn.lock index 26480cccca..884f820c1d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -35,6 +35,15 @@ dependencies: 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": version "6.1.5" 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" 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: version "0.0.5" 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-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: version "1.9.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" From 78d1c5ee2bfcc353b7ae452ab1ac3aa3c4ee65c3 Mon Sep 17 00:00:00 2001 From: Art Lowel Date: Mon, 2 Dec 2019 18:30:35 +0100 Subject: [PATCH 02/14] use reorderables instead of relationships --- ...on-item-metadata-list-element.component.ts | 7 +- ...amic-form-control-container.component.html | 4 +- ...ynamic-form-control-container.component.ts | 65 ++++----- ...sting-metadata-list-element.component.html | 4 +- ...xisting-metadata-list-element.component.ts | 127 +++++++++++------- 5 files changed, 119 insertions(+), 88 deletions(-) diff --git a/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.ts b/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.ts index f3d0a28fda..b571348122 100644 --- a/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.ts +++ b/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.ts @@ -1,4 +1,4 @@ -import { Component } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; import { metadataRepresentationComponent } from '../../../../shared/metadata-representation/metadata-representation.decorator'; import { MetadataRepresentationType } from '../../../../core/shared/metadata-representation/metadata-representation.model'; import { ItemMetadataRepresentationListElementComponent } from '../../../../shared/object-list/metadata-representation-list-element/item/item-metadata-representation-list-element.component'; @@ -11,5 +11,8 @@ import { ItemMetadataRepresentationListElementComponent } from '../../../../shar /** * The component for displaying an item of the type Person as a metadata field */ -export class PersonItemMetadataListElementComponent extends ItemMetadataRepresentationListElementComponent { +export class PersonItemMetadataListElementComponent extends ItemMetadataRepresentationListElementComponent implements OnInit { + ngOnInit(): void { + console.log('this.metadataRepresentation', this.metadataRepresentation); + } } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html index 64f8315575..d2a1996a60 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html @@ -54,8 +54,8 @@
      - ; - relationships: Relationship[]; + reorderables$: Observable; + reorderables: ReorderableRelationship[]; hasRelationLookup: boolean; modalRef: NgbModalRef; item: Item; listId: string; searchConfig: string; - /** * List of subscriptions to unsubscribe from */ @@ -223,6 +226,7 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo ngOnInit(): void { this.hasRelationLookup = hasValue(this.model.relationship); + this.reorderables = []; if (this.hasRelationLookup) { this.listId = 'list-' + this.model.relationship.relationshipType; const item$ = this.submissionObjectService @@ -238,7 +242,7 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo ); this.subs.push(item$.subscribe((item) => this.item = item)); - this.relationships$ = item$.pipe( + this.reorderables$ = item$.pipe( switchMap((item) => this.relationService.getItemRelationshipsByLabel(item, this.model.relationship.relationshipType) .pipe( getAllSucceededRemoteData(), @@ -251,28 +255,24 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo relationship.leftItem.pipe( getSucceededRemoteData(), getRemoteDataPayload(), - map((item: Item) => { - return { relationship, left: item.uuid === this.item.uuid } + map((leftItem: Item) => { + return new ReorderableRelationship(relationship, leftItem.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) - ) + map((relationships: ReorderableRelationship[]) => + relationships + .sort((a: Reorderable, b: Reorderable) => { + return Math.sign(a.getPlace() - b.getPlace()); + }) + ) ) ) ); - this.relationships$.subscribe((rels) => this.relationships = rels); + this.subs.push(this.reorderables$.subscribe((rs) => { + this.reorderables = rs + })); this.relationService.getRelatedItemsByLabel(this.item, this.model.relationship.relationshipType).pipe( map((items: RemoteData>) => items.payload.page.map((item) => Object.assign(new ItemSearchResult(), { indexableObject: item }))), @@ -334,27 +334,18 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo modalComp.item = this.item; } - moveSelection(event: CdkDragDrop) { - moveItemInArray(this.relationships, event.previousIndex, event.currentIndex); + moveItemInArray(this.reorderables, 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 } - } - }), - ) + this.reorderables.map((reo: Reorderable, index: number) => { + reo.oldIndex = reo.getPlace(); + reo.newIndex = index; + return reo; + } ) ).pipe( - switchMap((relationships: { relationship: Relationship, left: boolean, oldIndex: number, newIndex: number }[]) => + switchMap((relationships: Array<{ 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); @@ -381,7 +372,7 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo /** * Prevent unnecessary rerendering so fields don't lose focus */ - trackRelationship(index, relationship: Relationship) { - return hasValue(relationship) ? relationship.id : undefined; + trackReorderable(index, reorderable: Reorderable) { + return hasValue(reorderable) ? reorderable.getId() : undefined; } } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.html index ebda014e19..960dd78767 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.html @@ -1,4 +1,4 @@ -
    • +
    • @@ -6,6 +6,6 @@ - +
    • diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.ts index 4551a0a7d1..d31e9380a8 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.ts @@ -1,10 +1,16 @@ -import { Component, Input, OnChanges, OnInit } from '@angular/core'; +import { Component, Input, OnChanges, OnDestroy, OnInit } from '@angular/core'; import { Item } from '../../../../../core/shared/item.model'; -import { getRemoteDataPayload, getSucceededRemoteData } from '../../../../../core/shared/operators'; +import { MetadataRepresentation } from '../../../../../core/shared/metadata-representation/metadata-representation.model'; +import { + getAllSucceededRemoteData, + getRemoteDataPayload, + getSucceededRemoteData +} from '../../../../../core/shared/operators'; import { hasValue, isNotEmpty } from '../../../../empty.util'; -import { filter, map, take } from 'rxjs/operators'; +import { of as observableOf, Subscription } from 'rxjs'; +import { filter, map } from 'rxjs/operators'; import { Relationship } from '../../../../../core/shared/item-relationships/relationship.model'; -import { combineLatest as observableCombineLatest } from 'rxjs'; +import { combineLatest as observableCombineLatest, of } 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'; @@ -14,19 +20,55 @@ import { Store } from '@ngrx/store'; import { AppState } from '../../../../../app.reducer'; import { ItemSearchResult } from '../../../../object-collection/shared/item-search-result.model'; +export abstract class Reorderable { + constructor(public oldIndex?: number, public newIndex?: number) { + } + + abstract getId(): string; + abstract getPlace(): number; +} + +export class ReorderableRelationship extends Reorderable { + relationship: Relationship; + useLeftItem: boolean; + + constructor(relationship: Relationship, useLeftItem: boolean, oldIndex?: number, newIndex?: number) { + super(oldIndex, newIndex); + this.relationship = relationship; + this.useLeftItem = useLeftItem; + } + + getId(): string { + return this.relationship.id; + } + + getPlace(): number { + if (this.useLeftItem) { + return this.relationship.rightPlace + } else { + return this.relationship.leftPlace + } + } +} + @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 { +export class ExistingMetadataListElementComponent implements OnInit, OnChanges, OnDestroy { @Input() listId: string; @Input() submissionItem: Item; - @Input() relationship: Relationship; + @Input() reoRel: ReorderableRelationship; @Input() metadataFields: string[]; @Input() relationshipOptions: RelationshipOptions; - metadataRepresentation$; - relatedItem$; + metadataRepresentation: MetadataRepresentation; + relatedItem: Item; + + /** + * List of subscriptions to unsubscribe from + */ + private subs: Subscription[] = []; constructor( private selectableListService: SelectableListService, @@ -34,49 +76,44 @@ export class ExistingMetadataListElementComponent implements OnChanges { ) { } + ngOnInit(): void { + console.log('reoRel', this.reoRel); + } + ngOnChanges() { - const leftItem$ = this.relationship.leftItem.pipe( - getSucceededRemoteData(), + 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; - 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 - ) - } - } - ) - ); + 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 }); + this.metadataRepresentation = Object.assign( + new ItemMetadataRepresentation(metadataRepresentationMD), + this.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)) - }) + this.selectableListService.deselectSingle(this.listId, Object.assign(new ItemSearchResult(), { indexableObject: this.relatedItem })); + this.store.dispatch(new RemoveRelationshipAction(this.submissionItem, this.relatedItem, this.relationshipOptions.relationshipType)) } + + /** + * Unsubscribe from all subscriptions + */ + ngOnDestroy(): void { + this.subs + .filter((sub) => hasValue(sub)) + .forEach((sub) => sub.unsubscribe()); + } + } From c3ef2f8dee688587ce5ce7962e2f39785e16ab27 Mon Sep 17 00:00:00 2001 From: lotte Date: Tue, 3 Dec 2019 10:10:46 +0100 Subject: [PATCH 03/14] fixed reordering request --- src/app/core/data/data.service.spec.ts | 4 +- ...ynamic-form-control-container.component.ts | 43 ++++++++----------- 2 files changed, 21 insertions(+), 26 deletions(-) diff --git a/src/app/core/data/data.service.spec.ts b/src/app/core/data/data.service.spec.ts index 18e008fc0e..b690492c61 100644 --- a/src/app/core/data/data.service.spec.ts +++ b/src/app/core/data/data.service.spec.ts @@ -17,6 +17,7 @@ import { NormalizedObjectBuildService } from '../cache/builders/normalized-objec import { NotificationsService } from '../../shared/notifications/notifications.service'; import { Item } from '../shared/item.model'; import * as uuidv4 from 'uuid/v4'; +import { createSuccessfulRemoteDataObject$ } from '../../shared/testing/utils'; const endpoint = 'https://rest.api/core'; @@ -191,8 +192,7 @@ describe('DataService', () => { dso2.self = selfLink; dso2.metadata = [{ key: 'dc.title', value: name2 }]; - spyOn(service, 'findByHref').and.returnValues(observableOf(dso)); - spyOn(objectCache, 'getObjectBySelfLink').and.returnValues(observableOf(dso)); + spyOn(service, 'findByHref').and.returnValues(createSuccessfulRemoteDataObject$(dso)); spyOn(objectCache, 'addPatch'); }); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts index 8032cd606a..0cf939623e 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts @@ -260,12 +260,12 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo }), ) ))), - map((relationships: ReorderableRelationship[]) => - relationships - .sort((a: Reorderable, b: Reorderable) => { - return Math.sign(a.getPlace() - b.getPlace()); - }) - ) + map((relationships: ReorderableRelationship[]) => + relationships + .sort((a: Reorderable, b: Reorderable) => { + return Math.sign(a.getPlace() - b.getPlace()); + }) + ) ) ) ); @@ -337,25 +337,20 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo moveSelection(event: CdkDragDrop) { moveItemInArray(this.reorderables, event.previousIndex, event.currentIndex); this.zone.runOutsideAngular(() => { - observableCombineLatest( - this.reorderables.map((reo: Reorderable, index: number) => { - reo.oldIndex = reo.getPlace(); - reo.newIndex = index; - return reo; + const relationships = this.reorderables.map((reo: Reorderable, index: number) => { + reo.oldIndex = reo.getPlace(); + reo.newIndex = index; + return reo; + } + ); + return observableCombineLatest(relationships.map((rel: ReorderableRelationship) => { + console.log(rel); + if (rel.oldIndex !== rel.newIndex) { + return this.relationshipService.updatePlace(rel.relationship, rel.newIndex, !rel.useLeftItem); + } else { + return observableOf(undefined); } - ) - ).pipe( - switchMap((relationships: Array<{ 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(); }) } From c48932431f00ca9cb35765077fc2d933bd889dd2 Mon Sep 17 00:00:00 2001 From: lotte Date: Tue, 3 Dec 2019 11:43:19 +0100 Subject: [PATCH 04/14] fixes after merge + tslint changes --- src/app/+home-page/home-page.component.ts | 6 ++-- src/app/+home-page/home-page.resolver.ts | 4 +-- src/app/+lookup-by-id/lookup-guard.ts | 2 +- .../filtered-search-page.component.spec.ts | 2 +- .../+search-page/search-tracker.component.ts | 32 +++++++++-------- src/app/+search-page/search.component.html | 6 +++- src/app/+search-page/search.component.ts | 15 ++++---- src/app/core/auth/auth.interceptor.ts | 2 +- src/app/core/data/change-analyzer.ts | 2 +- src/app/core/data/site-data.service.spec.ts | 14 ++++---- src/app/core/data/site-data.service.ts | 34 ++++++++----------- src/app/core/shared/search/search.service.ts | 24 ++++++------- ...xisting-metadata-list-element.component.ts | 11 ++---- .../lang-switch/lang-switch.component.spec.ts | 2 +- .../shared/mocks/mock-angulartics.service.ts | 2 +- .../search-facet-filter.component.ts | 3 +- .../search-label/search-label.component.ts | 7 ++-- ...idebar-filter-selected-option.component.ts | 4 +-- .../sidebar/filter/sidebar-filter.actions.ts | 2 +- .../filter/sidebar-filter.component.ts | 22 ++++++------ .../sidebar/filter/sidebar-filter.reducer.ts | 8 ++--- .../sidebar/filter/sidebar-filter.service.ts | 22 ++++++------ .../page-with-sidebar.component.spec.ts | 9 +++-- .../sidebar/page-with-sidebar.component.ts | 22 ++++++------ .../sidebar/sidebar-dropdown.component.ts | 6 ++-- src/app/shared/utils/object-keys-pipe.ts | 2 +- src/app/shared/utils/object-values-pipe.ts | 2 +- .../angulartics/dspace-provider.spec.ts | 6 ++-- .../statistics/angulartics/dspace-provider.ts | 6 ++-- .../dspace/view-tracker.component.ts | 6 ++-- src/app/statistics/statistics.module.ts | 2 +- src/app/statistics/statistics.service.spec.ts | 21 ++++++------ src/app/statistics/statistics.service.ts | 22 ++++++------ tslint.json | 7 ++++ 34 files changed, 170 insertions(+), 167 deletions(-) diff --git a/src/app/+home-page/home-page.component.ts b/src/app/+home-page/home-page.component.ts index 1b915ae683..65caa01430 100644 --- a/src/app/+home-page/home-page.component.ts +++ b/src/app/+home-page/home-page.component.ts @@ -11,14 +11,14 @@ import { Site } from '../core/shared/site.model'; }) export class HomePageComponent implements OnInit { - site$:Observable; + site$: Observable; constructor( - private route:ActivatedRoute, + private route: ActivatedRoute, ) { } - ngOnInit():void { + ngOnInit(): void { this.site$ = this.route.data.pipe( map((data) => data.site as Site), ); diff --git a/src/app/+home-page/home-page.resolver.ts b/src/app/+home-page/home-page.resolver.ts index 1145d1d013..6b63a4e782 100644 --- a/src/app/+home-page/home-page.resolver.ts +++ b/src/app/+home-page/home-page.resolver.ts @@ -10,7 +10,7 @@ import { take } from 'rxjs/operators'; */ @Injectable() export class HomePageResolver implements Resolve { - constructor(private siteService:SiteDataService) { + constructor(private siteService: SiteDataService) { } /** @@ -19,7 +19,7 @@ export class HomePageResolver implements Resolve { * @param {RouterStateSnapshot} state The current RouterStateSnapshot * @returns Observable Emits the found Site object, or an error if something went wrong */ - resolve(route:ActivatedRouteSnapshot, state:RouterStateSnapshot):Observable | Promise | Site { + resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable | Promise | Site { return this.siteService.find().pipe(take(1)); } } diff --git a/src/app/+lookup-by-id/lookup-guard.ts b/src/app/+lookup-by-id/lookup-guard.ts index c89e329241..a7ddffcd4e 100644 --- a/src/app/+lookup-by-id/lookup-guard.ts +++ b/src/app/+lookup-by-id/lookup-guard.ts @@ -18,7 +18,7 @@ export class LookupGuard implements CanActivate { constructor(private dsoService: DsoRedirectDataService) { } - canActivate(route: ActivatedRouteSnapshot, state:RouterStateSnapshot): Observable { + canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable { const params = this.getLookupParams(route); return this.dsoService.findById(params.id, params.type).pipe( map((response: RemoteData) => response.hasFailed) diff --git a/src/app/+search-page/filtered-search-page.component.spec.ts b/src/app/+search-page/filtered-search-page.component.spec.ts index cf1668d8bc..e25cbd2e12 100644 --- a/src/app/+search-page/filtered-search-page.component.spec.ts +++ b/src/app/+search-page/filtered-search-page.component.spec.ts @@ -1,7 +1,7 @@ import { FilteredSearchPageComponent } from './filtered-search-page.component'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { configureSearchComponentTestingModule } from './search.component.spec'; -import { SearchConfigurationService } from './search-service/search-configuration.service'; +import { SearchConfigurationService } from '../core/shared/search/search-configuration.service'; describe('FilteredSearchPageComponent', () => { let comp: FilteredSearchPageComponent; diff --git a/src/app/+search-page/search-tracker.component.ts b/src/app/+search-page/search-tracker.component.ts index e1df9b3905..7e5aa49165 100644 --- a/src/app/+search-page/search-tracker.component.ts +++ b/src/app/+search-page/search-tracker.component.ts @@ -2,16 +2,17 @@ import { Component, Inject, OnInit } from '@angular/core'; import { Angulartics2 } from 'angulartics2'; import { filter, map, switchMap } from 'rxjs/operators'; import { SearchComponent } from './search.component'; -import { SearchService } from './search-service/search.service'; import { SidebarService } from '../shared/sidebar/sidebar.service'; -import { SearchConfigurationService } from './search-service/search-configuration.service'; import { HostWindowService } from '../shared/host-window.service'; import { SEARCH_CONFIG_SERVICE } from '../+my-dspace-page/my-dspace-page.component'; import { RouteService } from '../core/services/route.service'; import { hasValue } from '../shared/empty.util'; -import { SearchQueryResponse } from './search-service/search-query-response.model'; import { SearchSuccessResponse } from '../core/cache/response.models'; -import { PaginatedSearchOptions } from './paginated-search-options.model'; +import { SearchConfigurationService } from '../core/shared/search/search-configuration.service'; +import { SearchService } from '../core/shared/search/search.service'; +import { PaginatedSearchOptions } from '../shared/search/paginated-search-options.model'; +import { SearchQueryResponse } from '../shared/search/search-query-response.model'; +import { Router } from '@angular/router'; /** * This component triggers a page view statistic @@ -30,17 +31,18 @@ import { PaginatedSearchOptions } from './paginated-search-options.model'; export class SearchTrackerComponent extends SearchComponent implements OnInit { constructor( - protected service:SearchService, - protected sidebarService:SidebarService, - protected windowService:HostWindowService, - @Inject(SEARCH_CONFIG_SERVICE) public searchConfigService:SearchConfigurationService, - protected routeService:RouteService, - public angulartics2:Angulartics2 + protected service: SearchService, + protected sidebarService: SidebarService, + protected windowService: HostWindowService, + @Inject(SEARCH_CONFIG_SERVICE) public searchConfigService: SearchConfigurationService, + protected routeService: RouteService, + public angulartics2: Angulartics2, + protected router: Router ) { - super(service, sidebarService, windowService, searchConfigService, routeService); + super(service, sidebarService, windowService, searchConfigService, routeService, router); } - ngOnInit():void { + ngOnInit(): void { // super.ngOnInit(); this.getSearchOptions().pipe( switchMap((options) => this.service.searchEntries(options) @@ -58,9 +60,9 @@ export class SearchTrackerComponent extends SearchComponent implements OnInit { ) ) .subscribe((entry) => { - const config:PaginatedSearchOptions = entry.searchOptions; - const searchQueryResponse:SearchQueryResponse = entry.response; - const filters:Array<{ filter:string, operator:string, value:string, label:string; }> = []; + const config: PaginatedSearchOptions = entry.searchOptions; + const searchQueryResponse: SearchQueryResponse = entry.response; + const filters: Array<{ filter: string, operator: string, value: string, label: string; }> = []; const appliedFilters = searchQueryResponse.appliedFilters || []; for (let i = 0, filtersLength = appliedFilters.length; i < filtersLength; i++) { const appliedFilter = appliedFilters[i]; diff --git a/src/app/+search-page/search.component.html b/src/app/+search-page/search.component.html index 9423062bde..36879f33d4 100644 --- a/src/app/+search-page/search.component.html +++ b/src/app/+search-page/search.component.html @@ -46,5 +46,9 @@ [scopes]="(scopeListRD$ | async)" [inPlaceSearch]="inPlaceSearch"> - +
      +
      + +
      +
      diff --git a/src/app/+search-page/search.component.ts b/src/app/+search-page/search.component.ts index cc763e253f..5b5787c91f 100644 --- a/src/app/+search-page/search.component.ts +++ b/src/app/+search-page/search.component.ts @@ -6,15 +6,17 @@ import { RemoteData } from '../core/data/remote-data'; import { DSpaceObject } from '../core/shared/dspace-object.model'; import { pushInOut } from '../shared/animations/push'; import { HostWindowService } from '../shared/host-window.service'; -import { PaginatedSearchOptions } from './paginated-search-options.model'; -import { SearchResult } from './search-result.model'; -import { SearchService } from './search-service/search.service'; import { SidebarService } from '../shared/sidebar/sidebar.service'; import { hasValue, isNotEmpty } from '../shared/empty.util'; -import { SearchConfigurationService } from './search-service/search-configuration.service'; import { getSucceededRemoteData } from '../core/shared/operators'; import { RouteService } from '../core/services/route.service'; import { SEARCH_CONFIG_SERVICE } from '../+my-dspace-page/my-dspace-page.component'; +import { PaginatedSearchOptions } from '../shared/search/paginated-search-options.model'; +import { SearchResult } from '../shared/search/search-result.model'; +import { SearchConfigurationService } from '../core/shared/search/search-configuration.service'; +import { SearchService } from '../core/shared/search/search.service'; +import { currentPath } from '../shared/utils/route.utils'; +import { Router } from '@angular/router'; @Component({ selector: 'ds-search', @@ -96,7 +98,8 @@ export class SearchComponent implements OnInit { protected sidebarService: SidebarService, protected windowService: HostWindowService, @Inject(SEARCH_CONFIG_SERVICE) public searchConfigService: SearchConfigurationService, - protected routeService: RouteService) { + protected routeService: RouteService, + protected router: Router) { this.isXsOrSm$ = this.windowService.isXsOrSm(); } @@ -159,7 +162,7 @@ export class SearchComponent implements OnInit { */ private getSearchLink(): string { if (this.inPlaceSearch) { - return './'; + return currentPath(this.router); } return this.service.getSearchLink(); } diff --git a/src/app/core/auth/auth.interceptor.ts b/src/app/core/auth/auth.interceptor.ts index da760b8faa..08e892bbd9 100644 --- a/src/app/core/auth/auth.interceptor.ts +++ b/src/app/core/auth/auth.interceptor.ts @@ -56,7 +56,7 @@ export class AuthInterceptor implements HttpInterceptor { return http.url && http.url.endsWith('/authn/logout'); } - private makeAuthStatusObject(authenticated:boolean, accessToken?: string, error?: string): AuthStatus { + private makeAuthStatusObject(authenticated: boolean, accessToken?: string, error?: string): AuthStatus { const authStatus = new AuthStatus(); authStatus.id = null; authStatus.okay = true; diff --git a/src/app/core/data/change-analyzer.ts b/src/app/core/data/change-analyzer.ts index 6b5a69259b..c45c9e55b7 100644 --- a/src/app/core/data/change-analyzer.ts +++ b/src/app/core/data/change-analyzer.ts @@ -17,5 +17,5 @@ export interface ChangeAnalyzer { * @param {NormalizedObject} object2 * The second object to compare */ - diff(object1: T | NormalizedObject, object2: T | NormalizedObject): Operation[]; + diff(object1: T | NormalizedObject, object2: T | NormalizedObject): Operation[]; } diff --git a/src/app/core/data/site-data.service.spec.ts b/src/app/core/data/site-data.service.spec.ts index 189218b5cf..3059ab9948 100644 --- a/src/app/core/data/site-data.service.spec.ts +++ b/src/app/core/data/site-data.service.spec.ts @@ -19,12 +19,12 @@ import { PaginatedList } from './paginated-list'; import { RemoteData } from './remote-data'; describe('SiteDataService', () => { - let scheduler:TestScheduler; - let service:SiteDataService; - let halService:HALEndpointService; - let requestService:RequestService; - let rdbService:RemoteDataBuildService; - let objectCache:ObjectCacheService; + let scheduler: TestScheduler; + let service: SiteDataService; + let halService: HALEndpointService; + let requestService: RequestService; + let rdbService: RemoteDataBuildService; + let objectCache: ObjectCacheService; const testObject = Object.assign(new Site(), { uuid: '9b4f22f4-164a-49db-8817-3316b6ee5746', @@ -33,7 +33,7 @@ describe('SiteDataService', () => { const requestUUID = '34cfed7c-f597-49ef-9cbe-ea351f0023c2'; const options = Object.assign(new FindAllOptions(), {}); - const getRequestEntry$ = (successful:boolean, statusCode:number, statusText:string) => { + const getRequestEntry$ = (successful: boolean, statusCode: number, statusText: string) => { return observableOf({ response: new RestResponse(successful, statusCode, statusText) } as RequestEntry); diff --git a/src/app/core/data/site-data.service.ts b/src/app/core/data/site-data.service.ts index 4993d47226..ba395b40ed 100644 --- a/src/app/core/data/site-data.service.ts +++ b/src/app/core/data/site-data.service.ts @@ -22,47 +22,41 @@ import { getSucceededRemoteData } from '../shared/operators'; * Service responsible for handling requests related to the Site object */ @Injectable() -export class SiteDataService extends DataService { -​ +export class SiteDataService extends DataService {​ protected linkPath = 'sites'; protected forceBypassCache = false; -​ constructor( - protected requestService:RequestService, - protected rdbService:RemoteDataBuildService, - protected dataBuildService:NormalizedObjectBuildService, - protected store:Store, - protected objectCache:ObjectCacheService, - protected halService:HALEndpointService, - protected notificationsService:NotificationsService, - protected http:HttpClient, - protected comparator:DSOChangeAnalyzer, + protected requestService: RequestService, + protected rdbService: RemoteDataBuildService, + protected dataBuildService: NormalizedObjectBuildService, + protected store: Store, + protected objectCache: ObjectCacheService, + protected halService: HALEndpointService, + protected notificationsService: NotificationsService, + protected http: HttpClient, + protected comparator: DSOChangeAnalyzer, ) { super(); } -​ - /** * Get the endpoint for browsing the site object * @param {FindAllOptions} options * @param {Observable} linkPath */ - getBrowseEndpoint(options:FindAllOptions, linkPath?:string):Observable { + getBrowseEndpoint(options: FindAllOptions, linkPath?: string): Observable { return this.halService.getEndpoint(this.linkPath); } -​ - /** * Retrieve the Site Object */ - find():Observable { + find(): Observable { return this.findAll().pipe( getSucceededRemoteData(), - map((remoteData:RemoteData>) => remoteData.payload), - map((list:PaginatedList) => list.page[0]) + map((remoteData: RemoteData>) => remoteData.payload), + map((list: PaginatedList) => list.page[0]) ); } } diff --git a/src/app/core/shared/search/search.service.ts b/src/app/core/shared/search/search.service.ts index f6886c268e..141f261990 100644 --- a/src/app/core/shared/search/search.service.ts +++ b/src/app/core/shared/search/search.service.ts @@ -89,9 +89,9 @@ export class SearchService implements OnDestroy { } } - getEndpoint(searchOptions?:PaginatedSearchOptions):Observable { + getEndpoint(searchOptions?: PaginatedSearchOptions): Observable { return this.halService.getEndpoint(this.searchLinkPath).pipe( - map((url:string) => { + map((url: string) => { if (hasValue(searchOptions)) { return (searchOptions as PaginatedSearchOptions).toRestUrl(url); } else { @@ -117,16 +117,15 @@ export class SearchService implements OnDestroy { * @param responseMsToLive The amount of milliseconds for the response to live in cache * @returns {Observable} Emits an observable with the request entries */ - searchEntries(searchOptions?: PaginatedSearchOptions, responseMsToLive?:number) - :Observable<{searchOptions: PaginatedSearchOptions, requestEntry: RequestEntry}> { + searchEntries(searchOptions?: PaginatedSearchOptions, responseMsToLive?: number): Observable<{searchOptions: PaginatedSearchOptions, requestEntry: RequestEntry}> { const hrefObs = this.getEndpoint(searchOptions); const requestObs = hrefObs.pipe( - map((url:string) => { + map((url: string) => { const request = new this.request(this.requestService.generateRequestId(), url); - const getResponseParserFn:() => GenericConstructor = () => { + const getResponseParserFn: () => GenericConstructor = () => { return this.parser; }; @@ -139,8 +138,8 @@ export class SearchService implements OnDestroy { configureRequest(this.requestService), ); return requestObs.pipe( - switchMap((request:RestRequest) => this.requestService.getByHref(request.href)), - map(((requestEntry:RequestEntry) => ({ + switchMap((request: RestRequest) => this.requestService.getByHref(request.href)), + map(((requestEntry: RequestEntry) => ({ searchOptions: searchOptions, requestEntry: requestEntry }))) @@ -152,16 +151,15 @@ export class SearchService implements OnDestroy { * @param searchEntries: The request entries from the search method * @returns {Observable>>>} Emits a paginated list with all search results found */ - getPaginatedResults(searchEntries:Observable<{ searchOptions:PaginatedSearchOptions, requestEntry:RequestEntry }>) - :Observable>>> { - const requestEntryObs:Observable = searchEntries.pipe( + getPaginatedResults(searchEntries: Observable<{ searchOptions: PaginatedSearchOptions, requestEntry: RequestEntry }>): Observable>>> { + const requestEntryObs: Observable = searchEntries.pipe( map((entry) => entry.requestEntry), ); // get search results from response cache - const sqrObs:Observable = requestEntryObs.pipe( + const sqrObs: Observable = requestEntryObs.pipe( filterSuccessfulResponses(), - map((response:SearchSuccessResponse) => response.results), + map((response: SearchSuccessResponse) => response.results), ); // turn dspace href from search results to effective list of DSpaceObjects diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.ts index d31e9380a8..def879701e 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.ts @@ -1,16 +1,11 @@ import { Component, Input, OnChanges, OnDestroy, OnInit } from '@angular/core'; import { Item } from '../../../../../core/shared/item.model'; import { MetadataRepresentation } from '../../../../../core/shared/metadata-representation/metadata-representation.model'; -import { - getAllSucceededRemoteData, - getRemoteDataPayload, - getSucceededRemoteData -} from '../../../../../core/shared/operators'; +import { getAllSucceededRemoteData, getRemoteDataPayload } from '../../../../../core/shared/operators'; import { hasValue, isNotEmpty } from '../../../../empty.util'; -import { of as observableOf, Subscription } from 'rxjs'; -import { filter, map } from 'rxjs/operators'; +import { Subscription } from 'rxjs'; +import { filter } from 'rxjs/operators'; import { Relationship } from '../../../../../core/shared/item-relationships/relationship.model'; -import { combineLatest as observableCombineLatest, of } 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'; diff --git a/src/app/shared/lang-switch/lang-switch.component.spec.ts b/src/app/shared/lang-switch/lang-switch.component.spec.ts index 5b10578f77..3d7aca46b6 100644 --- a/src/app/shared/lang-switch/lang-switch.component.spec.ts +++ b/src/app/shared/lang-switch/lang-switch.component.spec.ts @@ -78,7 +78,7 @@ describe('LangSwitchComponent', () => { }).compileComponents() .then(() => { translate = TestBed.get(TranslateService); - translate.addLangs(mockConfig.languages.filter((langConfig:LangConfig) => langConfig.active === true).map((a) => a.code)); + translate.addLangs(mockConfig.languages.filter((langConfig: LangConfig) => langConfig.active === true).map((a) => a.code)); translate.setDefaultLang('en'); translate.use('en'); http = TestBed.get(HttpTestingController); diff --git a/src/app/shared/mocks/mock-angulartics.service.ts b/src/app/shared/mocks/mock-angulartics.service.ts index 5581e183d1..a7516eb44a 100644 --- a/src/app/shared/mocks/mock-angulartics.service.ts +++ b/src/app/shared/mocks/mock-angulartics.service.ts @@ -1,5 +1,5 @@ /* tslint:disable:no-empty */ export class AngularticsMock { public eventTrack(action, properties) { } - public startTracking():void {} + public startTracking(): void {} } diff --git a/src/app/shared/search/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts b/src/app/shared/search/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts index 3bed8e7397..1d6a85b95b 100644 --- a/src/app/shared/search/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts +++ b/src/app/shared/search/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts @@ -24,6 +24,7 @@ import { getSucceededRemoteData } from '../../../../../core/shared/operators'; import { InputSuggestion } from '../../../../input-suggestions/input-suggestions.model'; import { SearchOptions } from '../../../search-options.model'; import { SEARCH_CONFIG_SERVICE } from '../../../../../+my-dspace-page/my-dspace-page.component'; +import { currentPath } from '../../../../utils/route.utils'; @Component({ selector: 'ds-search-facet-filter', @@ -185,7 +186,7 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy { */ public getSearchLink(): string { if (this.inPlaceSearch) { - return ''; + return currentPath(this.router); } return this.searchService.getSearchLink(); } diff --git a/src/app/shared/search/search-labels/search-label/search-label.component.ts b/src/app/shared/search/search-labels/search-label/search-label.component.ts index e821af19c9..bc3a8b2897 100644 --- a/src/app/shared/search/search-labels/search-label/search-label.component.ts +++ b/src/app/shared/search/search-labels/search-label/search-label.component.ts @@ -1,9 +1,10 @@ import { Component, Input, OnInit } from '@angular/core'; import { Observable } from 'rxjs'; -import { Params } from '@angular/router'; +import { Params, Router } from '@angular/router'; import { map } from 'rxjs/operators'; import { hasValue, isNotEmpty } from '../../../empty.util'; import { SearchService } from '../../../../core/shared/search/search.service'; +import { currentPath } from '../../../utils/route.utils'; @Component({ selector: 'ds-search-label', @@ -25,7 +26,7 @@ export class SearchLabelComponent implements OnInit { * Initialize the instance variable */ constructor( - private searchService: SearchService) { + private searchService: SearchService, private router: Router) { } ngOnInit(): void { @@ -55,7 +56,7 @@ export class SearchLabelComponent implements OnInit { */ private getSearchLink(): string { if (this.inPlaceSearch) { - return './'; + return currentPath(this.router); } return this.searchService.getSearchLink(); } diff --git a/src/app/shared/sidebar/filter/sidebar-filter-selected-option.component.ts b/src/app/shared/sidebar/filter/sidebar-filter-selected-option.component.ts index 5c80a9cd87..4f1d2415ae 100644 --- a/src/app/shared/sidebar/filter/sidebar-filter-selected-option.component.ts +++ b/src/app/shared/sidebar/filter/sidebar-filter-selected-option.component.ts @@ -10,6 +10,6 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; * Represents a single selected option in a sidebar filter */ export class SidebarFilterSelectedOptionComponent { - @Input() label:string; - @Output() click:EventEmitter = new EventEmitter(); + @Input() label: string; + @Output() click: EventEmitter = new EventEmitter(); } diff --git a/src/app/shared/sidebar/filter/sidebar-filter.actions.ts b/src/app/shared/sidebar/filter/sidebar-filter.actions.ts index 2391274489..644bebd949 100644 --- a/src/app/shared/sidebar/filter/sidebar-filter.actions.ts +++ b/src/app/shared/sidebar/filter/sidebar-filter.actions.ts @@ -45,7 +45,7 @@ export class FilterInitializeAction extends SidebarFilterAction { type = SidebarFilterActionTypes.INITIALIZE; initiallyExpanded; - constructor(name:string, initiallyExpanded:boolean) { + constructor(name: string, initiallyExpanded: boolean) { super(name); this.initiallyExpanded = initiallyExpanded; } diff --git a/src/app/shared/sidebar/filter/sidebar-filter.component.ts b/src/app/shared/sidebar/filter/sidebar-filter.component.ts index 2a98565639..5a019d41df 100644 --- a/src/app/shared/sidebar/filter/sidebar-filter.component.ts +++ b/src/app/shared/sidebar/filter/sidebar-filter.component.ts @@ -15,13 +15,13 @@ import { slide } from '../../animations/slide'; */ export class SidebarFilterComponent implements OnInit { - @Input() name:string; - @Input() type:string; - @Input() label:string; + @Input() name: string; + @Input() type: string; + @Input() label: string; @Input() expanded = true; @Input() singleValue = false; - @Input() selectedValues:Observable; - @Output() removeValue:EventEmitter = new EventEmitter(); + @Input() selectedValues: Observable; + @Output() removeValue: EventEmitter = new EventEmitter(); /** * True when the filter is 100% collapsed in the UI @@ -31,10 +31,10 @@ export class SidebarFilterComponent implements OnInit { /** * Emits true when the filter is currently collapsed in the store */ - collapsed$:Observable; + collapsed$: Observable; constructor( - protected filterService:SidebarFilterService, + protected filterService: SidebarFilterService, ) { } @@ -49,7 +49,7 @@ export class SidebarFilterComponent implements OnInit { * Method to change this.collapsed to false when the slide animation ends and is sliding open * @param event The animation event */ - finishSlide(event:any):void { + finishSlide(event: any): void { if (event.fromState === 'collapsed') { this.closed = false; } @@ -59,13 +59,13 @@ export class SidebarFilterComponent implements OnInit { * Method to change this.collapsed to true when the slide animation starts and is sliding closed * @param event The animation event */ - startSlide(event:any):void { + startSlide(event: any): void { if (event.toState === 'collapsed') { this.closed = true; } } - ngOnInit():void { + ngOnInit(): void { this.closed = !this.expanded; this.initializeFilter(); this.collapsed$ = this.isCollapsed(); @@ -82,7 +82,7 @@ export class SidebarFilterComponent implements OnInit { * Checks if the filter is currently collapsed * @returns {Observable} Emits true when the current state of the filter is collapsed, false when it's expanded */ - private isCollapsed():Observable { + private isCollapsed(): Observable { return this.filterService.isCollapsed(this.name); } diff --git a/src/app/shared/sidebar/filter/sidebar-filter.reducer.ts b/src/app/shared/sidebar/filter/sidebar-filter.reducer.ts index d25737eaa9..672a7a2a2d 100644 --- a/src/app/shared/sidebar/filter/sidebar-filter.reducer.ts +++ b/src/app/shared/sidebar/filter/sidebar-filter.reducer.ts @@ -8,17 +8,17 @@ import { * Interface that represents the state for a single filters */ export interface SidebarFilterState { - filterCollapsed:boolean, + filterCollapsed: boolean, } /** * Interface that represents the state for all available filters */ export interface SidebarFiltersState { - [name:string]:SidebarFilterState + [name: string]: SidebarFilterState } -const initialState:SidebarFiltersState = Object.create(null); +const initialState: SidebarFiltersState = Object.create(null); /** * Performs a filter action on the current state @@ -26,7 +26,7 @@ const initialState:SidebarFiltersState = Object.create(null); * @param {SidebarFilterAction} action The action that should be performed * @returns {SidebarFiltersState} The state after the action is performed */ -export function sidebarFilterReducer(state = initialState, action:SidebarFilterAction):SidebarFiltersState { +export function sidebarFilterReducer(state = initialState, action: SidebarFilterAction): SidebarFiltersState { switch (action.type) { diff --git a/src/app/shared/sidebar/filter/sidebar-filter.service.ts b/src/app/shared/sidebar/filter/sidebar-filter.service.ts index 2ff28fd2f5..36244b087c 100644 --- a/src/app/shared/sidebar/filter/sidebar-filter.service.ts +++ b/src/app/shared/sidebar/filter/sidebar-filter.service.ts @@ -16,7 +16,7 @@ import { hasValue } from '../../empty.util'; @Injectable() export class SidebarFilterService { - constructor(private store:Store) { + constructor(private store: Store) { } /** @@ -24,7 +24,7 @@ export class SidebarFilterService { * @param {string} filter The filter for which the action is dispatched * @param {boolean} expanded If the filter should be open from the start */ - public initializeFilter(filter:string, expanded:boolean):void { + public initializeFilter(filter: string, expanded: boolean): void { this.store.dispatch(new FilterInitializeAction(filter, expanded)); } @@ -32,7 +32,7 @@ export class SidebarFilterService { * Dispatches a collapse action to the store for a given filter * @param {string} filterName The filter for which the action is dispatched */ - public collapse(filterName:string):void { + public collapse(filterName: string): void { this.store.dispatch(new FilterCollapseAction(filterName)); } @@ -40,7 +40,7 @@ export class SidebarFilterService { * Dispatches an expand action to the store for a given filter * @param {string} filterName The filter for which the action is dispatched */ - public expand(filterName:string):void { + public expand(filterName: string): void { this.store.dispatch(new FilterExpandAction(filterName)); } @@ -48,7 +48,7 @@ export class SidebarFilterService { * Dispatches a toggle action to the store for a given filter * @param {string} filterName The filter for which the action is dispatched */ - public toggle(filterName:string):void { + public toggle(filterName: string): void { this.store.dispatch(new FilterToggleAction(filterName)); } @@ -57,10 +57,10 @@ export class SidebarFilterService { * @param {string} filterName The filtername for which the collapsed state is checked * @returns {Observable} Emits the current collapsed state of the given filter, if it's unavailable, return false */ - isCollapsed(filterName:string):Observable { + isCollapsed(filterName: string): Observable { return this.store.pipe( select(filterByNameSelector(filterName)), - map((object:SidebarFilterState) => { + map((object: SidebarFilterState) => { if (object) { return object.filterCollapsed; } else { @@ -73,14 +73,14 @@ export class SidebarFilterService { } -const filterStateSelector = (state:SidebarFiltersState) => state.sidebarFilter; +const filterStateSelector = (state: SidebarFiltersState) => state.sidebarFilter; -function filterByNameSelector(name:string):MemoizedSelector { +function filterByNameSelector(name: string): MemoizedSelector { return keySelector(name); } -export function keySelector(key:string):MemoizedSelector { - return createSelector(filterStateSelector, (state:SidebarFilterState) => { +export function keySelector(key: string): MemoizedSelector { + return createSelector(filterStateSelector, (state: SidebarFilterState) => { if (hasValue(state)) { return state[key]; } else { diff --git a/src/app/shared/sidebar/page-with-sidebar.component.spec.ts b/src/app/shared/sidebar/page-with-sidebar.component.spec.ts index 77f59090ab..e9211797a9 100644 --- a/src/app/shared/sidebar/page-with-sidebar.component.spec.ts +++ b/src/app/shared/sidebar/page-with-sidebar.component.spec.ts @@ -7,8 +7,8 @@ import { HostWindowService } from '../host-window.service'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; describe('PageWithSidebarComponent', () => { - let comp:PageWithSidebarComponent; - let fixture:ComponentFixture; + let comp: PageWithSidebarComponent; + let fixture: ComponentFixture; const sidebarService = { isCollapsed: observableOf(true), @@ -42,7 +42,7 @@ describe('PageWithSidebarComponent', () => { }); describe('when sidebarCollapsed is true in mobile view', () => { - let menu:HTMLElement; + let menu: HTMLElement; beforeEach(() => { menu = fixture.debugElement.query(By.css('#mock-id-sidebar-content')).nativeElement; @@ -58,7 +58,7 @@ describe('PageWithSidebarComponent', () => { }); describe('when sidebarCollapsed is false in mobile view', () => { - let menu:HTMLElement; + let menu: HTMLElement; beforeEach(() => { menu = fixture.debugElement.query(By.css('#mock-id-sidebar-content')).nativeElement; @@ -70,6 +70,5 @@ describe('PageWithSidebarComponent', () => { it('should open the menu', () => { expect(menu.classList).toContain('active'); }); - }); }); diff --git a/src/app/shared/sidebar/page-with-sidebar.component.ts b/src/app/shared/sidebar/page-with-sidebar.component.ts index 8b7f987a37..44fa238d3b 100644 --- a/src/app/shared/sidebar/page-with-sidebar.component.ts +++ b/src/app/shared/sidebar/page-with-sidebar.component.ts @@ -18,13 +18,13 @@ import { map } from 'rxjs/operators'; * the template outlet (inside the page-width-sidebar tags). */ export class PageWithSidebarComponent implements OnInit { - @Input() id:string; - @Input() sidebarContent:TemplateRef; + @Input() id: string; + @Input() sidebarContent: TemplateRef; /** * Emits true if were on a small screen */ - isXsOrSm$:Observable; + isXsOrSm$: Observable; /** * The width of the sidebar (bootstrap columns) @@ -35,16 +35,16 @@ export class PageWithSidebarComponent implements OnInit { /** * Observable for whether or not the sidebar is currently collapsed */ - isSidebarCollapsed$:Observable; + isSidebarCollapsed$: Observable; - sidebarClasses:Observable; + sidebarClasses: Observable; - constructor(protected sidebarService:SidebarService, - protected windowService:HostWindowService, + constructor(protected sidebarService: SidebarService, + protected windowService: HostWindowService, ) { } - ngOnInit():void { + ngOnInit(): void { this.isXsOrSm$ = this.windowService.isXsOrSm(); this.isSidebarCollapsed$ = this.isSidebarCollapsed(); this.sidebarClasses = this.isSidebarCollapsed$.pipe( @@ -56,21 +56,21 @@ export class PageWithSidebarComponent implements OnInit { * Check if the sidebar is collapsed * @returns {Observable} emits true if the sidebar is currently collapsed, false if it is expanded */ - private isSidebarCollapsed():Observable { + private isSidebarCollapsed(): Observable { return this.sidebarService.isCollapsed; } /** * Set the sidebar to a collapsed state */ - public closeSidebar():void { + public closeSidebar(): void { this.sidebarService.collapse() } /** * Set the sidebar to an expanded state */ - public openSidebar():void { + public openSidebar(): void { this.sidebarService.expand(); } diff --git a/src/app/shared/sidebar/sidebar-dropdown.component.ts b/src/app/shared/sidebar/sidebar-dropdown.component.ts index 313538eded..471d357e25 100644 --- a/src/app/shared/sidebar/sidebar-dropdown.component.ts +++ b/src/app/shared/sidebar/sidebar-dropdown.component.ts @@ -10,7 +10,7 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; * The options should still be provided in the content. */ export class SidebarDropdownComponent { - @Input() id:string; - @Input() label:string; - @Output() change:EventEmitter = new EventEmitter(); + @Input() id: string; + @Input() label: string; + @Output() change: EventEmitter = new EventEmitter(); } diff --git a/src/app/shared/utils/object-keys-pipe.ts b/src/app/shared/utils/object-keys-pipe.ts index fd3d018b88..1320dbc4bf 100644 --- a/src/app/shared/utils/object-keys-pipe.ts +++ b/src/app/shared/utils/object-keys-pipe.ts @@ -10,7 +10,7 @@ export class ObjectKeysPipe implements PipeTransform { * @param value An object * @returns {any} Array with all keys the input object */ - transform(value, args:string[]): any { + transform(value, args: string[]): any { const keys = []; Object.keys(value).forEach((k) => keys.push(k)); return keys; diff --git a/src/app/shared/utils/object-values-pipe.ts b/src/app/shared/utils/object-values-pipe.ts index 79efd1cb76..bb511b4e5c 100644 --- a/src/app/shared/utils/object-values-pipe.ts +++ b/src/app/shared/utils/object-values-pipe.ts @@ -10,7 +10,7 @@ export class ObjectValuesPipe implements PipeTransform { * @param value An object * @returns {any} Array with all values of the input object */ - transform(value, args:string[]): any { + transform(value, args: string[]): any { const values = []; Object.values(value).forEach((v) => values.push(v)); return values; diff --git a/src/app/statistics/angulartics/dspace-provider.spec.ts b/src/app/statistics/angulartics/dspace-provider.spec.ts index d89d2d9fc6..39b90af998 100644 --- a/src/app/statistics/angulartics/dspace-provider.spec.ts +++ b/src/app/statistics/angulartics/dspace-provider.spec.ts @@ -5,9 +5,9 @@ import { filter } from 'rxjs/operators'; import { of as observableOf } from 'rxjs'; describe('Angulartics2DSpace', () => { - let provider:Angulartics2DSpace; - let angulartics2:Angulartics2; - let statisticsService:jasmine.SpyObj; + let provider: Angulartics2DSpace; + let angulartics2: Angulartics2; + let statisticsService: jasmine.SpyObj; beforeEach(() => { angulartics2 = { diff --git a/src/app/statistics/angulartics/dspace-provider.ts b/src/app/statistics/angulartics/dspace-provider.ts index 9ab01f6023..cd1aab94bd 100644 --- a/src/app/statistics/angulartics/dspace-provider.ts +++ b/src/app/statistics/angulartics/dspace-provider.ts @@ -9,15 +9,15 @@ import { StatisticsService } from '../statistics.service'; export class Angulartics2DSpace { constructor( - private angulartics2:Angulartics2, - private statisticsService:StatisticsService, + private angulartics2: Angulartics2, + private statisticsService: StatisticsService, ) { } /** * Activates this plugin */ - startTracking():void { + startTracking(): void { this.angulartics2.eventTrack .pipe(this.angulartics2.filterDeveloperMode()) .subscribe((event) => this.eventTrack(event)); diff --git a/src/app/statistics/angulartics/dspace/view-tracker.component.ts b/src/app/statistics/angulartics/dspace/view-tracker.component.ts index 1151287ea8..85588aeb97 100644 --- a/src/app/statistics/angulartics/dspace/view-tracker.component.ts +++ b/src/app/statistics/angulartics/dspace/view-tracker.component.ts @@ -11,14 +11,14 @@ import { DSpaceObject } from '../../../core/shared/dspace-object.model'; templateUrl: './view-tracker.component.html', }) export class ViewTrackerComponent implements OnInit { - @Input() object:DSpaceObject; + @Input() object: DSpaceObject; constructor( - public angulartics2:Angulartics2 + public angulartics2: Angulartics2 ) { } - ngOnInit():void { + ngOnInit(): void { this.angulartics2.eventTrack.next({ action: 'pageView', properties: {object: this.object}, diff --git a/src/app/statistics/statistics.module.ts b/src/app/statistics/statistics.module.ts index a67ff7613c..58ac1f07ab 100644 --- a/src/app/statistics/statistics.module.ts +++ b/src/app/statistics/statistics.module.ts @@ -25,7 +25,7 @@ import { StatisticsService } from './statistics.service'; * This module handles the statistics */ export class StatisticsModule { - static forRoot():ModuleWithProviders { + static forRoot(): ModuleWithProviders { return { ngModule: StatisticsModule, providers: [ diff --git a/src/app/statistics/statistics.service.spec.ts b/src/app/statistics/statistics.service.spec.ts index 3a416968f8..1d659aac2b 100644 --- a/src/app/statistics/statistics.service.spec.ts +++ b/src/app/statistics/statistics.service.spec.ts @@ -3,16 +3,15 @@ import { RequestService } from '../core/data/request.service'; import { HALEndpointServiceStub } from '../shared/testing/hal-endpoint-service-stub'; import { getMockRequestService } from '../shared/mocks/mock-request.service'; import { TrackRequest } from './track-request.model'; -import { ResourceType } from '../core/shared/resource-type'; -import { SearchOptions } from '../+search-page/search-options.model'; import { isEqual } from 'lodash'; import { DSpaceObjectType } from '../core/shared/dspace-object-type.model'; +import { SearchOptions } from '../shared/search/search-options.model'; describe('StatisticsService', () => { - let service:StatisticsService; - let requestService:jasmine.SpyObj; + let service: StatisticsService; + let requestService: jasmine.SpyObj; const restURL = 'https://rest.api'; - const halService:any = new HALEndpointServiceStub(restURL); + const halService: any = new HALEndpointServiceStub(restURL); function initTestService() { return new StatisticsService( @@ -26,9 +25,9 @@ describe('StatisticsService', () => { service = initTestService(); it('should send a request to track an item view ', () => { - const mockItem:any = {uuid: 'mock-item-uuid', type: 'item'}; + const mockItem: any = {uuid: 'mock-item-uuid', type: 'item'}; service.trackViewEvent(mockItem); - const request:TrackRequest = requestService.configure.calls.mostRecent().args[0]; + const request: TrackRequest = requestService.configure.calls.mostRecent().args[0]; expect(request.body).toBeDefined('request.body'); const body = JSON.parse(request.body); expect(body.targetId).toBe('mock-item-uuid'); @@ -40,7 +39,7 @@ describe('StatisticsService', () => { requestService = getMockRequestService(); service = initTestService(); - const mockSearch:any = new SearchOptions({ + const mockSearch: any = new SearchOptions({ query: 'mock-query', }); @@ -52,7 +51,7 @@ describe('StatisticsService', () => { }; const sort = {by: 'search-field', order: 'ASC'}; service.trackSearchEvent(mockSearch, page, sort); - const request:TrackRequest = requestService.configure.calls.mostRecent().args[0]; + const request: TrackRequest = requestService.configure.calls.mostRecent().args[0]; const body = JSON.parse(request.body); it('should specify the right query', () => { @@ -80,7 +79,7 @@ describe('StatisticsService', () => { requestService = getMockRequestService(); service = initTestService(); - const mockSearch:any = new SearchOptions({ + const mockSearch: any = new SearchOptions({ query: 'mock-query', configuration: 'mock-configuration', dsoType: DSpaceObjectType.ITEM, @@ -109,7 +108,7 @@ describe('StatisticsService', () => { } ]; service.trackSearchEvent(mockSearch, page, sort, filters); - const request:TrackRequest = requestService.configure.calls.mostRecent().args[0]; + const request: TrackRequest = requestService.configure.calls.mostRecent().args[0]; const body = JSON.parse(request.body); it('should specify the dsoType', () => { diff --git a/src/app/statistics/statistics.service.ts b/src/app/statistics/statistics.service.ts index cd89125b3c..0c16dc4755 100644 --- a/src/app/statistics/statistics.service.ts +++ b/src/app/statistics/statistics.service.ts @@ -3,10 +3,10 @@ import { Injectable } from '@angular/core'; import { DSpaceObject } from '../core/shared/dspace-object.model'; import { map, take } from 'rxjs/operators'; import { TrackRequest } from './track-request.model'; -import { SearchOptions } from '../+search-page/search-options.model'; import { hasValue, isNotEmpty } from '../shared/empty.util'; import { HALEndpointService } from '../core/shared/hal-endpoint.service'; import { RestRequest } from '../core/data/request.models'; +import { SearchOptions } from '../shared/search/search-options.model'; /** * The statistics service @@ -15,24 +15,24 @@ import { RestRequest } from '../core/data/request.models'; export class StatisticsService { constructor( - protected requestService:RequestService, - protected halService:HALEndpointService, + protected requestService: RequestService, + protected halService: HALEndpointService, ) { } - private sendEvent(linkPath:string, body:any) { + private sendEvent(linkPath: string, body: any) { const requestId = this.requestService.generateRequestId(); this.halService.getEndpoint(linkPath).pipe( - map((endpoint:string) => new TrackRequest(requestId, endpoint, JSON.stringify(body))), + map((endpoint: string) => new TrackRequest(requestId, endpoint, JSON.stringify(body))), take(1) // otherwise the previous events will fire again - ).subscribe((request:RestRequest) => this.requestService.configure(request)); + ).subscribe((request: RestRequest) => this.requestService.configure(request)); } /** * To track a page view * @param dso: The dso which was viewed */ - trackViewEvent(dso:DSpaceObject) { + trackViewEvent(dso: DSpaceObject) { this.sendEvent('/statistics/viewevents', { targetId: dso.uuid, targetType: (dso as any).type @@ -47,10 +47,10 @@ export class StatisticsService { * @param filters: An array of search filters used to filter the result set */ trackSearchEvent( - searchOptions:SearchOptions, - page:{ size:number, totalElements:number, totalPages:number, number:number }, - sort:{ by:string, order:string }, - filters?:Array<{ filter:string, operator:string, value:string, label:string }> + searchOptions: SearchOptions, + page: { size: number, totalElements: number, totalPages: number, number: number }, + sort: { by: string, order: string }, + filters?: Array<{ filter: string, operator: string, value: string, label: string }> ) { const body = { query: searchOptions.query, diff --git a/tslint.json b/tslint.json index b4f905d324..dd04bffb04 100644 --- a/tslint.json +++ b/tslint.json @@ -114,6 +114,13 @@ "parameter": "nospace", "property-declaration": "nospace", "variable-declaration": "nospace" + }, + { + "call-signature": "onespace", + "index-signature": "onespace", + "parameter": "onespace", + "property-declaration": "onespace", + "variable-declaration": "onespace" } ], "unified-signatures": true, From ef1ed04fd2579ad7815f5ac4d83abf22f9bd6578 Mon Sep 17 00:00:00 2001 From: lotte Date: Tue, 3 Dec 2019 13:57:56 +0100 Subject: [PATCH 05/14] manual change detection for preview list in submission --- ...-dynamic-form-control-container.component.html | 3 ++- ...ds-dynamic-form-control-container.component.ts | 15 +++++++++------ .../existing-metadata-list-element.component.ts | 1 - 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html index d2a1996a60..a31171d7ef 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html @@ -54,7 +54,8 @@
        - , - private submissionObjectService: SubmissionObjectDataService + private submissionObjectService: SubmissionObjectDataService, + private ref: ChangeDetectorRef ) { super(componentFactoryResolver, layoutService, validationService); } @@ -228,6 +229,7 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo this.hasRelationLookup = hasValue(this.model.relationship); this.reorderables = []; if (this.hasRelationLookup) { + this.listId = 'list-' + this.model.relationship.relationshipType; const item$ = this.submissionObjectService .findById(this.model.submissionId).pipe( @@ -271,7 +273,8 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo ); this.subs.push(this.reorderables$.subscribe((rs) => { - this.reorderables = rs + this.reorderables = rs; + this.ref.detectChanges(); })); this.relationService.getRelatedItemsByLabel(this.item, this.model.relationship.relationshipType).pipe( @@ -335,8 +338,8 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo } moveSelection(event: CdkDragDrop) { - moveItemInArray(this.reorderables, event.previousIndex, event.currentIndex); this.zone.runOutsideAngular(() => { + moveItemInArray(this.reorderables, event.previousIndex, event.currentIndex); const relationships = this.reorderables.map((reo: Reorderable, index: number) => { reo.oldIndex = reo.getPlace(); reo.newIndex = index; @@ -351,7 +354,7 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo return observableOf(undefined); } }) - ).subscribe(); + ).pipe(getSucceededRemoteData()).subscribe(); }) } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.ts index def879701e..c222feb3f0 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.ts @@ -85,7 +85,6 @@ export class ExistingMetadataListElementComponent implements OnInit, OnChanges, filter((item: Item) => hasValue(item) && isNotEmpty(item.uuid)) ).subscribe((item: Item) => { this.relatedItem = item; - 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 }); From 71a3a22a7c8cfa75bcf1759709fd4aa7d7ea5f33 Mon Sep 17 00:00:00 2001 From: Art Lowel Date: Tue, 3 Dec 2019 14:46:33 +0100 Subject: [PATCH 06/14] fix infinite loop --- src/app/core/data/relationship.service.ts | 117 +++++++++++------- ...ynamic-form-control-container.component.ts | 6 +- 2 files changed, 78 insertions(+), 45 deletions(-) diff --git a/src/app/core/data/relationship.service.ts b/src/app/core/data/relationship.service.ts index fb9e75bd4d..21e5cd8794 100644 --- a/src/app/core/data/relationship.service.ts +++ b/src/app/core/data/relationship.service.ts @@ -1,34 +1,61 @@ -import { Injectable } from '@angular/core'; -import { RequestService } from './request.service'; -import { HALEndpointService } from '../shared/hal-endpoint.service'; -import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; -import { hasValue, hasValueOperator, isNotEmpty, isNotEmptyOperator } from '../../shared/empty.util'; -import { distinctUntilChanged, filter, map, mergeMap, skipWhile, startWith, switchMap, take, tap } from 'rxjs/operators'; -import { configureRequest, getRemoteDataPayload, getResponseFromEntry, getSucceededRemoteData } from '../shared/operators'; -import { DeleteRequest, FindAllOptions, PostRequest, RestRequest } from './request.models'; -import { Observable } from 'rxjs/internal/Observable'; -import { RestResponse } from '../cache/response.models'; -import { Item } from '../shared/item.model'; -import { Relationship } from '../shared/item-relationships/relationship.model'; -import { RelationshipType } from '../shared/item-relationships/relationship-type.model'; -import { RemoteData } from './remote-data'; -import { combineLatest, combineLatest as observableCombineLatest } from 'rxjs'; -import { PaginatedList } from './paginated-list'; -import { ItemDataService } from './item-data.service'; -import { compareArraysUsingIds, paginatedRelationsToItems, relationsToItems } from '../../+item-page/simple/item-types/shared/item-relationships-utils'; -import { ObjectCacheService } from '../cache/object-cache.service'; -import { DataService } from './data.service'; -import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; -import { MemoizedSelector, select, Store } from '@ngrx/store'; -import { CoreState } from '../core.reducers'; -import { NotificationsService } from '../../shared/notifications/notifications.service'; import { HttpClient, HttpHeaders } from '@angular/common/http'; -import { DefaultChangeAnalyzer } from './default-change-analyzer.service'; -import { SearchParam } from '../cache/models/search-param.model'; -import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service'; +import { Injectable } from '@angular/core'; +import { MemoizedSelector, select, Store } from '@ngrx/store'; +import { combineLatest, combineLatest as observableCombineLatest } from 'rxjs'; +import { Observable } from 'rxjs/internal/Observable'; +import { + distinctUntilChanged, + filter, + map, + mergeMap, + startWith, + switchMap, + take, + tap +} from 'rxjs/operators'; +import { + compareArraysUsingIds, + paginatedRelationsToItems, + relationsToItems +} from '../../+item-page/simple/item-types/shared/item-relationships-utils'; import { AppState, keySelector } from '../../app.reducer'; +import { + hasValue, + hasValueOperator, + isNotEmpty, + isNotEmptyOperator +} from '../../shared/empty.util'; +import { ReorderableRelationship } from '../../shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component'; +import { + RemoveNameVariantAction, + SetNameVariantAction +} from '../../shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/name-variant.actions'; import { NameVariantListState } from '../../shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/name-variant.reducer'; -import { RemoveNameVariantAction, SetNameVariantAction } from '../../shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/name-variant.actions'; +import { NotificationsService } from '../../shared/notifications/notifications.service'; +import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; +import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; +import { SearchParam } from '../cache/models/search-param.model'; +import { ObjectCacheService } from '../cache/object-cache.service'; +import { RestResponse } from '../cache/response.models'; +import { CoreState } from '../core.reducers'; +import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service'; +import { HALEndpointService } from '../shared/hal-endpoint.service'; +import { RelationshipType } from '../shared/item-relationships/relationship-type.model'; +import { Relationship } from '../shared/item-relationships/relationship.model'; +import { Item } from '../shared/item.model'; +import { + configureRequest, + getRemoteDataPayload, + getResponseFromEntry, + getSucceededRemoteData +} from '../shared/operators'; +import { DataService } from './data.service'; +import { DefaultChangeAnalyzer } from './default-change-analyzer.service'; +import { ItemDataService } from './item-data.service'; +import { PaginatedList } from './paginated-list'; +import { RemoteData, RemoteDataState } from './remote-data'; +import { DeleteRequest, FindAllOptions, PostRequest, RestRequest } from './request.models'; +import { RequestService } from './request.service'; const relationshipListsStateSelector = (state: AppState) => state.relationshipLists; @@ -116,9 +143,9 @@ export class RelationshipService extends DataService { this.findById(relationshipId).pipe( getSucceededRemoteData(), getRemoteDataPayload(), - switchMap((relationship: Relationship) => combineLatest( - relationship.leftItem.pipe(getSucceededRemoteData(), getRemoteDataPayload()), - relationship.rightItem.pipe(getSucceededRemoteData(), getRemoteDataPayload()) + switchMap((rel: Relationship) => combineLatest( + rel.leftItem.pipe(getSucceededRemoteData(), getRemoteDataPayload()), + rel.rightItem.pipe(getSucceededRemoteData(), getRemoteDataPayload()) ) ), take(1) @@ -336,20 +363,26 @@ export class RelationshipService extends DataService { ) } - public updatePlace(relationship: Relationship, newIndex: number, left: boolean): Observable> { + public updatePlace(reoRel: ReorderableRelationship): Observable> { let updatedRelationship; - if (left) { - updatedRelationship = Object.assign(new Relationship(), relationship, { leftPlace: newIndex }); + if (reoRel.useLeftItem) { + updatedRelationship = Object.assign(new Relationship(), reoRel.relationship, { rightPlace: reoRel.newIndex }); } else { - updatedRelationship = Object.assign(new Relationship(), relationship, { rightPlace: newIndex }); + updatedRelationship = Object.assign(new Relationship(), reoRel.relationship, { leftPlace: reoRel.newIndex }); } - return this.update(updatedRelationship).pipe( - tap((relationshipRD: RemoteData) => { - if (relationshipRD.hasSucceeded) { - this.removeRelationshipItemsFromCacheByRelationship(relationship.id); - } - }) - ); + + const update$ = this.update(updatedRelationship); + + update$.pipe( + filter((relationshipRD: RemoteData) => relationshipRD.state === RemoteDataState.ResponsePending), + take(1), + ).subscribe((relationshipRD: RemoteData) => { + if (relationshipRD.state === RemoteDataState.ResponsePending) { + this.removeRelationshipItemsFromCacheByRelationship(reoRel.relationship.id); + } + }); + + return update$; } } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts index ce3a09689c..82f65c940f 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts @@ -340,16 +340,16 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo moveSelection(event: CdkDragDrop) { this.zone.runOutsideAngular(() => { moveItemInArray(this.reorderables, event.previousIndex, event.currentIndex); - const relationships = this.reorderables.map((reo: Reorderable, index: number) => { + const reorderables = this.reorderables.map((reo: Reorderable, index: number) => { reo.oldIndex = reo.getPlace(); reo.newIndex = index; return reo; } ); - return observableCombineLatest(relationships.map((rel: ReorderableRelationship) => { + return observableCombineLatest(reorderables.map((rel: ReorderableRelationship) => { console.log(rel); if (rel.oldIndex !== rel.newIndex) { - return this.relationshipService.updatePlace(rel.relationship, rel.newIndex, !rel.useLeftItem); + return this.relationshipService.updatePlace(rel); } else { return observableOf(undefined); } From 5234a7b01566a09994927c750f0f31a3250a7008 Mon Sep 17 00:00:00 2001 From: Art Lowel Date: Tue, 3 Dec 2019 15:09:29 +0100 Subject: [PATCH 07/14] fix loop for name variants as well --- src/app/core/data/data.service.ts | 1 + src/app/core/data/relationship.service.ts | 20 +++++++++++-------- .../relationship.effects.ts | 3 ++- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/app/core/data/data.service.ts b/src/app/core/data/data.service.ts index b8e511524d..189ffef6b8 100644 --- a/src/app/core/data/data.service.ts +++ b/src/app/core/data/data.service.ts @@ -236,6 +236,7 @@ export abstract class DataService { console.log(oldVersion); const operations = this.comparator.diff(oldVersion, object); if (isNotEmpty(operations)) { + console.log('operations', operations); this.objectCache.addPatch(object.self, operations); } return this.findByHref(object.self); diff --git a/src/app/core/data/relationship.service.ts b/src/app/core/data/relationship.service.ts index 21e5cd8794..d8cc027348 100644 --- a/src/app/core/data/relationship.service.ts +++ b/src/app/core/data/relationship.service.ts @@ -333,7 +333,7 @@ export class RelationshipService extends DataService { } public updateNameVariant(item1: Item, item2: Item, relationshipLabel: string, nameVariant: string): Observable> { - return this.getRelationshipByItemsAndLabel(item1, item2, relationshipLabel) + const update$ = this.getRelationshipByItemsAndLabel(item1, item2, relationshipLabel) .pipe( switchMap((relation: Relationship) => relation.relationshipType.pipe( @@ -354,13 +354,17 @@ export class RelationshipService extends DataService { } return this.update(updatedRelationship); }), - tap((relationshipRD: RemoteData) => { - if (relationshipRD.hasSucceeded) { - this.removeRelationshipItemsFromCache(item1); - this.removeRelationshipItemsFromCache(item2); - } - }), - ) + ); + + update$.pipe( + filter((relationshipRD: RemoteData) => relationshipRD.state === RemoteDataState.ResponsePending), + take(1), + ).subscribe(() => { + this.removeRelationshipItemsFromCache(item1); + this.removeRelationshipItemsFromCache(item2); + }); + + return update$ } public updatePlace(reoRel: ReorderableRelationship): Observable> { diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/relationship.effects.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/relationship.effects.ts index 7b530f39c5..a17e042c2b 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/relationship.effects.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/relationship.effects.ts @@ -3,6 +3,7 @@ import { Actions, Effect, ofType } from '@ngrx/effects'; import { debounceTime, map, mergeMap, take, tap } from 'rxjs/operators'; import { BehaviorSubject } from 'rxjs'; import { RelationshipService } from '../../../../../core/data/relationship.service'; +import { getSucceededRemoteData } from '../../../../../core/shared/operators'; import { AddRelationshipAction, RelationshipAction, RelationshipActionTypes, RemoveRelationshipAction, UpdateRelationshipAction } from './relationship.actions'; import { Item } from '../../../../../core/shared/item.model'; import { hasNoValue, hasValue, hasValueOperator } from '../../../../empty.util'; @@ -83,7 +84,7 @@ export class RelationshipEffects { this.nameVariantUpdates[identifier] = nameVariant; } else { this.relationshipService.updateNameVariant(item1, item2, relationshipType, nameVariant) - .pipe() + .pipe(getSucceededRemoteData()) .subscribe(); } } From 69d58c08819d038c04ed1bdb9861ecf3a7597885 Mon Sep 17 00:00:00 2001 From: lotte Date: Tue, 3 Dec 2019 16:37:58 +0100 Subject: [PATCH 08/14] removed console logs and reinstated thumbnails --- src/app/core/data/data.service.ts | 2 -- src/app/core/data/relationship.service.ts | 2 +- .../person/person-item-metadata-list-element.component.ts | 5 +---- ...nit-search-result-list-submission-element.component.html | 2 +- ...son-search-result-list-submission-element.component.html | 2 +- .../ds-dynamic-form-control-container.component.ts | 1 - .../existing-metadata-list-element.component.ts | 6 +----- 7 files changed, 5 insertions(+), 15 deletions(-) diff --git a/src/app/core/data/data.service.ts b/src/app/core/data/data.service.ts index 189ffef6b8..ddf2c3a1d5 100644 --- a/src/app/core/data/data.service.ts +++ b/src/app/core/data/data.service.ts @@ -233,10 +233,8 @@ export abstract class DataService { getSucceededRemoteData(), getRemoteDataPayload(), mergeMap((oldVersion: T) => { - console.log(oldVersion); const operations = this.comparator.diff(oldVersion, object); if (isNotEmpty(operations)) { - console.log('operations', operations); this.objectCache.addPatch(object.self, operations); } return this.findByHref(object.self); diff --git a/src/app/core/data/relationship.service.ts b/src/app/core/data/relationship.service.ts index d8cc027348..9bd59ce151 100644 --- a/src/app/core/data/relationship.service.ts +++ b/src/app/core/data/relationship.service.ts @@ -357,7 +357,7 @@ export class RelationshipService extends DataService { ); update$.pipe( - filter((relationshipRD: RemoteData) => relationshipRD.state === RemoteDataState.ResponsePending), + filter((relationshipRD: RemoteData) => relationshipRD.state === RemoteDataState.RequestPending), take(1), ).subscribe(() => { this.removeRelationshipItemsFromCache(item1); diff --git a/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.ts b/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.ts index b571348122..867b5890eb 100644 --- a/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.ts +++ b/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.ts @@ -11,8 +11,5 @@ import { ItemMetadataRepresentationListElementComponent } from '../../../../shar /** * The component for displaying an item of the type Person as a metadata field */ -export class PersonItemMetadataListElementComponent extends ItemMetadataRepresentationListElementComponent implements OnInit { - ngOnInit(): void { - console.log('this.metadataRepresentation', this.metadataRepresentation); - } +export class PersonItemMetadataListElementComponent extends ItemMetadataRepresentationListElementComponent { } diff --git a/src/app/entity-groups/research-entities/submission/item-list-elements/org-unit/org-unit-search-result-list-submission-element.component.html b/src/app/entity-groups/research-entities/submission/item-list-elements/org-unit/org-unit-search-result-list-submission-element.component.html index 61bcbc9a4f..b0fa714371 100644 --- a/src/app/entity-groups/research-entities/submission/item-list-elements/org-unit/org-unit-search-result-list-submission-element.component.html +++ b/src/app/entity-groups/research-entities/submission/item-list-elements/org-unit/org-unit-search-result-list-submission-element.component.html @@ -1,6 +1,6 @@
        - +
        - +
        diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts index 82f65c940f..f1b8bd40b5 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts @@ -347,7 +347,6 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo } ); return observableCombineLatest(reorderables.map((rel: ReorderableRelationship) => { - console.log(rel); if (rel.oldIndex !== rel.newIndex) { return this.relationshipService.updatePlace(rel); } else { diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.ts index c222feb3f0..a0de289a04 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.ts @@ -51,7 +51,7 @@ export class ReorderableRelationship extends Reorderable { templateUrl: './existing-metadata-list-element.component.html', styleUrls: ['./existing-metadata-list-element.component.scss'] }) -export class ExistingMetadataListElementComponent implements OnInit, OnChanges, OnDestroy { +export class ExistingMetadataListElementComponent implements OnChanges, OnDestroy { @Input() listId: string; @Input() submissionItem: Item; @Input() reoRel: ReorderableRelationship; @@ -71,10 +71,6 @@ export class ExistingMetadataListElementComponent implements OnInit, OnChanges, ) { } - ngOnInit(): void { - console.log('reoRel', this.reoRel); - } - ngOnChanges() { const item$ = this.reoRel.useLeftItem ? this.reoRel.relationship.leftItem : this.reoRel.relationship.rightItem; From 9d185e8a152d46600960faa7e70105f159bddf9f Mon Sep 17 00:00:00 2001 From: lotte Date: Fri, 20 Dec 2019 08:55:23 +0100 Subject: [PATCH 09/14] fixing tests --- src/app/core/data/data.service.spec.ts | 2 +- src/app/core/data/relationship.service.spec.ts | 4 ++-- src/app/core/data/relationship.service.ts | 2 +- .../object-select/item-select/item-select.component.spec.ts | 2 +- .../search-label/search-label.component.spec.ts | 5 +++-- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/app/core/data/data.service.spec.ts b/src/app/core/data/data.service.spec.ts index 98e5f7afaa..ca5f2cc12e 100644 --- a/src/app/core/data/data.service.spec.ts +++ b/src/app/core/data/data.service.spec.ts @@ -192,7 +192,7 @@ describe('DataService', () => { dso2.self = selfLink; dso2.metadata = [{ key: 'dc.title', value: name2 }]; - spyOn(service, 'findByHref').and.returnValues(createSuccessfulRemoteDataObject$(dso)); + spyOn(service, 'findByHref').and.returnValue(createSuccessfulRemoteDataObject$(dso)); spyOn(objectCache, 'addPatch'); }); diff --git a/src/app/core/data/relationship.service.spec.ts b/src/app/core/data/relationship.service.spec.ts index b33db80fbe..9287935f59 100644 --- a/src/app/core/data/relationship.service.spec.ts +++ b/src/app/core/data/relationship.service.spec.ts @@ -123,8 +123,8 @@ describe('RelationshipService', () => { it('should clear the related items their cache', () => { expect(objectCache.remove).toHaveBeenCalledWith(relatedItem1.self); expect(objectCache.remove).toHaveBeenCalledWith(item.self); - expect(requestService.removeByHrefSubstring).toHaveBeenCalledWith(relatedItem1.self); - expect(requestService.removeByHrefSubstring).toHaveBeenCalledWith(item.self); + expect(requestService.removeByHrefSubstring).toHaveBeenCalledWith(relatedItem1.uuid); + expect(requestService.removeByHrefSubstring).toHaveBeenCalledWith(item.uuid); }); }); diff --git a/src/app/core/data/relationship.service.ts b/src/app/core/data/relationship.service.ts index e155b1f90b..325bb59399 100644 --- a/src/app/core/data/relationship.service.ts +++ b/src/app/core/data/relationship.service.ts @@ -150,7 +150,7 @@ export class RelationshipService extends DataService { this.requestService.removeByHrefSubstring(item.uuid); combineLatest( this.objectCache.hasBySelfLinkObservable(item.self), - this.requestService.hasByHrefObservable(item.self) + this.requestService.hasByHrefObservable(item.uuid) ).pipe( filter(([existsInOC, existsInRC]) => !existsInOC && !existsInRC), take(1), diff --git a/src/app/shared/object-select/item-select/item-select.component.spec.ts b/src/app/shared/object-select/item-select/item-select.component.spec.ts index 26dd55f010..08305080ca 100644 --- a/src/app/shared/object-select/item-select/item-select.component.spec.ts +++ b/src/app/shared/object-select/item-select/item-select.component.spec.ts @@ -16,7 +16,7 @@ import { NO_ERRORS_SCHEMA } from '@angular/core'; import { By } from '@angular/platform-browser'; import { of } from 'rxjs/internal/observable/of'; -describe('ItemSelectComponent', () => { +fdescribe('ItemSelectComponent', () => { let comp: ItemSelectComponent; let fixture: ComponentFixture; let objectSelectService: ObjectSelectService; diff --git a/src/app/shared/search/search-labels/search-label/search-label.component.spec.ts b/src/app/shared/search/search-labels/search-label/search-label.component.spec.ts index 0b382015af..5de87be3bc 100644 --- a/src/app/shared/search/search-labels/search-label/search-label.component.spec.ts +++ b/src/app/shared/search/search-labels/search-label/search-label.component.spec.ts @@ -4,7 +4,7 @@ import { TranslateModule } from '@ngx-translate/core'; import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { Observable, of as observableOf } from 'rxjs'; -import { Params } from '@angular/router'; +import { Params, Router } from '@angular/router'; import { SearchLabelComponent } from './search-label.component'; import { ObjectKeysPipe } from '../../../utils/object-keys-pipe'; import { SEARCH_CONFIG_SERVICE } from '../../../../+my-dspace-page/my-dspace-page.component'; @@ -39,7 +39,8 @@ describe('SearchLabelComponent', () => { declarations: [SearchLabelComponent, ObjectKeysPipe], providers: [ { provide: SearchService, useValue: new SearchServiceStub(searchLink) }, - { provide: SEARCH_CONFIG_SERVICE, useValue: new SearchConfigurationServiceStub() } + { provide: SEARCH_CONFIG_SERVICE, useValue: new SearchConfigurationServiceStub() }, + { provide: Router, useValue: {}} // { provide: SearchConfigurationService, useValue: {getCurrentFrontendFilters : () => observableOf({})} } ], schemas: [NO_ERRORS_SCHEMA] From 65b648b00016a1a3bd76e515e8ec9465f6ee5ca7 Mon Sep 17 00:00:00 2001 From: lotte Date: Fri, 20 Dec 2019 16:48:40 +0100 Subject: [PATCH 10/14] fixed existing tests --- ...ng-metadata-list-element.component.spec.ts | 12 +++- ...xisting-metadata-list-element.component.ts | 5 +- .../item-select/item-select.component.spec.ts | 2 +- .../submission-form-collection.component.ts | 59 ++++++++++++------- 4 files changed, 53 insertions(+), 25 deletions(-) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.spec.ts index 7172653557..1b2f471f0b 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.spec.ts @@ -1,6 +1,9 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { ExistingMetadataListElementComponent } from './existing-metadata-list-element.component'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { SelectableListService } from '../../../../object-list/selectable-list/selectable-list.service'; +import { Store } from '@ngrx/store'; describe('ExistingMetadataListElementComponent', () => { let component: ExistingMetadataListElementComponent; @@ -8,9 +11,14 @@ describe('ExistingMetadataListElementComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ - declarations: [ ExistingMetadataListElementComponent ] + declarations: [ExistingMetadataListElementComponent], + providers: [ + { provide: SelectableListService, useValue: {} }, + { provide: Store, useValue: {} }, + ], + schemas: [NO_ERRORS_SCHEMA] }) - .compileComponents(); + .compileComponents(); })); beforeEach(() => { diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.ts index a0de289a04..d2b519b9a3 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.ts @@ -15,11 +15,13 @@ import { Store } from '@ngrx/store'; import { AppState } from '../../../../../app.reducer'; import { ItemSearchResult } from '../../../../object-collection/shared/item-search-result.model'; +// tslint:disable:max-classes-per-file export abstract class Reorderable { constructor(public oldIndex?: number, public newIndex?: number) { } abstract getId(): string; + abstract getPlace(): number; } @@ -84,7 +86,7 @@ export class ExistingMetadataListElementComponent implements OnChanges, OnDestro 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 }); - this.metadataRepresentation = Object.assign( + this.metadataRepresentation = Object.assign( new ItemMetadataRepresentation(metadataRepresentationMD), this.relatedItem ) @@ -107,3 +109,4 @@ export class ExistingMetadataListElementComponent implements OnChanges, OnDestro } } +// tslint:enable:max-classes-per-file diff --git a/src/app/shared/object-select/item-select/item-select.component.spec.ts b/src/app/shared/object-select/item-select/item-select.component.spec.ts index 08305080ca..26dd55f010 100644 --- a/src/app/shared/object-select/item-select/item-select.component.spec.ts +++ b/src/app/shared/object-select/item-select/item-select.component.spec.ts @@ -16,7 +16,7 @@ import { NO_ERRORS_SCHEMA } from '@angular/core'; import { By } from '@angular/platform-browser'; import { of } from 'rxjs/internal/observable/of'; -fdescribe('ItemSelectComponent', () => { +describe('ItemSelectComponent', () => { let comp: ItemSelectComponent; let fixture: ComponentFixture; let objectSelectService: ObjectSelectService; diff --git a/src/app/submission/form/collection/submission-form-collection.component.ts b/src/app/submission/form/collection/submission-form-collection.component.ts index 88bc4904d3..f84764d6a4 100644 --- a/src/app/submission/form/collection/submission-form-collection.component.ts +++ b/src/app/submission/form/collection/submission-form-collection.component.ts @@ -1,8 +1,28 @@ -import { ChangeDetectorRef, Component, EventEmitter, HostListener, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core'; +import { + ChangeDetectorRef, + Component, + EventEmitter, + HostListener, + Input, + OnChanges, + OnInit, + Output, + SimpleChanges +} from '@angular/core'; import { FormControl } from '@angular/forms'; import { BehaviorSubject, combineLatest, Observable, of as observableOf, Subscription } from 'rxjs'; -import { debounceTime, distinctUntilChanged, filter, map, mergeMap, reduce, startWith, flatMap, find } from 'rxjs/operators'; +import { + debounceTime, + distinctUntilChanged, + filter, + find, + flatMap, + map, + mergeMap, + reduce, + startWith +} from 'rxjs/operators'; import { Collection } from '../../../core/shared/collection.model'; import { CommunityDataService } from '../../../core/data/community-data.service'; @@ -197,23 +217,21 @@ export class SubmissionFormCollectionComponent implements OnChanges, OnInit { find((communities: RemoteData>) => isNotEmpty(communities.payload)), mergeMap((communities: RemoteData>) => communities.payload.page)); - const listCollection$ = observableOf([]); - - // const listCollection$ = communities$.pipe( - // flatMap((communityData: Community) => { - // return this.collectionDataService.getAuthorizedCollectionByCommunity(communityData.uuid, findOptions).pipe( - // find((collections: RemoteData>) => !collections.isResponsePending && collections.hasSucceeded), - // mergeMap((collections: RemoteData>) => collections.payload.page), - // filter((collectionData: Collection) => isNotEmpty(collectionData)), - // 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([]) - // ); + const listCollection$ = communities$.pipe( + flatMap((communityData: Community) => { + return this.collectionDataService.getAuthorizedCollectionByCommunity(communityData.uuid, findOptions).pipe( + find((collections: RemoteData>) => !collections.isResponsePending && collections.hasSucceeded), + mergeMap((collections: RemoteData>) => collections.payload.page), + filter((collectionData: Collection) => isNotEmpty(collectionData)), + 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([]) + ); const searchTerm$ = this.searchField.valueChanges.pipe( debounceTime(200), @@ -229,8 +247,7 @@ export class SubmissionFormCollectionComponent implements OnChanges, OnInit { } else { return listCollection.filter((v) => v.collection.name.toLowerCase().indexOf(searchTerm.toLowerCase()) > -1).slice(0, 5); } - }) - ); + })); } } } From 4dd66073fcb46bac527a2dee9d48b22c36ba3665 Mon Sep 17 00:00:00 2001 From: lotte Date: Mon, 23 Dec 2019 11:19:23 +0100 Subject: [PATCH 11/14] added tests for new component --- ...ng-metadata-list-element.component.spec.ts | 67 +++++++++++++++++-- ...xisting-metadata-list-element.component.ts | 1 - 2 files changed, 63 insertions(+), 5 deletions(-) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.spec.ts index 1b2f471f0b..fa13febcd1 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.spec.ts @@ -1,20 +1,59 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { ExistingMetadataListElementComponent } from './existing-metadata-list-element.component'; +import { ExistingMetadataListElementComponent, Reorderable, ReorderableRelationship } from './existing-metadata-list-element.component'; import { NO_ERRORS_SCHEMA } from '@angular/core'; import { SelectableListService } from '../../../../object-list/selectable-list/selectable-list.service'; -import { Store } from '@ngrx/store'; +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'; describe('ExistingMetadataListElementComponent', () => { let component: ExistingMetadataListElementComponent; let fixture: ComponentFixture; + 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; + + 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 }); + + relationship = Object.assign(new Relationship(), { leftItem: leftItemRD$, rightItem: rightItemRD$ }); + reoRel = new ReorderableRelationship(relationship, true); + } beforeEach(async(() => { + init(); TestBed.configureTestingModule({ declarations: [ExistingMetadataListElementComponent], providers: [ - { provide: SelectableListService, useValue: {} }, - { provide: Store, useValue: {} }, + { provide: SelectableListService, useValue: selectionService }, + { provide: Store, useValue: store }, ], schemas: [NO_ERRORS_SCHEMA] }) @@ -24,10 +63,30 @@ describe('ExistingMetadataListElementComponent', () => { beforeEach(() => { fixture = TestBed.createComponent(ExistingMetadataListElementComponent); component = fixture.componentInstance; + component.listId = listID; + component.submissionItem = submissionItem; + component.reoRel = reoRel; + component.metadataFields = metadataFields; + component.relationshipOptions = relationshipOptions; 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); + expect(store.dispatch).toHaveBeenCalledWith(action); + + }); + }) }); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.ts index d2b519b9a3..3c2c5dbe8b 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.ts @@ -76,7 +76,6 @@ export class ExistingMetadataListElementComponent implements OnChanges, OnDestro ngOnChanges() { const item$ = this.reoRel.useLeftItem ? this.reoRel.relationship.leftItem : this.reoRel.relationship.rightItem; - this.subs.push(item$.pipe( getAllSucceededRemoteData(), getRemoteDataPayload(), From f9fa8f0347826fd3cde72588643d51990e91cbc7 Mon Sep 17 00:00:00 2001 From: lotte Date: Wed, 8 Jan 2020 10:34:24 +0100 Subject: [PATCH 12/14] added typedoc --- src/app/core/data/relationship.service.ts | 5 +++++ .../ds-dynamic-form-control-container.component.ts | 5 +++++ .../existing-metadata-list-element.component.ts | 12 ++++++++++++ 3 files changed, 22 insertions(+) diff --git a/src/app/core/data/relationship.service.ts b/src/app/core/data/relationship.service.ts index 325bb59399..35ddd700eb 100644 --- a/src/app/core/data/relationship.service.ts +++ b/src/app/core/data/relationship.service.ts @@ -390,6 +390,11 @@ export class RelationshipService extends DataService { return update$ } + /** + * Method to update the the right or left place of a relationship + * The useLeftItem field in the reorderable relationship determines which place should be updated + * @param reoRel + */ public updatePlace(reoRel: ReorderableRelationship): Observable> { let updatedRelationship; if (reoRel.useLeftItem) { diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts index c8903b19ee..01b13e60da 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts @@ -343,6 +343,11 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo modalComp.item = this.item; } + /** + * Method to move a relationship inside the list of relationships + * This will update the view and update the right or left place field of the relationships in the list + * @param event + */ moveSelection(event: CdkDragDrop) { this.zone.runOutsideAngular(() => { moveItemInArray(this.reorderables, event.previousIndex, event.currentIndex); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.ts index 3c2c5dbe8b..09aaa253c6 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.ts @@ -16,6 +16,9 @@ import { AppState } from '../../../../../app.reducer'; import { ItemSearchResult } from '../../../../object-collection/shared/item-search-result.model'; // 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) { } @@ -25,6 +28,9 @@ export abstract class Reorderable { abstract getPlace(): number; } +/** + * Represents a single relationship that can be reordered in a list of multiple relationships + */ export class ReorderableRelationship extends Reorderable { relationship: Relationship; useLeftItem: boolean; @@ -48,6 +54,9 @@ export class ReorderableRelationship extends Reorderable { } } +/** + * Represents a single existing relationship value as metadata in submission + */ @Component({ selector: 'ds-existing-metadata-list-element', templateUrl: './existing-metadata-list-element.component.html', @@ -93,6 +102,9 @@ export class ExistingMetadataListElementComponent implements OnChanges, OnDestro })); } + /** + * 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)) From 1bc718237247afd3732c52af85c182211031f299 Mon Sep 17 00:00:00 2001 From: lotte Date: Tue, 14 Jan 2020 14:04:42 +0100 Subject: [PATCH 13/14] fixes after merge --- src/app/core/data/data.service.ts | 2 +- src/app/core/data/relationship.service.ts | 4 ++-- .../ds-dynamic-form-control-container.component.ts | 11 ++++++----- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/app/core/data/data.service.ts b/src/app/core/data/data.service.ts index c8dac45e75..d55b7353eb 100644 --- a/src/app/core/data/data.service.ts +++ b/src/app/core/data/data.service.ts @@ -252,7 +252,7 @@ export abstract class DataService { return oldVersion$.pipe( getSucceededRemoteData(), getRemoteDataPayload(), - mergeMap((oldVersion: NormalizedObject) => { + mergeMap((oldVersion: T) => { const operations = this.comparator.diff(oldVersion, object); if (isNotEmpty(operations)) { this.objectCache.addPatch(object.self, operations); diff --git a/src/app/core/data/relationship.service.ts b/src/app/core/data/relationship.service.ts index c262de6370..d6993ebcee 100644 --- a/src/app/core/data/relationship.service.ts +++ b/src/app/core/data/relationship.service.ts @@ -2,7 +2,7 @@ import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { MemoizedSelector, select, Store } from '@ngrx/store'; import { combineLatest, combineLatest as observableCombineLatest } from 'rxjs'; -import { distinctUntilChanged, filter, map, mergeMap, startWith, switchMap, take, tap } from 'rxjs'; +import { distinctUntilChanged, filter, map, mergeMap, startWith, switchMap, take, tap } from 'rxjs/operators'; import { compareArraysUsingIds, paginatedRelationsToItems, relationsToItems } from '../../+item-page/simple/item-types/shared/item-relationships-utils'; import { AppState, keySelector } from '../../app.reducer'; import { hasValue, hasValueOperator, isNotEmpty, isNotEmptyOperator } from '../../shared/empty.util'; @@ -356,7 +356,7 @@ export class RelationshipService extends DataService { * @param nameVariant The name variant to set for the matching relationship */ public updateNameVariant(item1: Item, item2: Item, relationshipLabel: string, nameVariant: string): Observable> { - const update$ = this.getRelationshipByItemsAndLabel(item1, item2, relationshipLabel) + const update$: Observable> = this.getRelationshipByItemsAndLabel(item1, item2, relationshipLabel) .pipe( switchMap((relation: Relationship) => relation.relationshipType.pipe( diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts index f7ca14574d..22376502e7 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts @@ -75,7 +75,7 @@ import { DsDynamicFormArrayComponent } from './models/array-group/dynamic-form-a 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 { DsDatePickerInlineComponent } from './models/date-picker-inline/dynamic-date-picker-inline.component'; -import { map, startWith, switchMap, take } from 'rxjs/operators'; +import { map, startWith, switchMap, find } from 'rxjs/operators'; import { combineLatest as observableCombineLatest, Observable, of as observableOf, Subscription } from 'rxjs'; import { SearchResult } from '../../../search/search-result.model'; import { DSpaceObject } from '../../../../core/shared/dspace-object.model'; @@ -353,20 +353,21 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo moveSelection(event: CdkDragDrop) { this.zone.runOutsideAngular(() => { moveItemInArray(this.reorderables, event.previousIndex, event.currentIndex); - const reorderables = this.reorderables.map((reo: Reorderable, index: number) => { + const reorderables: Reorderable[] = this.reorderables.map((reo: Reorderable, index: number) => { reo.oldIndex = reo.getPlace(); reo.newIndex = index; return reo; } ); - return observableCombineLatest(reorderables.map((rel: ReorderableRelationship) => { + observableCombineLatest( + reorderables.map((rel: ReorderableRelationship) => { if (rel.oldIndex !== rel.newIndex) { return this.relationshipService.updatePlace(rel); } else { - return observableOf(undefined); + return observableOf(undefined) as Observable>; } }) - ).pipe(getSucceededRemoteData()).subscribe(); + ).subscribe(); }) } From 78f9d62e004217d6c333f66e47a0a15a664a695f Mon Sep 17 00:00:00 2001 From: lotte Date: Tue, 14 Jan 2020 14:42:14 +0100 Subject: [PATCH 14/14] fixed linting error --- src/app/shared/sidebar/filter/sidebar-filter.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/shared/sidebar/filter/sidebar-filter.service.ts b/src/app/shared/sidebar/filter/sidebar-filter.service.ts index 60fc40d0a8..b67de24f9e 100644 --- a/src/app/shared/sidebar/filter/sidebar-filter.service.ts +++ b/src/app/shared/sidebar/filter/sidebar-filter.service.ts @@ -16,7 +16,7 @@ import { hasValue } from '../../empty.util'; @Injectable() export class SidebarFilterService { - constructor(private store:Store) { + constructor(private store: Store) { } /**