From d9c177b10018f28493f18976daa761fa307098e4 Mon Sep 17 00:00:00 2001 From: Corrado Lombardi Date: Thu, 24 Sep 2020 13:02:38 +0200 Subject: [PATCH 01/43] added RequestService --- .../create-collection-page.component.ts | 6 ++++-- .../delete-collection-page.component.ts | 6 ++++-- .../create-community-page.component.ts | 6 ++++-- .../delete-community-page.component.ts | 7 +++++-- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/app/+collection-page/create-collection-page/create-collection-page.component.ts b/src/app/+collection-page/create-collection-page/create-collection-page.component.ts index ae31b94c3d..a38739c407 100644 --- a/src/app/+collection-page/create-collection-page/create-collection-page.component.ts +++ b/src/app/+collection-page/create-collection-page/create-collection-page.component.ts @@ -7,6 +7,7 @@ import { Collection } from '../../core/shared/collection.model'; import { CollectionDataService } from '../../core/data/collection-data.service'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { TranslateService } from '@ngx-translate/core'; +import {RequestService} from '../../core/data/request.service'; /** * Component that represents the page where a user can create a new Collection @@ -26,8 +27,9 @@ export class CreateCollectionPageComponent extends CreateComColPageComponent Date: Thu, 24 Sep 2020 13:03:29 +0200 Subject: [PATCH 02/43] cache cleared with parent community reference once a collection or a community is created or deleted --- .../create-comcol-page.component.ts | 70 +++++++++++++------ .../delete-comcol-page.component.ts | 47 ++++++++++--- 2 files changed, 85 insertions(+), 32 deletions(-) diff --git a/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.ts b/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.ts index 4a7cd9afb1..f55a7f0156 100644 --- a/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.ts +++ b/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.ts @@ -2,18 +2,24 @@ import { Component, OnInit } from '@angular/core'; import { Router } from '@angular/router'; import { TranslateService } from '@ngx-translate/core'; import { Observable } from 'rxjs'; -import { take } from 'rxjs/operators'; +import {flatMap, map, take} from 'rxjs/operators'; import { ComColDataService } from '../../../core/data/comcol-data.service'; import { CommunityDataService } from '../../../core/data/community-data.service'; import { RemoteData } from '../../../core/data/remote-data'; import { RouteService } from '../../../core/services/route.service'; import { Community } from '../../../core/shared/community.model'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; -import { getSucceededRemoteData } from '../../../core/shared/operators'; +import { + getFirstSucceededRemoteDataPayload, + getRemoteDataPayload, + getSucceededRemoteData +} from '../../../core/shared/operators'; import { ResourceType } from '../../../core/shared/resource-type'; -import { hasValue, isNotEmpty, isNotUndefined } from '../../empty.util'; +import {hasValue, isEmpty, isNotEmpty, isNotUndefined} from '../../empty.util'; import { NotificationsService } from '../../notifications/notifications.service'; import { RequestParam } from '../../../core/cache/models/request-param.model'; +import {RequestService} from '../../../core/data/request.service'; +import {Collection} from '../../../core/shared/collection.model'; /** * Component representing the create page for communities and collections @@ -54,7 +60,8 @@ export class CreateComColPageComponent implements protected routeService: RouteService, protected router: Router, protected notificationsService: NotificationsService, - protected translate: TranslateService + protected translate: TranslateService, + protected requestService: RequestService ) { } @@ -76,25 +83,29 @@ export class CreateComColPageComponent implements const dso = event.dso; const uploader = event.uploader; - this.parentUUID$.pipe(take(1)).subscribe((uuid: string) => { + this.parentUUID$.pipe( + take(1), + flatMap((uuid: string) => { const params = uuid ? [new RequestParam('parent', uuid)] : []; - this.dsoDataService.create(dso, ...params) - .pipe(getSucceededRemoteData()) - .subscribe((dsoRD: RemoteData) => { - if (isNotUndefined(dsoRD)) { - this.newUUID = dsoRD.payload.uuid; - if (uploader.queue.length > 0) { - this.dsoDataService.getLogoEndpoint(this.newUUID).pipe(take(1)).subscribe((href: string) => { - uploader.options.url = href; - uploader.uploadAll(); - }); - } else { - this.navigateToNewPage(); - } - this.notificationsService.success(null, this.translate.get(this.type.value + '.create.notifications.success')); + return this.dsoDataService.create(dso, ...params) + .pipe(getFirstSucceededRemoteDataPayload() + ) + })) + .subscribe((dsoRD: TDomain) => { + if (isNotUndefined(dsoRD)) { + this.newUUID = dsoRD.uuid; + if (uploader.queue.length > 0) { + this.dsoDataService.getLogoEndpoint(this.newUUID).pipe(take(1)).subscribe((href: string) => { + uploader.options.url = href; + uploader.uploadAll(); + }); + } else { + this.navigateToNewPage(); } - }); - }); + this.refreshCache(dsoRD); + } + this.notificationsService.success(null, this.translate.get(this.type.value + '.create.notifications.success')); + }); } /** @@ -106,4 +117,21 @@ export class CreateComColPageComponent implements } } + private refreshCache(dso: TDomain) { + const parentCommunityUrl = this.parentCommunityUrl(dso as any); + if (!hasValue(parentCommunityUrl)) { + return; + } + this.dsoDataService.findByHref(parentCommunityUrl).pipe( + getSucceededRemoteData(), + getRemoteDataPayload(), + map((pc: TDomain) => isEmpty(pc) ? 'communities/search/top' : pc.id), + take(1) + ).subscribe((href: string) => this.requestService.removeByHrefSubstring(href)); + } + + private parentCommunityUrl(dso: Collection | Community) { + const parentCommunity = dso._links.parentCommunity; + return isNotEmpty(parentCommunity) ? parentCommunity.href : null; + } } diff --git a/src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.ts b/src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.ts index d07d7be032..29ec4f7b19 100644 --- a/src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.ts +++ b/src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.ts @@ -1,13 +1,18 @@ -import { Component, OnInit } from '@angular/core'; -import { Observable } from 'rxjs'; -import { ActivatedRoute, Router } from '@angular/router'; -import { RemoteData } from '../../../core/data/remote-data'; -import { first, map } from 'rxjs/operators'; -import { DataService } from '../../../core/data/data.service'; -import { DSpaceObject } from '../../../core/shared/dspace-object.model'; -import { NotificationsService } from '../../notifications/notifications.service'; -import { TranslateService } from '@ngx-translate/core'; -import { RestResponse } from '../../../core/cache/response.models'; +import {Component, OnInit} from '@angular/core'; +import {Observable} from 'rxjs'; +import {ActivatedRoute, Router} from '@angular/router'; +import {RemoteData} from '../../../core/data/remote-data'; +import {first, map, take} from 'rxjs/operators'; +import {DataService} from '../../../core/data/data.service'; +import {DSpaceObject} from '../../../core/shared/dspace-object.model'; +import {NotificationsService} from '../../notifications/notifications.service'; +import {TranslateService} from '@ngx-translate/core'; +import {RestResponse} from '../../../core/cache/response.models'; +import {hasValue, isEmpty, isNotEmpty} from '../../empty.util'; +import {RequestService} from '../../../core/data/request.service'; +import {getRemoteDataPayload, getSucceededRemoteData} from '../../../core/shared/operators'; +import {Community} from '../../../core/shared/community.model'; +import {Collection} from '../../../core/shared/collection.model'; /** * Component representing the delete page for communities and collections @@ -31,7 +36,8 @@ export class DeleteComColPageComponent implements protected router: Router, protected route: ActivatedRoute, protected notifications: NotificationsService, - protected translate: TranslateService + protected translate: TranslateService, + protected requestService: RequestService ) { } @@ -50,6 +56,7 @@ export class DeleteComColPageComponent implements if (response.isSuccessful) { const successMessage = this.translate.instant((dso as any).type + '.delete.notification.success'); this.notifications.success(successMessage) + this.refreshCache(dso); } else { const errorMessage = this.translate.instant((dso as any).type + '.delete.notification.fail'); this.notifications.error(errorMessage) @@ -65,4 +72,22 @@ export class DeleteComColPageComponent implements onCancel(dso: TDomain) { this.router.navigate([this.frontendURL + '/' + dso.uuid + '/edit']); } + + private refreshCache(dso: TDomain) { + const parentCommunity = this.parentCommunityUrl(dso as any); + if (!hasValue(parentCommunity)) { + return; + } + this.dsoDataService.findByHref(parentCommunity).pipe( + getSucceededRemoteData(), + getRemoteDataPayload(), + map((pc: TDomain) => isEmpty(pc) ? 'communities/search/top' : pc.id ), + take(1) + ).subscribe((id: string) => this.requestService.removeByHrefSubstring(id)); + } + + private parentCommunityUrl(dso: Collection | Community): string { + const parentCommunity = dso._links.parentCommunity; + return isNotEmpty(parentCommunity) ? parentCommunity.href : null; + } } From 1127b363e90ba4377cab130d8cdea42c75d3699a Mon Sep 17 00:00:00 2001 From: Corrado Lombardi Date: Thu, 22 Oct 2020 15:45:39 +0200 Subject: [PATCH 03/43] [CSTPER-66] function to get succeeded or no content response --- src/app/core/shared/operators.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/app/core/shared/operators.ts b/src/app/core/shared/operators.ts index ad2588f2b9..203f66b074 100644 --- a/src/app/core/shared/operators.ts +++ b/src/app/core/shared/operators.ts @@ -75,6 +75,11 @@ export const getSucceededRemoteWithNotEmptyData = () => (source: Observable>): Observable> => source.pipe(find((rd: RemoteData) => rd.hasSucceeded && isNotEmpty(rd.payload))); +export const getSucceededOrNoContentResponse = () => + (source: Observable>): Observable> => + source.pipe(find((rd: RemoteData) => rd.hasSucceeded || rd.hasNoContent)); + + /** * Get the first successful remotely retrieved object * From e1cce311e8a24f1183c377104fd6c31017ebf441 Mon Sep 17 00:00:00 2001 From: Corrado Lombardi Date: Thu, 22 Oct 2020 15:46:05 +0200 Subject: [PATCH 04/43] [CSTPER-66] utility method to check if remote data has no content --- src/app/core/data/remote-data.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/app/core/data/remote-data.ts b/src/app/core/data/remote-data.ts index 8502c8ba1d..17fbe6a8a6 100644 --- a/src/app/core/data/remote-data.ts +++ b/src/app/core/data/remote-data.ts @@ -55,4 +55,8 @@ export class RemoteData { return this.state === RemoteDataState.Success; } + get hasNoContent(): boolean { + return this.statusCode === 204; + } + } From 20c7afce06532c033552f69e35fdb183c2aac091 Mon Sep 17 00:00:00 2001 From: Corrado Lombardi Date: Thu, 22 Oct 2020 15:46:29 +0200 Subject: [PATCH 05/43] [CSTPER-66] utility functions to create remote data object without content --- src/app/shared/remote-data.utils.ts | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/app/shared/remote-data.utils.ts b/src/app/shared/remote-data.utils.ts index ce278e0229..580b68673b 100644 --- a/src/app/shared/remote-data.utils.ts +++ b/src/app/shared/remote-data.utils.ts @@ -69,3 +69,24 @@ export function createPendingRemoteDataObject(object?: T): RemoteData { export function createPendingRemoteDataObject$(object?: T): Observable> { return observableOf(createPendingRemoteDataObject(object)); } + +/** + * Method to create a remote data object with no content + */ +export function createNoContentRemoteDataObject(): RemoteData { + return new RemoteData( + true, + true, + true, + null, + null, + 204 + ); +} + +/** + * Method to create a remote data object that has succeeded with no content, wrapped in an observable + */ +export function createNoContentRemoteDataObject$(): Observable> { + return observableOf(createNoContentRemoteDataObject()); +} From be6a6a2f62cccd34d641882840103302dd99879c Mon Sep 17 00:00:00 2001 From: Corrado Lombardi Date: Thu, 22 Oct 2020 15:50:44 +0200 Subject: [PATCH 06/43] [CSTPER-66] when a community or a collection is created or deleted, angular cache is refreshed so that in case of new community or collection it appears immediately in pages where communities and collections lists are displayed, in case of community or collection deletion deleted community or collection does not appear anymore in pages where communities and collections lists are displayed. --- .../create-comcol-page.component.spec.ts | 108 +++++++++++++++++- .../create-comcol-page.component.ts | 14 +-- .../delete-comcol-page.component.spec.ts | 107 ++++++++++++++++- .../delete-comcol-page.component.ts | 21 ++-- 4 files changed, 226 insertions(+), 24 deletions(-) diff --git a/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.spec.ts b/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.spec.ts index 780589d0c5..d2335f623f 100644 --- a/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.spec.ts +++ b/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.spec.ts @@ -2,7 +2,7 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { CommunityDataService } from '../../../core/data/community-data.service'; import { RouteService } from '../../../core/services/route.service'; import { Router } from '@angular/router'; -import { TranslateModule } from '@ngx-translate/core'; +import {TranslateModule, TranslateService} from '@ngx-translate/core'; import { of as observableOf } from 'rxjs'; import { Community } from '../../../core/shared/community.model'; import { SharedModule } from '../../shared.module'; @@ -12,12 +12,14 @@ import { NO_ERRORS_SCHEMA } from '@angular/core'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { CreateComColPageComponent } from './create-comcol-page.component'; import { - createFailedRemoteDataObject$, + createFailedRemoteDataObject$, createNoContentRemoteDataObject$, createSuccessfulRemoteDataObject$ } from '../../remote-data.utils'; import { ComColDataService } from '../../../core/data/comcol-data.service'; import { NotificationsService } from '../../notifications/notifications.service'; import { NotificationsServiceStub } from '../../testing/notifications-service.stub'; +import { RequestService } from '../../../core/data/request.service'; +import {getTestScheduler} from 'jasmine-marbles'; describe('CreateComColPageComponent', () => { let comp: CreateComColPageComponent; @@ -29,9 +31,11 @@ describe('CreateComColPageComponent', () => { let community; let newCommunity; + let parentCommunity; let communityDataServiceStub; let routeServiceStub; let routerStub; + let requestServiceStub; const logoEndpoint = 'rest/api/logo/endpoint'; @@ -44,6 +48,15 @@ describe('CreateComColPageComponent', () => { }] }); + parentCommunity = Object.assign(new Community(), { + uuid: 'a20da287-e174-466a-9926-f66as300d399', + id: 'a20da287-e174-466a-9926-f66as300d399', + metadata: [{ + key: 'dc.title', + value: 'parent community' + }] + }); + newCommunity = Object.assign(new Community(), { uuid: '1ff59938-a69a-4e62-b9a4-718569c55d48', metadata: [{ @@ -61,7 +74,8 @@ describe('CreateComColPageComponent', () => { }] })), create: (com, uuid?) => createSuccessfulRemoteDataObject$(newCommunity), - getLogoEndpoint: () => observableOf(logoEndpoint) + getLogoEndpoint: () => observableOf(logoEndpoint), + findByHref: () => null }; routeServiceStub = { @@ -71,6 +85,10 @@ describe('CreateComColPageComponent', () => { navigate: (commands) => commands }; + requestServiceStub = jasmine.createSpyObj('RequestService', { + removeByHrefSubstring: jasmine.createSpy('removeByHrefSubstring'), + }); + } beforeEach(async(() => { @@ -82,7 +100,9 @@ describe('CreateComColPageComponent', () => { { provide: CommunityDataService, useValue: communityDataServiceStub }, { provide: RouteService, useValue: routeServiceStub }, { provide: Router, useValue: routerStub }, - { provide: NotificationsService, useValue: new NotificationsServiceStub() } + { provide: NotificationsService, useValue: new NotificationsServiceStub() }, + { provide: TranslateService, useValue: {}}, + { provide: RequestService, useValue: requestServiceStub} ], schemas: [NO_ERRORS_SCHEMA] }).compileComponents(); @@ -123,19 +143,23 @@ describe('CreateComColPageComponent', () => { }; }); - it('should navigate when successful', () => { + it('should navigate and refresh cache when successful', () => { spyOn(router, 'navigate'); + spyOn((comp as any), 'refreshCache'); comp.onSubmit(data); fixture.detectChanges(); expect(router.navigate).toHaveBeenCalled(); + expect((comp as any).refreshCache).toHaveBeenCalled(); }); - it('should not navigate on failure', () => { + it('should neither navigate nor refresh cache on failure', () => { spyOn(router, 'navigate'); spyOn(dsoDataService, 'create').and.returnValue(createFailedRemoteDataObject$(newCommunity)); + spyOn((comp as any), 'refreshCache') comp.onSubmit(data); fixture.detectChanges(); expect(router.navigate).not.toHaveBeenCalled(); + expect((comp as any).refreshCache).not.toHaveBeenCalled(); }); }); @@ -182,5 +206,77 @@ describe('CreateComColPageComponent', () => { expect(data.uploader.uploadAll).toHaveBeenCalled(); }); }); + + describe('cache refresh', () => { + let scheduler; + let communityWithoutParentHref; + + beforeEach(() => { + scheduler = getTestScheduler(); + + }) + describe('cache refreshed top level community', () => { + beforeEach(() => { + spyOn(dsoDataService, 'findByHref').and.returnValue(createNoContentRemoteDataObject$()); + data = { + dso: Object.assign(new Community(), { + metadata: [{ + key: 'dc.title', + value: 'top level community' + }] + }), + _links: { + parentCommunity: { + href: 'topLevel/parentCommunity' + } + } + }; + communityWithoutParentHref = { + dso: Object.assign(new Community(), { + metadata: [{ + key: 'dc.title', + value: 'top level community' + }] + }), + _links: {} + }; + }); + it('top level community cache refreshed', () => { + scheduler.schedule(() => (comp as any).refreshCache(data)); + scheduler.flush(); + expect(requestServiceStub.removeByHrefSubstring).toHaveBeenCalledWith('communities/search/top'); + }); + it('top level community without parent link, cache not refreshed', () => { + scheduler.schedule(() => (comp as any).refreshCache(communityWithoutParentHref)); + scheduler.flush(); + expect(requestServiceStub.removeByHrefSubstring).not.toHaveBeenCalled(); + }); + }); + + describe('cache refreshed child community', () => { + beforeEach(() => { + spyOn(dsoDataService, 'findByHref').and.returnValue(createSuccessfulRemoteDataObject$(parentCommunity)); + data = { + dso: Object.assign(new Community(), { + metadata: [{ + key: 'dc.title', + value: 'child community' + }] + }), + _links: { + parentCommunity: { + href: 'child/parentCommunity' + } + } + }; + }); + it('child level community cache refreshed', () => { + scheduler.schedule(() => (comp as any).refreshCache(data)); + scheduler.flush(); + expect(requestServiceStub.removeByHrefSubstring).toHaveBeenCalledWith('a20da287-e174-466a-9926-f66as300d399'); + }); + }); + }); + }); }); diff --git a/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.ts b/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.ts index f55a7f0156..336998aab3 100644 --- a/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.ts +++ b/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.ts @@ -11,8 +11,7 @@ import { Community } from '../../../core/shared/community.model'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { getFirstSucceededRemoteDataPayload, - getRemoteDataPayload, - getSucceededRemoteData + getSucceededOrNoContentResponse, } from '../../../core/shared/operators'; import { ResourceType } from '../../../core/shared/resource-type'; import {hasValue, isEmpty, isNotEmpty, isNotUndefined} from '../../empty.util'; @@ -123,11 +122,12 @@ export class CreateComColPageComponent implements return; } this.dsoDataService.findByHref(parentCommunityUrl).pipe( - getSucceededRemoteData(), - getRemoteDataPayload(), - map((pc: TDomain) => isEmpty(pc) ? 'communities/search/top' : pc.id), - take(1) - ).subscribe((href: string) => this.requestService.removeByHrefSubstring(href)); + getSucceededOrNoContentResponse(), + take(1), + ).subscribe((rd: RemoteData) => { + const href = rd.hasSucceeded && !isEmpty(rd.payload.id) ? rd.payload.id : 'communities/search/top'; + this.requestService.removeByHrefSubstring(href) + }); } private parentCommunityUrl(dso: Collection | Community) { diff --git a/src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.spec.ts b/src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.spec.ts index e791f41d56..9da77df007 100644 --- a/src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.spec.ts +++ b/src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.spec.ts @@ -1,7 +1,7 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { CommunityDataService } from '../../../core/data/community-data.service'; import { ActivatedRoute, Router } from '@angular/router'; -import { TranslateModule } from '@ngx-translate/core'; +import {TranslateModule, TranslateService} from '@ngx-translate/core'; import { of as observableOf } from 'rxjs'; import { Community } from '../../../core/shared/community.model'; import { SharedModule } from '../../shared.module'; @@ -13,6 +13,9 @@ import { DataService } from '../../../core/data/data.service'; import { DeleteComColPageComponent } from './delete-comcol-page.component'; import { NotificationsService } from '../../notifications/notifications.service'; import { NotificationsServiceStub } from '../../testing/notifications-service.stub'; +import {RequestService} from '../../../core/data/request.service'; +import {getTestScheduler} from 'jasmine-marbles'; +import {createNoContentRemoteDataObject$, createSuccessfulRemoteDataObject$} from '../../remote-data.utils'; describe('DeleteComColPageComponent', () => { let comp: DeleteComColPageComponent; @@ -22,9 +25,13 @@ describe('DeleteComColPageComponent', () => { let community; let newCommunity; + let parentCommunity; let routerStub; let routeStub; let notificationsService; + let translateServiceStub; + let requestServiceStub; + const validUUID = 'valid-uuid'; const invalidUUID = 'invalid-uuid'; const frontendURL = '/testType'; @@ -45,10 +52,20 @@ describe('DeleteComColPageComponent', () => { }] }); + parentCommunity = Object.assign(new Community(), { + uuid: 'a20da287-e174-466a-9926-f66as300d399', + id: 'a20da287-e174-466a-9926-f66as300d399', + metadata: [{ + key: 'dc.title', + value: 'parent community' + }] + }); + dsoDataService = jasmine.createSpyObj( 'dsoDataService', { - delete: observableOf({ isSuccessful: true }) + delete: observableOf({ isSuccessful: true }), + findByHref: jasmine.createSpy('findByHref') }); routerStub = { @@ -59,6 +76,14 @@ describe('DeleteComColPageComponent', () => { data: observableOf(community) }; + requestServiceStub = jasmine.createSpyObj('RequestService', { + removeByHrefSubstring: jasmine.createSpy('removeByHrefSubstring') + }); + + translateServiceStub = jasmine.createSpyObj('TranslateService', { + instant: jasmine.createSpy('instant') + }); + } beforeEach(async(() => { @@ -70,6 +95,8 @@ describe('DeleteComColPageComponent', () => { { provide: Router, useValue: routerStub }, { provide: ActivatedRoute, useValue: routeStub }, { provide: NotificationsService, useValue: new NotificationsServiceStub() }, + { provide: TranslateService, useValue: translateServiceStub}, + { provide: RequestService, useValue: requestServiceStub} ], schemas: [NO_ERRORS_SCHEMA] }).compileComponents(); @@ -108,17 +135,21 @@ describe('DeleteComColPageComponent', () => { it('should show an error notification on failure', () => { (dsoDataService.delete as any).and.returnValue(observableOf({ isSuccessful: false })); spyOn(router, 'navigate'); + spyOn((comp as any), 'refreshCache'); comp.onConfirm(data2); fixture.detectChanges(); expect(notificationsService.error).toHaveBeenCalled(); + expect((comp as any).refreshCache).not.toHaveBeenCalled(); expect(router.navigate).toHaveBeenCalled(); }); it('should show a success notification on success and navigate', () => { spyOn(router, 'navigate'); + spyOn((comp as any), 'refreshCache'); comp.onConfirm(data1); fixture.detectChanges(); expect(notificationsService.success).toHaveBeenCalled(); + expect((comp as any).refreshCache).toHaveBeenCalled(); expect(router.navigate).toHaveBeenCalled(); }); @@ -127,6 +158,78 @@ describe('DeleteComColPageComponent', () => { fixture.detectChanges(); expect(dsoDataService.delete).toHaveBeenCalledWith(data1.id); }); + + describe('cache refresh', () => { + let scheduler; + let communityWithoutParentHref; + let deletedCommunity; + + beforeEach(() => { + scheduler = getTestScheduler(); + + }) + describe('cache refreshed top level community', () => { + beforeEach(() => { + (dsoDataService.findByHref as any).and.returnValue(createNoContentRemoteDataObject$()); + deletedCommunity = { + dso: Object.assign(new Community(), { + metadata: [{ + key: 'dc.title', + value: 'top level community' + }] + }), + _links: { + parentCommunity: { + href: 'topLevel/parentCommunity' + } + } + }; + communityWithoutParentHref = { + dso: Object.assign(new Community(), { + metadata: [{ + key: 'dc.title', + value: 'top level community' + }] + }), + _links: {} + }; + }); + it('top level community cache refreshed', () => { + scheduler.schedule(() => (comp as any).refreshCache(deletedCommunity)); + scheduler.flush(); + expect(requestServiceStub.removeByHrefSubstring).toHaveBeenCalledWith('communities/search/top'); + }); + it('top level community without parent link, cache not refreshed', () => { + scheduler.schedule(() => (comp as any).refreshCache(communityWithoutParentHref)); + scheduler.flush(); + expect(requestServiceStub.removeByHrefSubstring).not.toHaveBeenCalled(); + }); + }); + + describe('cache refreshed child community', () => { + beforeEach(() => { + (dsoDataService.findByHref as any).and.returnValue(createSuccessfulRemoteDataObject$(parentCommunity)); + deletedCommunity = { + dso: Object.assign(new Community(), { + metadata: [{ + key: 'dc.title', + value: 'child community' + }] + }), + _links: { + parentCommunity: { + href: 'child/parentCommunity' + } + } + }; + }); + it('child level community cache refreshed', () => { + scheduler.schedule(() => (comp as any).refreshCache(deletedCommunity)); + scheduler.flush(); + expect(requestServiceStub.removeByHrefSubstring).toHaveBeenCalledWith('a20da287-e174-466a-9926-f66as300d399'); + }); + }); + }); }); describe('onCancel', () => { diff --git a/src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.ts b/src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.ts index 29ec4f7b19..835d302de3 100644 --- a/src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.ts +++ b/src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.ts @@ -10,7 +10,9 @@ import {TranslateService} from '@ngx-translate/core'; import {RestResponse} from '../../../core/cache/response.models'; import {hasValue, isEmpty, isNotEmpty} from '../../empty.util'; import {RequestService} from '../../../core/data/request.service'; -import {getRemoteDataPayload, getSucceededRemoteData} from '../../../core/shared/operators'; +import { + getSucceededOrNoContentResponse, +} from '../../../core/shared/operators'; import {Community} from '../../../core/shared/community.model'; import {Collection} from '../../../core/shared/collection.model'; @@ -74,16 +76,17 @@ export class DeleteComColPageComponent implements } private refreshCache(dso: TDomain) { - const parentCommunity = this.parentCommunityUrl(dso as any); - if (!hasValue(parentCommunity)) { + const parentCommunityUrl = this.parentCommunityUrl(dso as any); + if (!hasValue(parentCommunityUrl)) { return; } - this.dsoDataService.findByHref(parentCommunity).pipe( - getSucceededRemoteData(), - getRemoteDataPayload(), - map((pc: TDomain) => isEmpty(pc) ? 'communities/search/top' : pc.id ), - take(1) - ).subscribe((id: string) => this.requestService.removeByHrefSubstring(id)); + this.dsoDataService.findByHref(parentCommunityUrl).pipe( + getSucceededOrNoContentResponse(), + take(1), + ).subscribe((rd: RemoteData) => { + const href = rd.hasSucceeded && !isEmpty(rd.payload.id) ? rd.payload.id : 'communities/search/top'; + this.requestService.removeByHrefSubstring(href) + }); } private parentCommunityUrl(dso: Collection | Community): string { From 5ef329f7a62d581a629d73351d1f0bf80c8588f8 Mon Sep 17 00:00:00 2001 From: Corrado Lombardi Date: Thu, 22 Oct 2020 16:44:49 +0200 Subject: [PATCH 07/43] [CSTPER-66] removed consecutive blank lines --- src/app/core/shared/operators.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/app/core/shared/operators.ts b/src/app/core/shared/operators.ts index 203f66b074..80c12612e0 100644 --- a/src/app/core/shared/operators.ts +++ b/src/app/core/shared/operators.ts @@ -79,7 +79,6 @@ export const getSucceededOrNoContentResponse = () => (source: Observable>): Observable> => source.pipe(find((rd: RemoteData) => rd.hasSucceeded || rd.hasNoContent)); - /** * Get the first successful remotely retrieved object * From 8424ab89d74c2d3dbd69122e4265ede5d6cfc816 Mon Sep 17 00:00:00 2001 From: Corrado Lombardi Date: Thu, 22 Oct 2020 20:15:08 +0200 Subject: [PATCH 08/43] [CSTPER-66] provided RequestService in constructor and parent community empty link --- .../create-collection-page.component.spec.ts | 4 +++- .../delete-community-page.component.spec.ts | 2 ++ .../create-comcol-page/create-comcol-page.component.spec.ts | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/app/+collection-page/create-collection-page/create-collection-page.component.spec.ts b/src/app/+collection-page/create-collection-page/create-collection-page.component.spec.ts index d64e510a23..13047593cd 100644 --- a/src/app/+collection-page/create-collection-page/create-collection-page.component.spec.ts +++ b/src/app/+collection-page/create-collection-page/create-collection-page.component.spec.ts @@ -12,6 +12,7 @@ import { CommunityDataService } from '../../core/data/community-data.service'; import { CreateCollectionPageComponent } from './create-collection-page.component'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { NotificationsServiceStub } from '../../shared/testing/notifications-service.stub'; +import {RequestService} from '../../core/data/request.service'; describe('CreateCollectionPageComponent', () => { let comp: CreateCollectionPageComponent; @@ -29,7 +30,8 @@ describe('CreateCollectionPageComponent', () => { }, { provide: RouteService, useValue: { getQueryParameterValue: () => observableOf('1234') } }, { provide: Router, useValue: {} }, - { provide: NotificationsService, useValue: new NotificationsServiceStub() } + { provide: NotificationsService, useValue: new NotificationsServiceStub() }, + { provide: RequestService, useValue: {}} ], schemas: [NO_ERRORS_SCHEMA] }).compileComponents(); diff --git a/src/app/+community-page/delete-community-page/delete-community-page.component.spec.ts b/src/app/+community-page/delete-community-page/delete-community-page.component.spec.ts index 613be9deb3..6c5f29b4b5 100644 --- a/src/app/+community-page/delete-community-page/delete-community-page.component.spec.ts +++ b/src/app/+community-page/delete-community-page/delete-community-page.component.spec.ts @@ -9,6 +9,7 @@ import { CommunityDataService } from '../../core/data/community-data.service'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { SharedModule } from '../../shared/shared.module'; import { DeleteCommunityPageComponent } from './delete-community-page.component'; +import {RequestService} from '../../core/data/request.service'; describe('DeleteCommunityPageComponent', () => { let comp: DeleteCommunityPageComponent; @@ -22,6 +23,7 @@ describe('DeleteCommunityPageComponent', () => { { provide: CommunityDataService, useValue: {} }, { provide: ActivatedRoute, useValue: { data: observableOf({ dso: { payload: {} } }) } }, { provide: NotificationsService, useValue: {} }, + { provide: RequestService, useValue: {}} ], schemas: [NO_ERRORS_SCHEMA] }).compileComponents(); diff --git a/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.spec.ts b/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.spec.ts index d2335f623f..bdd00a3a49 100644 --- a/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.spec.ts +++ b/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.spec.ts @@ -131,6 +131,7 @@ describe('CreateComColPageComponent', () => { value: 'test' }] }), + _links: {}, uploader: { options: { url: '' From d50d1506efa48e615268b21477c89c8aa0ea2051 Mon Sep 17 00:00:00 2001 From: Corrado Lombardi Date: Thu, 22 Oct 2020 23:41:18 +0200 Subject: [PATCH 09/43] [CSTPER-66] provided RequestService --- .../delete-collection-page.component.spec.ts | 2 ++ .../create-community-page.component.spec.ts | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/app/+collection-page/delete-collection-page/delete-collection-page.component.spec.ts b/src/app/+collection-page/delete-collection-page/delete-collection-page.component.spec.ts index d64c1d1915..efe7e99550 100644 --- a/src/app/+collection-page/delete-collection-page/delete-collection-page.component.spec.ts +++ b/src/app/+collection-page/delete-collection-page/delete-collection-page.component.spec.ts @@ -9,6 +9,7 @@ import { of as observableOf } from 'rxjs'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { DeleteCollectionPageComponent } from './delete-collection-page.component'; import { CollectionDataService } from '../../core/data/collection-data.service'; +import {RequestService} from '../../core/data/request.service'; describe('DeleteCollectionPageComponent', () => { let comp: DeleteCollectionPageComponent; @@ -22,6 +23,7 @@ describe('DeleteCollectionPageComponent', () => { { provide: CollectionDataService, useValue: {} }, { provide: ActivatedRoute, useValue: { data: observableOf({ dso: { payload: {} } }) } }, { provide: NotificationsService, useValue: {} }, + { provide: RequestService, useValue: {} } ], schemas: [NO_ERRORS_SCHEMA] }).compileComponents(); diff --git a/src/app/+community-page/create-community-page/create-community-page.component.spec.ts b/src/app/+community-page/create-community-page/create-community-page.component.spec.ts index b4da0be4d1..c48e9158fb 100644 --- a/src/app/+community-page/create-community-page/create-community-page.component.spec.ts +++ b/src/app/+community-page/create-community-page/create-community-page.component.spec.ts @@ -12,6 +12,7 @@ import { CommunityDataService } from '../../core/data/community-data.service'; import { CreateCommunityPageComponent } from './create-community-page.component'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { NotificationsServiceStub } from '../../shared/testing/notifications-service.stub'; +import {RequestService} from '../../core/data/request.service'; describe('CreateCommunityPageComponent', () => { let comp: CreateCommunityPageComponent; @@ -25,7 +26,8 @@ describe('CreateCommunityPageComponent', () => { { provide: CommunityDataService, useValue: { findById: () => observableOf({}) } }, { provide: RouteService, useValue: { getQueryParameterValue: () => observableOf('1234') } }, { provide: Router, useValue: {} }, - { provide: NotificationsService, useValue: new NotificationsServiceStub() } + { provide: NotificationsService, useValue: new NotificationsServiceStub() }, + { provide: RequestService, useValue: {} } ], schemas: [NO_ERRORS_SCHEMA] }).compileComponents(); From 564e4e0b02ac4887a277f3abf039c0d66fb0ad68 Mon Sep 17 00:00:00 2001 From: Corrado Lombardi Date: Fri, 23 Oct 2020 11:53:35 +0200 Subject: [PATCH 10/43] [CSTPER-66] onSubmit test executed within a scheduler and provided _links section on tested data --- .../create-comcol-page.component.spec.ts | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.spec.ts b/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.spec.ts index bdd00a3a49..898727b813 100644 --- a/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.spec.ts +++ b/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.spec.ts @@ -36,6 +36,7 @@ describe('CreateComColPageComponent', () => { let routeServiceStub; let routerStub; let requestServiceStub; + let scheduler; const logoEndpoint = 'rest/api/logo/endpoint'; @@ -117,6 +118,7 @@ describe('CreateComColPageComponent', () => { communityDataService = (comp as any).communityDataService; routeService = (comp as any).routeService; router = (comp as any).router; + scheduler = getTestScheduler(); }); describe('onSubmit', () => { @@ -146,8 +148,9 @@ describe('CreateComColPageComponent', () => { it('should navigate and refresh cache when successful', () => { spyOn(router, 'navigate'); - spyOn((comp as any), 'refreshCache'); - comp.onSubmit(data); + spyOn((comp as any), 'refreshCache') + scheduler.schedule(() => comp.onSubmit(data)); + scheduler.flush(); fixture.detectChanges(); expect(router.navigate).toHaveBeenCalled(); expect((comp as any).refreshCache).toHaveBeenCalled(); @@ -157,7 +160,8 @@ describe('CreateComColPageComponent', () => { spyOn(router, 'navigate'); spyOn(dsoDataService, 'create').and.returnValue(createFailedRemoteDataObject$(newCommunity)); spyOn((comp as any), 'refreshCache') - comp.onSubmit(data); + scheduler.schedule(() => comp.onSubmit(data)); + scheduler.flush(); fixture.detectChanges(); expect(router.navigate).not.toHaveBeenCalled(); expect((comp as any).refreshCache).not.toHaveBeenCalled(); @@ -173,6 +177,7 @@ describe('CreateComColPageComponent', () => { value: 'test' }] }), + _links: {}, uploader: { options: { url: '' @@ -189,27 +194,29 @@ describe('CreateComColPageComponent', () => { it('should not navigate', () => { spyOn(router, 'navigate'); - comp.onSubmit(data); + scheduler.schedule(() => comp.onSubmit(data)); + scheduler.flush(); fixture.detectChanges(); expect(router.navigate).not.toHaveBeenCalled(); }); it('should set the uploader\'s url to the logo\'s endpoint', () => { - comp.onSubmit(data); + scheduler.schedule(() => comp.onSubmit(data)); + scheduler.flush(); fixture.detectChanges(); expect(data.uploader.options.url).toEqual(logoEndpoint); }); it('should call the uploader\'s uploadAll', () => { spyOn(data.uploader, 'uploadAll'); - comp.onSubmit(data); + scheduler.schedule(() => comp.onSubmit(data)); + scheduler.flush(); fixture.detectChanges(); expect(data.uploader.uploadAll).toHaveBeenCalled(); }); }); describe('cache refresh', () => { - let scheduler; let communityWithoutParentHref; beforeEach(() => { From 4bed16af3297fd6ce394b442d11c4066ae8d05c9 Mon Sep 17 00:00:00 2001 From: Corrado Lombardi Date: Fri, 23 Oct 2020 11:54:07 +0200 Subject: [PATCH 11/43] [CSTPER-66] onConfirm tests executed within a scheduler and provided _links section on tested data --- .../delete-comcol-page.component.spec.ts | 57 ++++++++++++------- 1 file changed, 36 insertions(+), 21 deletions(-) diff --git a/src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.spec.ts b/src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.spec.ts index 9da77df007..b5a3ccea5d 100644 --- a/src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.spec.ts +++ b/src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.spec.ts @@ -32,6 +32,8 @@ describe('DeleteComColPageComponent', () => { let translateServiceStub; let requestServiceStub; + let scheduler; + const validUUID = 'valid-uuid'; const invalidUUID = 'invalid-uuid'; const frontendURL = '/testType'; @@ -109,34 +111,51 @@ describe('DeleteComColPageComponent', () => { notificationsService = (comp as any).notifications; (comp as any).frontendURL = frontendURL; router = (comp as any).router; + scheduler = getTestScheduler(); }); describe('onConfirm', () => { let data1; let data2; beforeEach(() => { - data1 = Object.assign(new Community(), { - uuid: validUUID, - metadata: [{ - key: 'dc.title', - value: 'test' - }] - }); + data1 = { + dso: Object.assign(new Community(), { + uuid: validUUID, + metadata: [{ + key: 'dc.title', + value: 'test' + }] + }), + _links: {} + }; - data2 = Object.assign(new Community(), { - uuid: invalidUUID, - metadata: [{ - key: 'dc.title', - value: 'test' - }] - }); + data2 = { + dso: Object.assign(new Community(), { + uuid: invalidUUID, + metadata: [{ + key: 'dc.title', + value: 'test' + }] + }), + _links: {}, + uploader: { + options: { + url: '' + }, + queue: [], + /* tslint:disable:no-empty */ + uploadAll: () => {} + /* tslint:enable:no-empty */ + } + }; }); it('should show an error notification on failure', () => { (dsoDataService.delete as any).and.returnValue(observableOf({ isSuccessful: false })); spyOn(router, 'navigate'); spyOn((comp as any), 'refreshCache'); - comp.onConfirm(data2); + scheduler.schedule(() => comp.onConfirm(data2)); + scheduler.flush(); fixture.detectChanges(); expect(notificationsService.error).toHaveBeenCalled(); expect((comp as any).refreshCache).not.toHaveBeenCalled(); @@ -146,7 +165,8 @@ describe('DeleteComColPageComponent', () => { it('should show a success notification on success and navigate', () => { spyOn(router, 'navigate'); spyOn((comp as any), 'refreshCache'); - comp.onConfirm(data1); + scheduler.schedule(() => comp.onConfirm(data1)); + scheduler.flush(); fixture.detectChanges(); expect(notificationsService.success).toHaveBeenCalled(); expect((comp as any).refreshCache).toHaveBeenCalled(); @@ -160,14 +180,9 @@ describe('DeleteComColPageComponent', () => { }); describe('cache refresh', () => { - let scheduler; let communityWithoutParentHref; let deletedCommunity; - beforeEach(() => { - scheduler = getTestScheduler(); - - }) describe('cache refreshed top level community', () => { beforeEach(() => { (dsoDataService.findByHref as any).and.returnValue(createNoContentRemoteDataObject$()); From 9658da4fc01d24f2f7da9f979b3f668ee058d69e Mon Sep 17 00:00:00 2001 From: Corrado Lombardi Date: Fri, 23 Oct 2020 16:40:49 +0200 Subject: [PATCH 12/43] [CSTPER-66] removed detectChanges in single tests, removed TranslateService stub provision, added _links section in community objects --- .../create-comcol-page.component.spec.ts | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.spec.ts b/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.spec.ts index 898727b813..a7496fbf7a 100644 --- a/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.spec.ts +++ b/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.spec.ts @@ -46,7 +46,8 @@ describe('CreateComColPageComponent', () => { metadata: [{ key: 'dc.title', value: 'test community' - }] + }], + _links: {} }); parentCommunity = Object.assign(new Community(), { @@ -55,7 +56,8 @@ describe('CreateComColPageComponent', () => { metadata: [{ key: 'dc.title', value: 'parent community' - }] + }], + _links: {} }); newCommunity = Object.assign(new Community(), { @@ -63,7 +65,8 @@ describe('CreateComColPageComponent', () => { metadata: [{ key: 'dc.title', value: 'new community' - }] + }], + _links: {} }); communityDataServiceStub = { @@ -102,7 +105,6 @@ describe('CreateComColPageComponent', () => { { provide: RouteService, useValue: routeServiceStub }, { provide: Router, useValue: routerStub }, { provide: NotificationsService, useValue: new NotificationsServiceStub() }, - { provide: TranslateService, useValue: {}}, { provide: RequestService, useValue: requestServiceStub} ], schemas: [NO_ERRORS_SCHEMA] @@ -151,7 +153,6 @@ describe('CreateComColPageComponent', () => { spyOn((comp as any), 'refreshCache') scheduler.schedule(() => comp.onSubmit(data)); scheduler.flush(); - fixture.detectChanges(); expect(router.navigate).toHaveBeenCalled(); expect((comp as any).refreshCache).toHaveBeenCalled(); }); @@ -162,7 +163,6 @@ describe('CreateComColPageComponent', () => { spyOn((comp as any), 'refreshCache') scheduler.schedule(() => comp.onSubmit(data)); scheduler.flush(); - fixture.detectChanges(); expect(router.navigate).not.toHaveBeenCalled(); expect((comp as any).refreshCache).not.toHaveBeenCalled(); }); @@ -196,14 +196,12 @@ describe('CreateComColPageComponent', () => { spyOn(router, 'navigate'); scheduler.schedule(() => comp.onSubmit(data)); scheduler.flush(); - fixture.detectChanges(); expect(router.navigate).not.toHaveBeenCalled(); }); it('should set the uploader\'s url to the logo\'s endpoint', () => { scheduler.schedule(() => comp.onSubmit(data)); scheduler.flush(); - fixture.detectChanges(); expect(data.uploader.options.url).toEqual(logoEndpoint); }); @@ -211,7 +209,6 @@ describe('CreateComColPageComponent', () => { spyOn(data.uploader, 'uploadAll'); scheduler.schedule(() => comp.onSubmit(data)); scheduler.flush(); - fixture.detectChanges(); expect(data.uploader.uploadAll).toHaveBeenCalled(); }); }); From d7d527b735b9debd914a12b9655c1b6e24d90b77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20P=C3=A9ter=20Sipos?= Date: Tue, 27 Oct 2020 10:00:21 +0100 Subject: [PATCH 13/43] #0 fix thumbnail --- .../grid-thumbnail.component.html | 11 +++++-- .../grid-thumbnail.component.ts | 33 ++++++++++++++----- ...-search-result-grid-element.component.html | 4 +-- .../search-result-grid-element.component.ts | 11 ++++--- 4 files changed, 42 insertions(+), 17 deletions(-) diff --git a/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.html b/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.html index 5b09d09a55..3671073500 100644 --- a/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.html +++ b/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.html @@ -1,3 +1,10 @@ -
- +
+ + + +
diff --git a/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.ts b/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.ts index 4622483f2f..1033defaf9 100644 --- a/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.ts +++ b/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.ts @@ -1,4 +1,6 @@ import { Component, Input, OnInit } from '@angular/core'; +import { BehaviorSubject, Observable, isObservable } from 'rxjs'; +import { RemoteData } from '../../../core/data/remote-data'; import { Bitstream } from '../../../core/shared/bitstream.model'; import { hasValue } from '../../empty.util'; @@ -11,30 +13,45 @@ import { hasValue } from '../../empty.util'; @Component({ selector: 'ds-grid-thumbnail', styleUrls: ['./grid-thumbnail.component.scss'], - templateUrl: './grid-thumbnail.component.html' + templateUrl: './grid-thumbnail.component.html', }) export class GridThumbnailComponent implements OnInit { - - @Input() thumbnail: Bitstream; + @Input() thumbnail: string | Observable>; data: any = {}; /** * The default 'holder.js' image */ - @Input() defaultImage? = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9InllcyI/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMjYwIiBoZWlnaHQ9IjE4MCIgdmlld0JveD0iMCAwIDI2MCAxODAiIHByZXNlcnZlQXNwZWN0UmF0aW89Im5vbmUiPjwhLS0KU291cmNlIFVSTDogaG9sZGVyLmpzLzEwMCV4MTgwL3RleHQ6Tm8gVGh1bWJuYWlsCkNyZWF0ZWQgd2l0aCBIb2xkZXIuanMgMi42LjAuCkxlYXJuIG1vcmUgYXQgaHR0cDovL2hvbGRlcmpzLmNvbQooYykgMjAxMi0yMDE1IEl2YW4gTWFsb3BpbnNreSAtIGh0dHA6Ly9pbXNreS5jbwotLT48ZGVmcz48c3R5bGUgdHlwZT0idGV4dC9jc3MiPjwhW0NEQVRBWyNob2xkZXJfMTVmNzJmMmFlMGIgdGV4dCB7IGZpbGw6I0FBQUFBQTtmb250LXdlaWdodDpib2xkO2ZvbnQtZmFtaWx5OkFyaWFsLCBIZWx2ZXRpY2EsIE9wZW4gU2Fucywgc2Fucy1zZXJpZiwgbW9ub3NwYWNlO2ZvbnQtc2l6ZToxM3B0IH0gXV0+PC9zdHlsZT48L2RlZnM+PGcgaWQ9ImhvbGRlcl8xNWY3MmYyYWUwYiI+PHJlY3Qgd2lkdGg9IjI2MCIgaGVpZ2h0PSIxODAiIGZpbGw9IiNFRUVFRUUiLz48Zz48dGV4dCB4PSI3Mi4yNDIxODc1IiB5PSI5NiI+Tm8gVGh1bWJuYWlsPC90ZXh0PjwvZz48L2c+PC9zdmc+'; + @Input() defaultImage? = + 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9InllcyI/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMjYwIiBoZWlnaHQ9IjE4MCIgdmlld0JveD0iMCAwIDI2MCAxODAiIHByZXNlcnZlQXNwZWN0UmF0aW89Im5vbmUiPjwhLS0KU291cmNlIFVSTDogaG9sZGVyLmpzLzEwMCV4MTgwL3RleHQ6Tm8gVGh1bWJuYWlsCkNyZWF0ZWQgd2l0aCBIb2xkZXIuanMgMi42LjAuCkxlYXJuIG1vcmUgYXQgaHR0cDovL2hvbGRlcmpzLmNvbQooYykgMjAxMi0yMDE1IEl2YW4gTWFsb3BpbnNreSAtIGh0dHA6Ly9pbXNreS5jbwotLT48ZGVmcz48c3R5bGUgdHlwZT0idGV4dC9jc3MiPjwhW0NEQVRBWyNob2xkZXJfMTVmNzJmMmFlMGIgdGV4dCB7IGZpbGw6I0FBQUFBQTtmb250LXdlaWdodDpib2xkO2ZvbnQtZmFtaWx5OkFyaWFsLCBIZWx2ZXRpY2EsIE9wZW4gU2Fucywgc2Fucy1zZXJpZiwgbW9ub3NwYWNlO2ZvbnQtc2l6ZToxM3B0IH0gXV0+PC9zdHlsZT48L2RlZnM+PGcgaWQ9ImhvbGRlcl8xNWY3MmYyYWUwYiI+PHJlY3Qgd2lkdGg9IjI2MCIgaGVpZ2h0PSIxODAiIGZpbGw9IiNFRUVFRUUiLz48Zz48dGV4dCB4PSI3Mi4yNDIxODc1IiB5PSI5NiI+Tm8gVGh1bWJuYWlsPC90ZXh0PjwvZz48L2c+PC9zdmc+'; - src: string; + src$: BehaviorSubject; errorHandler(event) { event.currentTarget.src = this.defaultImage; } ngOnInit(): void { - if (hasValue(this.thumbnail) && hasValue(this.thumbnail._links) && this.thumbnail._links.content.href) { - this.src = this.thumbnail._links.content.href; + this.src$ = new BehaviorSubject(this.defaultImage); + console.log('this.thumbnail', this.thumbnail); + if (isObservable(this.thumbnail)) { + this.thumbnail.subscribe((thumbnailRD) => { + this.checkThumbnail(thumbnailRD.payload); + }); } else { - this.src = this.defaultImage + if (this.thumbnail) { + this.src$.next(this.thumbnail); + } } } + checkThumbnail(thumbnail: Bitstream) { + if ( + hasValue(thumbnail) && + hasValue(thumbnail._links) && + thumbnail._links.content.href + ) { + this.src$.next(thumbnail._links.content.href); + } + } } diff --git a/src/app/shared/object-grid/search-result-grid-element/item-search-result/publication/publication-search-result-grid-element.component.html b/src/app/shared/object-grid/search-result-grid-element/item-search-result/publication/publication-search-result-grid-element.component.html index 3c2d54b003..22f898662d 100644 --- a/src/app/shared/object-grid/search-result-grid-element/item-search-result/publication/publication-search-result-grid-element.component.html +++ b/src/app/shared/object-grid/search-result-grid-element/item-search-result/publication/publication-search-result-grid-element.component.html @@ -4,13 +4,13 @@
- +
- +
diff --git a/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts b/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts index dc05f78e40..9a4e7045a5 100644 --- a/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts +++ b/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts @@ -6,10 +6,11 @@ import { BitstreamDataService } from '../../../core/data/bitstream-data.service' import { Bitstream } from '../../../core/shared/bitstream.model'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { Metadata } from '../../../core/shared/metadata.utils'; -import { getFirstSucceededRemoteDataPayload } from '../../../core/shared/operators'; import { hasValue } from '../../empty.util'; import { AbstractListableElementComponent } from '../../object-collection/shared/object-collection-element/abstract-listable-element.component'; import { TruncatableService } from '../../truncatable/truncatable.service'; +import { RemoteData } from '../../../core/data/remote-data'; +import { filter, map } from 'rxjs/operators'; @Component({ selector: 'ds-search-result-grid-element', @@ -42,7 +43,9 @@ export class SearchResultGridElementComponent, K exten */ ngOnInit(): void { if (hasValue(this.object)) { + console.log(this.object) this.dso = this.object.indexableObject; + console.log('this.dso',this.dso) } } @@ -71,9 +74,7 @@ export class SearchResultGridElementComponent, K exten } // TODO refactor to return RemoteData, and thumbnail template to deal with loading - getThumbnail(): Observable { - return this.bitstreamDataService.getThumbnailFor(this.dso as any).pipe( - getFirstSucceededRemoteDataPayload() - ); + getThumbnail(): Observable> { + return this.bitstreamDataService.getThumbnailFor(this.dso as any); } } From 23c01b4683009b94076726ad5ffe2573dafbbef8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20P=C3=A9ter=20Sipos?= Date: Wed, 28 Oct 2020 10:44:51 +0100 Subject: [PATCH 14/43] #0-remove --- .editorconfig | 3 +++ .../object-grid/grid-thumbnail/grid-thumbnail.component.ts | 6 ++---- src/app/shared/object-grid/object-grid.component.ts | 1 + .../search-result-grid-element.component.ts | 2 -- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.editorconfig b/.editorconfig index 70ce43b68e..15d4c87b14 100644 --- a/.editorconfig +++ b/.editorconfig @@ -12,3 +12,6 @@ trim_trailing_whitespace = true [*.md] insert_final_newline = false trim_trailing_whitespace = false + +[*.ts] +quote_type = single diff --git a/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.ts b/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.ts index 1033defaf9..3c22eef7db 100644 --- a/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.ts +++ b/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.ts @@ -16,7 +16,7 @@ import { hasValue } from '../../empty.util'; templateUrl: './grid-thumbnail.component.html', }) export class GridThumbnailComponent implements OnInit { - @Input() thumbnail: string | Observable>; + @Input() thumbnail: Bitstream | Observable>; data: any = {}; @@ -39,9 +39,7 @@ export class GridThumbnailComponent implements OnInit { this.checkThumbnail(thumbnailRD.payload); }); } else { - if (this.thumbnail) { - this.src$.next(this.thumbnail); - } + this.checkThumbnail(this.thumbnail); } } diff --git a/src/app/shared/object-grid/object-grid.component.ts b/src/app/shared/object-grid/object-grid.component.ts index c6f8347217..446517023c 100644 --- a/src/app/shared/object-grid/object-grid.component.ts +++ b/src/app/shared/object-grid/object-grid.component.ts @@ -169,6 +169,7 @@ export class ObjectGridComponent implements OnInit { this._objects$).pipe(map(([nbColumns, objects]) => { if (hasValue(objects) && hasValue(objects.payload) && hasValue(objects.payload.page)) { const page = objects.payload.page; + console.log(page) const result = []; diff --git a/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts b/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts index 9a4e7045a5..bcc5153745 100644 --- a/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts +++ b/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts @@ -43,9 +43,7 @@ export class SearchResultGridElementComponent, K exten */ ngOnInit(): void { if (hasValue(this.object)) { - console.log(this.object) this.dso = this.object.indexableObject; - console.log('this.dso',this.dso) } } From 0ea105c73e48cb1adc5ea646a914487ee12707ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20P=C3=A9ter=20Sipos?= Date: Wed, 28 Oct 2020 16:01:26 +0100 Subject: [PATCH 15/43] #674 fix community and collection thumblogo --- src/app/+search-page/search.component.ts | 4 +++- src/app/core/cache/builders/link.service.ts | 6 ++++-- .../object-grid/grid-thumbnail/grid-thumbnail.component.ts | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/app/+search-page/search.component.ts b/src/app/+search-page/search.component.ts index bbbfdba513..412534a708 100644 --- a/src/app/+search-page/search.component.ts +++ b/src/app/+search-page/search.component.ts @@ -18,6 +18,7 @@ import { SearchService } from '../core/shared/search/search.service'; import { currentPath } from '../shared/utils/route.utils'; import { Router } from '@angular/router'; import { Context } from '../core/shared/context.model'; +import { followLink } from '../shared/utils/follow-link-config.model'; @Component({ selector: 'ds-search', @@ -122,8 +123,9 @@ export class SearchComponent implements OnInit { this.searchLink = this.getSearchLink(); this.searchOptions$ = this.getSearchOptions(); this.sub = this.searchOptions$.pipe( - switchMap((options) => this.service.search(options).pipe(getSucceededRemoteData(), startWith(undefined)))) + switchMap((options) => this.service.search(options, null, followLink('logo')).pipe(getSucceededRemoteData(), startWith(undefined)))) .subscribe((results) => { + console.log('result', results) this.resultsRD$.next(results); }); this.scopeListRD$ = this.searchConfigService.getCurrentScope('').pipe( diff --git a/src/app/core/cache/builders/link.service.ts b/src/app/core/cache/builders/link.service.ts index dc65eab68f..3592d1058c 100644 --- a/src/app/core/cache/builders/link.service.ts +++ b/src/app/core/cache/builders/link.service.ts @@ -27,7 +27,7 @@ export class LinkService { */ public resolveLinks(model: T, ...linksToFollow: Array>): T { linksToFollow.forEach((linkToFollow: FollowLinkConfig) => { - this.resolveLink(model, linkToFollow); + this.resolveLink(model, linkToFollow); }); return model; } @@ -39,10 +39,12 @@ export class LinkService { * @param linkToFollow the {@link FollowLinkConfig} to resolve */ public resolveLink(model, linkToFollow: FollowLinkConfig): T { + console.log('model', model, 'links', linkToFollow) const matchingLinkDef = getLinkDefinition(model.constructor, linkToFollow.name); if (hasNoValue(matchingLinkDef)) { - throw new Error(`followLink('${linkToFollow.name}') was used for a ${model.constructor.name}, but there is no property on ${model.constructor.name} models with an @link() for ${linkToFollow.name}`); + console.error(`followLink('${linkToFollow.name}') was used for a ${model.constructor.name}, but there is no property on ${model.constructor.name} models with an @link() for ${linkToFollow.name}`); + return model; } else { const provider = getDataServiceFor(matchingLinkDef.resourceType); diff --git a/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.ts b/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.ts index 3c22eef7db..f124613104 100644 --- a/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.ts +++ b/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.ts @@ -33,7 +33,7 @@ export class GridThumbnailComponent implements OnInit { ngOnInit(): void { this.src$ = new BehaviorSubject(this.defaultImage); - console.log('this.thumbnail', this.thumbnail); + // console.log('this.thumbnail', this.thumbnail); if (isObservable(this.thumbnail)) { this.thumbnail.subscribe((thumbnailRD) => { this.checkThumbnail(thumbnailRD.payload); From 371b8e72f79480ff6ced42c357cdc35cbfb5143a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20P=C3=A9ter=20Sipos?= Date: Wed, 28 Oct 2020 16:13:41 +0100 Subject: [PATCH 16/43] #674 remove async --- .../simple/item-types/publication/publication.component.html | 2 +- src/app/+search-page/search.component.ts | 1 - src/app/core/cache/builders/link.service.ts | 1 - .../journal-issue-search-result-grid-element.component.html | 4 ++-- .../journal-volume-search-result-grid-element.component.html | 4 ++-- .../journal/journal-search-result-grid-element.component.html | 4 ++-- .../item-pages/journal-issue/journal-issue.component.html | 2 +- .../item-pages/journal-volume/journal-volume.component.html | 2 +- .../item-pages/journal/journal.component.html | 2 +- .../org-unit-search-result-grid-element.component.html | 4 ++-- .../person/person-search-result-grid-element.component.html | 4 ++-- .../project/project-search-result-grid-element.component.html | 4 ++-- .../item-pages/org-unit/org-unit.component.html | 2 +- .../research-entities/item-pages/person/person.component.html | 2 +- .../item-pages/project/project.component.html | 2 +- ...-unit-search-result-list-submission-element.component.html | 2 +- .../item-detail-preview/item-detail-preview.component.html | 2 +- .../object-grid/grid-thumbnail/grid-thumbnail.component.ts | 1 - src/app/shared/object-grid/object-grid.component.ts | 1 - 19 files changed, 21 insertions(+), 25 deletions(-) diff --git a/src/app/+item-page/simple/item-types/publication/publication.component.html b/src/app/+item-page/simple/item-types/publication/publication.component.html index 9eb704b9e9..f0361d9d53 100644 --- a/src/app/+item-page/simple/item-types/publication/publication.component.html +++ b/src/app/+item-page/simple/item-types/publication/publication.component.html @@ -4,7 +4,7 @@
- + diff --git a/src/app/+search-page/search.component.ts b/src/app/+search-page/search.component.ts index 412534a708..4e50a82827 100644 --- a/src/app/+search-page/search.component.ts +++ b/src/app/+search-page/search.component.ts @@ -125,7 +125,6 @@ export class SearchComponent implements OnInit { this.sub = this.searchOptions$.pipe( switchMap((options) => this.service.search(options, null, followLink('logo')).pipe(getSucceededRemoteData(), startWith(undefined)))) .subscribe((results) => { - console.log('result', results) this.resultsRD$.next(results); }); this.scopeListRD$ = this.searchConfigService.getCurrentScope('').pipe( diff --git a/src/app/core/cache/builders/link.service.ts b/src/app/core/cache/builders/link.service.ts index 3592d1058c..35c2fbac9c 100644 --- a/src/app/core/cache/builders/link.service.ts +++ b/src/app/core/cache/builders/link.service.ts @@ -39,7 +39,6 @@ export class LinkService { * @param linkToFollow the {@link FollowLinkConfig} to resolve */ public resolveLink(model, linkToFollow: FollowLinkConfig): T { - console.log('model', model, 'links', linkToFollow) const matchingLinkDef = getLinkDefinition(model.constructor, linkToFollow.name); if (hasNoValue(matchingLinkDef)) { diff --git a/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-issue/journal-issue-search-result-grid-element.component.html b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-issue/journal-issue-search-result-grid-element.component.html index 1ae772a3c3..358a459b4c 100644 --- a/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-issue/journal-issue-search-result-grid-element.component.html +++ b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-issue/journal-issue-search-result-grid-element.component.html @@ -6,13 +6,13 @@ rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]" class="card-img-top full-width">
- +
- +
diff --git a/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-volume/journal-volume-search-result-grid-element.component.html b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-volume/journal-volume-search-result-grid-element.component.html index 75d29781b7..e4d3cddd45 100644 --- a/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-volume/journal-volume-search-result-grid-element.component.html +++ b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-volume/journal-volume-search-result-grid-element.component.html @@ -6,13 +6,13 @@ rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]" class="card-img-top full-width">
- +
- +
diff --git a/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal/journal-search-result-grid-element.component.html b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal/journal-search-result-grid-element.component.html index 8c7e5c2f44..135161a9a1 100644 --- a/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal/journal-search-result-grid-element.component.html +++ b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal/journal-search-result-grid-element.component.html @@ -6,13 +6,13 @@ rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]" class="card-img-top full-width">
- +
- +
diff --git a/src/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.html b/src/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.html index cdfa6293c4..a7175db516 100644 --- a/src/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.html +++ b/src/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.html @@ -4,7 +4,7 @@
- +
- +
- +
- +
- +
diff --git a/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/person/person-search-result-grid-element.component.html b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/person/person-search-result-grid-element.component.html index 1b45c7c4f9..bc1516aa33 100644 --- a/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/person/person-search-result-grid-element.component.html +++ b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/person/person-search-result-grid-element.component.html @@ -6,13 +6,13 @@ rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]" class="card-img-top full-width">
- +
- +
diff --git a/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/project/project-search-result-grid-element.component.html b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/project/project-search-result-grid-element.component.html index ac3c3ea453..cc3d162453 100644 --- a/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/project/project-search-result-grid-element.component.html +++ b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/project/project-search-result-grid-element.component.html @@ -6,13 +6,13 @@ rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]" class="card-img-top full-width">
- +
- +
diff --git a/src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.html b/src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.html index 784000b446..8f343ed701 100644 --- a/src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.html +++ b/src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.html @@ -4,7 +4,7 @@
- +
- +
- + 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 063e1393cc..f12f01b7fd 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/object-grid/grid-thumbnail/grid-thumbnail.component.ts b/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.ts index f124613104..15839af1e5 100644 --- a/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.ts +++ b/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.ts @@ -33,7 +33,6 @@ export class GridThumbnailComponent implements OnInit { ngOnInit(): void { this.src$ = new BehaviorSubject(this.defaultImage); - // console.log('this.thumbnail', this.thumbnail); if (isObservable(this.thumbnail)) { this.thumbnail.subscribe((thumbnailRD) => { this.checkThumbnail(thumbnailRD.payload); diff --git a/src/app/shared/object-grid/object-grid.component.ts b/src/app/shared/object-grid/object-grid.component.ts index 446517023c..c6f8347217 100644 --- a/src/app/shared/object-grid/object-grid.component.ts +++ b/src/app/shared/object-grid/object-grid.component.ts @@ -169,7 +169,6 @@ export class ObjectGridComponent implements OnInit { this._objects$).pipe(map(([nbColumns, objects]) => { if (hasValue(objects) && hasValue(objects.payload) && hasValue(objects.payload.page)) { const page = objects.payload.page; - console.log(page) const result = []; From 7925e9134a809c9c5839d6810219b99cbc6961fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20P=C3=A9ter=20Sipos?= Date: Wed, 28 Oct 2020 16:29:02 +0100 Subject: [PATCH 17/43] Revert "#674 remove async" This reverts commit 371b8e72f79480ff6ced42c357cdc35cbfb5143a. --- .../simple/item-types/publication/publication.component.html | 2 +- src/app/+search-page/search.component.ts | 1 + src/app/core/cache/builders/link.service.ts | 1 + .../journal-issue-search-result-grid-element.component.html | 4 ++-- .../journal-volume-search-result-grid-element.component.html | 4 ++-- .../journal/journal-search-result-grid-element.component.html | 4 ++-- .../item-pages/journal-issue/journal-issue.component.html | 2 +- .../item-pages/journal-volume/journal-volume.component.html | 2 +- .../item-pages/journal/journal.component.html | 2 +- .../org-unit-search-result-grid-element.component.html | 4 ++-- .../person/person-search-result-grid-element.component.html | 4 ++-- .../project/project-search-result-grid-element.component.html | 4 ++-- .../item-pages/org-unit/org-unit.component.html | 2 +- .../research-entities/item-pages/person/person.component.html | 2 +- .../item-pages/project/project.component.html | 2 +- ...-unit-search-result-list-submission-element.component.html | 2 +- .../item-detail-preview/item-detail-preview.component.html | 2 +- .../object-grid/grid-thumbnail/grid-thumbnail.component.ts | 1 + src/app/shared/object-grid/object-grid.component.ts | 1 + 19 files changed, 25 insertions(+), 21 deletions(-) diff --git a/src/app/+item-page/simple/item-types/publication/publication.component.html b/src/app/+item-page/simple/item-types/publication/publication.component.html index f0361d9d53..9eb704b9e9 100644 --- a/src/app/+item-page/simple/item-types/publication/publication.component.html +++ b/src/app/+item-page/simple/item-types/publication/publication.component.html @@ -4,7 +4,7 @@
- + diff --git a/src/app/+search-page/search.component.ts b/src/app/+search-page/search.component.ts index 4e50a82827..412534a708 100644 --- a/src/app/+search-page/search.component.ts +++ b/src/app/+search-page/search.component.ts @@ -125,6 +125,7 @@ export class SearchComponent implements OnInit { this.sub = this.searchOptions$.pipe( switchMap((options) => this.service.search(options, null, followLink('logo')).pipe(getSucceededRemoteData(), startWith(undefined)))) .subscribe((results) => { + console.log('result', results) this.resultsRD$.next(results); }); this.scopeListRD$ = this.searchConfigService.getCurrentScope('').pipe( diff --git a/src/app/core/cache/builders/link.service.ts b/src/app/core/cache/builders/link.service.ts index 35c2fbac9c..3592d1058c 100644 --- a/src/app/core/cache/builders/link.service.ts +++ b/src/app/core/cache/builders/link.service.ts @@ -39,6 +39,7 @@ export class LinkService { * @param linkToFollow the {@link FollowLinkConfig} to resolve */ public resolveLink(model, linkToFollow: FollowLinkConfig): T { + console.log('model', model, 'links', linkToFollow) const matchingLinkDef = getLinkDefinition(model.constructor, linkToFollow.name); if (hasNoValue(matchingLinkDef)) { diff --git a/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-issue/journal-issue-search-result-grid-element.component.html b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-issue/journal-issue-search-result-grid-element.component.html index 358a459b4c..1ae772a3c3 100644 --- a/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-issue/journal-issue-search-result-grid-element.component.html +++ b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-issue/journal-issue-search-result-grid-element.component.html @@ -6,13 +6,13 @@ rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]" class="card-img-top full-width">
- +
- +
diff --git a/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-volume/journal-volume-search-result-grid-element.component.html b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-volume/journal-volume-search-result-grid-element.component.html index e4d3cddd45..75d29781b7 100644 --- a/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-volume/journal-volume-search-result-grid-element.component.html +++ b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-volume/journal-volume-search-result-grid-element.component.html @@ -6,13 +6,13 @@ rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]" class="card-img-top full-width">
- +
- +
diff --git a/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal/journal-search-result-grid-element.component.html b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal/journal-search-result-grid-element.component.html index 135161a9a1..8c7e5c2f44 100644 --- a/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal/journal-search-result-grid-element.component.html +++ b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal/journal-search-result-grid-element.component.html @@ -6,13 +6,13 @@ rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]" class="card-img-top full-width">
- +
- +
diff --git a/src/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.html b/src/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.html index a7175db516..cdfa6293c4 100644 --- a/src/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.html +++ b/src/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.html @@ -4,7 +4,7 @@
- +
- +
- +
- +
- +
diff --git a/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/person/person-search-result-grid-element.component.html b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/person/person-search-result-grid-element.component.html index bc1516aa33..1b45c7c4f9 100644 --- a/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/person/person-search-result-grid-element.component.html +++ b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/person/person-search-result-grid-element.component.html @@ -6,13 +6,13 @@ rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]" class="card-img-top full-width">
- +
- +
diff --git a/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/project/project-search-result-grid-element.component.html b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/project/project-search-result-grid-element.component.html index cc3d162453..ac3c3ea453 100644 --- a/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/project/project-search-result-grid-element.component.html +++ b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/project/project-search-result-grid-element.component.html @@ -6,13 +6,13 @@ rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]" class="card-img-top full-width">
- +
- +
diff --git a/src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.html b/src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.html index 8f343ed701..784000b446 100644 --- a/src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.html +++ b/src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.html @@ -4,7 +4,7 @@
- +
- +
- + 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 f12f01b7fd..063e1393cc 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/object-grid/grid-thumbnail/grid-thumbnail.component.ts b/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.ts index 15839af1e5..f124613104 100644 --- a/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.ts +++ b/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.ts @@ -33,6 +33,7 @@ export class GridThumbnailComponent implements OnInit { ngOnInit(): void { this.src$ = new BehaviorSubject(this.defaultImage); + // console.log('this.thumbnail', this.thumbnail); if (isObservable(this.thumbnail)) { this.thumbnail.subscribe((thumbnailRD) => { this.checkThumbnail(thumbnailRD.payload); diff --git a/src/app/shared/object-grid/object-grid.component.ts b/src/app/shared/object-grid/object-grid.component.ts index c6f8347217..446517023c 100644 --- a/src/app/shared/object-grid/object-grid.component.ts +++ b/src/app/shared/object-grid/object-grid.component.ts @@ -169,6 +169,7 @@ export class ObjectGridComponent implements OnInit { this._objects$).pipe(map(([nbColumns, objects]) => { if (hasValue(objects) && hasValue(objects.payload) && hasValue(objects.payload.page)) { const page = objects.payload.page; + console.log(page) const result = []; From 77e7d0effd6ec0e72816095d2e2855f0e7ea024a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20P=C3=A9ter=20Sipos?= Date: Thu, 29 Oct 2020 11:23:02 +0100 Subject: [PATCH 18/43] #674 remove consle logs --- src/app/+search-page/search.component.ts | 1 - src/app/core/cache/builders/link.service.ts | 1 - .../grid-thumbnail/grid-thumbnail.component.html | 13 ++++--------- src/app/shared/object-grid/object-grid.component.ts | 1 - 4 files changed, 4 insertions(+), 12 deletions(-) diff --git a/src/app/+search-page/search.component.ts b/src/app/+search-page/search.component.ts index 412534a708..4e50a82827 100644 --- a/src/app/+search-page/search.component.ts +++ b/src/app/+search-page/search.component.ts @@ -125,7 +125,6 @@ export class SearchComponent implements OnInit { this.sub = this.searchOptions$.pipe( switchMap((options) => this.service.search(options, null, followLink('logo')).pipe(getSucceededRemoteData(), startWith(undefined)))) .subscribe((results) => { - console.log('result', results) this.resultsRD$.next(results); }); this.scopeListRD$ = this.searchConfigService.getCurrentScope('').pipe( diff --git a/src/app/core/cache/builders/link.service.ts b/src/app/core/cache/builders/link.service.ts index 3592d1058c..35c2fbac9c 100644 --- a/src/app/core/cache/builders/link.service.ts +++ b/src/app/core/cache/builders/link.service.ts @@ -39,7 +39,6 @@ export class LinkService { * @param linkToFollow the {@link FollowLinkConfig} to resolve */ public resolveLink(model, linkToFollow: FollowLinkConfig): T { - console.log('model', model, 'links', linkToFollow) const matchingLinkDef = getLinkDefinition(model.constructor, linkToFollow.name); if (hasNoValue(matchingLinkDef)) { diff --git a/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.html b/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.html index 3671073500..89ea44061b 100644 --- a/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.html +++ b/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.html @@ -1,10 +1,5 @@ -
- - + +
- -
+
+
diff --git a/src/app/shared/object-grid/object-grid.component.ts b/src/app/shared/object-grid/object-grid.component.ts index 446517023c..c6f8347217 100644 --- a/src/app/shared/object-grid/object-grid.component.ts +++ b/src/app/shared/object-grid/object-grid.component.ts @@ -169,7 +169,6 @@ export class ObjectGridComponent implements OnInit { this._objects$).pipe(map(([nbColumns, objects]) => { if (hasValue(objects) && hasValue(objects.payload) && hasValue(objects.payload.page)) { const page = objects.payload.page; - console.log(page) const result = []; From 6f7a226b81176cc918d1917e36e4e20a3e8e8f4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20P=C3=A9ter=20Sipos?= Date: Thu, 29 Oct 2020 14:28:49 +0100 Subject: [PATCH 19/43] #674 refactore thumbnail --- .../core/cache/builders/link.service.spec.ts | 9 ++--- .../grid-thumbnail.component.html | 8 ++--- .../grid-thumbnail.component.ts | 36 ++++++++++++------- ...-search-result-grid-element.component.html | 4 +-- ...-search-result-grid-element.component.html | 4 +-- ...-search-result-grid-element.component.html | 4 +-- .../search-result-grid-element.component.ts | 7 ++-- 7 files changed, 40 insertions(+), 32 deletions(-) diff --git a/src/app/core/cache/builders/link.service.spec.ts b/src/app/core/cache/builders/link.service.spec.ts index 95a7570207..6b7c154137 100644 --- a/src/app/core/cache/builders/link.service.spec.ts +++ b/src/app/core/cache/builders/link.service.spec.ts @@ -139,13 +139,10 @@ describe('LinkService', () => { }); describe(`when the specified link doesn't exist on the model's class`, () => { - beforeEach(() => { - spyOnFunction(decorators, 'getLinkDefinition').and.returnValue(undefined); - }); - it('should throw an error', () => { - expect(() => { + it('should return with the same model', () => { + expect( service.resolveLink(testModel, followLink('predecessor', {}, true, followLink('successor'))) - }).toThrow(); + ).toEqual(testModel); }); }); diff --git a/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.html b/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.html index 89ea44061b..1df4026f83 100644 --- a/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.html +++ b/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.html @@ -1,5 +1,3 @@ - -
- -
-
+
+ +
diff --git a/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.ts b/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.ts index f124613104..90eb6c1bb0 100644 --- a/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.ts +++ b/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.ts @@ -1,4 +1,10 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { + Component, + Input, + OnChanges, + OnInit, + SimpleChanges, +} from '@angular/core'; import { BehaviorSubject, Observable, isObservable } from 'rxjs'; import { RemoteData } from '../../../core/data/remote-data'; import { Bitstream } from '../../../core/shared/bitstream.model'; @@ -15,8 +21,8 @@ import { hasValue } from '../../empty.util'; styleUrls: ['./grid-thumbnail.component.scss'], templateUrl: './grid-thumbnail.component.html', }) -export class GridThumbnailComponent implements OnInit { - @Input() thumbnail: Bitstream | Observable>; +export class GridThumbnailComponent implements OnInit, OnChanges { + @Input() thumbnail: Bitstream; data: any = {}; @@ -26,20 +32,24 @@ export class GridThumbnailComponent implements OnInit { @Input() defaultImage? = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9InllcyI/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMjYwIiBoZWlnaHQ9IjE4MCIgdmlld0JveD0iMCAwIDI2MCAxODAiIHByZXNlcnZlQXNwZWN0UmF0aW89Im5vbmUiPjwhLS0KU291cmNlIFVSTDogaG9sZGVyLmpzLzEwMCV4MTgwL3RleHQ6Tm8gVGh1bWJuYWlsCkNyZWF0ZWQgd2l0aCBIb2xkZXIuanMgMi42LjAuCkxlYXJuIG1vcmUgYXQgaHR0cDovL2hvbGRlcmpzLmNvbQooYykgMjAxMi0yMDE1IEl2YW4gTWFsb3BpbnNreSAtIGh0dHA6Ly9pbXNreS5jbwotLT48ZGVmcz48c3R5bGUgdHlwZT0idGV4dC9jc3MiPjwhW0NEQVRBWyNob2xkZXJfMTVmNzJmMmFlMGIgdGV4dCB7IGZpbGw6I0FBQUFBQTtmb250LXdlaWdodDpib2xkO2ZvbnQtZmFtaWx5OkFyaWFsLCBIZWx2ZXRpY2EsIE9wZW4gU2Fucywgc2Fucy1zZXJpZiwgbW9ub3NwYWNlO2ZvbnQtc2l6ZToxM3B0IH0gXV0+PC9zdHlsZT48L2RlZnM+PGcgaWQ9ImhvbGRlcl8xNWY3MmYyYWUwYiI+PHJlY3Qgd2lkdGg9IjI2MCIgaGVpZ2h0PSIxODAiIGZpbGw9IiNFRUVFRUUiLz48Zz48dGV4dCB4PSI3Mi4yNDIxODc1IiB5PSI5NiI+Tm8gVGh1bWJuYWlsPC90ZXh0PjwvZz48L2c+PC9zdmc+'; - src$: BehaviorSubject; + src: string; + errorHandler(event) { event.currentTarget.src = this.defaultImage; } ngOnInit(): void { - this.src$ = new BehaviorSubject(this.defaultImage); - // console.log('this.thumbnail', this.thumbnail); - if (isObservable(this.thumbnail)) { - this.thumbnail.subscribe((thumbnailRD) => { - this.checkThumbnail(thumbnailRD.payload); - }); - } else { - this.checkThumbnail(this.thumbnail); + this.src = this.defaultImage; + + this.checkThumbnail(this.thumbnail); + } + + ngOnChanges(changes: SimpleChanges): void { + if ( + !hasValue(changes.thumbnail.previousValue) && + hasValue(changes.thumbnail.currentValue) + ) { + this.checkThumbnail(changes.thumbnail.currentValue); } } @@ -49,7 +59,7 @@ export class GridThumbnailComponent implements OnInit { hasValue(thumbnail._links) && thumbnail._links.content.href ) { - this.src$.next(thumbnail._links.content.href); + this.src = thumbnail._links.content.href; } } } diff --git a/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.html b/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.html index a2933fd0ec..09d7a190d9 100644 --- a/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.html +++ b/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.html @@ -1,10 +1,10 @@
- + - +
diff --git a/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.html b/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.html index 8d5f288498..3d4b95739f 100644 --- a/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.html +++ b/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.html @@ -1,10 +1,10 @@
- + - +
diff --git a/src/app/shared/object-grid/search-result-grid-element/item-search-result/publication/publication-search-result-grid-element.component.html b/src/app/shared/object-grid/search-result-grid-element/item-search-result/publication/publication-search-result-grid-element.component.html index 22f898662d..125553054e 100644 --- a/src/app/shared/object-grid/search-result-grid-element/item-search-result/publication/publication-search-result-grid-element.component.html +++ b/src/app/shared/object-grid/search-result-grid-element/item-search-result/publication/publication-search-result-grid-element.component.html @@ -4,13 +4,13 @@
- +
- +
diff --git a/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts b/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts index 6f60341c0f..e660c060e6 100644 --- a/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts +++ b/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts @@ -11,6 +11,7 @@ import { AbstractListableElementComponent } from '../../object-collection/shared import { TruncatableService } from '../../truncatable/truncatable.service'; import { RemoteData } from '../../../core/data/remote-data'; import { filter, map } from 'rxjs/operators'; +import { getFirstSucceededRemoteDataPayload, getSucceededRemoteData } from '../../../core/shared/operators'; @Component({ selector: 'ds-search-result-grid-element', @@ -70,7 +71,9 @@ export class SearchResultGridElementComponent, K exten } // TODO refactor to return RemoteData, and thumbnail template to deal with loading - getThumbnail(): Observable> { - return this.bitstreamDataService.getThumbnailFor(this.dso as any); + getThumbnail(): Observable { + return this.bitstreamDataService.getThumbnailFor(this.dso as any).pipe( + getFirstSucceededRemoteDataPayload() + ); } } From 71ca57a5ce1e467eacd53b25341fcc3bcda67dec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20P=C3=A9ter=20Sipos?= Date: Thu, 29 Oct 2020 14:35:44 +0100 Subject: [PATCH 20/43] #674 update other grid elements --- .../collection-grid-element.component.html | 4 ++-- .../community-grid-element.component.html | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.html b/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.html index 0b1a85d0ef..9b9d174704 100644 --- a/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.html +++ b/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.html @@ -1,10 +1,10 @@
- + - +
diff --git a/src/app/shared/object-grid/community-grid-element/community-grid-element.component.html b/src/app/shared/object-grid/community-grid-element/community-grid-element.component.html index eed29367fa..f676ba303b 100644 --- a/src/app/shared/object-grid/community-grid-element/community-grid-element.component.html +++ b/src/app/shared/object-grid/community-grid-element/community-grid-element.component.html @@ -1,10 +1,10 @@
- + - +
From 9a1b21aeefd753216e11a10c7cd26db9f116780f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20P=C3=A9ter=20Sipos?= Date: Thu, 29 Oct 2020 14:43:17 +0100 Subject: [PATCH 21/43] #675 remove unused imports --- .../object-grid/grid-thumbnail/grid-thumbnail.component.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.ts b/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.ts index 90eb6c1bb0..3122650bd0 100644 --- a/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.ts +++ b/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.ts @@ -5,8 +5,6 @@ import { OnInit, SimpleChanges, } from '@angular/core'; -import { BehaviorSubject, Observable, isObservable } from 'rxjs'; -import { RemoteData } from '../../../core/data/remote-data'; import { Bitstream } from '../../../core/shared/bitstream.model'; import { hasValue } from '../../empty.util'; From 22fe1841428af3064ea4ded517b16edc462a3ce5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20P=C3=A9ter=20Sipos?= Date: Thu, 29 Oct 2020 14:57:09 +0100 Subject: [PATCH 22/43] #674 ad doctype --- .../object-grid/grid-thumbnail/grid-thumbnail.component.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.ts b/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.ts index 3122650bd0..fb736cd102 100644 --- a/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.ts +++ b/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.ts @@ -36,6 +36,9 @@ export class GridThumbnailComponent implements OnInit, OnChanges { event.currentTarget.src = this.defaultImage; } + /** + * Initialize the src + */ ngOnInit(): void { this.src = this.defaultImage; @@ -51,6 +54,9 @@ export class GridThumbnailComponent implements OnInit, OnChanges { } } + /** + * check if the Bitstream has any content than set the src + */ checkThumbnail(thumbnail: Bitstream) { if ( hasValue(thumbnail) && From 17455a786054c1fda9e1d1ea87d9e04b04fd2d59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20P=C3=A9ter=20Sipos?= Date: Thu, 29 Oct 2020 15:19:04 +0100 Subject: [PATCH 23/43] #674 add dock type --- .../object-grid/grid-thumbnail/grid-thumbnail.component.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.ts b/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.ts index fb736cd102..92d93686dc 100644 --- a/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.ts +++ b/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.ts @@ -45,6 +45,9 @@ export class GridThumbnailComponent implements OnInit, OnChanges { this.checkThumbnail(this.thumbnail); } + /** + * If the old input is undefined and the new one is a bitsream then set src + */ ngOnChanges(changes: SimpleChanges): void { if ( !hasValue(changes.thumbnail.previousValue) && From 9339cfaafd884d9fc5d60e4f5f643f6c6fddcf65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20P=C3=A9ter=20Sipos?= Date: Thu, 29 Oct 2020 16:14:35 +0100 Subject: [PATCH 24/43] #674 remove un used import --- .../search-result-grid-element.component.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts b/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts index e660c060e6..a53beaf922 100644 --- a/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts +++ b/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts @@ -9,9 +9,7 @@ import { Metadata } from '../../../core/shared/metadata.utils'; import { hasValue } from '../../empty.util'; import { AbstractListableElementComponent } from '../../object-collection/shared/object-collection-element/abstract-listable-element.component'; import { TruncatableService } from '../../truncatable/truncatable.service'; -import { RemoteData } from '../../../core/data/remote-data'; -import { filter, map } from 'rxjs/operators'; -import { getFirstSucceededRemoteDataPayload, getSucceededRemoteData } from '../../../core/shared/operators'; +import { getFirstSucceededRemoteDataPayload } from '../../../core/shared/operators'; @Component({ selector: 'ds-search-result-grid-element', From 5ef7ae1b86e4cf1f9dbcbabac305e8c5f6222030 Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Fri, 6 Nov 2020 14:30:39 +0100 Subject: [PATCH 25/43] 74348: Fix security issues reported by LGTM --- package.json | 1 + server.ts | 21 ++++++++++++++++++--- src/config/global-config.interface.ts | 3 ++- src/config/ui-server-config.interface.ts | 14 ++++++++++++++ src/environments/environment.common.ts | 4 ++++ src/environments/mock-environment.ts | 1 + yarn.lock | 5 +++++ 7 files changed, 45 insertions(+), 4 deletions(-) create mode 100644 src/config/ui-server-config.interface.ts diff --git a/package.json b/package.json index ae4abd2e41..07d1f90da8 100644 --- a/package.json +++ b/package.json @@ -88,6 +88,7 @@ "debug-loader": "^0.0.1", "deepmerge": "^4.2.2", "express": "4.16.2", + "express-rate-limit": "^5.1.3", "fast-json-patch": "^2.0.7", "file-saver": "^1.3.8", "filesize": "^6.1.0", diff --git a/server.ts b/server.ts index c640a95ef4..202d5a58bc 100644 --- a/server.ts +++ b/server.ts @@ -28,12 +28,13 @@ import * as compression from 'compression'; import * as cookieParser from 'cookie-parser'; import { join } from 'path'; -import { enableProdMode, NgModuleFactory, Type } from '@angular/core'; +import { enableProdMode } from '@angular/core'; import { REQUEST, RESPONSE } from '@nguniversal/express-engine/tokens'; import { environment } from './src/environments/environment'; import { createProxyMiddleware } from 'http-proxy-middleware'; -import { hasValue, hasNoValue } from './src/app/shared/empty.util'; +import { hasNoValue, hasValue } from './src/app/shared/empty.util'; +import { UIServerConfig } from './src/config/ui-server-config.interface'; /* * Set path for the browser application's dist folder @@ -121,6 +122,19 @@ function cacheControl(req, res, next) { next(); } +/** + * Checks if the rateLimiter property is present + * When it is present, the rateLimiter will be enabled. When it is undefined, the rateLimiter will be disabled. + */ +if (hasValue((environment.ui as UIServerConfig).rateLimiter)) { + const RateLimit = require('express-rate-limit'); + const limiter = new RateLimit({ + windowMs: (environment.ui as UIServerConfig).rateLimiter.windowMs, + max: (environment.ui as UIServerConfig).rateLimiter.max + }); + app.use(limiter); +} + /* * Serve static resources (images, i18n messages, …) */ @@ -209,8 +223,9 @@ if (environment.ui.ssl) { certificate: certificate }); } else { + console.warn('Disabling certificate validation and proceeding with a self-signed certificate. If this is a production server, it is recommended that you configure a valid certificate instead.'); - process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; + process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; // lgtm[js/disabling-certificate-validation] pem.createCertificate({ days: 1, diff --git a/src/config/global-config.interface.ts b/src/config/global-config.interface.ts index 07ee4ca444..0bc3d5eec4 100644 --- a/src/config/global-config.interface.ts +++ b/src/config/global-config.interface.ts @@ -11,9 +11,10 @@ import { ItemPageConfig } from './item-page-config.interface'; import { CollectionPageConfig } from './collection-page-config.interface'; import { Theme } from './theme.inferface'; import {AuthConfig} from './auth-config.interfaces'; +import { UIServerConfig } from './ui-server-config.interface'; export interface GlobalConfig extends Config { - ui: ServerConfig; + ui: UIServerConfig; rest: ServerConfig; production: boolean; cache: CacheConfig; diff --git a/src/config/ui-server-config.interface.ts b/src/config/ui-server-config.interface.ts new file mode 100644 index 0000000000..3e9e9134f3 --- /dev/null +++ b/src/config/ui-server-config.interface.ts @@ -0,0 +1,14 @@ +import { ServerConfig } from './server-config.interface'; + +/** + * Server configuration related to the UI. + */ +export class UIServerConfig extends ServerConfig { + + // rateLimiter is used to reduce the amount consequential hits and add a delay + rateLimiter?: { + windowMs: number; + max: number; + }; + +} diff --git a/src/environments/environment.common.ts b/src/environments/environment.common.ts index 4f73339690..7e3d7c6543 100644 --- a/src/environments/environment.common.ts +++ b/src/environments/environment.common.ts @@ -13,6 +13,10 @@ export const environment: GlobalConfig = { port: 4000, // NOTE: Space is capitalized because 'namespace' is a reserved string in TypeScript nameSpace: '/', + rateLimiter: { + windowMs: 1 * 60 * 1000, + max: 100 + } }, // The REST API server settings. // NOTE: these must be "synced" with the 'dspace.server.url' setting in your backend's local.cfg. diff --git a/src/environments/mock-environment.ts b/src/environments/mock-environment.ts index 6e4d60e268..b220c46083 100644 --- a/src/environments/mock-environment.ts +++ b/src/environments/mock-environment.ts @@ -19,6 +19,7 @@ export const environment: Partial = { port: 80, // NOTE: Space is capitalized because 'namespace' is a reserved string in TypeScript nameSpace: '/angular-dspace', + rateLimiter: undefined }, // Caching settings cache: { diff --git a/yarn.lock b/yarn.lock index d44182cc51..cb6a29e9f5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4124,6 +4124,11 @@ expand-tilde@^2.0.0, expand-tilde@^2.0.2: dependencies: homedir-polyfill "^1.0.1" +express-rate-limit@^5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/express-rate-limit/-/express-rate-limit-5.1.3.tgz#656bacce3f093034976346958a0f0199902c9174" + integrity sha512-TINcxve5510pXj4n9/1AMupkj3iWxl3JuZaWhCdYDlZeoCPqweGZrxbrlqTCFb1CT5wli7s8e2SH/Qz2c9GorA== + express@4.16.2: version "4.16.2" resolved "https://registry.yarnpkg.com/express/-/express-4.16.2.tgz#e35c6dfe2d64b7dca0a5cd4f21781be3299e076c" From 3a486f51179c8311b091963ba7fe514c48c02799 Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Fri, 6 Nov 2020 14:47:14 +0100 Subject: [PATCH 26/43] Update comment to be more clear --- src/config/ui-server-config.interface.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config/ui-server-config.interface.ts b/src/config/ui-server-config.interface.ts index 3e9e9134f3..93f90c345c 100644 --- a/src/config/ui-server-config.interface.ts +++ b/src/config/ui-server-config.interface.ts @@ -5,7 +5,7 @@ import { ServerConfig } from './server-config.interface'; */ export class UIServerConfig extends ServerConfig { - // rateLimiter is used to reduce the amount consequential hits and add a delay + // rateLimiter is used to limit the amount of requests a user is allowed make in an amount of time, in order to prevent overloading the server rateLimiter?: { windowMs: number; max: number; From 7b160cdbd3eb0fc83f9b29995639500417efab61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20P=C3=A9ter=20Sipos?= Date: Fri, 13 Nov 2020 14:12:27 +0100 Subject: [PATCH 27/43] #674 revert eror throw and ad set/get for grid communities and collections --- src/app/+search-page/search.component.ts | 2 +- .../core/cache/builders/link.service.spec.ts | 9 +++-- src/app/core/cache/builders/link.service.ts | 3 +- .../collection-grid-element.component.ts | 24 +++++++++++- .../community-grid-element.component.ts | 24 +++++++++++- .../grid-thumbnail.component.ts | 1 + ...on-search-result-grid-element.component.ts | 34 ++++++++++++++++- ...ty-search-result-grid-element.component.ts | 37 +++++++++++++++++-- 8 files changed, 118 insertions(+), 16 deletions(-) diff --git a/src/app/+search-page/search.component.ts b/src/app/+search-page/search.component.ts index 4e50a82827..999d703dd5 100644 --- a/src/app/+search-page/search.component.ts +++ b/src/app/+search-page/search.component.ts @@ -123,7 +123,7 @@ export class SearchComponent implements OnInit { this.searchLink = this.getSearchLink(); this.searchOptions$ = this.getSearchOptions(); this.sub = this.searchOptions$.pipe( - switchMap((options) => this.service.search(options, null, followLink('logo')).pipe(getSucceededRemoteData(), startWith(undefined)))) + switchMap((options) => this.service.search(options).pipe(getSucceededRemoteData(), startWith(undefined)))) .subscribe((results) => { this.resultsRD$.next(results); }); diff --git a/src/app/core/cache/builders/link.service.spec.ts b/src/app/core/cache/builders/link.service.spec.ts index 6b7c154137..95a7570207 100644 --- a/src/app/core/cache/builders/link.service.spec.ts +++ b/src/app/core/cache/builders/link.service.spec.ts @@ -139,10 +139,13 @@ describe('LinkService', () => { }); describe(`when the specified link doesn't exist on the model's class`, () => { - it('should return with the same model', () => { - expect( + beforeEach(() => { + spyOnFunction(decorators, 'getLinkDefinition').and.returnValue(undefined); + }); + it('should throw an error', () => { + expect(() => { service.resolveLink(testModel, followLink('predecessor', {}, true, followLink('successor'))) - ).toEqual(testModel); + }).toThrow(); }); }); diff --git a/src/app/core/cache/builders/link.service.ts b/src/app/core/cache/builders/link.service.ts index 35c2fbac9c..8d0def71fc 100644 --- a/src/app/core/cache/builders/link.service.ts +++ b/src/app/core/cache/builders/link.service.ts @@ -42,8 +42,7 @@ export class LinkService { const matchingLinkDef = getLinkDefinition(model.constructor, linkToFollow.name); if (hasNoValue(matchingLinkDef)) { - console.error(`followLink('${linkToFollow.name}') was used for a ${model.constructor.name}, but there is no property on ${model.constructor.name} models with an @link() for ${linkToFollow.name}`); - return model; + throw new Error(`followLink('${linkToFollow.name}') was used for a ${model.constructor.name}, but there is no property on ${model.constructor.name} models with an @link() for ${linkToFollow.name}`); } else { const provider = getDataServiceFor(matchingLinkDef.resourceType); diff --git a/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.ts b/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.ts index 6f8bf5264e..4ffaafa0f3 100644 --- a/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.ts +++ b/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.ts @@ -1,9 +1,12 @@ -import { Component, Inject } from '@angular/core'; +import { Component, Inject, Input } from '@angular/core'; import { Collection } from '../../../core/shared/collection.model'; import { AbstractListableElementComponent } from '../../object-collection/shared/object-collection-element/abstract-listable-element.component'; import { ViewMode } from '../../../core/shared/view-mode.model'; import { listableObjectComponent } from '../../object-collection/shared/listable-object/listable-object.decorator'; +import { hasNoValue, hasValue } from '../../empty.util'; +import { followLink } from '../../utils/follow-link-config.model'; +import { LinkService } from '../../../core/cache/builders/link.service'; /** * Component representing a grid element for collection @@ -15,4 +18,21 @@ import { listableObjectComponent } from '../../object-collection/shared/listable }) @listableObjectComponent(Collection, ViewMode.GridElement) -export class CollectionGridElementComponent extends AbstractListableElementComponent {} +export class CollectionGridElementComponent extends AbstractListableElementComponent { + private _object: Collection; + + constructor( private linkService: LinkService){ + super(); + } + + @Input() set object(object: Collection) { + this._object = object; + if (hasValue(this._object) && hasNoValue(this._object.logo)) { + this.linkService.resolveLink(this._object, followLink('logo')) + } + } + + get object(): Collection { + return this._object; + } +} diff --git a/src/app/shared/object-grid/community-grid-element/community-grid-element.component.ts b/src/app/shared/object-grid/community-grid-element/community-grid-element.component.ts index 05c84b683b..47ab77de5f 100644 --- a/src/app/shared/object-grid/community-grid-element/community-grid-element.component.ts +++ b/src/app/shared/object-grid/community-grid-element/community-grid-element.component.ts @@ -1,9 +1,12 @@ -import { Component } from '@angular/core'; +import { Component, Input } from '@angular/core'; import { Community } from '../../../core/shared/community.model'; import { AbstractListableElementComponent } from '../../object-collection/shared/object-collection-element/abstract-listable-element.component'; import { ViewMode } from '../../../core/shared/view-mode.model'; import { listableObjectComponent } from '../../object-collection/shared/listable-object/listable-object.decorator'; +import { followLink } from '../../utils/follow-link-config.model'; +import { LinkService } from '../../../core/cache/builders/link.service'; +import { hasNoValue, hasValue } from '../../empty.util'; /** * Component representing a grid element for a community @@ -15,4 +18,21 @@ import { listableObjectComponent } from '../../object-collection/shared/listable }) @listableObjectComponent(Community, ViewMode.GridElement) -export class CommunityGridElementComponent extends AbstractListableElementComponent {} +export class CommunityGridElementComponent extends AbstractListableElementComponent { + private _object: Community; + + constructor( private linkService: LinkService){ + super(); + } + + @Input() set object(object: Community) { + this._object = object; + if (hasValue(this._object) && hasNoValue(this._object.logo)) { + this.linkService.resolveLink(this._object, followLink('logo')) + } + } + + get object(): Community { + return this._object; + } +} diff --git a/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.ts b/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.ts index 92d93686dc..8e6af1e1a7 100644 --- a/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.ts +++ b/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.ts @@ -53,6 +53,7 @@ export class GridThumbnailComponent implements OnInit, OnChanges { !hasValue(changes.thumbnail.previousValue) && hasValue(changes.thumbnail.currentValue) ) { + console.log('this.thumbnail', changes.thumbnail.currentValue); this.checkThumbnail(changes.thumbnail.currentValue); } } diff --git a/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.ts b/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.ts index a834327736..cf5a93aa56 100644 --- a/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.ts +++ b/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.ts @@ -1,10 +1,15 @@ -import { Component } from '@angular/core'; +import { Component, Input } from '@angular/core'; import { SearchResultGridElementComponent } from '../search-result-grid-element.component'; import { Collection } from '../../../../core/shared/collection.model'; import { CollectionSearchResult } from '../../../object-collection/shared/collection-search-result.model'; import { ViewMode } from '../../../../core/shared/view-mode.model'; import { listableObjectComponent } from '../../../object-collection/shared/listable-object/listable-object.decorator'; +import { hasNoValue, hasValue } from '../../../empty.util'; +import { followLink } from '../../../utils/follow-link-config.model'; +import { LinkService } from '../../../../core/cache/builders/link.service'; +import { TruncatableService } from '../../../truncatable/truncatable.service'; +import { BitstreamDataService } from '../../../../core/data/bitstream-data.service'; @Component({ selector: 'ds-collection-search-result-grid-element', @@ -15,4 +20,29 @@ import { listableObjectComponent } from '../../../object-collection/shared/lista * Component representing a grid element for a collection search result */ @listableObjectComponent(CollectionSearchResult, ViewMode.GridElement) -export class CollectionSearchResultGridElementComponent extends SearchResultGridElementComponent {} +export class CollectionSearchResultGridElementComponent extends SearchResultGridElementComponent< CollectionSearchResult, Collection > { + private _dso: Collection; + + constructor( + private linkService: LinkService, + protected truncatableService: TruncatableService, + protected bitstreamDataService: BitstreamDataService + ) { + super(truncatableService, bitstreamDataService); + } + + @Input() set dso(dso: Collection) { + this._dso = dso; + console.log('aaasdasd') + if (hasValue(this._dso) && hasNoValue(this._dso.logo)) { + this.linkService.resolveLink( + this._dso, + followLink('logo') + ); + } + } + + get dso(): Collection { + return this._dso; + } +} diff --git a/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.ts b/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.ts index e726c3e803..b622651e10 100644 --- a/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.ts +++ b/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.ts @@ -1,18 +1,47 @@ -import { Component } from '@angular/core'; +import { Component, Input } from '@angular/core'; import { Community } from '../../../../core/shared/community.model'; import { SearchResultGridElementComponent } from '../search-result-grid-element.component'; import { CommunitySearchResult } from '../../../object-collection/shared/community-search-result.model'; import { ViewMode } from '../../../../core/shared/view-mode.model'; import { listableObjectComponent } from '../../../object-collection/shared/listable-object/listable-object.decorator'; +import { LinkService } from '../../../../core/cache/builders/link.service'; +import { TruncatableService } from '../../../truncatable/truncatable.service'; +import { BitstreamDataService } from '../../../../core/data/bitstream-data.service'; +import { hasNoValue, hasValue } from '../../../empty.util'; +import { followLink } from '../../../utils/follow-link-config.model'; @Component({ selector: 'ds-community-search-result-grid-element', - styleUrls: ['../search-result-grid-element.component.scss', 'community-search-result-grid-element.component.scss'], - templateUrl: 'community-search-result-grid-element.component.html' + styleUrls: [ + '../search-result-grid-element.component.scss', + 'community-search-result-grid-element.component.scss', + ], + templateUrl: 'community-search-result-grid-element.component.html', }) /** * Component representing a grid element for a community search result */ @listableObjectComponent(CommunitySearchResult, ViewMode.GridElement) -export class CommunitySearchResultGridElementComponent extends SearchResultGridElementComponent { +export class CommunitySearchResultGridElementComponent extends SearchResultGridElementComponent { + private _dso: Community; + + constructor( + private linkService: LinkService, + protected truncatableService: TruncatableService, + protected bitstreamDataService: BitstreamDataService + ) { + super(truncatableService, bitstreamDataService); + } + + @Input() set dso(dso: Community) { + this._dso = dso; + console.log('aaasdasd'); + if (hasValue(this._dso) && hasNoValue(this._dso.logo)) { + this.linkService.resolveLink(this._dso, followLink('logo')); + } + } + + get dso(): Community { + return this._dso; + } } From cb3131e31bfba9b8674f0079da6c2ef93c0226be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20P=C3=A9ter=20Sipos?= Date: Fri, 13 Nov 2020 14:29:03 +0100 Subject: [PATCH 28/43] #674 remove un used imports --- src/app/+search-page/search.component.ts | 1 - src/app/core/cache/builders/link.service.spec.ts | 1 - .../collection-grid-element.component.ts | 2 +- 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/app/+search-page/search.component.ts b/src/app/+search-page/search.component.ts index 999d703dd5..bbbfdba513 100644 --- a/src/app/+search-page/search.component.ts +++ b/src/app/+search-page/search.component.ts @@ -18,7 +18,6 @@ import { SearchService } from '../core/shared/search/search.service'; import { currentPath } from '../shared/utils/route.utils'; import { Router } from '@angular/router'; import { Context } from '../core/shared/context.model'; -import { followLink } from '../shared/utils/follow-link-config.model'; @Component({ selector: 'ds-search', diff --git a/src/app/core/cache/builders/link.service.spec.ts b/src/app/core/cache/builders/link.service.spec.ts index 95a7570207..871be7e9ae 100644 --- a/src/app/core/cache/builders/link.service.spec.ts +++ b/src/app/core/cache/builders/link.service.spec.ts @@ -6,7 +6,6 @@ import { HALLink } from '../../shared/hal-link.model'; import { HALResource } from '../../shared/hal-resource.model'; import { ResourceType } from '../../shared/resource-type'; import * as decorators from './build-decorators'; -import { getDataServiceFor } from './build-decorators'; import { LinkService } from './link.service'; const spyOnFunction = (obj: T, func: keyof T) => { diff --git a/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.ts b/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.ts index 4ffaafa0f3..2e1688a0a9 100644 --- a/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.ts +++ b/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.ts @@ -1,4 +1,4 @@ -import { Component, Inject, Input } from '@angular/core'; +import { Component, Input } from '@angular/core'; import { Collection } from '../../../core/shared/collection.model'; import { AbstractListableElementComponent } from '../../object-collection/shared/object-collection-element/abstract-listable-element.component'; From bb1d8634709a9d5967f9c8eca17a7ce3512aa055 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20P=C3=A9ter=20Sipos?= Date: Fri, 13 Nov 2020 16:08:52 +0100 Subject: [PATCH 29/43] #674 fix tests --- ...min-search-result-grid-element.component.spec.ts | 7 +++++++ ...min-search-result-grid-element.component.spec.ts | 7 +++++++ .../collection-grid-element.component.spec.ts | 13 ++++++++++++- .../community-grid-element.component.spec.ts | 8 +++++++- ...ion-search-result-grid-element.component.spec.ts | 5 +++++ ...llection-search-result-grid-element.component.ts | 1 - ...ity-search-result-grid-element.component.spec.ts | 5 +++++ ...ommunity-search-result-grid-element.component.ts | 1 - 8 files changed, 43 insertions(+), 4 deletions(-) diff --git a/src/app/+admin/admin-search-page/admin-search-results/admin-search-result-grid-element/collection-search-result/collection-admin-search-result-grid-element.component.spec.ts b/src/app/+admin/admin-search-page/admin-search-results/admin-search-result-grid-element/collection-search-result/collection-admin-search-result-grid-element.component.spec.ts index 34db71db77..8ca02fa8ad 100644 --- a/src/app/+admin/admin-search-page/admin-search-results/admin-search-result-grid-element/collection-search-result/collection-admin-search-result-grid-element.component.spec.ts +++ b/src/app/+admin/admin-search-page/admin-search-results/admin-search-result-grid-element/collection-search-result/collection-admin-search-result-grid-element.component.spec.ts @@ -13,6 +13,7 @@ import { Collection } from '../../../../../core/shared/collection.model'; import { By } from '@angular/platform-browser'; import { RouterTestingModule } from '@angular/router/testing'; import { getCollectionEditRoute } from '../../../../../+collection-page/collection-page-routing-paths'; +import { LinkService } from '../../../../../core/cache/builders/link.service'; describe('CollectionAdminSearchResultGridElementComponent', () => { let component: CollectionAdminSearchResultGridElementComponent; @@ -26,6 +27,11 @@ describe('CollectionAdminSearchResultGridElementComponent', () => { searchResult.indexableObject = new Collection(); searchResult.indexableObject.uuid = id; } + + const linkService = jasmine.createSpyObj('linkService', { + resolveLink: {} + }); + beforeEach(async(() => { init(); TestBed.configureTestingModule({ @@ -39,6 +45,7 @@ describe('CollectionAdminSearchResultGridElementComponent', () => { providers: [ { provide: TruncatableService, useValue: mockTruncatableService }, { provide: BitstreamDataService, useValue: {} }, + { provide: LinkService, useValue: linkService} ] }) .compileComponents(); diff --git a/src/app/+admin/admin-search-page/admin-search-results/admin-search-result-grid-element/community-search-result/community-admin-search-result-grid-element.component.spec.ts b/src/app/+admin/admin-search-page/admin-search-results/admin-search-result-grid-element/community-search-result/community-admin-search-result-grid-element.component.spec.ts index 85c81d55a4..f6a4d02c13 100644 --- a/src/app/+admin/admin-search-page/admin-search-results/admin-search-result-grid-element/community-search-result/community-admin-search-result-grid-element.component.spec.ts +++ b/src/app/+admin/admin-search-page/admin-search-results/admin-search-result-grid-element/community-search-result/community-admin-search-result-grid-element.component.spec.ts @@ -16,6 +16,7 @@ import { CommunitySearchResult } from '../../../../../shared/object-collection/s import { Community } from '../../../../../core/shared/community.model'; import { CommunityAdminSearchResultListElementComponent } from '../../admin-search-result-list-element/community-search-result/community-admin-search-result-list-element.component'; import { getCommunityEditRoute } from '../../../../../+community-page/community-page-routing-paths'; +import { LinkService } from '../../../../../core/cache/builders/link.service'; describe('CommunityAdminSearchResultGridElementComponent', () => { let component: CommunityAdminSearchResultGridElementComponent; @@ -29,6 +30,11 @@ describe('CommunityAdminSearchResultGridElementComponent', () => { searchResult.indexableObject = new Community(); searchResult.indexableObject.uuid = id; } + + const linkService = jasmine.createSpyObj('linkService', { + resolveLink: {} + }); + beforeEach(async(() => { init(); TestBed.configureTestingModule({ @@ -42,6 +48,7 @@ describe('CommunityAdminSearchResultGridElementComponent', () => { providers: [ { provide: TruncatableService, useValue: mockTruncatableService }, { provide: BitstreamDataService, useValue: {} }, + { provide: LinkService, useValue: linkService} ], schemas: [NO_ERRORS_SCHEMA] }) diff --git a/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.spec.ts b/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.spec.ts index 66807c6b20..9101561a51 100644 --- a/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.spec.ts +++ b/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.spec.ts @@ -3,10 +3,16 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { By } from '@angular/platform-browser'; import { Collection } from '../../../core/shared/collection.model'; +import { of } from 'rxjs'; +import { createSuccessfulRemoteDataObject$ } from '../../remote-data.utils'; +import { Bitstream } from '../../../core/shared/bitstream.model'; +import { LinkService } from '../../../core/cache/builders/link.service'; let collectionGridElementComponent: CollectionGridElementComponent; let fixture: ComponentFixture; + + const mockCollectionWithAbstract: Collection = Object.assign(new Collection(), { metadata: { 'dc.description.abstract': [ @@ -29,12 +35,17 @@ const mockCollectionWithoutAbstract: Collection = Object.assign(new Collection() } }); +const linkService = jasmine.createSpyObj('linkService', { + resolveLink: mockCollectionWithAbstract +}); + describe('CollectionGridElementComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [ CollectionGridElementComponent ], providers: [ - { provide: 'objectElementProvider', useValue: (mockCollectionWithAbstract)} + { provide: 'objectElementProvider', useValue: (mockCollectionWithAbstract)}, + { provide: LinkService, useValue: linkService} ], schemas: [ NO_ERRORS_SCHEMA ] diff --git a/src/app/shared/object-grid/community-grid-element/community-grid-element.component.spec.ts b/src/app/shared/object-grid/community-grid-element/community-grid-element.component.spec.ts index bb6c81144a..dfcac7dc1f 100644 --- a/src/app/shared/object-grid/community-grid-element/community-grid-element.component.spec.ts +++ b/src/app/shared/object-grid/community-grid-element/community-grid-element.component.spec.ts @@ -3,6 +3,7 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { By } from '@angular/platform-browser'; import { Community } from '../../../core/shared/community.model'; +import { LinkService } from '../../../core/cache/builders/link.service'; let communityGridElementComponent: CommunityGridElementComponent; let fixture: ComponentFixture; @@ -29,12 +30,17 @@ const mockCommunityWithoutAbstract: Community = Object.assign(new Community(), { } }); +const linkService = jasmine.createSpyObj('linkService', { + resolveLink: mockCommunityWithAbstract +}); + describe('CommunityGridElementComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [ CommunityGridElementComponent ], providers: [ - { provide: 'objectElementProvider', useValue: (mockCommunityWithAbstract)} + { provide: 'objectElementProvider', useValue: (mockCommunityWithAbstract)}, + { provide: LinkService, useValue: linkService} ], schemas: [ NO_ERRORS_SCHEMA ] diff --git a/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.spec.ts b/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.spec.ts index d065f9c7e4..d40b99316a 100644 --- a/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.spec.ts +++ b/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.spec.ts @@ -19,6 +19,7 @@ import { TruncatableService } from '../../../truncatable/truncatable.service'; import { TruncatePipe } from '../../../utils/truncate.pipe'; import { CollectionSearchResultGridElementComponent } from './collection-search-result-grid-element.component'; import { BitstreamFormatDataService } from '../../../../core/data/bitstream-format-data.service'; +import { LinkService } from '../../../../core/cache/builders/link.service'; let collectionSearchResultGridElementComponent: CollectionSearchResultGridElementComponent; let fixture: ComponentFixture; @@ -52,6 +53,9 @@ mockCollectionWithoutAbstract.indexableObject = Object.assign(new Collection(), ] } }); +const linkService = jasmine.createSpyObj('linkService', { + resolveLink: mockCollectionWithAbstract +}); describe('CollectionSearchResultGridElementComponent', () => { beforeEach(async(() => { @@ -72,6 +76,7 @@ describe('CollectionSearchResultGridElementComponent', () => { { provide: DSOChangeAnalyzer, useValue: {} }, { provide: DefaultChangeAnalyzer, useValue: {} }, { provide: BitstreamFormatDataService, useValue: {} }, + { provide: LinkService, useValue: linkService} ], schemas: [ NO_ERRORS_SCHEMA ] diff --git a/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.ts b/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.ts index cf5a93aa56..e0182c3fb4 100644 --- a/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.ts +++ b/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.ts @@ -33,7 +33,6 @@ export class CollectionSearchResultGridElementComponent extends SearchResultGrid @Input() set dso(dso: Collection) { this._dso = dso; - console.log('aaasdasd') if (hasValue(this._dso) && hasNoValue(this._dso.logo)) { this.linkService.resolveLink( this._dso, diff --git a/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.spec.ts b/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.spec.ts index 0d59273111..7b3fe0a7dc 100644 --- a/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.spec.ts +++ b/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.spec.ts @@ -19,6 +19,7 @@ import { TruncatableService } from '../../../truncatable/truncatable.service'; import { TruncatePipe } from '../../../utils/truncate.pipe'; import { CommunitySearchResultGridElementComponent } from './community-search-result-grid-element.component'; import { BitstreamFormatDataService } from '../../../../core/data/bitstream-format-data.service'; +import { LinkService } from '../../../../core/cache/builders/link.service'; let communitySearchResultGridElementComponent: CommunitySearchResultGridElementComponent; let fixture: ComponentFixture; @@ -52,6 +53,9 @@ mockCommunityWithoutAbstract.indexableObject = Object.assign(new Community(), { ] } }); +const linkService = jasmine.createSpyObj('linkService', { + resolveLink: mockCommunityWithAbstract +}); describe('CommunitySearchResultGridElementComponent', () => { beforeEach(async(() => { @@ -72,6 +76,7 @@ describe('CommunitySearchResultGridElementComponent', () => { { provide: DSOChangeAnalyzer, useValue: {} }, { provide: DefaultChangeAnalyzer, useValue: {} }, { provide: BitstreamFormatDataService, useValue: {} }, + { provide: LinkService, useValue: linkService} ], schemas: [ NO_ERRORS_SCHEMA ] diff --git a/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.ts b/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.ts index b622651e10..5c4deb1064 100644 --- a/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.ts +++ b/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.ts @@ -35,7 +35,6 @@ export class CommunitySearchResultGridElementComponent extends SearchResultGridE @Input() set dso(dso: Community) { this._dso = dso; - console.log('aaasdasd'); if (hasValue(this._dso) && hasNoValue(this._dso.logo)) { this.linkService.resolveLink(this._dso, followLink('logo')); } From 5923a973363db8e4115fc6a9aad38e09bbc88cfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20P=C3=A9ter=20Sipos?= Date: Fri, 13 Nov 2020 16:51:23 +0100 Subject: [PATCH 30/43] #674 remove un used imports --- .../collection-grid-element.component.spec.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.spec.ts b/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.spec.ts index 9101561a51..5a3cb2c74b 100644 --- a/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.spec.ts +++ b/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.spec.ts @@ -3,9 +3,6 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { By } from '@angular/platform-browser'; import { Collection } from '../../../core/shared/collection.model'; -import { of } from 'rxjs'; -import { createSuccessfulRemoteDataObject$ } from '../../remote-data.utils'; -import { Bitstream } from '../../../core/shared/bitstream.model'; import { LinkService } from '../../../core/cache/builders/link.service'; let collectionGridElementComponent: CollectionGridElementComponent; From c377a3e45ad61ed81a7e87b265283c9578106c87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20P=C3=A9ter=20Sipos?= Date: Fri, 13 Nov 2020 17:31:05 +0100 Subject: [PATCH 31/43] #674 fix --- .../collection-grid-element.component.spec.ts | 2 -- .../collection-grid-element.component.ts | 15 +++++++++------ .../community-grid-element.component.ts | 3 +-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.spec.ts b/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.spec.ts index 5a3cb2c74b..efd4d0645c 100644 --- a/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.spec.ts +++ b/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.spec.ts @@ -8,8 +8,6 @@ import { LinkService } from '../../../core/cache/builders/link.service'; let collectionGridElementComponent: CollectionGridElementComponent; let fixture: ComponentFixture; - - const mockCollectionWithAbstract: Collection = Object.assign(new Collection(), { metadata: { 'dc.description.abstract': [ diff --git a/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.ts b/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.ts index 2e1688a0a9..bbb729d0ca 100644 --- a/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.ts +++ b/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.ts @@ -1,5 +1,4 @@ import { Component, Input } from '@angular/core'; - import { Collection } from '../../../core/shared/collection.model'; import { AbstractListableElementComponent } from '../../object-collection/shared/object-collection-element/abstract-listable-element.component'; import { ViewMode } from '../../../core/shared/view-mode.model'; @@ -14,21 +13,25 @@ import { LinkService } from '../../../core/cache/builders/link.service'; @Component({ selector: 'ds-collection-grid-element', styleUrls: ['./collection-grid-element.component.scss'], - templateUrl: './collection-grid-element.component.html' + templateUrl: './collection-grid-element.component.html', }) - @listableObjectComponent(Collection, ViewMode.GridElement) -export class CollectionGridElementComponent extends AbstractListableElementComponent { +export class CollectionGridElementComponent extends AbstractListableElementComponent< + Collection +> { private _object: Collection; - constructor( private linkService: LinkService){ + constructor(private linkService: LinkService) { super(); } @Input() set object(object: Collection) { this._object = object; if (hasValue(this._object) && hasNoValue(this._object.logo)) { - this.linkService.resolveLink(this._object, followLink('logo')) + this.linkService.resolveLink( + this._object, + followLink('logo') + ); } } diff --git a/src/app/shared/object-grid/community-grid-element/community-grid-element.component.ts b/src/app/shared/object-grid/community-grid-element/community-grid-element.component.ts index 47ab77de5f..3bf6ffe104 100644 --- a/src/app/shared/object-grid/community-grid-element/community-grid-element.component.ts +++ b/src/app/shared/object-grid/community-grid-element/community-grid-element.component.ts @@ -1,5 +1,4 @@ import { Component, Input } from '@angular/core'; - import { Community } from '../../../core/shared/community.model'; import { AbstractListableElementComponent } from '../../object-collection/shared/object-collection-element/abstract-listable-element.component'; import { ViewMode } from '../../../core/shared/view-mode.model'; @@ -21,7 +20,7 @@ import { hasNoValue, hasValue } from '../../empty.util'; export class CommunityGridElementComponent extends AbstractListableElementComponent { private _object: Community; - constructor( private linkService: LinkService){ + constructor( private linkService: LinkService) { super(); } From 82811ebafd0af55ddefb435449bd0c8cad62ecb7 Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Mon, 16 Nov 2020 09:34:34 +0100 Subject: [PATCH 32/43] 74348: Add comments and update rate limit config --- src/environments/environment.common.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/environments/environment.common.ts b/src/environments/environment.common.ts index 7e3d7c6543..a7c8b2a5ff 100644 --- a/src/environments/environment.common.ts +++ b/src/environments/environment.common.ts @@ -13,9 +13,10 @@ export const environment: GlobalConfig = { port: 4000, // NOTE: Space is capitalized because 'namespace' is a reserved string in TypeScript nameSpace: '/', + // The rateLimiter settings limit each IP to a "max" of 120 requests per "windowMs" (1 minute). rateLimiter: { - windowMs: 1 * 60 * 1000, - max: 100 + windowMs: 1 * 60 * 1000, // 1 minute + max: 120 // limit each IP to 120 requests per windowMs } }, // The REST API server settings. From 140f660cf46fd4153d5264f829abb3c80d7f00ad Mon Sep 17 00:00:00 2001 From: Marie Verdonck Date: Mon, 16 Nov 2020 17:57:59 +0100 Subject: [PATCH 33/43] 74345: Fix com/col tree issues (#899 & #908): https://github.com/DSpace/dspace-angular/issues/899 https://github.com/DSpace/dspace-angular/issues/908 --- .../community-list-datasource.ts | 23 ++++----- .../community-list-service.ts | 48 ++++++++++++------- .../community-list.component.html | 2 +- .../community-list.component.ts | 11 ++--- 4 files changed, 50 insertions(+), 34 deletions(-) diff --git a/src/app/community-list-page/community-list-datasource.ts b/src/app/community-list-page/community-list-datasource.ts index b77cbb5246..041785e9e8 100644 --- a/src/app/community-list-page/community-list-datasource.ts +++ b/src/app/community-list-page/community-list-datasource.ts @@ -1,9 +1,10 @@ -import { NgZone } from '@angular/core'; +import { Subscription } from 'rxjs/internal/Subscription'; import { FindListOptions } from '../core/data/request.models'; +import { hasValue } from '../shared/empty.util'; import { CommunityListService, FlatNode } from './community-list-service'; import { CollectionViewer, DataSource } from '@angular/cdk/typings/collections'; import { BehaviorSubject, Observable, } from 'rxjs'; -import { finalize, take, } from 'rxjs/operators'; +import { finalize } from 'rxjs/operators'; /** * DataSource object needed by a CDK Tree to render its nodes. @@ -15,9 +16,9 @@ export class CommunityListDatasource implements DataSource { private communityList$ = new BehaviorSubject([]); public loading$ = new BehaviorSubject(false); + private subLoadCommunities: Subscription; - constructor(private communityListService: CommunityListService, - private zone: NgZone) { + constructor(private communityListService: CommunityListService) { } connect(collectionViewer: CollectionViewer): Observable { @@ -26,13 +27,13 @@ export class CommunityListDatasource implements DataSource { loadCommunities(findOptions: FindListOptions, expandedNodes: FlatNode[]) { this.loading$.next(true); - this.zone.runOutsideAngular(() => { - this.communityListService.loadCommunities(findOptions, expandedNodes).pipe( - take(1), - finalize(() => this.zone.run(() => this.loading$.next(false))), - ).subscribe((flatNodes: FlatNode[]) => { - this.zone.run(() => this.communityList$.next(flatNodes)); - }); + if (hasValue(this.subLoadCommunities)) { + this.subLoadCommunities.unsubscribe(); + } + this.subLoadCommunities = this.communityListService.loadCommunities(findOptions, expandedNodes).pipe( + finalize(() => this.loading$.next(false)), + ).subscribe((flatNodes: FlatNode[]) => { + this.communityList$.next(flatNodes); }); } diff --git a/src/app/community-list-page/community-list-service.ts b/src/app/community-list-page/community-list-service.ts index 4699e6faaa..5905fd8639 100644 --- a/src/app/community-list-page/community-list-service.ts +++ b/src/app/community-list-page/community-list-service.ts @@ -2,13 +2,12 @@ import { Injectable } from '@angular/core'; import { createSelector, Store } from '@ngrx/store'; import { combineLatest as observableCombineLatest } from 'rxjs/internal/observable/combineLatest'; import { Observable, of as observableOf } from 'rxjs'; +import { map, switchMap } from 'rxjs/operators'; import { AppState } from '../app.reducer'; import { CommunityDataService } from '../core/data/community-data.service'; import { FindListOptions } from '../core/data/request.models'; -import { map, flatMap } from 'rxjs/operators'; import { Community } from '../core/shared/community.model'; import { Collection } from '../core/shared/collection.model'; -import { getSucceededRemoteData } from '../core/shared/operators'; import { PageInfo } from '../core/shared/page-info.model'; import { hasValue, isNotEmpty } from '../shared/empty.util'; import { RemoteData } from '../core/data/remote-data'; @@ -148,7 +147,7 @@ export class CommunityListService { return new PaginatedList(newPageInfo, newPage); }) ); - return topComs$.pipe(flatMap((topComs: PaginatedList) => this.transformListOfCommunities(topComs, 0, null, expandedNodes))); + return topComs$.pipe(switchMap((topComs: PaginatedList) => this.transformListOfCommunities(topComs, 0, null, expandedNodes))); }; /** @@ -228,9 +227,13 @@ export class CommunityListService { currentPage: i }) .pipe( - getSucceededRemoteData(), - flatMap((rd: RemoteData>) => - this.transformListOfCommunities(rd.payload, level + 1, communityFlatNode, expandedNodes)) + switchMap((rd: RemoteData>) => { + if (hasValue(rd) && hasValue(rd.payload)) { + return this.transformListOfCommunities(rd.payload, level + 1, communityFlatNode, expandedNodes); + } else { + return []; + } + }) ); subcoms = [...subcoms, nextSetOfSubcommunitiesPage]; @@ -246,14 +249,17 @@ export class CommunityListService { currentPage: i }) .pipe( - getSucceededRemoteData(), map((rd: RemoteData>) => { - let nodes = rd.payload.page - .map((collection: Collection) => toFlatNode(collection, observableOf(false), level + 1, false, communityFlatNode)); - if (currentCollectionPage < rd.payload.totalPages && currentCollectionPage === rd.payload.currentPage) { - nodes = [...nodes, showMoreFlatNode('collection', level + 1, communityFlatNode)]; + if (hasValue(rd) && hasValue(rd.payload)) { + let nodes = rd.payload.page + .map((collection: Collection) => toFlatNode(collection, observableOf(false), level + 1, false, communityFlatNode)); + if (currentCollectionPage < rd.payload.totalPages && currentCollectionPage === rd.payload.currentPage) { + nodes = [...nodes, showMoreFlatNode('collection', level + 1, communityFlatNode)]; + } + return nodes; + } else { + return []; } - return nodes; }), ); collections = [...collections, nextSetOfCollectionsPage]; @@ -275,14 +281,24 @@ export class CommunityListService { let hasColls$: Observable; hasSubcoms$ = this.communityDataService.findByParent(community.uuid, { elementsPerPage: 1 }) .pipe( - getSucceededRemoteData(), - map((results) => results.payload.totalElements > 0), + map((rd: RemoteData>) => { + if (hasValue(rd) && hasValue(rd.payload)) { + return rd.payload.totalElements > 0; + } else { + return false; + } + }), ); hasColls$ = this.collectionDataService.findByParent(community.uuid, { elementsPerPage: 1 }) .pipe( - getSucceededRemoteData(), - map((results) => results.payload.totalElements > 0), + map((rd: RemoteData>) => { + if (hasValue(rd) && hasValue(rd.payload)) { + return rd.payload.totalElements > 0; + } else { + return false; + } + }), ); let hasChildren$: Observable; diff --git a/src/app/community-list-page/community-list/community-list.component.html b/src/app/community-list-page/community-list/community-list.component.html index c179715bf1..07e06f3131 100644 --- a/src/app/community-list-page/community-list/community-list.component.html +++ b/src/app/community-list-page/community-list/community-list.component.html @@ -28,7 +28,7 @@ diff --git a/src/app/community-list-page/community-list/community-list.component.ts b/src/app/community-list-page/community-list/community-list.component.ts index be96ff1a0a..49065c5ec5 100644 --- a/src/app/community-list-page/community-list/community-list.component.ts +++ b/src/app/community-list-page/community-list/community-list.component.ts @@ -1,4 +1,4 @@ -import { Component, NgZone, OnDestroy, OnInit } from '@angular/core'; +import { Component, OnDestroy, OnInit } from '@angular/core'; import { take } from 'rxjs/operators'; import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; import { FindListOptions } from '../../core/data/request.models'; @@ -24,15 +24,14 @@ export class CommunityListComponent implements OnInit, OnDestroy { public loadingNode: FlatNode; treeControl = new FlatTreeControl( - (node) => node.level, (node) => true + (node: FlatNode) => node.level, (node: FlatNode) => true ); dataSource: CommunityListDatasource; paginationConfig: FindListOptions; - constructor(private communityListService: CommunityListService, - private zone: NgZone) { + constructor(private communityListService: CommunityListService) { this.paginationConfig = new FindListOptions(); this.paginationConfig.elementsPerPage = 2; this.paginationConfig.currentPage = 1; @@ -40,7 +39,7 @@ export class CommunityListComponent implements OnInit, OnDestroy { } ngOnInit() { - this.dataSource = new CommunityListDatasource(this.communityListService, this.zone); + this.dataSource = new CommunityListDatasource(this.communityListService); this.communityListService.getLoadingNodeFromStore().pipe(take(1)).subscribe((result) => { this.loadingNode = result; }); @@ -65,7 +64,7 @@ export class CommunityListComponent implements OnInit, OnDestroy { } /** - * Toggles the expanded variable of a node, adds it to the exapanded nodes list and reloads the tree so this node is expanded + * Toggles the expanded variable of a node, adds it to the expanded nodes list and reloads the tree so this node is expanded * @param node Node we want to expand */ toggleExpanded(node: FlatNode) { From c40f31279f820a80570cd82ef01ab53d065628b1 Mon Sep 17 00:00:00 2001 From: Corrado Lombardi Date: Tue, 17 Nov 2020 09:29:01 +0100 Subject: [PATCH 34/43] [CSTPER-66] moved refreshCache function to common ComColDataService, tests have been moved accordingly. Used HalEndpointService to discover communities search top endpoint --- src/app/core/data/comcol-data.service.spec.ts | 89 ++++++++++++++++++- src/app/core/data/comcol-data.service.ts | 21 +++++ .../create-comcol-page.component.spec.ts | 82 ++--------------- .../create-comcol-page.component.ts | 21 +---- .../delete-comcol-page.component.spec.ts | 79 ++-------------- .../delete-comcol-page.component.ts | 24 +---- 6 files changed, 125 insertions(+), 191 deletions(-) diff --git a/src/app/core/data/comcol-data.service.spec.ts b/src/app/core/data/comcol-data.service.spec.ts index 1ba19df18c..f48022e6f1 100644 --- a/src/app/core/data/comcol-data.service.spec.ts +++ b/src/app/core/data/comcol-data.service.spec.ts @@ -17,6 +17,7 @@ import { DSOChangeAnalyzer } from './dso-change-analyzer.service'; import { FindByIDRequest, FindListOptions } from './request.models'; import { RequestEntry } from './request.reducer'; import { RequestService } from './request.service'; +import {createNoContentRemoteDataObject$, createSuccessfulRemoteDataObject$} from '../../shared/remote-data.utils'; const LINK_NAME = 'test'; @@ -51,7 +52,9 @@ describe('ComColDataService', () => { let objectCache: ObjectCacheService; let halService: any = {}; - const rdbService = {} as RemoteDataBuildService; + const rdbService = { + buildSingle : () => null + } as any; const store = {} as Store; const notificationsService = {} as NotificationsService; const http = {} as HttpClient; @@ -178,6 +181,90 @@ describe('ComColDataService', () => { }); }); + describe('cache refresh', () => { + let communityWithoutParentHref; + let data; + + beforeEach(() => { + scheduler = getTestScheduler(); + halService = { + getEndpoint: (linkPath) => 'https://rest.api/core/' + linkPath + }; + service = initTestService(); + + }) + describe('cache refreshed top level community', () => { + beforeEach(() => { + spyOn(rdbService, 'buildSingle').and.returnValue(createNoContentRemoteDataObject$()); + data = { + dso: Object.assign(new Community(), { + metadata: [{ + key: 'dc.title', + value: 'top level community' + }] + }), + _links: { + parentCommunity: { + href: 'topLevel/parentCommunity' + } + } + }; + communityWithoutParentHref = { + dso: Object.assign(new Community(), { + metadata: [{ + key: 'dc.title', + value: 'top level community' + }] + }), + _links: {} + }; + }); + it('top level community cache refreshed', () => { + scheduler.schedule(() => (service as any).refreshCache(data)); + scheduler.flush(); + expect(requestService.removeByHrefSubstring).toHaveBeenCalledWith('https://rest.api/core/communities/search/top'); + }); + it('top level community without parent link, cache not refreshed', () => { + scheduler.schedule(() => (service as any).refreshCache(communityWithoutParentHref)); + scheduler.flush(); + expect(requestService.removeByHrefSubstring).not.toHaveBeenCalled(); + }); + }); + + describe('cache refreshed child community', () => { + beforeEach(() => { + const parentCommunity = Object.assign(new Community(), { + uuid: 'a20da287-e174-466a-9926-f66as300d399', + id: 'a20da287-e174-466a-9926-f66as300d399', + metadata: [{ + key: 'dc.title', + value: 'parent community' + }], + _links: {} + }); + spyOn(rdbService, 'buildSingle').and.returnValue(createSuccessfulRemoteDataObject$(parentCommunity)); + data = { + dso: Object.assign(new Community(), { + metadata: [{ + key: 'dc.title', + value: 'child community' + }] + }), + _links: { + parentCommunity: { + href: 'child/parentCommunity' + } + } + }; + }); + it('child level community cache refreshed', () => { + scheduler.schedule(() => (service as any).refreshCache(data)); + scheduler.flush(); + expect(requestService.removeByHrefSubstring).toHaveBeenCalledWith('a20da287-e174-466a-9926-f66as300d399'); + }); + }); + }); + }); }); diff --git a/src/app/core/data/comcol-data.service.ts b/src/app/core/data/comcol-data.service.ts index d83518a3b0..86731b9696 100644 --- a/src/app/core/data/comcol-data.service.ts +++ b/src/app/core/data/comcol-data.service.ts @@ -21,12 +21,14 @@ import { configureRequest, getRemoteDataPayload, getResponseFromEntry, + getSucceededOrNoContentResponse, getSucceededRemoteData } from '../shared/operators'; import { CacheableObject } from '../cache/object-cache.reducer'; import { RestResponse } from '../cache/response.models'; import { Bitstream } from '../shared/bitstream.model'; import { DSpaceObject } from '../shared/dspace-object.model'; +import {Collection} from '../shared/collection.model'; export abstract class ComColDataService extends DataService { protected abstract cds: CommunityDataService; @@ -119,4 +121,23 @@ export abstract class ComColDataService extends DataS ); } } + + public refreshCache(dso: T) { + const parentCommunityUrl = this.parentCommunityUrl(dso as any); + if (!hasValue(parentCommunityUrl)) { + return; + } + this.findByHref(parentCommunityUrl).pipe( + getSucceededOrNoContentResponse(), + take(1), + ).subscribe((rd: RemoteData) => { + const href = rd.hasSucceeded && !isEmpty(rd.payload.id) ? rd.payload.id : this.halService.getEndpoint('communities/search/top'); + this.requestService.removeByHrefSubstring(href) + }); + } + + private parentCommunityUrl(dso: Collection | Community) { + const parentCommunity = dso._links.parentCommunity; + return isNotEmpty(parentCommunity) ? parentCommunity.href : null; + } } diff --git a/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.spec.ts b/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.spec.ts index a7496fbf7a..d7827957a1 100644 --- a/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.spec.ts +++ b/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.spec.ts @@ -79,7 +79,8 @@ describe('CreateComColPageComponent', () => { })), create: (com, uuid?) => createSuccessfulRemoteDataObject$(newCommunity), getLogoEndpoint: () => observableOf(logoEndpoint), - findByHref: () => null + findByHref: () => null, + refreshCache: () => {return} }; routeServiceStub = { @@ -150,21 +151,21 @@ describe('CreateComColPageComponent', () => { it('should navigate and refresh cache when successful', () => { spyOn(router, 'navigate'); - spyOn((comp as any), 'refreshCache') + spyOn((dsoDataService as any), 'refreshCache') scheduler.schedule(() => comp.onSubmit(data)); scheduler.flush(); expect(router.navigate).toHaveBeenCalled(); - expect((comp as any).refreshCache).toHaveBeenCalled(); + expect((dsoDataService as any).refreshCache).toHaveBeenCalled(); }); it('should neither navigate nor refresh cache on failure', () => { spyOn(router, 'navigate'); spyOn(dsoDataService, 'create').and.returnValue(createFailedRemoteDataObject$(newCommunity)); - spyOn((comp as any), 'refreshCache') + spyOn(dsoDataService, 'refreshCache') scheduler.schedule(() => comp.onSubmit(data)); scheduler.flush(); expect(router.navigate).not.toHaveBeenCalled(); - expect((comp as any).refreshCache).not.toHaveBeenCalled(); + expect((dsoDataService as any).refreshCache).not.toHaveBeenCalled(); }); }); @@ -212,76 +213,5 @@ describe('CreateComColPageComponent', () => { expect(data.uploader.uploadAll).toHaveBeenCalled(); }); }); - - describe('cache refresh', () => { - let communityWithoutParentHref; - - beforeEach(() => { - scheduler = getTestScheduler(); - - }) - describe('cache refreshed top level community', () => { - beforeEach(() => { - spyOn(dsoDataService, 'findByHref').and.returnValue(createNoContentRemoteDataObject$()); - data = { - dso: Object.assign(new Community(), { - metadata: [{ - key: 'dc.title', - value: 'top level community' - }] - }), - _links: { - parentCommunity: { - href: 'topLevel/parentCommunity' - } - } - }; - communityWithoutParentHref = { - dso: Object.assign(new Community(), { - metadata: [{ - key: 'dc.title', - value: 'top level community' - }] - }), - _links: {} - }; - }); - it('top level community cache refreshed', () => { - scheduler.schedule(() => (comp as any).refreshCache(data)); - scheduler.flush(); - expect(requestServiceStub.removeByHrefSubstring).toHaveBeenCalledWith('communities/search/top'); - }); - it('top level community without parent link, cache not refreshed', () => { - scheduler.schedule(() => (comp as any).refreshCache(communityWithoutParentHref)); - scheduler.flush(); - expect(requestServiceStub.removeByHrefSubstring).not.toHaveBeenCalled(); - }); - }); - - describe('cache refreshed child community', () => { - beforeEach(() => { - spyOn(dsoDataService, 'findByHref').and.returnValue(createSuccessfulRemoteDataObject$(parentCommunity)); - data = { - dso: Object.assign(new Community(), { - metadata: [{ - key: 'dc.title', - value: 'child community' - }] - }), - _links: { - parentCommunity: { - href: 'child/parentCommunity' - } - } - }; - }); - it('child level community cache refreshed', () => { - scheduler.schedule(() => (comp as any).refreshCache(data)); - scheduler.flush(); - expect(requestServiceStub.removeByHrefSubstring).toHaveBeenCalledWith('a20da287-e174-466a-9926-f66as300d399'); - }); - }); - }); - }); }); diff --git a/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.ts b/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.ts index 336998aab3..cb1f41dd23 100644 --- a/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.ts +++ b/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.ts @@ -101,7 +101,7 @@ export class CreateComColPageComponent implements } else { this.navigateToNewPage(); } - this.refreshCache(dsoRD); + this.dsoDataService.refreshCache(dsoRD); } this.notificationsService.success(null, this.translate.get(this.type.value + '.create.notifications.success')); }); @@ -115,23 +115,4 @@ export class CreateComColPageComponent implements this.router.navigate([this.frontendURL + this.newUUID]); } } - - private refreshCache(dso: TDomain) { - const parentCommunityUrl = this.parentCommunityUrl(dso as any); - if (!hasValue(parentCommunityUrl)) { - return; - } - this.dsoDataService.findByHref(parentCommunityUrl).pipe( - getSucceededOrNoContentResponse(), - take(1), - ).subscribe((rd: RemoteData) => { - const href = rd.hasSucceeded && !isEmpty(rd.payload.id) ? rd.payload.id : 'communities/search/top'; - this.requestService.removeByHrefSubstring(href) - }); - } - - private parentCommunityUrl(dso: Collection | Community) { - const parentCommunity = dso._links.parentCommunity; - return isNotEmpty(parentCommunity) ? parentCommunity.href : null; - } } diff --git a/src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.spec.ts b/src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.spec.ts index b5a3ccea5d..6669f4c395 100644 --- a/src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.spec.ts +++ b/src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.spec.ts @@ -16,6 +16,7 @@ import { NotificationsServiceStub } from '../../testing/notifications-service.st import {RequestService} from '../../../core/data/request.service'; import {getTestScheduler} from 'jasmine-marbles'; import {createNoContentRemoteDataObject$, createSuccessfulRemoteDataObject$} from '../../remote-data.utils'; +import {ComColDataService} from '../../../core/data/comcol-data.service'; describe('DeleteComColPageComponent', () => { let comp: DeleteComColPageComponent; @@ -67,7 +68,8 @@ describe('DeleteComColPageComponent', () => { 'dsoDataService', { delete: observableOf({ isSuccessful: true }), - findByHref: jasmine.createSpy('findByHref') + findByHref: jasmine.createSpy('findByHref'), + refreshCache: jasmine.createSpy('refreshCache') }); routerStub = { @@ -93,7 +95,7 @@ describe('DeleteComColPageComponent', () => { TestBed.configureTestingModule({ imports: [TranslateModule.forRoot(), SharedModule, CommonModule, RouterTestingModule], providers: [ - { provide: DataService, useValue: dsoDataService }, + { provide: ComColDataService, useValue: dsoDataService }, { provide: Router, useValue: routerStub }, { provide: ActivatedRoute, useValue: routeStub }, { provide: NotificationsService, useValue: new NotificationsServiceStub() }, @@ -153,23 +155,21 @@ describe('DeleteComColPageComponent', () => { it('should show an error notification on failure', () => { (dsoDataService.delete as any).and.returnValue(observableOf({ isSuccessful: false })); spyOn(router, 'navigate'); - spyOn((comp as any), 'refreshCache'); scheduler.schedule(() => comp.onConfirm(data2)); scheduler.flush(); fixture.detectChanges(); expect(notificationsService.error).toHaveBeenCalled(); - expect((comp as any).refreshCache).not.toHaveBeenCalled(); + expect(dsoDataService.refreshCache).not.toHaveBeenCalled(); expect(router.navigate).toHaveBeenCalled(); }); it('should show a success notification on success and navigate', () => { spyOn(router, 'navigate'); - spyOn((comp as any), 'refreshCache'); scheduler.schedule(() => comp.onConfirm(data1)); scheduler.flush(); fixture.detectChanges(); expect(notificationsService.success).toHaveBeenCalled(); - expect((comp as any).refreshCache).toHaveBeenCalled(); + expect(dsoDataService.refreshCache).toHaveBeenCalled(); expect(router.navigate).toHaveBeenCalled(); }); @@ -178,73 +178,6 @@ describe('DeleteComColPageComponent', () => { fixture.detectChanges(); expect(dsoDataService.delete).toHaveBeenCalledWith(data1.id); }); - - describe('cache refresh', () => { - let communityWithoutParentHref; - let deletedCommunity; - - describe('cache refreshed top level community', () => { - beforeEach(() => { - (dsoDataService.findByHref as any).and.returnValue(createNoContentRemoteDataObject$()); - deletedCommunity = { - dso: Object.assign(new Community(), { - metadata: [{ - key: 'dc.title', - value: 'top level community' - }] - }), - _links: { - parentCommunity: { - href: 'topLevel/parentCommunity' - } - } - }; - communityWithoutParentHref = { - dso: Object.assign(new Community(), { - metadata: [{ - key: 'dc.title', - value: 'top level community' - }] - }), - _links: {} - }; - }); - it('top level community cache refreshed', () => { - scheduler.schedule(() => (comp as any).refreshCache(deletedCommunity)); - scheduler.flush(); - expect(requestServiceStub.removeByHrefSubstring).toHaveBeenCalledWith('communities/search/top'); - }); - it('top level community without parent link, cache not refreshed', () => { - scheduler.schedule(() => (comp as any).refreshCache(communityWithoutParentHref)); - scheduler.flush(); - expect(requestServiceStub.removeByHrefSubstring).not.toHaveBeenCalled(); - }); - }); - - describe('cache refreshed child community', () => { - beforeEach(() => { - (dsoDataService.findByHref as any).and.returnValue(createSuccessfulRemoteDataObject$(parentCommunity)); - deletedCommunity = { - dso: Object.assign(new Community(), { - metadata: [{ - key: 'dc.title', - value: 'child community' - }] - }), - _links: { - parentCommunity: { - href: 'child/parentCommunity' - } - } - }; - }); - it('child level community cache refreshed', () => { - scheduler.schedule(() => (comp as any).refreshCache(deletedCommunity)); - scheduler.flush(); - expect(requestServiceStub.removeByHrefSubstring).toHaveBeenCalledWith('a20da287-e174-466a-9926-f66as300d399'); - }); - }); - }); }); describe('onCancel', () => { diff --git a/src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.ts b/src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.ts index 835d302de3..d71660b297 100644 --- a/src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.ts +++ b/src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.ts @@ -15,6 +15,7 @@ import { } from '../../../core/shared/operators'; import {Community} from '../../../core/shared/community.model'; import {Collection} from '../../../core/shared/collection.model'; +import {ComColDataService} from '../../../core/data/comcol-data.service'; /** * Component representing the delete page for communities and collections @@ -34,7 +35,7 @@ export class DeleteComColPageComponent implements public dsoRD$: Observable>; public constructor( - protected dsoDataService: DataService, + protected dsoDataService: ComColDataService, protected router: Router, protected route: ActivatedRoute, protected notifications: NotificationsService, @@ -58,7 +59,7 @@ export class DeleteComColPageComponent implements if (response.isSuccessful) { const successMessage = this.translate.instant((dso as any).type + '.delete.notification.success'); this.notifications.success(successMessage) - this.refreshCache(dso); + this.dsoDataService.refreshCache(dso); } else { const errorMessage = this.translate.instant((dso as any).type + '.delete.notification.fail'); this.notifications.error(errorMessage) @@ -74,23 +75,4 @@ export class DeleteComColPageComponent implements onCancel(dso: TDomain) { this.router.navigate([this.frontendURL + '/' + dso.uuid + '/edit']); } - - private refreshCache(dso: TDomain) { - const parentCommunityUrl = this.parentCommunityUrl(dso as any); - if (!hasValue(parentCommunityUrl)) { - return; - } - this.dsoDataService.findByHref(parentCommunityUrl).pipe( - getSucceededOrNoContentResponse(), - take(1), - ).subscribe((rd: RemoteData) => { - const href = rd.hasSucceeded && !isEmpty(rd.payload.id) ? rd.payload.id : 'communities/search/top'; - this.requestService.removeByHrefSubstring(href) - }); - } - - private parentCommunityUrl(dso: Collection | Community): string { - const parentCommunity = dso._links.parentCommunity; - return isNotEmpty(parentCommunity) ? parentCommunity.href : null; - } } From 55b6486cda74466842fa1f78ff42c4f334012d58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20P=C3=A9ter=20Sipos?= Date: Tue, 17 Nov 2020 14:09:03 +0100 Subject: [PATCH 35/43] #674 fix --- .../collection-grid-element.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.ts b/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.ts index bbb729d0ca..4d7e91b0c9 100644 --- a/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.ts +++ b/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.ts @@ -1,4 +1,4 @@ -import { Component, Input } from '@angular/core'; +import { Input, Component } from '@angular/core'; import { Collection } from '../../../core/shared/collection.model'; import { AbstractListableElementComponent } from '../../object-collection/shared/object-collection-element/abstract-listable-element.component'; import { ViewMode } from '../../../core/shared/view-mode.model'; From aca064123204aa51f7d9eb16e4e42031ac0d3994 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20P=C3=A9ter=20Sipos?= Date: Tue, 17 Nov 2020 14:32:10 +0100 Subject: [PATCH 36/43] #674 fix --- ...community-admin-search-result-grid-element.component.spec.ts | 1 - src/app/+item-page/simple/item-page.component.spec.ts | 1 - .../collection-grid-element.component.ts | 2 +- 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/app/+admin/admin-search-page/admin-search-results/admin-search-result-grid-element/community-search-result/community-admin-search-result-grid-element.component.spec.ts b/src/app/+admin/admin-search-page/admin-search-results/admin-search-result-grid-element/community-search-result/community-admin-search-result-grid-element.component.spec.ts index f6a4d02c13..6a834dd753 100644 --- a/src/app/+admin/admin-search-page/admin-search-results/admin-search-result-grid-element/community-search-result/community-admin-search-result-grid-element.component.spec.ts +++ b/src/app/+admin/admin-search-page/admin-search-results/admin-search-result-grid-element/community-search-result/community-admin-search-result-grid-element.component.spec.ts @@ -14,7 +14,6 @@ import { RouterTestingModule } from '@angular/router/testing'; import { CommunityAdminSearchResultGridElementComponent } from './community-admin-search-result-grid-element.component'; import { CommunitySearchResult } from '../../../../../shared/object-collection/shared/community-search-result.model'; import { Community } from '../../../../../core/shared/community.model'; -import { CommunityAdminSearchResultListElementComponent } from '../../admin-search-result-list-element/community-search-result/community-admin-search-result-list-element.component'; import { getCommunityEditRoute } from '../../../../../+community-page/community-page-routing-paths'; import { LinkService } from '../../../../../core/cache/builders/link.service'; diff --git a/src/app/+item-page/simple/item-page.component.spec.ts b/src/app/+item-page/simple/item-page.component.spec.ts index 6c26e75908..d0e0b0590b 100644 --- a/src/app/+item-page/simple/item-page.component.spec.ts +++ b/src/app/+item-page/simple/item-page.component.spec.ts @@ -8,7 +8,6 @@ import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRouteStub } from '../../shared/testing/active-router.stub'; import { MetadataService } from '../../core/metadata/metadata.service'; import { VarDirective } from '../../shared/utils/var.directive'; -import { RemoteData } from '../../core/data/remote-data'; import { Item } from '../../core/shared/item.model'; import { PaginatedList } from '../../core/data/paginated-list'; import { PageInfo } from '../../core/shared/page-info.model'; diff --git a/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.ts b/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.ts index 4d7e91b0c9..bbb729d0ca 100644 --- a/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.ts +++ b/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.ts @@ -1,4 +1,4 @@ -import { Input, Component } from '@angular/core'; +import { Component, Input } from '@angular/core'; import { Collection } from '../../../core/shared/collection.model'; import { AbstractListableElementComponent } from '../../object-collection/shared/object-collection-element/abstract-listable-element.component'; import { ViewMode } from '../../../core/shared/view-mode.model'; From 3303094efee05f3fa37b37ccd48833c2cd2a6209 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20P=C3=A9ter=20Sipos?= Date: Tue, 17 Nov 2020 14:34:42 +0100 Subject: [PATCH 37/43] #674 imort fix --- src/app/+item-page/full/full-item-page.component.spec.ts | 1 - .../collection-search-result-grid-element.component.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/src/app/+item-page/full/full-item-page.component.spec.ts b/src/app/+item-page/full/full-item-page.component.spec.ts index 0512ea2fef..a1ec7a7856 100644 --- a/src/app/+item-page/full/full-item-page.component.spec.ts +++ b/src/app/+item-page/full/full-item-page.component.spec.ts @@ -13,7 +13,6 @@ import { RouterTestingModule } from '@angular/router/testing'; import { Item } from '../../core/shared/item.model'; import { PageInfo } from '../../core/shared/page-info.model'; import { PaginatedList } from '../../core/data/paginated-list'; -import { RemoteData } from '../../core/data/remote-data'; import { of as observableOf } from 'rxjs'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { By } from '@angular/platform-browser'; diff --git a/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.ts b/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.ts index e0182c3fb4..72dfe97edf 100644 --- a/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.ts +++ b/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.ts @@ -1,5 +1,4 @@ import { Component, Input } from '@angular/core'; - import { SearchResultGridElementComponent } from '../search-result-grid-element.component'; import { Collection } from '../../../../core/shared/collection.model'; import { CollectionSearchResult } from '../../../object-collection/shared/collection-search-result.model'; From 77ca0f049a6262c0df51433e5358e7f931dc3550 Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Tue, 17 Nov 2020 15:38:30 +0100 Subject: [PATCH 38/43] 74615: Remove workaround for baseUrl ending in /api --- scripts/set-env.ts | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/scripts/set-env.ts b/scripts/set-env.ts index 0aa106538c..5eee22a4be 100644 --- a/scripts/set-env.ts +++ b/scripts/set-env.ts @@ -54,13 +54,6 @@ import(environmentFilePath) function generateEnvironmentFile(file: GlobalConfig): void { file.production = production; buildBaseUrls(file); - - // TODO remove workaround in beta 5 - if (file.rest.nameSpace.match("(.*)/api/?$") !== null) { - file.rest.nameSpace = getNameSpace(file.rest.nameSpace); - console.log(colors.white.bgMagenta.bold(`The rest.nameSpace property in your environment file or in your DSPACE_REST_NAMESPACE environment variable ends with '/api'.\nThis is deprecated. As '/api' isn't configurable on the rest side, it shouldn't be repeated in every environment file.\nPlease change the rest nameSpace to '${file.rest.nameSpace}'`)); - } - const contents = `export const environment = ` + JSON.stringify(file); writeFile(targetPath, contents, (err) => { if (err) { @@ -119,16 +112,5 @@ function getPort(port: number): string { } function getNameSpace(nameSpace: string): string { - // TODO remove workaround in beta 5 - const apiMatches = nameSpace.match("(.*)/api/?$"); - if (apiMatches != null) { - let newValue = '/' - if (hasValue(apiMatches[1])) { - newValue = apiMatches[1]; - } - return newValue; - } - else { - return nameSpace ? nameSpace.charAt(0) === '/' ? nameSpace : '/' + nameSpace : ''; - } + return nameSpace ? nameSpace.charAt(0) === '/' ? nameSpace : '/' + nameSpace : ''; } From 8da8273d82ee8c4b32b9cc7e1144439632286ec4 Mon Sep 17 00:00:00 2001 From: Corrado Lombardi Date: Tue, 17 Nov 2020 18:51:49 +0100 Subject: [PATCH 39/43] removed unused imports --- .../create-comcol-page/create-comcol-page.component.ts | 4 +--- .../delete-comcol-page/delete-comcol-page.component.ts | 9 +-------- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.ts b/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.ts index cb1f41dd23..8c29a17f73 100644 --- a/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.ts +++ b/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.ts @@ -2,7 +2,7 @@ import { Component, OnInit } from '@angular/core'; import { Router } from '@angular/router'; import { TranslateService } from '@ngx-translate/core'; import { Observable } from 'rxjs'; -import {flatMap, map, take} from 'rxjs/operators'; +import {flatMap, take} from 'rxjs/operators'; import { ComColDataService } from '../../../core/data/comcol-data.service'; import { CommunityDataService } from '../../../core/data/community-data.service'; import { RemoteData } from '../../../core/data/remote-data'; @@ -11,14 +11,12 @@ import { Community } from '../../../core/shared/community.model'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { getFirstSucceededRemoteDataPayload, - getSucceededOrNoContentResponse, } from '../../../core/shared/operators'; import { ResourceType } from '../../../core/shared/resource-type'; import {hasValue, isEmpty, isNotEmpty, isNotUndefined} from '../../empty.util'; import { NotificationsService } from '../../notifications/notifications.service'; import { RequestParam } from '../../../core/cache/models/request-param.model'; import {RequestService} from '../../../core/data/request.service'; -import {Collection} from '../../../core/shared/collection.model'; /** * Component representing the create page for communities and collections diff --git a/src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.ts b/src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.ts index d71660b297..825fad495f 100644 --- a/src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.ts +++ b/src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.ts @@ -2,19 +2,12 @@ import {Component, OnInit} from '@angular/core'; import {Observable} from 'rxjs'; import {ActivatedRoute, Router} from '@angular/router'; import {RemoteData} from '../../../core/data/remote-data'; -import {first, map, take} from 'rxjs/operators'; -import {DataService} from '../../../core/data/data.service'; +import {first, map} from 'rxjs/operators'; import {DSpaceObject} from '../../../core/shared/dspace-object.model'; import {NotificationsService} from '../../notifications/notifications.service'; import {TranslateService} from '@ngx-translate/core'; import {RestResponse} from '../../../core/cache/response.models'; -import {hasValue, isEmpty, isNotEmpty} from '../../empty.util'; import {RequestService} from '../../../core/data/request.service'; -import { - getSucceededOrNoContentResponse, -} from '../../../core/shared/operators'; -import {Community} from '../../../core/shared/community.model'; -import {Collection} from '../../../core/shared/collection.model'; import {ComColDataService} from '../../../core/data/comcol-data.service'; /** From c2e65e2811e0b5b5502373399a764cec7c820c8d Mon Sep 17 00:00:00 2001 From: Corrado Lombardi Date: Tue, 17 Nov 2020 19:12:34 +0100 Subject: [PATCH 40/43] removed unused import --- .../create-comcol-page/create-comcol-page.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.ts b/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.ts index 8c29a17f73..49c27591d1 100644 --- a/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.ts +++ b/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.ts @@ -13,7 +13,7 @@ import { getFirstSucceededRemoteDataPayload, } from '../../../core/shared/operators'; import { ResourceType } from '../../../core/shared/resource-type'; -import {hasValue, isEmpty, isNotEmpty, isNotUndefined} from '../../empty.util'; +import {hasValue, isNotEmpty, isNotUndefined} from '../../empty.util'; import { NotificationsService } from '../../notifications/notifications.service'; import { RequestParam } from '../../../core/cache/models/request-param.model'; import {RequestService} from '../../../core/data/request.service'; From dfc26efd1288982a72f604e88c3863fefefd9ce6 Mon Sep 17 00:00:00 2001 From: Corrado Lombardi Date: Wed, 18 Nov 2020 10:51:55 +0100 Subject: [PATCH 41/43] renamed private function --- src/app/core/data/comcol-data.service.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/core/data/comcol-data.service.ts b/src/app/core/data/comcol-data.service.ts index 86731b9696..a06a6bac9a 100644 --- a/src/app/core/data/comcol-data.service.ts +++ b/src/app/core/data/comcol-data.service.ts @@ -123,7 +123,7 @@ export abstract class ComColDataService extends DataS } public refreshCache(dso: T) { - const parentCommunityUrl = this.parentCommunityUrl(dso as any); + const parentCommunityUrl = this.parentCommunityUrlLookup(dso as any); if (!hasValue(parentCommunityUrl)) { return; } @@ -136,7 +136,7 @@ export abstract class ComColDataService extends DataS }); } - private parentCommunityUrl(dso: Collection | Community) { + private parentCommunityUrlLookup(dso: Collection | Community) { const parentCommunity = dso._links.parentCommunity; return isNotEmpty(parentCommunity) ? parentCommunity.href : null; } From 963d72ddcd605bb5c38c45a8f615328cd42af6aa Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Thu, 19 Nov 2020 12:11:40 +0100 Subject: [PATCH 42/43] 74348: Increase ratelimiter to 500 --- src/environments/environment.common.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/environments/environment.common.ts b/src/environments/environment.common.ts index a7c8b2a5ff..eb961a38eb 100644 --- a/src/environments/environment.common.ts +++ b/src/environments/environment.common.ts @@ -13,10 +13,10 @@ export const environment: GlobalConfig = { port: 4000, // NOTE: Space is capitalized because 'namespace' is a reserved string in TypeScript nameSpace: '/', - // The rateLimiter settings limit each IP to a "max" of 120 requests per "windowMs" (1 minute). + // The rateLimiter settings limit each IP to a "max" of 500 requests per "windowMs" (1 minute). rateLimiter: { windowMs: 1 * 60 * 1000, // 1 minute - max: 120 // limit each IP to 120 requests per windowMs + max: 500 // limit each IP to 500 requests per windowMs } }, // The REST API server settings. From de28b02cf6e87abbe3fcfe7519bbe611166031ad Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Thu, 19 Nov 2020 14:41:41 -0600 Subject: [PATCH 43/43] Switch patch checks to informational only --- .codecov.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.codecov.yml b/.codecov.yml index 3dba42ef37..326dd3e0b2 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -17,10 +17,9 @@ coverage: # Configuration for patch-level checks. This checks the relative coverage of the new PR code ONLY. patch: default: - # For each PR, make sure the coverage of the new code is within 1% of current overall coverage. - # We let 'patch' be more lenient as we only require *project* coverage to not drop significantly. - target: auto - threshold: 1% + # Enable informational mode, which just provides info to reviewers & always passes + # https://docs.codecov.io/docs/commit-status#section-informational + informational: true # Turn PR comments "off". This feature adds the code coverage summary as a # comment on each PR. See https://docs.codecov.io/docs/pull-request-comments