From 81696dfd04f915986f0ae9ba54686821bb1392d0 Mon Sep 17 00:00:00 2001 From: Sufiyan Shaikh Date: Wed, 4 Jan 2023 13:12:57 +0530 Subject: [PATCH] [CST-7755] Modified the changes related to the reload the object and authorization --- ...admin-workflow-list-element.component.html | 1 + ...t-admin-workflow-list-element.component.ts | 7 ++ ...arch-result-list-element.component.spec.ts | 29 ++++++- ...arch-result-list-element.component.spec.ts | 24 +++++- ...arch-result-list-element.component.spec.ts | 25 +++++- ...arch-result-list-element.component.spec.ts | 29 ++++++- ...arch-result-list-element.component.spec.ts | 25 +++++- ...on-search-result-list-element.component.ts | 10 ++- ...arch-result-list-element.component.spec.ts | 27 ++++++- .../supervision-group-selector.component.ts | 2 + ...table-object-component-loader.component.ts | 8 +- .../abstract-listable-element.component.ts | 5 ++ .../item/item-list-element.component.html | 2 +- ...arch-result-list-element.component.spec.ts | 37 ++++++++- ...em-search-result-list-element.component.ts | 78 +++++++++++++++---- src/app/shared/search/search.component.ts | 13 +++- 16 files changed, 289 insertions(+), 33 deletions(-) diff --git a/src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-list-element/workflow-item/workflow-item-search-result-admin-workflow-list-element.component.html b/src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-list-element/workflow-item/workflow-item-search-result-admin-workflow-list-element.component.html index 77ece5254d..32ba7b9cc8 100644 --- a/src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-list-element/workflow-item/workflow-item-search-result-admin-workflow-list-element.component.html +++ b/src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-list-element/workflow-item/workflow-item-search-result-admin-workflow-list-element.component.html @@ -6,6 +6,7 @@ ; + /** + * The supervision orders linked to the workflow item + */ + public supervisionOrder$: Observable; + constructor(private linkService: LinkService, protected truncatableService: TruncatableService, protected dsoNameService: DSONameService, @@ -47,6 +53,7 @@ export class WorkflowItemSearchResultAdminWorkflowListElementComponent extends S ngOnInit(): void { super.ngOnInit(); this.dso = this.linkService.resolveLink(this.dso, followLink('item')); + this.supervisionOrder$ = (this.dso.supervisionOrders as Observable>)?.pipe(getAllSucceededRemoteData(), getRemoteDataPayload()); this.item$ = (this.dso.item as Observable>).pipe(getAllSucceededRemoteData(), getRemoteDataPayload()); } } diff --git a/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-issue/journal-issue-search-result-list-element.component.spec.ts b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-issue/journal-issue-search-result-list-element.component.spec.ts index be110db101..9f8963b60b 100644 --- a/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-issue/journal-issue-search-result-list-element.component.spec.ts +++ b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-issue/journal-issue-search-result-list-element.component.spec.ts @@ -1,7 +1,7 @@ import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { By } from '@angular/platform-browser'; -import { of as observableOf } from 'rxjs'; +import { of as observableOf, of } from 'rxjs'; import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model'; import { JournalIssueSearchResultListElementComponent } from './journal-issue-search-result-list-element.component'; import { Item } from '../../../../../core/shared/item.model'; @@ -18,9 +18,24 @@ import { PageInfo } from '../../../../../core/shared/page-info.model'; import { buildPaginatedList } from '../../../../../core/data/paginated-list.model'; import { GroupMock } from '../../../../../shared/testing/group-mock'; import { hot } from 'jasmine-marbles'; +import { AuthService } from '../../../../../core/auth/auth.service'; +import { AuthorizationDataService } from '../../../../../core/data/feature-authorization/authorization-data.service'; +import { EPersonDataService } from '../../../../../core/eperson/eperson-data.service'; +import { ResourcePolicyDataService } from '../../../../../core/resource-policy/resource-policy-data.service'; +import { AuthServiceStub } from '../../../../../shared/testing/auth-service.stub'; +import { EPersonMock } from '../../../../../shared/testing/eperson.mock'; let journalIssueListElementComponent: JournalIssueSearchResultListElementComponent; let fixture: ComponentFixture; +let authorizationService = jasmine.createSpyObj('authorizationService', { + isAuthorized: observableOf(true) +}); + +const authService: AuthServiceStub = Object.assign(new AuthServiceStub(), { + getAuthenticatedUserFromStore: () => { + return of(EPersonMock); + } +}); const mockItemWithMetadata: ItemSearchResult = Object.assign( new ItemSearchResult(), @@ -131,8 +146,12 @@ describe('JournalIssueSearchResultListElementComponent', () => { providers: [ { provide: TruncatableService, useValue: {} }, { provide: SupervisionOrderDataService, useValue: supervisionOrderDataService }, - {provide: NotificationsService, useValue: {}}, - {provide: TranslateService, useValue: {}}, + { provide: NotificationsService, useValue: {}}, + { provide: TranslateService, useValue: {}}, + { provide: ResourcePolicyDataService, useValue: {}}, + { provide: AuthService, useValue: authService}, + { provide: EPersonDataService, useValue: {}}, + { provide: AuthorizationDataService, useValue: authorizationService}, { provide: DSONameService, useClass: DSONameServiceMock }, { provide: APP_CONFIG, useValue: environmentUseThumbs } ], @@ -227,6 +246,10 @@ describe('JournalIssueSearchResultListElementComponent', () => { {provide: SupervisionOrderDataService, useValue: supervisionOrderDataService }, {provide: NotificationsService, useValue: {}}, {provide: TranslateService, useValue: {}}, + {provide: ResourcePolicyDataService, useValue: {}}, + {provide: AuthService, useValue: authService}, + {provide: EPersonDataService, useValue: {}}, + {provide: AuthorizationDataService, useValue: authorizationService}, {provide: DSONameService, useClass: DSONameServiceMock}, { provide: APP_CONFIG, useValue: enviromentNoThumbs } ], diff --git a/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-volume/journal-volume-search-result-list-element.component.spec.ts b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-volume/journal-volume-search-result-list-element.component.spec.ts index 76d516e76e..03c0151693 100644 --- a/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-volume/journal-volume-search-result-list-element.component.spec.ts +++ b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-volume/journal-volume-search-result-list-element.component.spec.ts @@ -1,7 +1,7 @@ import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { By } from '@angular/platform-browser'; -import { of as observableOf } from 'rxjs'; +import { of as observableOf, of } from 'rxjs'; import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model'; import { Item } from '../../../../../core/shared/item.model'; import { JournalVolumeSearchResultListElementComponent } from './journal-volume-search-result-list-element.component'; @@ -18,10 +18,24 @@ import { PageInfo } from '../../../../../core/shared/page-info.model'; import { buildPaginatedList } from '../../../../../core/data/paginated-list.model'; import { GroupMock } from '../../../../../shared/testing/group-mock'; import { hot } from 'jasmine-marbles'; +import { ResourcePolicyDataService } from '../../../../../core/resource-policy/resource-policy-data.service'; +import { AuthService } from '../../../../../core/auth/auth.service'; +import { EPersonDataService } from '../../../../../core/eperson/eperson-data.service'; +import { AuthorizationDataService } from '../../../../../core/data/feature-authorization/authorization-data.service'; +import { AuthServiceStub } from '../../../../../shared/testing/auth-service.stub'; +import { EPersonMock } from '../../../../../shared/testing/eperson.mock'; let journalVolumeListElementComponent: JournalVolumeSearchResultListElementComponent; let fixture: ComponentFixture; +let authorizationService = jasmine.createSpyObj('authorizationService', { + isAuthorized: observableOf(true) +}); +const authService: AuthServiceStub = Object.assign(new AuthServiceStub(), { + getAuthenticatedUserFromStore: () => { + return of(EPersonMock); + } +}); const mockItemWithMetadata: ItemSearchResult = Object.assign( new ItemSearchResult(), { @@ -132,6 +146,10 @@ describe('JournalVolumeSearchResultListElementComponent', () => { { provide: SupervisionOrderDataService, useValue: supervisionOrderDataService }, { provide: NotificationsService, useValue: {}}, { provide: TranslateService, useValue: {}}, + { provide: ResourcePolicyDataService, useValue: {}}, + { provide: AuthService, useValue: authService}, + { provide: EPersonDataService, useValue: {}}, + { provide: AuthorizationDataService, useValue: authorizationService}, { provide: DSONameService, useClass: DSONameServiceMock }, { provide: APP_CONFIG, useValue: environmentUseThumbs } ], @@ -225,6 +243,10 @@ describe('JournalVolumeSearchResultListElementComponent', () => { {provide: SupervisionOrderDataService, useValue: supervisionOrderDataService }, {provide: NotificationsService, useValue: {}}, {provide: TranslateService, useValue: {}}, + {provide: ResourcePolicyDataService, useValue: {}}, + {provide: AuthService, useValue: authService}, + {provide: EPersonDataService, useValue: {}}, + {provide: AuthorizationDataService, useValue: authorizationService}, {provide: DSONameService, useClass: DSONameServiceMock}, { provide: APP_CONFIG, useValue: enviromentNoThumbs } ], diff --git a/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal/journal-search-result-list-element.component.spec.ts b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal/journal-search-result-list-element.component.spec.ts index 55f0875731..bc1a560613 100644 --- a/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal/journal-search-result-list-element.component.spec.ts +++ b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal/journal-search-result-list-element.component.spec.ts @@ -1,7 +1,7 @@ import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { By } from '@angular/platform-browser'; -import { of as observableOf } from 'rxjs'; +import { of as observableOf, of } from 'rxjs'; import { JournalSearchResultListElementComponent } from './journal-search-result-list-element.component'; import { Item } from '../../../../../core/shared/item.model'; import { TruncatePipe } from '../../../../../shared/utils/truncate.pipe'; @@ -18,9 +18,24 @@ import { PageInfo } from '../../../../../core/shared/page-info.model'; import { buildPaginatedList } from '../../../../../core/data/paginated-list.model'; import { GroupMock } from '../../../../../shared/testing/group-mock'; import { hot } from 'jasmine-marbles'; +import { AuthServiceStub } from '../../../../../shared/testing/auth-service.stub'; +import { AuthService } from '../../../../../core/auth/auth.service'; +import { AuthorizationDataService } from '../../../../../core/data/feature-authorization/authorization-data.service'; +import { EPersonDataService } from '../../../../../core/eperson/eperson-data.service'; +import { ResourcePolicyDataService } from '../../../../../core/resource-policy/resource-policy-data.service'; +import { EPersonMock } from '../../../../../shared/testing/eperson.mock'; let journalListElementComponent: JournalSearchResultListElementComponent; let fixture: ComponentFixture; +let authorizationService = jasmine.createSpyObj('authorizationService', { + isAuthorized: observableOf(true) +}); + +const authService: AuthServiceStub = Object.assign(new AuthServiceStub(), { + getAuthenticatedUserFromStore: () => { + return of(EPersonMock); + } +}); const mockItemWithMetadata: ItemSearchResult = Object.assign( new ItemSearchResult(), @@ -128,6 +143,10 @@ describe('JournalSearchResultListElementComponent', () => { { provide: SupervisionOrderDataService, useValue: supervisionOrderDataService }, { provide: NotificationsService, useValue: {}}, { provide: TranslateService, useValue: {}}, + { provide: ResourcePolicyDataService, useValue: {}}, + { provide: AuthService, useValue: authService}, + { provide: EPersonDataService, useValue: {}}, + { provide: AuthorizationDataService, useValue: authorizationService}, { provide: DSONameService, useClass: DSONameServiceMock }, { provide: APP_CONFIG, useValue: environmentUseThumbs } ], @@ -197,6 +216,10 @@ describe('JournalSearchResultListElementComponent', () => { {provide: SupervisionOrderDataService, useValue: supervisionOrderDataService }, {provide: NotificationsService, useValue: {}}, {provide: TranslateService, useValue: {}}, + {provide: ResourcePolicyDataService, useValue: {}}, + {provide: AuthService, useValue: authService}, + {provide: EPersonDataService, useValue: {}}, + {provide: AuthorizationDataService, useValue: authorizationService}, {provide: DSONameService, useClass: DSONameServiceMock}, { provide: APP_CONFIG, useValue: enviromentNoThumbs } ], diff --git a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/org-unit/org-unit-search-result-list-element.component.spec.ts b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/org-unit/org-unit-search-result-list-element.component.spec.ts index b8f30fe66e..8be5f7496b 100644 --- a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/org-unit/org-unit-search-result-list-element.component.spec.ts +++ b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/org-unit/org-unit-search-result-list-element.component.spec.ts @@ -1,7 +1,7 @@ import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { By } from '@angular/platform-browser'; -import { of as observableOf } from 'rxjs'; +import { of as observableOf, of } from 'rxjs'; import { OrgUnitSearchResultListElementComponent } from './org-unit-search-result-list-element.component'; import { Item } from '../../../../../core/shared/item.model'; import { TruncatePipe } from '../../../../../shared/utils/truncate.pipe'; @@ -19,9 +19,24 @@ import { PageInfo } from '../../../../../core/shared/page-info.model'; import { buildPaginatedList } from '../../../../../core/data/paginated-list.model'; import { GroupMock } from '../../../../../shared/testing/group-mock'; import { hot } from 'jasmine-marbles'; +import { AuthService } from '../../../../../core/auth/auth.service'; +import { AuthorizationDataService } from '../../../../../core/data/feature-authorization/authorization-data.service'; +import { EPersonDataService } from '../../../../../core/eperson/eperson-data.service'; +import { ResourcePolicyDataService } from '../../../../../core/resource-policy/resource-policy-data.service'; +import { AuthServiceStub } from '../../../../../shared/testing/auth-service.stub'; +import { EPersonMock } from '../../../../../shared/testing/eperson.mock'; let orgUnitListElementComponent: OrgUnitSearchResultListElementComponent; let fixture: ComponentFixture; +let authorizationService = jasmine.createSpyObj('authorizationService', { + isAuthorized: observableOf(true) +}); + +const authService: AuthServiceStub = Object.assign(new AuthServiceStub(), { + getAuthenticatedUserFromStore: () => { + return of(EPersonMock); + } +}); const mockItemWithMetadata: ItemSearchResult = Object.assign( new ItemSearchResult(), @@ -131,8 +146,12 @@ describe('OrgUnitSearchResultListElementComponent', () => { declarations: [ OrgUnitSearchResultListElementComponent , TruncatePipe], providers: [ { provide: TruncatableService, useValue: {} }, - {provide: SupervisionOrderDataService, useValue: supervisionOrderDataService }, - {provide: NotificationsService, useValue: {}}, + { provide: SupervisionOrderDataService, useValue: supervisionOrderDataService }, + { provide: NotificationsService, useValue: {}}, + { provide: ResourcePolicyDataService, useValue: {}}, + { provide: AuthService, useValue: authService}, + { provide: EPersonDataService, useValue: {}}, + { provide: AuthorizationDataService, useValue: authorizationService}, { provide: DSONameService, useClass: DSONameServiceMock }, { provide: APP_CONFIG, useValue: environmentUseThumbs } ], @@ -208,6 +227,10 @@ describe('OrgUnitSearchResultListElementComponent', () => { {provide: TruncatableService, useValue: {}}, {provide: SupervisionOrderDataService, useValue: supervisionOrderDataService }, {provide: NotificationsService, useValue: {}}, + {provide: ResourcePolicyDataService, useValue: {}}, + {provide: AuthService, useValue: authService}, + {provide: EPersonDataService, useValue: {}}, + {provide: AuthorizationDataService, useValue: authorizationService}, {provide: DSONameService, useClass: DSONameServiceMock}, { provide: APP_CONFIG, useValue: enviromentNoThumbs } ], diff --git a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/person/person-search-result-list-element.component.spec.ts b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/person/person-search-result-list-element.component.spec.ts index 3f4cc1d294..e8cb217cdf 100644 --- a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/person/person-search-result-list-element.component.spec.ts +++ b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/person/person-search-result-list-element.component.spec.ts @@ -1,7 +1,7 @@ import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { By } from '@angular/platform-browser'; -import { of as observableOf } from 'rxjs'; +import { of as observableOf, of } from 'rxjs'; import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model'; import { PersonSearchResultListElementComponent } from './person-search-result-list-element.component'; import { Item } from '../../../../../core/shared/item.model'; @@ -19,12 +19,27 @@ import { hot } from 'jasmine-marbles'; import { PageInfo } from '../../../../../core/shared/page-info.model'; import { GroupMock } from '../../../../../shared/testing/group-mock'; import { buildPaginatedList } from '../../../../../core/data/paginated-list.model'; +import { AuthServiceStub } from '../../../../../shared/testing/auth-service.stub'; +import { EPersonMock } from '../../../../../shared/testing/eperson.mock'; +import { ResourcePolicyDataService } from '../../../../../core/resource-policy/resource-policy-data.service'; +import { AuthService } from '../../../../../core/auth/auth.service'; +import { AuthorizationDataService } from '../../../../../core/data/feature-authorization/authorization-data.service'; +import { EPersonDataService } from '../../../../../core/eperson/eperson-data.service'; let personListElementComponent: PersonSearchResultListElementComponent; let fixture: ComponentFixture; const supervisionOrderDataService: any = jasmine.createSpyObj('supervisionOrderDataService', { searchByItem: jasmine.createSpy('searchByItem'), }); +let authorizationService = jasmine.createSpyObj('authorizationService', { + isAuthorized: observableOf(true) +}); + +const authService: AuthServiceStub = Object.assign(new AuthServiceStub(), { + getAuthenticatedUserFromStore: () => { + return of(EPersonMock); + } +}); const mockItemWithMetadata: ItemSearchResult = Object.assign( new ItemSearchResult(), @@ -132,6 +147,10 @@ describe('PersonSearchResultListElementComponent', () => { { provide: TruncatableService, useValue: {} }, { provide: SupervisionOrderDataService, useValue: supervisionOrderDataService }, { provide: NotificationsService, useValue: {} }, + { provide: ResourcePolicyDataService, useValue: {}}, + { provide: AuthService, useValue: authService}, + { provide: EPersonDataService, useValue: {}}, + { provide: AuthorizationDataService, useValue: authorizationService}, { provide: DSONameService, useClass: DSONameServiceMock }, { provide: APP_CONFIG, useValue: environmentUseThumbs } ], @@ -207,6 +226,10 @@ describe('PersonSearchResultListElementComponent', () => { {provide: TruncatableService, useValue: {}}, {provide: SupervisionOrderDataService, useValue: supervisionOrderDataService}, {provide: NotificationsService, useValue: {}}, + {provide: ResourcePolicyDataService, useValue: {}}, + {provide: AuthService, useValue: authService}, + {provide: EPersonDataService, useValue: {}}, + {provide: AuthorizationDataService, useValue: authorizationService}, {provide: DSONameService, useClass: DSONameServiceMock}, { provide: APP_CONFIG, useValue: enviromentNoThumbs } ], diff --git a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/person/person-search-result-list-element.component.ts b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/person/person-search-result-list-element.component.ts index 6f78c709ba..09142fc02e 100644 --- a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/person/person-search-result-list-element.component.ts +++ b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/person/person-search-result-list-element.component.ts @@ -13,6 +13,10 @@ import { SupervisionOrderDataService } from '../../../../../core/supervision-ord import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { NotificationsService } from '../../../../../shared/notifications/notifications.service'; import { TranslateService } from '@ngx-translate/core'; +import { ResourcePolicyDataService } from '../../../../../core/resource-policy/resource-policy-data.service'; +import { AuthService } from '../../../../../core/auth/auth.service'; +import { EPersonDataService } from '../../../../../core/eperson/eperson-data.service'; +import { AuthorizationDataService } from '../../../../../core/data/feature-authorization/authorization-data.service'; @listableObjectComponent('PersonSearchResult', ViewMode.ListElement) @Component({ @@ -33,8 +37,12 @@ export class PersonSearchResultListElementComponent extends ItemSearchResultList protected modalService: NgbModal, protected notificationsService: NotificationsService, protected translateService: TranslateService, + protected resourcePolicyService: ResourcePolicyDataService, + protected authService: AuthService, + protected epersonService: EPersonDataService, + protected authorizationService: AuthorizationDataService ) { - super(truncatableService, dsoNameService, appConfig, supervisionOrderDataService, modalService, notificationsService, translateService); + super(truncatableService, dsoNameService, appConfig, supervisionOrderDataService, modalService, notificationsService, translateService, resourcePolicyService, authService, epersonService, authorizationService); } /** diff --git a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/project/project-search-result-list-element.component.spec.ts b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/project/project-search-result-list-element.component.spec.ts index f3ef14e4f6..6af4f9c43b 100644 --- a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/project/project-search-result-list-element.component.spec.ts +++ b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/project/project-search-result-list-element.component.spec.ts @@ -1,6 +1,6 @@ import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; -import { of as observableOf } from 'rxjs'; +import { of as observableOf, of } from 'rxjs'; import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model'; import { ProjectSearchResultListElementComponent } from './project-search-result-list-element.component'; import { Item } from '../../../../../core/shared/item.model'; @@ -18,9 +18,24 @@ import { PageInfo } from '../../../../../core/shared/page-info.model'; import { buildPaginatedList } from '../../../../../core/data/paginated-list.model'; import { GroupMock } from '../../../../../shared/testing/group-mock'; import { hot } from 'jasmine-marbles'; +import { AuthService } from '../../../../../core/auth/auth.service'; +import { AuthorizationDataService } from '../../../../../core/data/feature-authorization/authorization-data.service'; +import { EPersonDataService } from '../../../../../core/eperson/eperson-data.service'; +import { ResourcePolicyDataService } from '../../../../../core/resource-policy/resource-policy-data.service'; +import { AuthServiceStub } from '../../../../../shared/testing/auth-service.stub'; +import { EPersonMock } from '../../../../../shared/testing/eperson.mock'; let projectListElementComponent: ProjectSearchResultListElementComponent; let fixture: ComponentFixture; +let authorizationService = jasmine.createSpyObj('authorizationService', { + isAuthorized: observableOf(true) +}); + +const authService: AuthServiceStub = Object.assign(new AuthServiceStub(), { + getAuthenticatedUserFromStore: () => { + return of(EPersonMock); + } +}); const mockItemWithMetadata: ItemSearchResult = Object.assign( new ItemSearchResult(), @@ -126,7 +141,11 @@ describe('ProjectSearchResultListElementComponent', () => { { provide: TruncatableService, useValue: {} }, { provide: SupervisionOrderDataService, useValue: supervisionOrderDataService }, { provide: NotificationsService, useValue: {}}, - {provide: TranslateService, useValue: {}}, + { provide: TranslateService, useValue: {}}, + { provide: ResourcePolicyDataService, useValue: {}}, + { provide: AuthService, useValue: authService}, + { provide: EPersonDataService, useValue: {}}, + { provide: AuthorizationDataService, useValue: authorizationService}, { provide: DSONameService, useClass: DSONameServiceMock }, { provide: APP_CONFIG, useValue: environmentUseThumbs } ], @@ -196,6 +215,10 @@ describe('ProjectSearchResultListElementComponent', () => { {provide: SupervisionOrderDataService, useValue: supervisionOrderDataService }, {provide: NotificationsService, useValue: {}}, {provide: TranslateService, useValue: {}}, + {provide: ResourcePolicyDataService, useValue: {}}, + {provide: AuthService, useValue: authService}, + {provide: EPersonDataService, useValue: {}}, + {provide: AuthorizationDataService, useValue: authorizationService}, {provide: DSONameService, useClass: DSONameServiceMock}, { provide: APP_CONFIG, useValue: enviromentNoThumbs } diff --git a/src/app/shared/dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component.ts index c69c5d5177..1ae2d496d2 100644 --- a/src/app/shared/dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component.ts +++ b/src/app/shared/dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component.ts @@ -7,6 +7,7 @@ import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service'; import { Group } from '../../../../core/eperson/models/group.model'; import { SupervisionOrder } from '../../../../core/supervision-order/models/supervision-order.model'; import { SupervisionOrderDataService } from '../../../../core/supervision-order/supervision-order-data.service'; +import { followLink } from '../../../../shared/utils/follow-link-config.model'; /** * Component to wrap a dropdown - for type of order - @@ -76,6 +77,7 @@ export class SupervisionGroupSelectorComponent { getFirstCompletedRemoteData(), ).subscribe(rd => { if (rd.state === 'Success') { + this.supervisionOrderDataService.searchByItem(this.itemUUID, null, null, followLink('group')); this.notificationsService.success(this.translateService.get('supervision-group-selector.notification.create.success.title', { name: this.selectedGroup.name })); } else { this.notificationsService.error( diff --git a/src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.ts b/src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.ts index 6b75c59181..9779ecd830 100644 --- a/src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.ts +++ b/src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.ts @@ -13,7 +13,7 @@ import { ViewChild } from '@angular/core'; -import { Subscription } from 'rxjs'; +import { Observable, Subscription } from 'rxjs'; import { take } from 'rxjs/operators'; import { ListableObject } from '../listable-object.model'; @@ -41,6 +41,11 @@ export class ListableObjectComponentLoaderComponent implements OnInit, OnChanges */ @Input() object: ListableObject; + /** + * The supervision order to determine supervision orders + */ + @Input() supervisionOrders: Observable; + /** * The index of the object in the list */ @@ -123,6 +128,7 @@ export class ListableObjectComponentLoaderComponent implements OnInit, OnChanges */ protected inAndOutputNames: string[] = [ 'object', + 'supervisionOrders', 'index', 'linkType', 'listID', diff --git a/src/app/shared/object-collection/shared/object-collection-element/abstract-listable-element.component.ts b/src/app/shared/object-collection/shared/object-collection-element/abstract-listable-element.component.ts index 7d4e107b2b..dde9cf61dc 100644 --- a/src/app/shared/object-collection/shared/object-collection-element/abstract-listable-element.component.ts +++ b/src/app/shared/object-collection/shared/object-collection-element/abstract-listable-element.component.ts @@ -16,6 +16,11 @@ export class AbstractListableElementComponent { */ @Input() object: T; + /** + * The supervision orders to render in this list element + */ + @Input() supervisionOrders: T; + /** * The link type to determine the type of link rendered in this element */ diff --git a/src/app/shared/object-list/item-list-element/item-types/item/item-list-element.component.html b/src/app/shared/object-list/item-list-element/item-types/item/item-list-element.component.html index 3877e2f335..f244da97bd 100644 --- a/src/app/shared/object-list/item-list-element/item-types/item/item-list-element.component.html +++ b/src/app/shared/object-list/item-list-element/item-types/item/item-list-element.component.html @@ -1 +1 @@ - + diff --git a/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.spec.ts b/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.spec.ts index 887ecb30a0..9e21ae5289 100644 --- a/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.spec.ts +++ b/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.spec.ts @@ -1,7 +1,7 @@ import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { By } from '@angular/platform-browser'; -import { of as observableOf } from 'rxjs'; +import { of as observableOf, of } from 'rxjs'; import { ItemSearchResultListElementComponent } from './item-search-result-list-element.component'; import { Item } from '../../../../../../core/shared/item.model'; import { TruncatePipe } from '../../../../../utils/truncate.pipe'; @@ -13,14 +13,39 @@ import { APP_CONFIG } from '../../../../../../../config/app-config.interface'; import { SupervisionOrderDataService } from '../../../../../../core/supervision-order/supervision-order-data.service'; import { NotificationsService } from '../../../../../../shared/notifications/notifications.service'; import { TranslateService } from '@ngx-translate/core'; -import { createSuccessfulRemoteDataObject } from '../../../../../../shared/remote-data.utils'; +import { createSuccessfulRemoteDataObject, createSuccessfulRemoteDataObject$ } from '../../../../../../shared/remote-data.utils'; import { PageInfo } from '../../../../../../core/shared/page-info.model'; import { buildPaginatedList } from '../../../../../../core/data/paginated-list.model'; import { GroupMock } from '../../../../../../shared/testing/group-mock'; import { hot } from 'jasmine-marbles'; +import { AuthService } from '../../../../../../core/auth/auth.service'; +import { AuthorizationDataService } from '../../../../../../core/data/feature-authorization/authorization-data.service'; +import { EPersonDataService } from '../../../../../../core/eperson/eperson-data.service'; +import { ResourcePolicyDataService } from '../../../../../../core/resource-policy/resource-policy-data.service'; +import { AuthServiceStub } from '../../../../../../shared/testing/auth-service.stub'; +import { EPersonMock } from '../../../../../../shared/testing/eperson.mock'; +import { EPerson } from 'src/app/core/eperson/models/eperson.model'; +import { createPaginatedList } from 'src/app/shared/testing/utils.test'; let publicationListElementComponent: ItemSearchResultListElementComponent; let fixture: ComponentFixture; +let authorizationService = jasmine.createSpyObj('authorizationService', { + isAuthorized: observableOf(true) +}); + +const authService: AuthServiceStub = Object.assign(new AuthServiceStub(), { + getAuthenticatedUserFromStore: () => { + return of(EPersonMock); + } +}); +const user = Object.assign(new EPerson(), { + id: 'userId', + groups: createSuccessfulRemoteDataObject$(createPaginatedList([])), + _links: { self: { href: 'test.com/uuid/1234567654321' } } +}); +const epersonService = jasmine.createSpyObj('epersonService', { + findById: createSuccessfulRemoteDataObject$(user), +}); const mockItemWithMetadata: ItemSearchResult = Object.assign(new ItemSearchResult(), { indexableObject: @@ -135,6 +160,10 @@ describe('ItemSearchResultListElementComponent', () => { { provide: SupervisionOrderDataService, useValue: supervisionOrderDataService }, { provide: NotificationsService, useValue: {}}, { provide: TranslateService, useValue: {}}, + { provide: ResourcePolicyDataService, useValue: {}}, + { provide: AuthService, useValue: authService}, + { provide: EPersonDataService, useValue: epersonService}, + { provide: AuthorizationDataService, useValue: authorizationService}, { provide: DSONameService, useClass: DSONameServiceMock }, { provide: APP_CONFIG, useValue: environmentUseThumbs } ], @@ -288,6 +317,10 @@ describe('ItemSearchResultListElementComponent', () => { {provide: SupervisionOrderDataService, useValue: supervisionOrderDataService }, {provide: NotificationsService, useValue: {}}, {provide: TranslateService, useValue: {}}, + {provide: ResourcePolicyDataService, useValue: {}}, + {provide: AuthService, useValue: authService}, + {provide: EPersonDataService, useValue: epersonService}, + {provide: AuthorizationDataService, useValue: authorizationService}, {provide: DSONameService, useClass: DSONameServiceMock}, { provide: APP_CONFIG, useValue: enviromentNoThumbs } ], diff --git a/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.ts b/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.ts index b1b5b0d1a7..41afab0ab8 100644 --- a/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.ts +++ b/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.ts @@ -10,7 +10,7 @@ import { TruncatableService } from '../../../../../../shared/truncatable/truncat import { DSONameService } from '../../../../../../core/breadcrumbs/dso-name.service'; import { AppConfig, APP_CONFIG } from '../../../../../../../config/app-config.interface'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; -import { combineLatest, map, Observable, switchMap, take } from 'rxjs'; +import { combineLatest, filter, map, Observable, switchMap, take } from 'rxjs'; import { ConfirmationModalComponent } from '../../../../../../shared/confirmation-modal/confirmation-modal.component'; import { hasValue } from '../../../../../../shared/empty.util'; import { NotificationsService } from '../../../../../../shared/notifications/notifications.service'; @@ -19,6 +19,13 @@ import { followLink } from '../../../../../../shared/utils/follow-link-config.mo import { getAllSucceededRemoteListPayload, getFirstSucceededRemoteDataPayload } from '../../../../../../core/shared/operators'; import { SupervisionOrder } from '../../../../../../core/supervision-order/models/supervision-order.model'; import { Group } from '../../../../../../core/eperson/models/group.model'; +import { ResourcePolicyDataService } from '../../../../../../core/resource-policy/resource-policy-data.service'; +import { getAllSucceededRemoteData, getRemoteDataPayload } from '../../../../../../core/shared/operators'; +import { AuthService } from '../../../../../../core/auth/auth.service'; +import { EPerson } from '../../../../../../core/eperson/models/eperson.model'; +import { EPersonDataService } from '../../../../../../core/eperson/eperson-data.service'; +import { AuthorizationDataService } from '../../../../../../core/data/feature-authorization/authorization-data.service'; +import { FeatureID } from '../../../../../../core/data/feature-authorization/feature-id'; @listableObjectComponent('PublicationSearchResult', ViewMode.ListElement) @listableObjectComponent(ItemSearchResult, ViewMode.ListElement) @@ -48,6 +55,11 @@ export class ItemSearchResultListElementComponent extends SearchResultListElemen */ supervisionOrder$: Observable<{ supervisionOrder: SupervisionOrder; group: Group; }[]>; + /** + * The groups the user belongs to + */ + groups: Group[]; + constructor( protected truncatableService: TruncatableService, protected dsoNameService: DSONameService, @@ -56,24 +68,63 @@ export class ItemSearchResultListElementComponent extends SearchResultListElemen protected modalService: NgbModal, protected notificationsService: NotificationsService, protected translateService: TranslateService, + protected resourcePolicyService: ResourcePolicyDataService, + protected authService: AuthService, + protected epersonService: EPersonDataService, + protected authorizationService: AuthorizationDataService ) { super(truncatableService, dsoNameService, appConfig); } ngOnInit(): void { super.ngOnInit(); this.showThumbnails = this.appConfig.browseBy.showThumbnails; + let isAdmin = false; + this.authorizationService.isAuthorized(FeatureID.AdministratorOf).subscribe(isadmin => { + isAdmin = isadmin; + }); + + this.authService.getAuthenticatedUserFromStore().pipe( + filter((user: EPerson) => hasValue(user.id)), + switchMap((user: EPerson) => this.epersonService.findById(user.id, true, true, followLink('groups'))), + getAllSucceededRemoteData(), + getRemoteDataPayload(), + switchMap((user: EPerson) => user.groups), + ).subscribe(groups => { + this.groups = groups?.payload?.page; + }); + this.itemPageRoute = getItemPageRoute(this.dso); - this.supervisionOrder$ = this.supervisionOrderDataService.searchByItem(this.dso.uuid, null, null, followLink('group')).pipe( - getAllSucceededRemoteListPayload(), - switchMap((supervisionOrders: SupervisionOrder[]) => { - const supervisionOrdersArray = supervisionOrders.map((supervisionOrder: SupervisionOrder) => { - return supervisionOrder.group.pipe( - getFirstSucceededRemoteDataPayload(), - map((group: Group) => ({ supervisionOrder, group })) - ); - }); - return combineLatest(supervisionOrdersArray); - }) - ); + if (this.supervisionOrders) { + this.resourcePolicyService.searchByResource( + this.dso.uuid, null, false, true, + followLink('eperson'), followLink('group') + ).pipe( + getAllSucceededRemoteData(), + ).subscribe((result) => { + this.supervisionOrder$ = this.supervisionOrderDataService.searchByItem(this.dso.uuid, null, null, followLink('group')).pipe( + getAllSucceededRemoteListPayload(), + switchMap((supervisionOrders: SupervisionOrder[]) => { + const supervisionOrdersArray = supervisionOrders.map((supervisionOrder: SupervisionOrder) => { + return supervisionOrder.group.pipe( + getFirstSucceededRemoteDataPayload(), + map((group: Group) => { + let isAuthorized = false; + result.payload.page.forEach(resourcePolicy => { + resourcePolicy.group.subscribe(res => { + if (isAdmin || (res.payload && res.payload.uuid === group.uuid && this.groups.find(groups => groups.uuid === group.uuid))) { + isAuthorized = true; + } + }); + }); + return isAuthorized ? ({ supervisionOrder, group }) : null; + }), + ); + }); + return combineLatest(supervisionOrdersArray).pipe( + map(array => array.filter(hasValue)) + ); + })); + }); + } } /** @@ -95,6 +146,7 @@ export class ItemSearchResultListElementComponent extends SearchResultListElemen this.supervisionOrderDataService.delete(supervisionOrder.supervisionOrder.id) .subscribe((rd: boolean) => { if (rd) { + this.supervisionOrderDataService.searchByItem(this.dso.uuid, null, null, followLink('group')); this.notificationsService.success(this.translateService.get(this.messagePrefix + '.notification.deleted.success', { name: supervisionOrder.group._name })); } else { this.notificationsService.error( diff --git a/src/app/shared/search/search.component.ts b/src/app/shared/search/search.component.ts index e9a72ae338..e18505260c 100644 --- a/src/app/shared/search/search.component.ts +++ b/src/app/shared/search/search.component.ts @@ -399,15 +399,20 @@ export class SearchComponent implements OnInit { private retrieveSearchResults(searchOptions: PaginatedSearchOptions) { this.resultsRD$.next(null); this.lastSearchOptions = searchOptions; + let followLinks = [ + followLink('thumbnail', { isOptional: true }), + followLink('item', { isOptional: true }, followLink('thumbnail', { isOptional: true })) as any, + followLink('accessStatus', { isOptional: true, shouldEmbed: environment.item.showAccessStatuses }), + ]; + if (this.configuration === 'supervision') { + followLinks.push(followLink('supervisionOrders', { isOptional: true }) as any); + } this.service.search( searchOptions, undefined, this.useCachedVersionIfAvailable, true, - followLink('thumbnail', { isOptional: true }), - followLink('item', { isOptional: true }, followLink('thumbnail', { isOptional: true })) as any, - followLink('supervisionOrders', { isOptional: true }) as any, - followLink('accessStatus', { isOptional: true, shouldEmbed: environment.item.showAccessStatuses }), + ...followLinks ).pipe(getFirstCompletedRemoteData()) .subscribe((results: RemoteData>) => { if (results.hasSucceeded) {