From 09781c90573084bd56e76136702584a558882bb6 Mon Sep 17 00:00:00 2001 From: Sufiyan Shaikh Date: Thu, 29 Dec 2022 18:16:54 +0530 Subject: [PATCH 01/10] [CST-7755] LYRASIS: Supervisor orders (Angular) --- .../admin-workflow-page.component.html | 2 +- ...admin-workflow-list-element.component.html | 5 +- ...t-admin-workflow-list-element.component.ts | 2 + ...item-admin-workflow-actions.component.html | 7 + ...m-admin-workflow-actions.component.spec.ts | 15 + ...w-item-admin-workflow-actions.component.ts | 33 +++ src/app/core/core.module.ts | 2 + src/app/core/shared/context.model.ts | 1 + .../models/submission-object.model.ts | 10 + .../models/action-type.model.ts | 44 +++ .../models/supervision-order.model.ts | 74 +++++ .../models/supervision-order.resource-type.ts | 9 + .../supervision-order-data.service.spec.ts | 277 ++++++++++++++++++ .../supervision-order-data.service.ts | 181 ++++++++++++ ...arch-result-list-element.component.spec.ts | 67 ++++- ...arch-result-list-element.component.spec.ts | 66 +++++ ...arch-result-list-element.component.spec.ts | 66 +++++ ...arch-result-list-element.component.spec.ts | 64 +++- ...arch-result-list-element.component.spec.ts | 63 +++- ...on-search-result-list-element.component.ts | 12 +- ...arch-result-list-element.component.spec.ts | 67 ++++- .../my-dspace-configuration-value-type.ts | 1 + .../my-dspace-configuration.service.spec.ts | 4 +- .../my-dspace-configuration.service.ts | 2 + .../supervision-group-selector.component.html | 40 +++ ...supervision-group-selector.component.scss} | 0 ...pervision-group-selector.component.spec.ts | 70 +++++ .../supervision-group-selector.component.ts | 90 ++++++ .../eperson-group-list.component.html | 0 .../eperson-group-list.component.scss | 0 .../eperson-group-list.component.spec.ts | 26 +- .../eperson-group-list.component.ts | 32 +- .../eperson-search-box.component.html | 0 .../eperson-search-box.component.spec.ts | 2 +- .../eperson-search-box.component.ts | 2 +- .../group-search-box.component.html | 0 .../group-search-box.component.spec.ts | 2 +- .../group-search-box.component.ts | 2 +- ...-search-result-list-element.component.html | 13 + ...-search-result-list-element.component.scss | 6 + ...arch-result-list-element.component.spec.ts | 66 +++++ ...em-search-result-list-element.component.ts | 76 ++++- .../resource-policy-form.component.spec.ts | 2 +- .../resource-policies.module.ts | 6 - src/app/shared/search/search.component.ts | 6 +- src/app/shared/shared.module.ts | 12 + src/assets/i18n/en.json5 | 56 ++++ 47 files changed, 1531 insertions(+), 52 deletions(-) create mode 100644 src/app/core/supervision-order/models/action-type.model.ts create mode 100644 src/app/core/supervision-order/models/supervision-order.model.ts create mode 100644 src/app/core/supervision-order/models/supervision-order.resource-type.ts create mode 100644 src/app/core/supervision-order/supervision-order-data.service.spec.ts create mode 100644 src/app/core/supervision-order/supervision-order-data.service.ts create mode 100644 src/app/shared/dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component.html rename src/app/shared/{resource-policies/form/eperson-group-list/eperson-group-list.component.scss => dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component.scss} (100%) create mode 100644 src/app/shared/dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component.spec.ts create mode 100644 src/app/shared/dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component.ts rename src/app/shared/{resource-policies => }/form/eperson-group-list/eperson-group-list.component.html (100%) create mode 100644 src/app/shared/form/eperson-group-list/eperson-group-list.component.scss rename src/app/shared/{resource-policies => }/form/eperson-group-list/eperson-group-list.component.spec.ts (88%) rename src/app/shared/{resource-policies => }/form/eperson-group-list/eperson-group-list.component.ts (81%) rename src/app/shared/{resource-policies => }/form/eperson-group-list/eperson-search-box/eperson-search-box.component.html (100%) rename src/app/shared/{resource-policies => }/form/eperson-group-list/eperson-search-box/eperson-search-box.component.spec.ts (97%) rename src/app/shared/{resource-policies => }/form/eperson-group-list/eperson-search-box/eperson-search-box.component.ts (96%) rename src/app/shared/{resource-policies => }/form/eperson-group-list/group-search-box/group-search-box.component.html (100%) rename src/app/shared/{resource-policies => }/form/eperson-group-list/group-search-box/group-search-box.component.spec.ts (97%) rename src/app/shared/{resource-policies => }/form/eperson-group-list/group-search-box/group-search-box.component.ts (96%) diff --git a/src/app/admin/admin-workflow-page/admin-workflow-page.component.html b/src/app/admin/admin-workflow-page/admin-workflow-page.component.html index 404af131d1..d12cefb331 100644 --- a/src/app/admin/admin-workflow-page/admin-workflow-page.component.html +++ b/src/app/admin/admin-workflow-page/admin-workflow-page.component.html @@ -1 +1 @@ - + 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 192cc751f2..77ece5254d 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 @@ -1,6 +1,9 @@ -
+
{{ "admin.workflow.item.workflow" | translate }}
+
+ {{ "admin.workflow.item.workspace" | translate }} +
{{"admin.workflow.item.send-back" | translate}} + + {{'admin.workflow.item.policies' | translate}} + + + {{'admin.workflow.item.supervision' | translate}} +
diff --git a/src/app/admin/admin-workflow-page/admin-workflow-search-results/workflow-item-admin-workflow-actions.component.spec.ts b/src/app/admin/admin-workflow-page/admin-workflow-search-results/workflow-item-admin-workflow-actions.component.spec.ts index 75e0e2e7a8..9b2bffffef 100644 --- a/src/app/admin/admin-workflow-page/admin-workflow-search-results/workflow-item-admin-workflow-actions.component.spec.ts +++ b/src/app/admin/admin-workflow-page/admin-workflow-search-results/workflow-item-admin-workflow-actions.component.spec.ts @@ -11,17 +11,25 @@ import { getWorkflowItemDeleteRoute, getWorkflowItemSendBackRoute } from '../../../workflowitems-edit-page/workflowitems-edit-page-routing-paths'; +import { of } from 'rxjs'; +import { Item } from 'src/app/core/shared/item.model'; +import { RemoteData } from 'src/app/core/data/remote-data'; +import { RequestEntryState } from 'src/app/core/data/request-entry-state.model'; describe('WorkflowItemAdminWorkflowActionsComponent', () => { let component: WorkflowItemAdminWorkflowActionsComponent; let fixture: ComponentFixture; let id; let wfi; + let item = new Item(); + item.uuid = 'itemUUID1111'; + const rd = new RemoteData(undefined, undefined, undefined, RequestEntryState.Success, undefined, item, 200); function init() { id = '780b2588-bda5-4112-a1cd-0b15000a5339'; wfi = new WorkflowItem(); wfi.id = id; + wfi.item = of(rd); } beforeEach(waitForAsync(() => { @@ -59,4 +67,11 @@ describe('WorkflowItemAdminWorkflowActionsComponent', () => { const link = a.nativeElement.href; expect(link).toContain(new URLCombiner(getWorkflowItemSendBackRoute(wfi.id)).toString()); }); + + it('should render a policies button with the correct link', () => { + const a = fixture.debugElement.query(By.css('a.policies-link')); + const link = a.nativeElement.href; + expect(link).toContain(new URLCombiner('/items/itemUUID1111/edit/bitstreams').toString()); + }); + }); diff --git a/src/app/admin/admin-workflow-page/admin-workflow-search-results/workflow-item-admin-workflow-actions.component.ts b/src/app/admin/admin-workflow-page/admin-workflow-search-results/workflow-item-admin-workflow-actions.component.ts index 32725a0e7a..924f24e738 100644 --- a/src/app/admin/admin-workflow-page/admin-workflow-search-results/workflow-item-admin-workflow-actions.component.ts +++ b/src/app/admin/admin-workflow-page/admin-workflow-search-results/workflow-item-admin-workflow-actions.component.ts @@ -1,4 +1,9 @@ import { Component, Input } from '@angular/core'; +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { map, Observable } from 'rxjs'; +import { Item } from '../../../core/shared/item.model'; +import { getFirstSucceededRemoteDataPayload } from '../../../core/shared/operators'; +import { SupervisionGroupSelectorComponent } from '../../../shared/dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component'; import { WorkflowItem } from '../../../core/submission/models/workflowitem.model'; import { getWorkflowItemSendBackRoute, @@ -25,6 +30,10 @@ export class WorkflowItemAdminWorkflowActionsComponent { */ @Input() public small: boolean; + constructor( + private modalService: NgbModal + ) { } + /** * Returns the path to the delete page of this workflow item */ @@ -39,4 +48,28 @@ export class WorkflowItemAdminWorkflowActionsComponent { getSendBackRoute(): string { return getWorkflowItemSendBackRoute(this.wfi.id); } + + /** + * Returns the path to the to administrative edit page policies tab + */ + getPoliciesRoute(): Observable { + return this.wfi.item.pipe( + getFirstSucceededRemoteDataPayload(), + map((item: Item) => { + return '/items/' + item.uuid + '/edit/bitstreams'; + }) + ); + } + + /** + * Opens the Supervision Modal to create a supervision order + */ + openSupervisionModal() { + this.wfi.item.pipe( + getFirstSucceededRemoteDataPayload(), + ).subscribe((item: Item) => { + const supervisionModal = this.modalService.open(SupervisionGroupSelectorComponent, { size: 'lg', backdrop: 'static' }); + supervisionModal.componentInstance.itemUUID = item.uuid; + }); + } } diff --git a/src/app/core/core.module.ts b/src/app/core/core.module.ts index ede23ba43b..845bab2ea8 100644 --- a/src/app/core/core.module.ts +++ b/src/app/core/core.module.ts @@ -170,6 +170,7 @@ import { OrcidHistory } from './orcid/model/orcid-history.model'; import { OrcidAuthService } from './orcid/orcid-auth.service'; import { VocabularyDataService } from './submission/vocabularies/vocabulary.data.service'; import { VocabularyEntryDetailsDataService } from './submission/vocabularies/vocabulary-entry-details.data.service'; +import { SupervisionOrderDataService } from './supervision-order/supervision-order-data.service'; /** * When not in production, endpoint responses can be mocked for testing purposes @@ -292,6 +293,7 @@ const PROVIDERS = [ OrcidAuthService, OrcidQueueDataService, OrcidHistoryDataService, + SupervisionOrderDataService ]; /** diff --git a/src/app/core/shared/context.model.ts b/src/app/core/shared/context.model.ts index 126896e3e1..0f1130ebda 100644 --- a/src/app/core/shared/context.model.ts +++ b/src/app/core/shared/context.model.ts @@ -8,6 +8,7 @@ export enum Context { Search = 'search', Workflow = 'workflow', Workspace = 'workspace', + SupervisedItems = 'otherworkspace', AdminMenu = 'adminMenu', EntitySearchModalWithNameVariants = 'EntitySearchModalWithNameVariants', EntitySearchModal = 'EntitySearchModal', diff --git a/src/app/core/submission/models/submission-object.model.ts b/src/app/core/submission/models/submission-object.model.ts index 3d7c0a3678..3d373d2522 100644 --- a/src/app/core/submission/models/submission-object.model.ts +++ b/src/app/core/submission/models/submission-object.model.ts @@ -14,6 +14,7 @@ import { ITEM } from '../../shared/item.resource-type'; import { excludeFromEquals } from '../../utilities/equals.decorators'; import { WorkspaceitemSectionsObject } from './workspaceitem-sections.model'; import { CacheableObject } from '../../cache/cacheable-object.model'; +import { SUPERVISION_ORDER } from '../../supervision-order/models/supervision-order.resource-type'; export interface SubmissionObjectError { message: string; @@ -65,6 +66,7 @@ export abstract class SubmissionObject extends DSpaceObject implements Cacheable item: HALLink; submissionDefinition: HALLink; submitter: HALLink; + supervisionOrders: HALLink; }; get self(): string { @@ -93,4 +95,12 @@ export abstract class SubmissionObject extends DSpaceObject implements Cacheable @link(EPERSON) submitter?: Observable> | EPerson; + /** + * The submission supervision order + * Will be undefined unless the workspace item {@link HALLink} has been resolved. + */ + @link(SUPERVISION_ORDER) + /* This was changed from 'Observable> | WorkspaceItem' to 'any' to prevent issues in templates with async */ + supervisionOrders?: any; + } diff --git a/src/app/core/supervision-order/models/action-type.model.ts b/src/app/core/supervision-order/models/action-type.model.ts new file mode 100644 index 0000000000..0e55689069 --- /dev/null +++ b/src/app/core/supervision-order/models/action-type.model.ts @@ -0,0 +1,44 @@ +/** + * Enum representing the Action Type of a Resource Policy + */ +export enum ActionType { + /** + * Action of reading, viewing or downloading something + */ + READ = 'READ', + + /** + * Action of modifying something + */ + WRITE = 'WRITE', + + /** + * Action of deleting something + */ + DELETE = 'DELETE', + + /** + * Action of adding something to a container + */ + ADD = 'ADD', + + /** + * Action of removing something from a container + */ + REMOVE = 'REMOVE', + + /** + * None Type of Supervision Order + */ + NONE = 'NONE', + + /** + * Editor Type of Supervision Order + */ + EDITOR = 'EDITOR', + + /** + * Observer Type of Supervision Order + */ + OBSERVER = 'OBSERVER', +} diff --git a/src/app/core/supervision-order/models/supervision-order.model.ts b/src/app/core/supervision-order/models/supervision-order.model.ts new file mode 100644 index 0000000000..e881c06d1b --- /dev/null +++ b/src/app/core/supervision-order/models/supervision-order.model.ts @@ -0,0 +1,74 @@ +import { autoserialize, deserialize, deserializeAs } from 'cerialize'; +import { link, typedObject } from '../../cache/builders/build-decorators'; +import { IDToUUIDSerializer } from '../../cache/id-to-uuid-serializer'; +import { HALLink } from '../../shared/hal-link.model'; +import { SUPERVISION_ORDER } from './supervision-order.resource-type'; +import { excludeFromEquals } from '../../utilities/equals.decorators'; +import { ResourceType } from '../../shared/resource-type'; +import { Observable } from 'rxjs'; +import { RemoteData } from '../../data/remote-data'; +import { GROUP } from '../../eperson/models/group.resource-type'; +import { Group } from '../../eperson/models/group.model'; +import { CacheableObject } from '../../cache/cacheable-object.model'; +import { ITEM } from '../../shared/item.resource-type'; +import { Item } from '../../shared/item.model'; + +/** + * Model class for a Supervision Order + */ +@typedObject +export class SupervisionOrder implements CacheableObject { + static type = SUPERVISION_ORDER; + + /** + * The identifier for this Supervision Order + */ + @autoserialize + id: string; + + /** + * The object type + */ + @excludeFromEquals + @autoserialize + type: ResourceType; + + /** + * The object type + */ + @excludeFromEquals + @autoserialize + ordertype: string; + + /** + * The universally unique identifier for this Supervision Order + * This UUID is generated client-side and isn't used by the backend. + * It is based on the ID, so it will be the same for each refresh. + */ + @deserializeAs(new IDToUUIDSerializer('supervision-order'), 'id') + uuid: string; + + /** + * The {@link HALLink}s for this SupervisionOrder + */ + @deserialize + _links: { + item: HALLink, + group: HALLink, + self: HALLink, + }; + + /** + * The related supervision Item + * Will be undefined unless the item {@link HALLink} has been resolved. + */ + @link(ITEM) + item?: Observable>; + + /** + * The group linked by this supervision order + * Will be undefined unless the version {@link HALLink} has been resolved. + */ + @link(GROUP) + group?: Observable>; +} diff --git a/src/app/core/supervision-order/models/supervision-order.resource-type.ts b/src/app/core/supervision-order/models/supervision-order.resource-type.ts new file mode 100644 index 0000000000..994c93ab74 --- /dev/null +++ b/src/app/core/supervision-order/models/supervision-order.resource-type.ts @@ -0,0 +1,9 @@ +import { ResourceType } from '../../shared/resource-type'; + +/** + * The resource type for SupervisionOrder + * + * Needs to be in a separate file to prevent circular + * dependencies in webpack. + */ +export const SUPERVISION_ORDER = new ResourceType('supervisionorder'); diff --git a/src/app/core/supervision-order/supervision-order-data.service.spec.ts b/src/app/core/supervision-order/supervision-order-data.service.spec.ts new file mode 100644 index 0000000000..b12817fa1a --- /dev/null +++ b/src/app/core/supervision-order/supervision-order-data.service.spec.ts @@ -0,0 +1,277 @@ +import { cold, getTestScheduler, hot } from 'jasmine-marbles'; +import { of as observableOf } from 'rxjs'; +import { TestScheduler } from 'rxjs/testing'; + +import { NotificationsService } from '../../shared/notifications/notifications.service'; +import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; +import { ObjectCacheService } from '../cache/object-cache.service'; +import { HALEndpointService } from '../shared/hal-endpoint.service'; +import { RequestService } from '../data/request.service'; +import { SupervisionOrderDataService } from './supervision-order-data.service'; +import { ActionType } from './models/action-type.model'; +import { RequestParam } from '../cache/models/request-param.model'; +import { PageInfo } from '../shared/page-info.model'; +import { buildPaginatedList } from '../data/paginated-list.model'; +import { createSuccessfulRemoteDataObject } from '../../shared/remote-data.utils'; +import { RestResponse } from '../cache/response.models'; +import { RequestEntry } from '../data/request-entry.model'; +import { FindListOptions } from '../data/find-list-options.model'; +import { GroupDataService } from '../eperson/group-data.service'; + +describe('SupervisionOrderService', () => { + let scheduler: TestScheduler; + let service: SupervisionOrderDataService; + let requestService: RequestService; + let rdbService: RemoteDataBuildService; + let objectCache: ObjectCacheService; + let halService: HALEndpointService; + let responseCacheEntry: RequestEntry; + let groupService: GroupDataService; + + const supervisionOrder: any = { + id: '1', + name: null, + description: null, + action: ActionType.READ, + startDate: null, + endDate: null, + type: 'supervisionOrder', + uuid: 'supervision-order-1', + _links: { + group: { + href: 'https://rest.api/rest/api/group' + }, + self: { + href: 'https://rest.api/rest/api/supervisionorder/1' + }, + } + }; + + const anothersupervisionOrder: any = { + id: '2', + name: null, + description: null, + action: ActionType.WRITE, + startDate: null, + endDate: null, + type: 'supervisionOrder', + uuid: 'supervision-order-2', + _links: { + group: { + href: 'https://rest.api/rest/api/group' + }, + self: { + href: 'https://rest.api/rest/api/supervisionorder/1' + }, + } + }; + const endpointURL = `https://rest.api/rest/api/supervisionorder`; + const requestURL = `https://rest.api/rest/api/supervisionorder/${supervisionOrder.id}`; + const requestUUID = '8b3c613a-5a4b-438b-9686-be1d5b4a1c5a'; + const supervisionOrderId = '1'; + const groupUUID = '8b39g7ya-5a4b-438b-9686-be1d5b4a1c5a'; + const itemUUID = '8b39g7ya-5a4b-438b-851f-be1d5b4a1c5a'; + const supervisionOrderType = 'NONE'; + + const pageInfo = new PageInfo(); + const array = [supervisionOrder, anothersupervisionOrder]; + const paginatedList = buildPaginatedList(pageInfo, array); + const supervisionOrderRD = createSuccessfulRemoteDataObject(supervisionOrder); + const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); + + const groupEndpoint = 'group_EP'; + + beforeEach(() => { + scheduler = getTestScheduler(); + + halService = jasmine.createSpyObj('halService', { + getEndpoint: cold('a', { a: endpointURL }) + }); + + responseCacheEntry = new RequestEntry(); + responseCacheEntry.request = { href: 'https://rest.api/' } as any; + responseCacheEntry.response = new RestResponse(true, 200, 'Success'); + + requestService = jasmine.createSpyObj('requestService', { + generateRequestId: requestUUID, + send: true, + removeByHrefSubstring: {}, + getByHref: observableOf(responseCacheEntry), + getByUUID: observableOf(responseCacheEntry), + setStaleByHrefSubstring: {}, + }); + rdbService = jasmine.createSpyObj('rdbService', { + buildSingle: hot('a|', { + a: supervisionOrderRD + }), + buildList: hot('a|', { + a: paginatedListRD + }), + buildFromRequestUUID: hot('a|', { + a: supervisionOrderRD + }), + buildFromRequestUUIDAndAwait: hot('a|', { + a: supervisionOrderRD + }) + }); + groupService = jasmine.createSpyObj('groupService', { + getBrowseEndpoint: hot('a', { + a: groupEndpoint + }), + getIDHrefObs: cold('a', { + a: 'https://rest.api/rest/api/group/groups/' + groupUUID + }), + }); + groupService = jasmine.createSpyObj('groupService', { + getIDHrefObs: cold('a', { + a: 'https://rest.api/rest/api/group/groups/' + groupUUID + }), + }); + objectCache = {} as ObjectCacheService; + const notificationsService = {} as NotificationsService; + const comparator = {} as any; + + service = new SupervisionOrderDataService( + requestService, + rdbService, + objectCache, + halService, + notificationsService, + comparator, + groupService, + ); + + spyOn(service, 'findById').and.callThrough(); + spyOn(service, 'findByHref').and.callThrough(); + spyOn(service, 'invalidateByHref').and.returnValue(observableOf(true)); + spyOn((service as any).createData, 'create').and.callThrough(); + spyOn((service as any).deleteData, 'delete').and.callThrough(); + spyOn((service as any).patchData, 'update').and.callThrough(); + spyOn((service as any).searchData, 'searchBy').and.callThrough(); + spyOn((service as any).searchData, 'getSearchByHref').and.returnValue(observableOf(requestURL)); + }); + + describe('create', () => { + it('should proxy the call to createData.create with group UUID', () => { + scheduler.schedule(() => service.create(supervisionOrder, itemUUID, groupUUID, supervisionOrderType)); + const params = [ + new RequestParam('uuid', itemUUID), + new RequestParam('group', groupUUID), + new RequestParam('type', supervisionOrderType), + ]; + scheduler.flush(); + + expect((service as any).createData.create).toHaveBeenCalledWith(supervisionOrder, ...params); + }); + + it('should proxy the call to createData.create with group UUID', () => { + scheduler.schedule(() => service.create(supervisionOrder, itemUUID, groupUUID, supervisionOrderType)); + const params = [ + new RequestParam('uuid', itemUUID), + new RequestParam('group', groupUUID), + new RequestParam('type', supervisionOrderType), + ]; + scheduler.flush(); + + expect((service as any).createData.create).toHaveBeenCalledWith(supervisionOrder, ...params); + }); + + it('should return a RemoteData for the object with the given id', () => { + const result = service.create(supervisionOrder, itemUUID, groupUUID, supervisionOrderType); + const expected = cold('a|', { + a: supervisionOrderRD + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('delete', () => { + it('should proxy the call to deleteData.delete', () => { + scheduler.schedule(() => service.delete(supervisionOrderId)); + scheduler.flush(); + + expect((service as any).deleteData.delete).toHaveBeenCalledWith(supervisionOrderId); + }); + }); + + describe('update', () => { + it('should proxy the call to updateData.update', () => { + scheduler.schedule(() => service.update(supervisionOrder)); + scheduler.flush(); + + expect((service as any).patchData.update).toHaveBeenCalledWith(supervisionOrder); + }); + }); + + describe('findById', () => { + it('should return a RemoteData for the object with the given id', () => { + const result = service.findById(supervisionOrderId); + const expected = cold('a|', { + a: supervisionOrderRD + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('findByHref', () => { + it('should return a RemoteData for the object with the given URL', () => { + const result = service.findByHref(requestURL); + const expected = cold('a|', { + a: supervisionOrderRD + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('searchByGroup', () => { + it('should proxy the call to searchData.searchBy', () => { + const options = new FindListOptions(); + options.searchParams = [new RequestParam('uuid', groupUUID)]; + scheduler.schedule(() => service.searchByGroup(groupUUID)); + scheduler.flush(); + + expect((service as any).searchData.searchBy).toHaveBeenCalledWith((service as any).searchByGroupMethod, options, true, true); + }); + + it('should proxy the call to searchData.searchBy with additional search param', () => { + const options = new FindListOptions(); + options.searchParams = [ + new RequestParam('uuid', groupUUID), + new RequestParam('item', itemUUID), + ]; + scheduler.schedule(() => service.searchByGroup(groupUUID, itemUUID)); + scheduler.flush(); + + expect((service as any).searchData.searchBy).toHaveBeenCalledWith((service as any).searchByGroupMethod, options, true, true); + }); + + it('should return a RemoteData) for the search', () => { + const result = service.searchByGroup(groupUUID); + const expected = cold('a|', { + a: paginatedListRD + }); + expect(result).toBeObservable(expected); + }); + + }); + + describe('searchByItem', () => { + it('should proxy the call to searchData.searchBy', () => { + const options = new FindListOptions(); + options.searchParams = [new RequestParam('uuid', itemUUID)]; + scheduler.schedule(() => service.searchByItem(itemUUID)); + scheduler.flush(); + + expect((service as any).searchData.searchBy).toHaveBeenCalledWith((service as any).searchByItemMethod, options, true, true); + }); + + it('should return a RemoteData) for the search', () => { + const result = service.searchByItem(itemUUID); + const expected = cold('a|', { + a: paginatedListRD + }); + expect(result).toBeObservable(expected); + }); + }); + +}); diff --git a/src/app/core/supervision-order/supervision-order-data.service.ts b/src/app/core/supervision-order/supervision-order-data.service.ts new file mode 100644 index 0000000000..fed0c57b09 --- /dev/null +++ b/src/app/core/supervision-order/supervision-order-data.service.ts @@ -0,0 +1,181 @@ +import { Injectable } from '@angular/core'; +import { HttpHeaders } from '@angular/common/http'; +import { Observable } from 'rxjs'; +import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model'; +import { RequestService } from '../data/request.service'; +import { HALEndpointService } from '../shared/hal-endpoint.service'; +import { SupervisionOrder } from './models/supervision-order.model'; +import { RemoteData } from '../data/remote-data'; +import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; +import { ObjectCacheService } from '../cache/object-cache.service'; +import { NotificationsService } from '../../shared/notifications/notifications.service'; +import { SUPERVISION_ORDER } from './models/supervision-order.resource-type'; +import { DefaultChangeAnalyzer } from '../data/default-change-analyzer.service'; +import { PaginatedList } from '../data/paginated-list.model'; +import { RequestParam } from '../cache/models/request-param.model'; +import { isNotEmpty } from '../../shared/empty.util'; +import { first, map } from 'rxjs/operators'; +import { NoContent } from '../shared/NoContent.model'; +import { getFirstCompletedRemoteData } from '../shared/operators'; +import { FindListOptions } from '../data/find-list-options.model'; +import { HttpOptions } from '../dspace-rest/dspace-rest.service'; +import { PutRequest } from '../data/request.models'; +import { GenericConstructor } from '../shared/generic-constructor'; +import { ResponseParsingService } from '../data/parsing.service'; +import { StatusCodeOnlyResponseParsingService } from '../data/status-code-only-response-parsing.service'; +import { GroupDataService } from '../eperson/group-data.service'; +import { IdentifiableDataService } from '../data/base/identifiable-data.service'; +import { CreateDataImpl } from '../data/base/create-data'; +import { SearchDataImpl } from '../data/base/search-data'; +import { PatchDataImpl } from '../data/base/patch-data'; +import { DeleteDataImpl } from '../data/base/delete-data'; +import { dataService } from '../data/base/data-service.decorator'; + +/** + * A service responsible for fetching/sending data from/to the REST API on the supervisionorders endpoint + */ +@Injectable() +@dataService(SUPERVISION_ORDER) +export class SupervisionOrderDataService extends IdentifiableDataService { + protected searchByGroupMethod = 'group'; + protected searchByItemMethod = 'byItem'; + + private createData: CreateDataImpl; + private searchData: SearchDataImpl; + private patchData: PatchDataImpl; + private deleteData: DeleteDataImpl; + + constructor( + protected requestService: RequestService, + protected rdbService: RemoteDataBuildService, + protected objectCache: ObjectCacheService, + protected halService: HALEndpointService, + protected notificationsService: NotificationsService, + protected comparator: DefaultChangeAnalyzer, + protected groupService: GroupDataService, + ) { + super('supervisionorders', requestService, rdbService, objectCache, halService); + + this.createData = new CreateDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, notificationsService, this.responseMsToLive); + this.searchData = new SearchDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, this.responseMsToLive); + this.patchData = new PatchDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, comparator, this.responseMsToLive, this.constructIdEndpoint); + this.deleteData = new DeleteDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, notificationsService, this.responseMsToLive, this.constructIdEndpoint); + } + + /** + * Create a new SupervisionOrder on the server, and store the response + * in the object cache + * + * @param {SupervisionOrder} supervisionOrder + * The supervision order to create + * @param {string} itemUUID + * The uuid of the item that will be grant of the permission. + * @param {string} groupUUID + * The uuid of the group that will be grant of the permission. + * @param {string} type + * The type of the supervision order that will be grant of the permission. + */ + create(supervisionOrder: SupervisionOrder, itemUUID: string, groupUUID: string, type: string): Observable> { + const params = []; + params.push(new RequestParam('uuid', itemUUID)); + params.push(new RequestParam('group', groupUUID)); + params.push(new RequestParam('type', type)); + return this.createData.create(supervisionOrder, ...params); + } + + /** + * Delete an existing SupervisionOrder on the server + * + * @param supervisionOrderID The supervision order's id to be removed + * @return an observable that emits true when the deletion was successful, false when it failed + */ + delete(supervisionOrderID: string): Observable { + return this.deleteData.delete(supervisionOrderID).pipe( + getFirstCompletedRemoteData(), + map((response: RemoteData) => response.hasSucceeded), + ); + } + + /** + * Add a new patch to the object cache + * The patch is derived from the differences between the given object and its version in the object cache + * @param {SupervisionOrder} object The given object + */ + update(object: SupervisionOrder): Observable> { + return this.patchData.update(object); + } + + /** + * Return the {@link SupervisionOrder} list for a {@link Group} + * + * @param UUID UUID of a given {@link Group} + * @param itemUUID Limit the returned policies to the specified DSO + * @param useCachedVersionIfAvailable If this is true, the request will only be sent if there's + * no valid cached version. Defaults to true + * @param reRequestOnStale Whether or not the request should automatically be re- + * requested after the response becomes stale + * @param linksToFollow List of {@link FollowLinkConfig} that indicate which + * {@link HALLink}s should be automatically resolved + */ + searchByGroup(UUID: string, itemUUID?: string, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig[]): Observable>> { + const options = new FindListOptions(); + options.searchParams = [new RequestParam('uuid', UUID)]; + if (isNotEmpty(itemUUID)) { + options.searchParams.push(new RequestParam('item', itemUUID)); + } + return this.searchData.searchBy(this.searchByGroupMethod, options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); + } + + /** + * Return the {@link SupervisionOrder} list for a given DSO + * + * @param UUID UUID of a given DSO + * @param action Limit the returned policies to the specified {@link ActionType} + * @param useCachedVersionIfAvailable If this is true, the request will only be sent if there's + * no valid cached version. Defaults to true + * @param reRequestOnStale Whether or not the request should automatically be re- + * requested after the response becomes stale + * @param linksToFollow List of {@link FollowLinkConfig} that indicate which + * {@link HALLink}s should be automatically resolved + */ + searchByItem(UUID: string, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig[]): Observable>> { + const options = new FindListOptions(); + options.searchParams = [new RequestParam('uuid', UUID)]; + return this.searchData.searchBy(this.searchByItemMethod, options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); + } + + /** + * Update the target of the supervision order + * @param supervisionOrderId the ID of the supervision order + * @param supervisionOrderHref the link to the supervision order + * @param targetUUID the UUID of the target to which the permission is being granted + * @param targetType the type of the target (eperson or group) to which the permission is being granted + */ + updateTarget(supervisionOrderId: string, supervisionOrderHref: string, targetUUID: string, targetType: string): Observable> { + const targetService = this.groupService; + const targetEndpoint$ = targetService.getIDHrefObs(targetUUID); + + const options: HttpOptions = Object.create({}); + let headers = new HttpHeaders(); + headers = headers.append('Content-Type', 'text/uri-list'); + options.headers = headers; + + const requestId = this.requestService.generateRequestId(); + + targetEndpoint$.pipe( + first(), + ).subscribe((targetEndpoint) => { + const resourceEndpoint = supervisionOrderHref + '/' + targetType; + const request = new PutRequest(requestId, resourceEndpoint, targetEndpoint, options); + Object.assign(request, { + getResponseParser(): GenericConstructor { + return StatusCodeOnlyResponseParsingService; + } + }); + this.requestService.send(request); + }); + + return this.rdbService.buildFromRequestUUIDAndAwait(requestId, () => this.invalidateByHref(supervisionOrderHref)); + } + +} 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 178ed86c40..be110db101 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 @@ -10,6 +10,14 @@ import { TruncatableService } from '../../../../../shared/truncatable/truncatabl import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service'; import { DSONameServiceMock } from '../../../../../shared/mocks/dso-name.service.mock'; 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 { 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'; let journalIssueListElementComponent: JournalIssueSearchResultListElementComponent; let fixture: ComponentFixture; @@ -70,12 +78,61 @@ const enviromentNoThumbs = { } }; +const supervisionOrderDataService: any = jasmine.createSpyObj('supervisionOrderDataService', { + searchByItem: jasmine.createSpy('searchByItem'), +}); + +const supervisionOrder: any = { + id: '1', + type: 'supervisionOrder', + uuid: 'supervision-order-1', + _links: { + item: { + href: 'https://rest.api/rest/api/eperson' + }, + group: { + href: 'https://rest.api/rest/api/group' + }, + self: { + href: 'https://rest.api/rest/api/supervisionorders/1' + }, + }, + item: observableOf(createSuccessfulRemoteDataObject({})), + group: observableOf(createSuccessfulRemoteDataObject(GroupMock)) +}; +const anothersupervisionOrder: any = { + id: '2', + type: 'supervisionOrder', + uuid: 'supervision-order-2', + _links: { + item: { + href: 'https://rest.api/rest/api/eperson' + }, + group: { + href: 'https://rest.api/rest/api/group' + }, + self: { + href: 'https://rest.api/rest/api/supervisionorders/1' + }, + }, + item: observableOf(createSuccessfulRemoteDataObject({})), + group: observableOf(createSuccessfulRemoteDataObject(GroupMock)) +}; + +const pageInfo = new PageInfo(); +const array = [supervisionOrder, anothersupervisionOrder]; +const paginatedList = buildPaginatedList(pageInfo, array); +const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); + describe('JournalIssueSearchResultListElementComponent', () => { beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [JournalIssueSearchResultListElementComponent, TruncatePipe], providers: [ { provide: TruncatableService, useValue: {} }, + { provide: SupervisionOrderDataService, useValue: supervisionOrderDataService }, + {provide: NotificationsService, useValue: {}}, + {provide: TranslateService, useValue: {}}, { provide: DSONameService, useClass: DSONameServiceMock }, { provide: APP_CONFIG, useValue: environmentUseThumbs } ], @@ -87,6 +144,9 @@ describe('JournalIssueSearchResultListElementComponent', () => { })); beforeEach(waitForAsync(() => { + supervisionOrderDataService.searchByItem.and.returnValue(hot('a|', { + a: paginatedListRD + })); fixture = TestBed.createComponent(JournalIssueSearchResultListElementComponent); journalIssueListElementComponent = fixture.componentInstance; @@ -164,6 +224,9 @@ describe('JournalIssueSearchResultListElementComponent', () => { declarations: [JournalIssueSearchResultListElementComponent, TruncatePipe], providers: [ {provide: TruncatableService, useValue: {}}, + {provide: SupervisionOrderDataService, useValue: supervisionOrderDataService }, + {provide: NotificationsService, useValue: {}}, + {provide: TranslateService, useValue: {}}, {provide: DSONameService, useClass: DSONameServiceMock}, { provide: APP_CONFIG, useValue: enviromentNoThumbs } ], @@ -181,7 +244,9 @@ describe('JournalIssueSearchResultListElementComponent', () => { describe('with environment.browseBy.showThumbnails set to false', () => { beforeEach(() => { - + supervisionOrderDataService.searchByItem.and.returnValue(hot('a|', { + a: paginatedListRD + })); journalIssueListElementComponent.object = mockItemWithMetadata; fixture.detectChanges(); }); 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 71fa83a3b1..76d516e76e 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 @@ -10,6 +10,14 @@ import { TruncatableService } from '../../../../../shared/truncatable/truncatabl import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service'; import { DSONameServiceMock } from '../../../../../shared/mocks/dso-name.service.mock'; 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 { 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'; let journalVolumeListElementComponent: JournalVolumeSearchResultListElementComponent; let fixture: ComponentFixture; @@ -69,12 +77,61 @@ const enviromentNoThumbs = { } }; +const supervisionOrderDataService: any = jasmine.createSpyObj('supervisionOrderDataService', { + searchByItem: jasmine.createSpy('searchByItem'), +}); + +const supervisionOrder: any = { + id: '1', + type: 'supervisionOrder', + uuid: 'supervision-order-1', + _links: { + item: { + href: 'https://rest.api/rest/api/eperson' + }, + group: { + href: 'https://rest.api/rest/api/group' + }, + self: { + href: 'https://rest.api/rest/api/supervisionorders/1' + }, + }, + item: observableOf(createSuccessfulRemoteDataObject({})), + group: observableOf(createSuccessfulRemoteDataObject(GroupMock)) +}; +const anothersupervisionOrder: any = { + id: '2', + type: 'supervisionOrder', + uuid: 'supervision-order-2', + _links: { + item: { + href: 'https://rest.api/rest/api/eperson' + }, + group: { + href: 'https://rest.api/rest/api/group' + }, + self: { + href: 'https://rest.api/rest/api/supervisionorders/1' + }, + }, + item: observableOf(createSuccessfulRemoteDataObject({})), + group: observableOf(createSuccessfulRemoteDataObject(GroupMock)) +}; + +const pageInfo = new PageInfo(); +const array = [supervisionOrder, anothersupervisionOrder]; +const paginatedList = buildPaginatedList(pageInfo, array); +const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); + describe('JournalVolumeSearchResultListElementComponent', () => { beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [JournalVolumeSearchResultListElementComponent, TruncatePipe], providers: [ { provide: TruncatableService, useValue: {} }, + { provide: SupervisionOrderDataService, useValue: supervisionOrderDataService }, + { provide: NotificationsService, useValue: {}}, + { provide: TranslateService, useValue: {}}, { provide: DSONameService, useClass: DSONameServiceMock }, { provide: APP_CONFIG, useValue: environmentUseThumbs } ], @@ -86,6 +143,9 @@ describe('JournalVolumeSearchResultListElementComponent', () => { })); beforeEach(waitForAsync(() => { + supervisionOrderDataService.searchByItem.and.returnValue(hot('a|', { + a: paginatedListRD + })); fixture = TestBed.createComponent(JournalVolumeSearchResultListElementComponent); journalVolumeListElementComponent = fixture.componentInstance; @@ -162,6 +222,9 @@ describe('JournalVolumeSearchResultListElementComponent', () => { declarations: [JournalVolumeSearchResultListElementComponent, TruncatePipe], providers: [ {provide: TruncatableService, useValue: {}}, + {provide: SupervisionOrderDataService, useValue: supervisionOrderDataService }, + {provide: NotificationsService, useValue: {}}, + {provide: TranslateService, useValue: {}}, {provide: DSONameService, useClass: DSONameServiceMock}, { provide: APP_CONFIG, useValue: enviromentNoThumbs } ], @@ -173,6 +236,9 @@ describe('JournalVolumeSearchResultListElementComponent', () => { })); beforeEach(waitForAsync(() => { + supervisionOrderDataService.searchByItem.and.returnValue(hot('a|', { + a: paginatedListRD + })); fixture = TestBed.createComponent(JournalVolumeSearchResultListElementComponent); journalVolumeListElementComponent = fixture.componentInstance; })); 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 07970d7128..55f0875731 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 @@ -10,6 +10,14 @@ import { ItemSearchResult } from '../../../../../shared/object-collection/shared import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service'; import { DSONameServiceMock } from '../../../../../shared/mocks/dso-name.service.mock'; 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 { 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'; let journalListElementComponent: JournalSearchResultListElementComponent; let fixture: ComponentFixture; @@ -65,12 +73,61 @@ const enviromentNoThumbs = { } }; +const supervisionOrderDataService: any = jasmine.createSpyObj('supervisionOrderDataService', { + searchByItem: jasmine.createSpy('searchByItem'), +}); + +const supervisionOrder: any = { + id: '1', + type: 'supervisionOrder', + uuid: 'supervision-order-1', + _links: { + item: { + href: 'https://rest.api/rest/api/eperson' + }, + group: { + href: 'https://rest.api/rest/api/group' + }, + self: { + href: 'https://rest.api/rest/api/supervisionorders/1' + }, + }, + item: observableOf(createSuccessfulRemoteDataObject({})), + group: observableOf(createSuccessfulRemoteDataObject(GroupMock)) +}; +const anothersupervisionOrder: any = { + id: '2', + type: 'supervisionOrder', + uuid: 'supervision-order-2', + _links: { + item: { + href: 'https://rest.api/rest/api/eperson' + }, + group: { + href: 'https://rest.api/rest/api/group' + }, + self: { + href: 'https://rest.api/rest/api/supervisionorders/1' + }, + }, + item: observableOf(createSuccessfulRemoteDataObject({})), + group: observableOf(createSuccessfulRemoteDataObject(GroupMock)) +}; + +const pageInfo = new PageInfo(); +const array = [supervisionOrder, anothersupervisionOrder]; +const paginatedList = buildPaginatedList(pageInfo, array); +const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); + describe('JournalSearchResultListElementComponent', () => { beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [JournalSearchResultListElementComponent, TruncatePipe], providers: [ { provide: TruncatableService, useValue: {} }, + { provide: SupervisionOrderDataService, useValue: supervisionOrderDataService }, + { provide: NotificationsService, useValue: {}}, + { provide: TranslateService, useValue: {}}, { provide: DSONameService, useClass: DSONameServiceMock }, { provide: APP_CONFIG, useValue: environmentUseThumbs } ], @@ -82,6 +139,9 @@ describe('JournalSearchResultListElementComponent', () => { })); beforeEach(waitForAsync(() => { + supervisionOrderDataService.searchByItem.and.returnValue(hot('a|', { + a: paginatedListRD + })); fixture = TestBed.createComponent(JournalSearchResultListElementComponent); journalListElementComponent = fixture.componentInstance; @@ -134,6 +194,9 @@ describe('JournalSearchResultListElementComponent', () => { declarations: [JournalSearchResultListElementComponent, TruncatePipe], providers: [ {provide: TruncatableService, useValue: {}}, + {provide: SupervisionOrderDataService, useValue: supervisionOrderDataService }, + {provide: NotificationsService, useValue: {}}, + {provide: TranslateService, useValue: {}}, {provide: DSONameService, useClass: DSONameServiceMock}, { provide: APP_CONFIG, useValue: enviromentNoThumbs } ], @@ -145,6 +208,9 @@ describe('JournalSearchResultListElementComponent', () => { })); beforeEach(waitForAsync(() => { + supervisionOrderDataService.searchByItem.and.returnValue(hot('a|', { + a: paginatedListRD + })); fixture = TestBed.createComponent(JournalSearchResultListElementComponent); journalListElementComponent = fixture.componentInstance; })); 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 9609a9582a..b8f30fe66e 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 @@ -12,6 +12,13 @@ import { DSONameServiceMock } from '../../../../../shared/mocks/dso-name.service import { APP_CONFIG } from '../../../../../../config/app-config.interface'; import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; import { TranslateLoaderMock } from '../../../../../shared/mocks/translate-loader.mock'; +import { SupervisionOrderDataService } from '../../../../../core/supervision-order/supervision-order-data.service'; +import { NotificationsService } from '../../../../../shared/notifications/notifications.service'; +import { 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'; let orgUnitListElementComponent: OrgUnitSearchResultListElementComponent; let fixture: ComponentFixture; @@ -65,6 +72,52 @@ const enviromentNoThumbs = { } }; +const supervisionOrderDataService: any = jasmine.createSpyObj('supervisionOrderDataService', { + searchByItem: jasmine.createSpy('searchByItem'), +}); + +const supervisionOrder: any = { + id: '1', + type: 'supervisionOrder', + uuid: 'supervision-order-1', + _links: { + item: { + href: 'https://rest.api/rest/api/eperson' + }, + group: { + href: 'https://rest.api/rest/api/group' + }, + self: { + href: 'https://rest.api/rest/api/supervisionorders/1' + }, + }, + item: observableOf(createSuccessfulRemoteDataObject({})), + group: observableOf(createSuccessfulRemoteDataObject(GroupMock)) +}; +const anothersupervisionOrder: any = { + id: '2', + type: 'supervisionOrder', + uuid: 'supervision-order-2', + _links: { + item: { + href: 'https://rest.api/rest/api/eperson' + }, + group: { + href: 'https://rest.api/rest/api/group' + }, + self: { + href: 'https://rest.api/rest/api/supervisionorders/1' + }, + }, + item: observableOf(createSuccessfulRemoteDataObject({})), + group: observableOf(createSuccessfulRemoteDataObject(GroupMock)) +}; + +const pageInfo = new PageInfo(); +const array = [supervisionOrder, anothersupervisionOrder]; +const paginatedList = buildPaginatedList(pageInfo, array); +const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); + describe('OrgUnitSearchResultListElementComponent', () => { beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ @@ -78,6 +131,8 @@ describe('OrgUnitSearchResultListElementComponent', () => { declarations: [ OrgUnitSearchResultListElementComponent , TruncatePipe], providers: [ { provide: TruncatableService, useValue: {} }, + {provide: SupervisionOrderDataService, useValue: supervisionOrderDataService }, + {provide: NotificationsService, useValue: {}}, { provide: DSONameService, useClass: DSONameServiceMock }, { provide: APP_CONFIG, useValue: environmentUseThumbs } ], @@ -89,6 +144,9 @@ describe('OrgUnitSearchResultListElementComponent', () => { })); beforeEach(waitForAsync(() => { + supervisionOrderDataService.searchByItem.and.returnValue(hot('a|', { + a: paginatedListRD + })); fixture = TestBed.createComponent(OrgUnitSearchResultListElementComponent); orgUnitListElementComponent = fixture.componentInstance; @@ -148,6 +206,8 @@ describe('OrgUnitSearchResultListElementComponent', () => { declarations: [OrgUnitSearchResultListElementComponent, TruncatePipe], providers: [ {provide: TruncatableService, useValue: {}}, + {provide: SupervisionOrderDataService, useValue: supervisionOrderDataService }, + {provide: NotificationsService, useValue: {}}, {provide: DSONameService, useClass: DSONameServiceMock}, { provide: APP_CONFIG, useValue: enviromentNoThumbs } ], @@ -165,7 +225,9 @@ describe('OrgUnitSearchResultListElementComponent', () => { describe('with environment.browseBy.showThumbnails set to false', () => { beforeEach(() => { - + supervisionOrderDataService.searchByItem.and.returnValue(hot('a|', { + a: paginatedListRD + })); orgUnitListElementComponent.object = mockItemWithMetadata; fixture.detectChanges(); }); 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 31018520f6..3f4cc1d294 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 @@ -12,9 +12,19 @@ import { DSONameServiceMock } from '../../../../../shared/mocks/dso-name.service import { APP_CONFIG } from '../../../../../../config/app-config.interface'; import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; import { TranslateLoaderMock } from '../../../../../shared/mocks/translate-loader.mock'; +import { SupervisionOrderDataService } from '../../../../../core/supervision-order/supervision-order-data.service'; +import { NotificationsService } from '../../../../../shared/notifications/notifications.service'; +import { createSuccessfulRemoteDataObject } from '../../../../../shared/remote-data.utils'; +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'; let personListElementComponent: PersonSearchResultListElementComponent; let fixture: ComponentFixture; +const supervisionOrderDataService: any = jasmine.createSpyObj('supervisionOrderDataService', { + searchByItem: jasmine.createSpy('searchByItem'), +}); const mockItemWithMetadata: ItemSearchResult = Object.assign( new ItemSearchResult(), @@ -65,6 +75,48 @@ const enviromentNoThumbs = { } }; +const supervisionOrder: any = { + id: '1', + type: 'supervisionOrder', + uuid: 'supervision-order-1', + _links: { + item: { + href: 'https://rest.api/rest/api/eperson' + }, + group: { + href: 'https://rest.api/rest/api/group' + }, + self: { + href: 'https://rest.api/rest/api/supervisionorders/1' + }, + }, + item: observableOf(createSuccessfulRemoteDataObject({})), + group: observableOf(createSuccessfulRemoteDataObject(GroupMock)) +}; +const anothersupervisionOrder: any = { + id: '2', + type: 'supervisionOrder', + uuid: 'supervision-order-2', + _links: { + item: { + href: 'https://rest.api/rest/api/eperson' + }, + group: { + href: 'https://rest.api/rest/api/group' + }, + self: { + href: 'https://rest.api/rest/api/supervisionorders/1' + }, + }, + item: observableOf(createSuccessfulRemoteDataObject({})), + group: observableOf(createSuccessfulRemoteDataObject(GroupMock)) +}; + +const pageInfo = new PageInfo(); +const array = [supervisionOrder, anothersupervisionOrder]; +const paginatedList = buildPaginatedList(pageInfo, array); +const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); + describe('PersonSearchResultListElementComponent', () => { beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ @@ -78,6 +130,8 @@ describe('PersonSearchResultListElementComponent', () => { declarations: [PersonSearchResultListElementComponent, TruncatePipe], providers: [ { provide: TruncatableService, useValue: {} }, + { provide: SupervisionOrderDataService, useValue: supervisionOrderDataService }, + { provide: NotificationsService, useValue: {} }, { provide: DSONameService, useClass: DSONameServiceMock }, { provide: APP_CONFIG, useValue: environmentUseThumbs } ], @@ -89,6 +143,9 @@ describe('PersonSearchResultListElementComponent', () => { })); beforeEach(waitForAsync(() => { + supervisionOrderDataService.searchByItem.and.returnValue(hot('a|', { + a: paginatedListRD + })); fixture = TestBed.createComponent(PersonSearchResultListElementComponent); personListElementComponent = fixture.componentInstance; @@ -148,6 +205,8 @@ describe('PersonSearchResultListElementComponent', () => { declarations: [PersonSearchResultListElementComponent, TruncatePipe], providers: [ {provide: TruncatableService, useValue: {}}, + {provide: SupervisionOrderDataService, useValue: supervisionOrderDataService}, + {provide: NotificationsService, useValue: {}}, {provide: DSONameService, useClass: DSONameServiceMock}, { provide: APP_CONFIG, useValue: enviromentNoThumbs } ], @@ -165,7 +224,9 @@ describe('PersonSearchResultListElementComponent', () => { describe('with environment.browseBy.showThumbnails set to false', () => { beforeEach(() => { - + supervisionOrderDataService.searchByItem.and.returnValue(hot('a|', { + a: paginatedListRD + })); personListElementComponent.object = mockItemWithMetadata; fixture.detectChanges(); }); 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 217d7baef9..6f78c709ba 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 @@ -9,6 +9,10 @@ import { import { TruncatableService } from '../../../../../shared/truncatable/truncatable.service'; import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service'; import { APP_CONFIG, AppConfig } from '../../../../../../config/app-config.interface'; +import { SupervisionOrderDataService } from '../../../../../core/supervision-order/supervision-order-data.service'; +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { NotificationsService } from '../../../../../shared/notifications/notifications.service'; +import { TranslateService } from '@ngx-translate/core'; @listableObjectComponent('PersonSearchResult', ViewMode.ListElement) @Component({ @@ -24,9 +28,13 @@ export class PersonSearchResultListElementComponent extends ItemSearchResultList public constructor( protected truncatableService: TruncatableService, protected dsoNameService: DSONameService, - @Inject(APP_CONFIG) protected appConfig: AppConfig + @Inject(APP_CONFIG) protected appConfig: AppConfig, + protected supervisionOrderDataService: SupervisionOrderDataService, + protected modalService: NgbModal, + protected notificationsService: NotificationsService, + protected translateService: TranslateService, ) { - super(truncatableService, dsoNameService, appConfig); + super(truncatableService, dsoNameService, appConfig, supervisionOrderDataService, modalService, notificationsService, translateService); } /** 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 0cb3e63e87..f3ef14e4f6 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 @@ -10,6 +10,14 @@ import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service import { DSONameServiceMock } from '../../../../../shared/mocks/dso-name.service.mock'; import { By } from '@angular/platform-browser'; 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 { 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'; let projectListElementComponent: ProjectSearchResultListElementComponent; let fixture: ComponentFixture; @@ -64,12 +72,61 @@ const enviromentNoThumbs = { } }; +const supervisionOrderDataService: any = jasmine.createSpyObj('supervisionOrderDataService', { + searchByItem: jasmine.createSpy('searchByItem'), +}); + +const supervisionOrder: any = { + id: '1', + type: 'supervisionOrder', + uuid: 'supervision-order-1', + _links: { + item: { + href: 'https://rest.api/rest/api/eperson' + }, + group: { + href: 'https://rest.api/rest/api/group' + }, + self: { + href: 'https://rest.api/rest/api/supervisionorders/1' + }, + }, + item: observableOf(createSuccessfulRemoteDataObject({})), + group: observableOf(createSuccessfulRemoteDataObject(GroupMock)) +}; +const anothersupervisionOrder: any = { + id: '2', + type: 'supervisionOrder', + uuid: 'supervision-order-2', + _links: { + item: { + href: 'https://rest.api/rest/api/eperson' + }, + group: { + href: 'https://rest.api/rest/api/group' + }, + self: { + href: 'https://rest.api/rest/api/supervisionorders/1' + }, + }, + item: observableOf(createSuccessfulRemoteDataObject({})), + group: observableOf(createSuccessfulRemoteDataObject(GroupMock)) +}; + +const pageInfo = new PageInfo(); +const array = [supervisionOrder, anothersupervisionOrder]; +const paginatedList = buildPaginatedList(pageInfo, array); +const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); + describe('ProjectSearchResultListElementComponent', () => { beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [ProjectSearchResultListElementComponent, TruncatePipe], providers: [ { provide: TruncatableService, useValue: {} }, + { provide: SupervisionOrderDataService, useValue: supervisionOrderDataService }, + { provide: NotificationsService, useValue: {}}, + {provide: TranslateService, useValue: {}}, { provide: DSONameService, useClass: DSONameServiceMock }, { provide: APP_CONFIG, useValue: environmentUseThumbs } ], @@ -81,6 +138,9 @@ describe('ProjectSearchResultListElementComponent', () => { })); beforeEach(waitForAsync(() => { + supervisionOrderDataService.searchByItem.and.returnValue(hot('a|', { + a: paginatedListRD + })); fixture = TestBed.createComponent(ProjectSearchResultListElementComponent); projectListElementComponent = fixture.componentInstance; @@ -133,6 +193,9 @@ describe('ProjectSearchResultListElementComponent', () => { declarations: [ProjectSearchResultListElementComponent, TruncatePipe], providers: [ {provide: TruncatableService, useValue: {}}, + {provide: SupervisionOrderDataService, useValue: supervisionOrderDataService }, + {provide: NotificationsService, useValue: {}}, + {provide: TranslateService, useValue: {}}, {provide: DSONameService, useClass: DSONameServiceMock}, { provide: APP_CONFIG, useValue: enviromentNoThumbs } @@ -151,7 +214,9 @@ describe('ProjectSearchResultListElementComponent', () => { describe('with environment.browseBy.showThumbnails set to false', () => { beforeEach(() => { - + supervisionOrderDataService.searchByItem.and.returnValue(hot('a|', { + a: paginatedListRD + })); projectListElementComponent.object = mockItemWithMetadata; fixture.detectChanges(); }); diff --git a/src/app/my-dspace-page/my-dspace-configuration-value-type.ts b/src/app/my-dspace-page/my-dspace-configuration-value-type.ts index baf2f0b920..52e6b01c11 100644 --- a/src/app/my-dspace-page/my-dspace-configuration-value-type.ts +++ b/src/app/my-dspace-page/my-dspace-configuration-value-type.ts @@ -1,4 +1,5 @@ export enum MyDSpaceConfigurationValueType { Workspace = 'workspace', + SupervisedItems = 'otherworkspace', Workflow = 'workflow' } diff --git a/src/app/my-dspace-page/my-dspace-configuration.service.spec.ts b/src/app/my-dspace-page/my-dspace-configuration.service.spec.ts index 669a97764a..34bfd946b6 100644 --- a/src/app/my-dspace-page/my-dspace-configuration.service.spec.ts +++ b/src/app/my-dspace-page/my-dspace-configuration.service.spec.ts @@ -184,7 +184,8 @@ describe('MyDSpaceConfigurationService', () => { expect(list$).toBeObservable(cold('(b|)', { b: [ - MyDSpaceConfigurationValueType.Workspace + MyDSpaceConfigurationValueType.Workspace, + MyDSpaceConfigurationValueType.SupervisedItems ] })); }); @@ -227,6 +228,7 @@ describe('MyDSpaceConfigurationService', () => { expect(list$).toBeObservable(cold('(b|)', { b: [ MyDSpaceConfigurationValueType.Workspace, + MyDSpaceConfigurationValueType.SupervisedItems, MyDSpaceConfigurationValueType.Workflow ] })); diff --git a/src/app/my-dspace-page/my-dspace-configuration.service.ts b/src/app/my-dspace-page/my-dspace-configuration.service.ts index dec8658910..86bbf0050c 100644 --- a/src/app/my-dspace-page/my-dspace-configuration.service.ts +++ b/src/app/my-dspace-page/my-dspace-configuration.service.ts @@ -20,6 +20,7 @@ import { Context } from '../core/shared/context.model'; export const MyDSpaceConfigurationToContextMap = new Map([ [MyDSpaceConfigurationValueType.Workspace, Context.Workspace], + [MyDSpaceConfigurationValueType.SupervisedItems, Context.SupervisedItems], [MyDSpaceConfigurationValueType.Workflow, Context.Workflow] ]); @@ -107,6 +108,7 @@ export class MyDSpaceConfigurationService extends SearchConfigurationService { const availableConf: MyDSpaceConfigurationValueType[] = []; if (isSubmitter) { availableConf.push(MyDSpaceConfigurationValueType.Workspace); + availableConf.push(MyDSpaceConfigurationValueType.SupervisedItems); } if (isController || isAdmin) { availableConf.push(MyDSpaceConfigurationValueType.Workflow); diff --git a/src/app/shared/dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component.html b/src/app/shared/dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component.html new file mode 100644 index 0000000000..f6a5c339ce --- /dev/null +++ b/src/app/shared/dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component.html @@ -0,0 +1,40 @@ +
+ + +
\ No newline at end of file diff --git a/src/app/shared/resource-policies/form/eperson-group-list/eperson-group-list.component.scss b/src/app/shared/dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component.scss similarity index 100% rename from src/app/shared/resource-policies/form/eperson-group-list/eperson-group-list.component.scss rename to src/app/shared/dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component.scss diff --git a/src/app/shared/dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component.spec.ts b/src/app/shared/dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component.spec.ts new file mode 100644 index 0000000000..b5e62ef8ac --- /dev/null +++ b/src/app/shared/dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component.spec.ts @@ -0,0 +1,70 @@ +import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { TranslateModule } from '@ngx-translate/core'; +import { DebugElement, NO_ERRORS_SCHEMA } from '@angular/core'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { SupervisionGroupSelectorComponent } from './supervision-group-selector.component'; +import { SupervisionOrderDataService } from '../../../../core/supervision-order/supervision-order-data.service'; +import { NotificationsService } from '../../../../shared/notifications/notifications.service'; +import { Group } from '../../../../core/eperson/models/group.model'; +import { SupervisionOrder } from '../../../../core/supervision-order/models/supervision-order.model'; +import { of } from 'rxjs'; + +describe('SupervisionGroupSelectorComponent', () => { + let component: SupervisionGroupSelectorComponent; + let fixture: ComponentFixture; + let debugElement: DebugElement; + + const modalStub = jasmine.createSpyObj('modalStub', ['close']); + + const supervisionOrderDataService: any = jasmine.createSpyObj('supervisionOrderDataService', { + create: of(new SupervisionOrder()) + }); + + const selectedOrderType = 'NONE'; + const itemUUID = 'itemUUID1234'; + + const selectedGroup = new Group(); + selectedGroup.uuid = 'GroupUUID1234'; + + const supervisionDataObject = new SupervisionOrder(); + supervisionDataObject.ordertype = selectedOrderType; + + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot()], + declarations: [SupervisionGroupSelectorComponent], + providers: [ + { provide: NgbActiveModal, useValue: modalStub }, + { provide: SupervisionOrderDataService, useValue: supervisionOrderDataService }, + { provide: NotificationsService, useValue: {} }, + ], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents(); + + })); + + beforeEach(waitForAsync(() => { + fixture = TestBed.createComponent(SupervisionGroupSelectorComponent); + component = fixture.componentInstance; + + })); + + beforeEach(() => { + component.itemUUID = itemUUID; + component.selectedGroup = selectedGroup; + component.selectedOrderType = selectedOrderType; + debugElement = fixture.debugElement; + fixture.detectChanges(); + }); + + it('should create component', () => { + expect(component).toBeTruthy(); + }); + + it('should call create for supervision order', () => { + component.save(); + fixture.detectChanges(); + expect(supervisionOrderDataService.create).toHaveBeenCalledWith(supervisionDataObject, itemUUID, selectedGroup.uuid, selectedOrderType); + }); + +}); 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 new file mode 100644 index 0000000000..c69c5d5177 --- /dev/null +++ b/src/app/shared/dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component.ts @@ -0,0 +1,90 @@ +import { Component } from '@angular/core'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateService } from '@ngx-translate/core'; +import { getFirstCompletedRemoteData } from 'src/app/core/shared/operators'; +import { NotificationsService } from 'src/app/shared/notifications/notifications.service'; +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'; + +/** + * Component to wrap a dropdown - for type of order - + * and a list of groups + * inside a modal + * Used to create a new supervision order + */ + +@Component({ + selector: 'ds-supervision-group-selector', + styleUrls: ['./supervision-group-selector.component.scss'], + templateUrl: './supervision-group-selector.component.html', +}) +export class SupervisionGroupSelectorComponent { + + /** + * The item to perform the actions on + */ + itemUUID: string; + + /** + * The selected supervision order type + */ + selectedOrderType: string; + + /** + * selected group for supervision + */ + selectedGroup: Group; + + /** + * boolean flag for the validations + */ + isSubmitted = false; + + constructor( + public dsoNameService: DSONameService, + private activeModal: NgbActiveModal, + private supervisionOrderDataService: SupervisionOrderDataService, + protected notificationsService: NotificationsService, + protected translateService: TranslateService, + ) { } + + /** + * Close the modal + */ + close() { + this.activeModal.close(); + } + + /** + * Assign the value of group on select + */ + updateGroupObjectSelected(object) { + this.selectedGroup = object; + } + + /** + * Save the supervision order + */ + save() { + this.isSubmitted = true; + if (this.selectedOrderType && this.selectedGroup) { + let supervisionDataObject = new SupervisionOrder(); + supervisionDataObject.ordertype = this.selectedOrderType; + this.supervisionOrderDataService.create(supervisionDataObject, this.itemUUID, this.selectedGroup.uuid, this.selectedOrderType).pipe( + getFirstCompletedRemoteData(), + ).subscribe(rd => { + if (rd.state === 'Success') { + this.notificationsService.success(this.translateService.get('supervision-group-selector.notification.create.success.title', { name: this.selectedGroup.name })); + } else { + this.notificationsService.error( + this.translateService.get('supervision-group-selector.notification.create.failure.title'), + rd.errorMessage); + } + }); + this.close(); + } + } + +} diff --git a/src/app/shared/resource-policies/form/eperson-group-list/eperson-group-list.component.html b/src/app/shared/form/eperson-group-list/eperson-group-list.component.html similarity index 100% rename from src/app/shared/resource-policies/form/eperson-group-list/eperson-group-list.component.html rename to src/app/shared/form/eperson-group-list/eperson-group-list.component.html diff --git a/src/app/shared/form/eperson-group-list/eperson-group-list.component.scss b/src/app/shared/form/eperson-group-list/eperson-group-list.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/shared/resource-policies/form/eperson-group-list/eperson-group-list.component.spec.ts b/src/app/shared/form/eperson-group-list/eperson-group-list.component.spec.ts similarity index 88% rename from src/app/shared/resource-policies/form/eperson-group-list/eperson-group-list.component.spec.ts rename to src/app/shared/form/eperson-group-list/eperson-group-list.component.spec.ts index cec67e721c..399080c0ef 100644 --- a/src/app/shared/resource-policies/form/eperson-group-list/eperson-group-list.component.spec.ts +++ b/src/app/shared/form/eperson-group-list/eperson-group-list.component.spec.ts @@ -6,21 +6,21 @@ import { TranslateModule } from '@ngx-translate/core'; import { cold } from 'jasmine-marbles'; import uniqueId from 'lodash/uniqueId'; -import { createSuccessfulRemoteDataObject } from '../../../remote-data.utils'; -import { createTestComponent } from '../../../testing/utils.test'; -import { EPersonDataService } from '../../../../core/eperson/eperson-data.service'; -import { GroupDataService } from '../../../../core/eperson/group-data.service'; -import { RequestService } from '../../../../core/data/request.service'; -import { getMockRequestService } from '../../../mocks/request.service.mock'; +import { createSuccessfulRemoteDataObject } from '../../remote-data.utils'; +import { createTestComponent } from '../../testing/utils.test'; +import { EPersonDataService } from '../../../core/eperson/eperson-data.service'; +import { GroupDataService } from '../../../core/eperson/group-data.service'; +import { RequestService } from '../../../core/data/request.service'; +import { getMockRequestService } from '../../mocks/request.service.mock'; import { EpersonGroupListComponent, SearchEvent } from './eperson-group-list.component'; -import { EPersonMock } from '../../../testing/eperson.mock'; -import { GroupMock } from '../../../testing/group-mock'; -import { PaginationComponentOptions } from '../../../pagination/pagination-component-options.model'; -import { buildPaginatedList } from '../../../../core/data/paginated-list.model'; -import { PageInfo } from '../../../../core/shared/page-info.model'; +import { EPersonMock } from '../../testing/eperson.mock'; +import { GroupMock } from '../../testing/group-mock'; +import { PaginationComponentOptions } from '../../pagination/pagination-component-options.model'; +import { buildPaginatedList } from '../../../core/data/paginated-list.model'; +import { PageInfo } from '../../../core/shared/page-info.model'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { PaginationService } from '../../../../core/pagination/pagination.service'; -import { PaginationServiceStub } from '../../../testing/pagination-service.stub'; +import { PaginationService } from '../../../core/pagination/pagination.service'; +import { PaginationServiceStub } from '../../testing/pagination-service.stub'; describe('EpersonGroupListComponent test suite', () => { let comp: EpersonGroupListComponent; diff --git a/src/app/shared/resource-policies/form/eperson-group-list/eperson-group-list.component.ts b/src/app/shared/form/eperson-group-list/eperson-group-list.component.ts similarity index 81% rename from src/app/shared/resource-policies/form/eperson-group-list/eperson-group-list.component.ts rename to src/app/shared/form/eperson-group-list/eperson-group-list.component.ts index b859184845..e2b56859dc 100644 --- a/src/app/shared/resource-policies/form/eperson-group-list/eperson-group-list.component.ts +++ b/src/app/shared/form/eperson-group-list/eperson-group-list.component.ts @@ -4,22 +4,22 @@ import { BehaviorSubject, Observable, Subscription } from 'rxjs'; import { map } from 'rxjs/operators'; import uniqueId from 'lodash/uniqueId'; -import { RemoteData } from '../../../../core/data/remote-data'; -import { PaginatedList } from '../../../../core/data/paginated-list.model'; -import { DSpaceObject } from '../../../../core/shared/dspace-object.model'; -import { PaginationComponentOptions } from '../../../pagination/pagination-component-options.model'; -import { hasValue, isNotEmpty } from '../../../empty.util'; -import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service'; -import { EPERSON } from '../../../../core/eperson/models/eperson.resource-type'; -import { GROUP } from '../../../../core/eperson/models/group.resource-type'; -import { ResourceType } from '../../../../core/shared/resource-type'; -import { EPersonDataService } from '../../../../core/eperson/eperson-data.service'; -import { GroupDataService } from '../../../../core/eperson/group-data.service'; -import { fadeInOut } from '../../../animations/fade'; -import { getFirstCompletedRemoteData } from '../../../../core/shared/operators'; -import { PaginationService } from '../../../../core/pagination/pagination.service'; -import { FindListOptions } from '../../../../core/data/find-list-options.model'; -import { getDataServiceFor } from '../../../../core/data/base/data-service.decorator'; +import { RemoteData } from '../../../core/data/remote-data'; +import { PaginatedList } from '../../../core/data/paginated-list.model'; +import { DSpaceObject } from '../../../core/shared/dspace-object.model'; +import { PaginationComponentOptions } from '../../pagination/pagination-component-options.model'; +import { hasValue, isNotEmpty } from '../../empty.util'; +import { DSONameService } from '../../../core/breadcrumbs/dso-name.service'; +import { EPERSON } from '../../../core/eperson/models/eperson.resource-type'; +import { GROUP } from '../../../core/eperson/models/group.resource-type'; +import { ResourceType } from '../../../core/shared/resource-type'; +import { EPersonDataService } from '../../../core/eperson/eperson-data.service'; +import { GroupDataService } from '../../../core/eperson/group-data.service'; +import { fadeInOut } from '../../animations/fade'; +import { getFirstCompletedRemoteData } from '../../../core/shared/operators'; +import { PaginationService } from '../../../core/pagination/pagination.service'; +import { FindListOptions } from '../../../core/data/find-list-options.model'; +import { getDataServiceFor } from '../../../core/data/base/data-service.decorator'; export interface SearchEvent { scope: string; diff --git a/src/app/shared/resource-policies/form/eperson-group-list/eperson-search-box/eperson-search-box.component.html b/src/app/shared/form/eperson-group-list/eperson-search-box/eperson-search-box.component.html similarity index 100% rename from src/app/shared/resource-policies/form/eperson-group-list/eperson-search-box/eperson-search-box.component.html rename to src/app/shared/form/eperson-group-list/eperson-search-box/eperson-search-box.component.html diff --git a/src/app/shared/resource-policies/form/eperson-group-list/eperson-search-box/eperson-search-box.component.spec.ts b/src/app/shared/form/eperson-group-list/eperson-search-box/eperson-search-box.component.spec.ts similarity index 97% rename from src/app/shared/resource-policies/form/eperson-group-list/eperson-search-box/eperson-search-box.component.spec.ts rename to src/app/shared/form/eperson-group-list/eperson-search-box/eperson-search-box.component.spec.ts index 311d911b26..db16af5edf 100644 --- a/src/app/shared/resource-policies/form/eperson-group-list/eperson-search-box/eperson-search-box.component.spec.ts +++ b/src/app/shared/form/eperson-group-list/eperson-search-box/eperson-search-box.component.spec.ts @@ -4,7 +4,7 @@ import { FormBuilder, FormsModule, ReactiveFormsModule } from '@angular/forms'; import { TranslateModule } from '@ngx-translate/core'; -import { createTestComponent } from '../../../../testing/utils.test'; +import { createTestComponent } from '../../../testing/utils.test'; import { EpersonSearchBoxComponent } from './eperson-search-box.component'; import { SearchEvent } from '../eperson-group-list.component'; diff --git a/src/app/shared/resource-policies/form/eperson-group-list/eperson-search-box/eperson-search-box.component.ts b/src/app/shared/form/eperson-group-list/eperson-search-box/eperson-search-box.component.ts similarity index 96% rename from src/app/shared/resource-policies/form/eperson-group-list/eperson-search-box/eperson-search-box.component.ts rename to src/app/shared/form/eperson-group-list/eperson-search-box/eperson-search-box.component.ts index 11c3dcd102..6ae3200d0b 100644 --- a/src/app/shared/resource-policies/form/eperson-group-list/eperson-search-box/eperson-search-box.component.ts +++ b/src/app/shared/form/eperson-group-list/eperson-search-box/eperson-search-box.component.ts @@ -4,7 +4,7 @@ import { FormBuilder } from '@angular/forms'; import { Subscription } from 'rxjs'; import { SearchEvent } from '../eperson-group-list.component'; -import { isNotNull } from '../../../../empty.util'; +import { isNotNull } from '../../../empty.util'; /** * A component used to show a search box for epersons. diff --git a/src/app/shared/resource-policies/form/eperson-group-list/group-search-box/group-search-box.component.html b/src/app/shared/form/eperson-group-list/group-search-box/group-search-box.component.html similarity index 100% rename from src/app/shared/resource-policies/form/eperson-group-list/group-search-box/group-search-box.component.html rename to src/app/shared/form/eperson-group-list/group-search-box/group-search-box.component.html diff --git a/src/app/shared/resource-policies/form/eperson-group-list/group-search-box/group-search-box.component.spec.ts b/src/app/shared/form/eperson-group-list/group-search-box/group-search-box.component.spec.ts similarity index 97% rename from src/app/shared/resource-policies/form/eperson-group-list/group-search-box/group-search-box.component.spec.ts rename to src/app/shared/form/eperson-group-list/group-search-box/group-search-box.component.spec.ts index dc39e30d3b..17e96fc71c 100644 --- a/src/app/shared/resource-policies/form/eperson-group-list/group-search-box/group-search-box.component.spec.ts +++ b/src/app/shared/form/eperson-group-list/group-search-box/group-search-box.component.spec.ts @@ -4,7 +4,7 @@ import { FormBuilder, FormsModule, ReactiveFormsModule } from '@angular/forms'; import { TranslateModule } from '@ngx-translate/core'; -import { createTestComponent } from '../../../../testing/utils.test'; +import { createTestComponent } from '../../../testing/utils.test'; import { GroupSearchBoxComponent } from './group-search-box.component'; import { SearchEvent } from '../eperson-group-list.component'; diff --git a/src/app/shared/resource-policies/form/eperson-group-list/group-search-box/group-search-box.component.ts b/src/app/shared/form/eperson-group-list/group-search-box/group-search-box.component.ts similarity index 96% rename from src/app/shared/resource-policies/form/eperson-group-list/group-search-box/group-search-box.component.ts rename to src/app/shared/form/eperson-group-list/group-search-box/group-search-box.component.ts index baef19f14a..ad181bdb64 100644 --- a/src/app/shared/resource-policies/form/eperson-group-list/group-search-box/group-search-box.component.ts +++ b/src/app/shared/form/eperson-group-list/group-search-box/group-search-box.component.ts @@ -4,7 +4,7 @@ import { FormBuilder } from '@angular/forms'; import { Subscription } from 'rxjs'; import { SearchEvent } from '../eperson-group-list.component'; -import { isNotNull } from '../../../../empty.util'; +import { isNotNull } from '../../../empty.util'; /** * A component used to show a search box for groups. diff --git a/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.html b/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.html index 6b2951495d..64108681f6 100644 --- a/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.html +++ b/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.html @@ -41,6 +41,19 @@ [innerHTML]="firstMetadataValue('dc.description.abstract')"> + +
+
+ {{'item.search.result.list.element.supervised-by' | translate}} +
+
+ + {{supervisionOrder.group._name}} + X + +
+
+
diff --git a/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.scss b/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.scss index 5e4536cf95..0d93ec744b 100644 --- a/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.scss +++ b/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.scss @@ -1 +1,7 @@ @import '../../../../../../../styles/variables'; + +.item-list-supervision { + a { + cursor: pointer; + } +} \ No newline at end of file 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 d1e6c27ba4..887ecb30a0 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 @@ -10,6 +10,14 @@ import { ItemSearchResult } from '../../../../../object-collection/shared/item-s import { DSONameService } from '../../../../../../core/breadcrumbs/dso-name.service'; import { DSONameServiceMock, UNDEFINED_NAME } from '../../../../../mocks/dso-name.service.mock'; 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 { 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'; let publicationListElementComponent: ItemSearchResultListElementComponent; let fixture: ComponentFixture; @@ -72,12 +80,61 @@ const enviromentNoThumbs = { } }; +const supervisionOrderDataService: any = jasmine.createSpyObj('supervisionOrderDataService', { + searchByItem: jasmine.createSpy('searchByItem'), +}); + +const supervisionOrder: any = { + id: '1', + type: 'supervisionOrder', + uuid: 'supervision-order-1', + _links: { + item: { + href: 'https://rest.api/rest/api/eperson' + }, + group: { + href: 'https://rest.api/rest/api/group' + }, + self: { + href: 'https://rest.api/rest/api/supervisionorders/1' + }, + }, + item: observableOf(createSuccessfulRemoteDataObject({})), + group: observableOf(createSuccessfulRemoteDataObject(GroupMock)) +}; +const anothersupervisionOrder: any = { + id: '2', + type: 'supervisionOrder', + uuid: 'supervision-order-2', + _links: { + item: { + href: 'https://rest.api/rest/api/eperson' + }, + group: { + href: 'https://rest.api/rest/api/group' + }, + self: { + href: 'https://rest.api/rest/api/supervisionorders/1' + }, + }, + item: observableOf(createSuccessfulRemoteDataObject({})), + group: observableOf(createSuccessfulRemoteDataObject(GroupMock)) +}; + +const pageInfo = new PageInfo(); +const array = [supervisionOrder, anothersupervisionOrder]; +const paginatedList = buildPaginatedList(pageInfo, array); +const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); + describe('ItemSearchResultListElementComponent', () => { beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [ItemSearchResultListElementComponent, TruncatePipe], providers: [ { provide: TruncatableService, useValue: {} }, + { provide: SupervisionOrderDataService, useValue: supervisionOrderDataService }, + { provide: NotificationsService, useValue: {}}, + { provide: TranslateService, useValue: {}}, { provide: DSONameService, useClass: DSONameServiceMock }, { provide: APP_CONFIG, useValue: environmentUseThumbs } ], @@ -89,6 +146,9 @@ describe('ItemSearchResultListElementComponent', () => { })); beforeEach(waitForAsync(() => { + supervisionOrderDataService.searchByItem.and.returnValue(hot('a|', { + a: paginatedListRD + })); fixture = TestBed.createComponent(ItemSearchResultListElementComponent); publicationListElementComponent = fixture.componentInstance; @@ -225,6 +285,9 @@ describe('ItemSearchResultListElementComponent', () => { declarations: [ItemSearchResultListElementComponent, TruncatePipe], providers: [ {provide: TruncatableService, useValue: {}}, + {provide: SupervisionOrderDataService, useValue: supervisionOrderDataService }, + {provide: NotificationsService, useValue: {}}, + {provide: TranslateService, useValue: {}}, {provide: DSONameService, useClass: DSONameServiceMock}, { provide: APP_CONFIG, useValue: enviromentNoThumbs } ], @@ -236,6 +299,9 @@ describe('ItemSearchResultListElementComponent', () => { })); beforeEach(waitForAsync(() => { + supervisionOrderDataService.searchByItem.and.returnValue(hot('a|', { + a: paginatedListRD + })); fixture = TestBed.createComponent(ItemSearchResultListElementComponent); publicationListElementComponent = fixture.componentInstance; })); 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 f84ae642ad..b1b5b0d1a7 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 @@ -1,10 +1,24 @@ -import { Component } from '@angular/core'; +import { Component, Inject } from '@angular/core'; import { listableObjectComponent } from '../../../../../object-collection/shared/listable-object/listable-object.decorator'; import { ViewMode } from '../../../../../../core/shared/view-mode.model'; import { ItemSearchResult } from '../../../../../object-collection/shared/item-search-result.model'; import { SearchResultListElementComponent } from '../../../search-result-list-element.component'; import { Item } from '../../../../../../core/shared/item.model'; import { getItemPageRoute } from '../../../../../../item-page/item-page-routing-paths'; +import { SupervisionOrderDataService } from '../../../../../../core/supervision-order/supervision-order-data.service'; +import { TruncatableService } from '../../../../../../shared/truncatable/truncatable.service'; +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 { ConfirmationModalComponent } from '../../../../../../shared/confirmation-modal/confirmation-modal.component'; +import { hasValue } from '../../../../../../shared/empty.util'; +import { NotificationsService } from '../../../../../../shared/notifications/notifications.service'; +import { TranslateService } from '@ngx-translate/core'; +import { followLink } from '../../../../../../shared/utils/follow-link-config.model'; +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'; @listableObjectComponent('PublicationSearchResult', ViewMode.ListElement) @listableObjectComponent(ItemSearchResult, ViewMode.ListElement) @@ -17,6 +31,8 @@ import { getItemPageRoute } from '../../../../../../item-page/item-page-routing- * The component for displaying a list element for an item search result of the type Publication */ export class ItemSearchResultListElementComponent extends SearchResultListElementComponent { + messagePrefix = 'item.search.result'; + /** * Route to the item's page */ @@ -27,9 +43,67 @@ export class ItemSearchResultListElementComponent extends SearchResultListElemen */ showThumbnails: boolean; + /** + * List of the supervision orders combined with the group + */ + supervisionOrder$: Observable<{ supervisionOrder: SupervisionOrder; group: Group; }[]>; + + constructor( + protected truncatableService: TruncatableService, + protected dsoNameService: DSONameService, + @Inject(APP_CONFIG) protected appConfig: AppConfig, + protected supervisionOrderDataService: SupervisionOrderDataService, + protected modalService: NgbModal, + protected notificationsService: NotificationsService, + protected translateService: TranslateService, + ) { super(truncatableService, dsoNameService, appConfig); } + ngOnInit(): void { super.ngOnInit(); this.showThumbnails = this.appConfig.browseBy.showThumbnails; 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); + }) + ); + } + + /** + * Deletes the Group from the Repository. The Group will be the only that this form is showing. + * It'll either show a success or error message depending on whether the delete was successful or not. + */ + deleteSupervisionOrder(supervisionOrder) { + const modalRef = this.modalService.open(ConfirmationModalComponent); + modalRef.componentInstance.dso = supervisionOrder.group; + modalRef.componentInstance.headerLabel = this.messagePrefix + '.delete-supervision.modal.header'; + modalRef.componentInstance.infoLabel = this.messagePrefix + '.delete-supervision.modal.info'; + modalRef.componentInstance.cancelLabel = this.messagePrefix + '.delete-supervision.modal.cancel'; + modalRef.componentInstance.confirmLabel = this.messagePrefix + '.delete-supervision.modal.confirm'; + modalRef.componentInstance.brandColor = 'danger'; + modalRef.componentInstance.confirmIcon = 'fas fa-trash'; + modalRef.componentInstance.response.pipe(take(1)).subscribe((confirm: boolean) => { + if (confirm) { + if (hasValue(supervisionOrder.supervisionOrder.id)) { + this.supervisionOrderDataService.delete(supervisionOrder.supervisionOrder.id) + .subscribe((rd: boolean) => { + if (rd) { + this.notificationsService.success(this.translateService.get(this.messagePrefix + '.notification.deleted.success', { name: supervisionOrder.group._name })); + } else { + this.notificationsService.error( + this.translateService.get(this.messagePrefix + '.notification.deleted.failure.title', { name: supervisionOrder.group._name }), + this.translateService.get(this.messagePrefix + '.notification.deleted.failure.content')); + } + }); + } + } + }); } } diff --git a/src/app/shared/resource-policies/form/resource-policy-form.component.spec.ts b/src/app/shared/resource-policies/form/resource-policy-form.component.spec.ts index e555522c79..1a84270f1b 100644 --- a/src/app/shared/resource-policies/form/resource-policy-form.component.spec.ts +++ b/src/app/shared/resource-policies/form/resource-policy-form.component.spec.ts @@ -24,7 +24,7 @@ import { ResourcePolicyEvent, ResourcePolicyFormComponent } from './resource-pol import { FormService } from '../../form/form.service'; import { getMockFormService } from '../../mocks/form-service.mock'; import { FormBuilderService } from '../../form/builder/form-builder.service'; -import { EpersonGroupListComponent } from './eperson-group-list/eperson-group-list.component'; +import { EpersonGroupListComponent } from '../../form/eperson-group-list/eperson-group-list.component'; import { FormComponent } from '../../form/form.component'; import { stringToNgbDateStruct, dateToISOFormat } from '../../date.util'; import { ResourcePolicy } from '../../../core/resource-policy/models/resource-policy.model'; diff --git a/src/app/shared/resource-policies/resource-policies.module.ts b/src/app/shared/resource-policies/resource-policies.module.ts index a7dc19b83e..8a7f6dca79 100644 --- a/src/app/shared/resource-policies/resource-policies.module.ts +++ b/src/app/shared/resource-policies/resource-policies.module.ts @@ -10,9 +10,6 @@ import { ResourcePolicyCreateComponent } from './create/resource-policy-create.c import { FormModule } from '../form/form.module'; import { ResourcePolicyResolver } from './resolvers/resource-policy.resolver'; import { ResourcePolicyTargetResolver } from './resolvers/resource-policy-target.resolver'; -import { EpersonGroupListComponent } from './form/eperson-group-list/eperson-group-list.component'; -import { GroupSearchBoxComponent } from './form/eperson-group-list/group-search-box/group-search-box.component'; -import { EpersonSearchBoxComponent } from './form/eperson-group-list/eperson-search-box/eperson-search-box.component'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { SharedModule } from '../shared.module'; import { ResourcePolicyEntryComponent } from './entry/resource-policy-entry.component'; @@ -23,9 +20,6 @@ const COMPONENTS = [ ResourcePolicyFormComponent, ResourcePolicyEditComponent, ResourcePolicyCreateComponent, - EpersonGroupListComponent, - EpersonSearchBoxComponent, - GroupSearchBoxComponent ]; const PROVIDERS = [ diff --git a/src/app/shared/search/search.component.ts b/src/app/shared/search/search.component.ts index c094e37ef2..e9a72ae338 100644 --- a/src/app/shared/search/search.component.ts +++ b/src/app/shared/search/search.component.ts @@ -34,6 +34,7 @@ import { CollectionElementLinkType } from '../object-collection/collection-eleme import { environment } from 'src/environments/environment'; import { SubmissionObject } from '../../core/submission/models/submission-object.model'; import { SearchFilterConfig } from './models/search-filter-config.model'; +import { WorkspaceItem } from '../..//core/submission/models/workspaceitem.model'; @Component({ selector: 'ds-search', @@ -405,8 +406,9 @@ export class SearchComponent implements OnInit { true, followLink('thumbnail', { isOptional: true }), followLink('item', { isOptional: true }, followLink('thumbnail', { isOptional: true })) as any, - followLink('accessStatus', { isOptional: true, shouldEmbed: environment.item.showAccessStatuses }) - ).pipe(getFirstCompletedRemoteData()) + followLink('supervisionOrders', { isOptional: true }) as any, + followLink('accessStatus', { isOptional: true, shouldEmbed: environment.item.showAccessStatuses }), + ).pipe(getFirstCompletedRemoteData()) .subscribe((results: RemoteData>) => { if (results.hasSucceeded) { if (this.trackStatistics) { diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index 13fdd3e12c..bd87b35c82 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -315,6 +315,10 @@ import { MenuModule } from './menu/menu.module'; import { ListableNotificationObjectComponent } from './object-list/listable-notification-object/listable-notification-object.component'; +import { SupervisionGroupSelectorComponent } from './dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component'; +import { EpersonGroupListComponent } from './form/eperson-group-list/eperson-group-list.component'; +import { EpersonSearchBoxComponent } from './form/eperson-group-list/eperson-search-box/eperson-search-box.component'; +import { GroupSearchBoxComponent } from './form/eperson-group-list/group-search-box/group-search-box.component'; const MODULES = [ CommonModule, @@ -436,6 +440,10 @@ const COMPONENTS = [ ItemPageTitleFieldComponent, ThemedSearchNavbarComponent, ListableNotificationObjectComponent, + EpersonGroupListComponent, + EpersonSearchBoxComponent, + GroupSearchBoxComponent, + SupervisionGroupSelectorComponent ]; const ENTRY_COMPONENTS = [ @@ -498,6 +506,10 @@ const ENTRY_COMPONENTS = [ CommunitySidebarSearchListElementComponent, ScopeSelectorModalComponent, ListableNotificationObjectComponent, + EpersonGroupListComponent, + EpersonSearchBoxComponent, + GroupSearchBoxComponent, + SupervisionGroupSelectorComponent ]; const SHARED_ITEM_PAGE_COMPONENTS = [ diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index d043d61ae5..26f9983c17 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -536,10 +536,16 @@ "admin.workflow.item.workflow": "Workflow", + "admin.workflow.item.workspace": "Workspace", + "admin.workflow.item.delete": "Delete", "admin.workflow.item.send-back": "Send back", + "admin.workflow.item.policies": "Policies", + + "admin.workflow.item.supervision": "Supervision", + "admin.metadata-import.breadcrumbs": "Import Metadata", @@ -1418,6 +1424,28 @@ "dso-selector.results-could-not-be-retrieved": "Something went wrong, please refresh again ↻", + "supervision-group-selector.header": "Supervision Group Selector", + + "supervision-group-selector.select.type-of-order.label": "Select a type of Order", + + "supervision-group-selector.select.type-of-order.option.none": "NONE", + + "supervision-group-selector.select.type-of-order.option.editor": "EDITOR", + + "supervision-group-selector.select.type-of-order.option.observer": "OBSERVER", + + "supervision-group-selector.select.group.label": "Select a Group", + + "supervision-group-selector.button.save": "Save", + + "supervision-group-selector.select.type-of-order.error": "Please select a type of order", + + "supervision-group-selector.select.group.error": "Please select a group", + + "supervision-group-selector.notification.create.success.title": "Successfully created supervision order for group {{ name }}", + + "supervision-group-selector.notification.create.failure.title": "Error", + "confirmation-modal.export-metadata.header": "Export metadata for {{ dsoName }}", "confirmation-modal.export-metadata.info": "Are you sure you want to export metadata for {{ dsoName }}", @@ -2222,6 +2250,22 @@ "item.truncatable-part.show-less": "Collapse", + "item.search.result.delete-supervision.modal.header": "Delete Supervision Order", + + "item.search.result.delete-supervision.modal.info": "Are you sure you want to delete Supervision Order", + + "item.search.result.delete-supervision.modal.cancel": "Cancel", + + "item.search.result.delete-supervision.modal.confirm": "Delete", + + "item.search.result.notification.deleted.success": "Successfully deleted supervision order \"{{name}}\"", + + "item.search.result.notification.deleted.failure.title": "Failed to delete supervision order \"{{name}}\"", + + "item.search.result.notification.deleted.failure.content": "Failed to delete supervision order", + + "item.search.result.list.element.supervised-by": "Supervised by:", + "item.page.abstract": "Abstract", @@ -2851,6 +2895,8 @@ "mydspace.show.workspace": "Your Submissions", + "mydspace.show.otherworkspace": "Supervised items", + "mydspace.status.archived": "Archived", "mydspace.status.validation": "Validation", @@ -3640,6 +3686,12 @@ "search.filters.filter.submitter.label": "Search submitter", + "search.filters.filter.supervisedBy.head": "Supervised By", + + "search.filters.filter.supervisedBy.placeholder": "Supervised By", + + "search.filters.filter.supervisedBy.label": "Search Supervised By", + "search.filters.entityType.JournalIssue": "Journal Issue", @@ -4534,12 +4586,16 @@ + "otherworkspace.search.results.head": "Supervised Items", + "workspace.search.results.head": "Your submissions", "workflowAdmin.search.results.head": "Administer Workflow", "workflow.search.results.head": "Workflow tasks", + "supervision.search.results.head": "Supervision tasks", + "workflow-item.edit.breadcrumbs": "Edit workflowitem", From 69390a71723326783a137e5cac8410832759fcfd Mon Sep 17 00:00:00 2001 From: corrado lombardi Date: Fri, 30 Dec 2022 16:05:39 +0100 Subject: [PATCH 02/10] [CST-7755] Updated label and made other workspace items option available to controllers --- .../my-dspace-page/my-dspace-configuration.service.spec.ts | 5 +++-- src/app/my-dspace-page/my-dspace-configuration.service.ts | 2 +- src/assets/i18n/en.json5 | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/app/my-dspace-page/my-dspace-configuration.service.spec.ts b/src/app/my-dspace-page/my-dspace-configuration.service.spec.ts index 34bfd946b6..c388d2d356 100644 --- a/src/app/my-dspace-page/my-dspace-configuration.service.spec.ts +++ b/src/app/my-dspace-page/my-dspace-configuration.service.spec.ts @@ -184,8 +184,7 @@ describe('MyDSpaceConfigurationService', () => { expect(list$).toBeObservable(cold('(b|)', { b: [ - MyDSpaceConfigurationValueType.Workspace, - MyDSpaceConfigurationValueType.SupervisedItems + MyDSpaceConfigurationValueType.Workspace ] })); }); @@ -199,6 +198,7 @@ describe('MyDSpaceConfigurationService', () => { expect(list$).toBeObservable(cold('(b|)', { b: [ + MyDSpaceConfigurationValueType.SupervisedItems, MyDSpaceConfigurationValueType.Workflow ] })); @@ -213,6 +213,7 @@ describe('MyDSpaceConfigurationService', () => { expect(list$).toBeObservable(cold('(b|)', { b: [ + MyDSpaceConfigurationValueType.SupervisedItems, MyDSpaceConfigurationValueType.Workflow ] })); diff --git a/src/app/my-dspace-page/my-dspace-configuration.service.ts b/src/app/my-dspace-page/my-dspace-configuration.service.ts index 86bbf0050c..bc18e0cc18 100644 --- a/src/app/my-dspace-page/my-dspace-configuration.service.ts +++ b/src/app/my-dspace-page/my-dspace-configuration.service.ts @@ -108,9 +108,9 @@ export class MyDSpaceConfigurationService extends SearchConfigurationService { const availableConf: MyDSpaceConfigurationValueType[] = []; if (isSubmitter) { availableConf.push(MyDSpaceConfigurationValueType.Workspace); - availableConf.push(MyDSpaceConfigurationValueType.SupervisedItems); } if (isController || isAdmin) { + availableConf.push(MyDSpaceConfigurationValueType.SupervisedItems); availableConf.push(MyDSpaceConfigurationValueType.Workflow); } return availableConf; diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 26f9983c17..436d667c8c 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -4594,7 +4594,7 @@ "workflow.search.results.head": "Workflow tasks", - "supervision.search.results.head": "Supervision tasks", + "supervision.search.results.head": "Workflow and Workspace tasks", From 81696dfd04f915986f0ae9ba54686821bb1392d0 Mon Sep 17 00:00:00 2001 From: Sufiyan Shaikh Date: Wed, 4 Jan 2023 13:12:57 +0530 Subject: [PATCH 03/10] [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) { From 4d2522a69aa4758c50cd0d0e397b4eab0f32370d Mon Sep 17 00:00:00 2001 From: Sufiyan Shaikh Date: Thu, 12 Jan 2023 19:00:44 +0530 Subject: [PATCH 04/10] [CST-7755] Build Failded Fixed --- ...search-result-list-element.component.spec.ts | 17 ++++++++++++++--- ...search-result-list-element.component.spec.ts | 17 ++++++++++++++--- ...search-result-list-element.component.spec.ts | 16 +++++++++++++--- ...search-result-list-element.component.spec.ts | 16 +++++++++++++--- ...search-result-list-element.component.spec.ts | 16 +++++++++++++--- ...search-result-list-element.component.spec.ts | 17 ++++++++++++++--- 6 files changed, 81 insertions(+), 18 deletions(-) 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 9f8963b60b..3a0e73e46c 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 @@ -13,7 +13,7 @@ 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'; @@ -24,6 +24,8 @@ import { EPersonDataService } from '../../../../../core/eperson/eperson-data.ser 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 '../../../../../core/eperson/models/eperson.model'; +import { createPaginatedList } from '../../../../../shared/testing/utils.test'; let journalIssueListElementComponent: JournalIssueSearchResultListElementComponent; let fixture: ComponentFixture; @@ -37,6 +39,15 @@ const authService: AuthServiceStub = Object.assign(new AuthServiceStub(), { } }); +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(), { @@ -150,7 +161,7 @@ describe('JournalIssueSearchResultListElementComponent', () => { { provide: TranslateService, useValue: {}}, { provide: ResourcePolicyDataService, useValue: {}}, { provide: AuthService, useValue: authService}, - { provide: EPersonDataService, useValue: {}}, + { provide: EPersonDataService, useValue: epersonService}, { provide: AuthorizationDataService, useValue: authorizationService}, { provide: DSONameService, useClass: DSONameServiceMock }, { provide: APP_CONFIG, useValue: environmentUseThumbs } @@ -248,7 +259,7 @@ describe('JournalIssueSearchResultListElementComponent', () => { {provide: TranslateService, useValue: {}}, {provide: ResourcePolicyDataService, useValue: {}}, {provide: AuthService, useValue: authService}, - {provide: EPersonDataService, useValue: {}}, + {provide: EPersonDataService, useValue: epersonService}, {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 03c0151693..67665403d1 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 @@ -13,7 +13,7 @@ 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'; @@ -24,6 +24,8 @@ import { EPersonDataService } from '../../../../../core/eperson/eperson-data.ser 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'; +import { EPerson } from '../../../../../core/eperson/models/eperson.model'; +import { createPaginatedList } from '../../../../../shared/testing/utils.test'; let journalVolumeListElementComponent: JournalVolumeSearchResultListElementComponent; let fixture: ComponentFixture; @@ -36,6 +38,15 @@ const authService: AuthServiceStub = Object.assign(new AuthServiceStub(), { 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(), { @@ -148,7 +159,7 @@ describe('JournalVolumeSearchResultListElementComponent', () => { { provide: TranslateService, useValue: {}}, { provide: ResourcePolicyDataService, useValue: {}}, { provide: AuthService, useValue: authService}, - { provide: EPersonDataService, useValue: {}}, + { provide: EPersonDataService, useValue: epersonService}, { provide: AuthorizationDataService, useValue: authorizationService}, { provide: DSONameService, useClass: DSONameServiceMock }, { provide: APP_CONFIG, useValue: environmentUseThumbs } @@ -245,7 +256,7 @@ describe('JournalVolumeSearchResultListElementComponent', () => { {provide: TranslateService, useValue: {}}, {provide: ResourcePolicyDataService, useValue: {}}, {provide: AuthService, useValue: authService}, - {provide: EPersonDataService, useValue: {}}, + {provide: EPersonDataService, useValue: epersonService}, {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 bc1a560613..63e8abda28 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 @@ -13,7 +13,7 @@ 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'; @@ -24,6 +24,8 @@ import { AuthorizationDataService } from '../../../../../core/data/feature-autho 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'; +import { EPerson } from '../../../../../core/eperson/models/eperson.model'; +import { createPaginatedList } from '../../../../../shared/testing/utils.test'; let journalListElementComponent: JournalSearchResultListElementComponent; let fixture: ComponentFixture; @@ -36,6 +38,14 @@ const authService: AuthServiceStub = Object.assign(new AuthServiceStub(), { 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(), @@ -145,7 +155,7 @@ describe('JournalSearchResultListElementComponent', () => { { provide: TranslateService, useValue: {}}, { provide: ResourcePolicyDataService, useValue: {}}, { provide: AuthService, useValue: authService}, - { provide: EPersonDataService, useValue: {}}, + { provide: EPersonDataService, useValue: epersonService}, { provide: AuthorizationDataService, useValue: authorizationService}, { provide: DSONameService, useClass: DSONameServiceMock }, { provide: APP_CONFIG, useValue: environmentUseThumbs } @@ -218,7 +228,7 @@ describe('JournalSearchResultListElementComponent', () => { {provide: TranslateService, useValue: {}}, {provide: ResourcePolicyDataService, useValue: {}}, {provide: AuthService, useValue: authService}, - {provide: EPersonDataService, useValue: {}}, + {provide: EPersonDataService, useValue: epersonService}, {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 8be5f7496b..102393ed8f 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 @@ -14,7 +14,7 @@ import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; import { TranslateLoaderMock } from '../../../../../shared/mocks/translate-loader.mock'; import { SupervisionOrderDataService } from '../../../../../core/supervision-order/supervision-order-data.service'; import { NotificationsService } from '../../../../../shared/notifications/notifications.service'; -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'; @@ -25,6 +25,8 @@ import { EPersonDataService } from '../../../../../core/eperson/eperson-data.ser 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 '../../../../../core/eperson/models/eperson.model'; +import { createPaginatedList } from '../../../../../shared/testing/utils.test'; let orgUnitListElementComponent: OrgUnitSearchResultListElementComponent; let fixture: ComponentFixture; @@ -37,6 +39,14 @@ const authService: AuthServiceStub = Object.assign(new AuthServiceStub(), { 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(), @@ -150,7 +160,7 @@ describe('OrgUnitSearchResultListElementComponent', () => { { provide: NotificationsService, useValue: {}}, { provide: ResourcePolicyDataService, useValue: {}}, { provide: AuthService, useValue: authService}, - { provide: EPersonDataService, useValue: {}}, + { provide: EPersonDataService, useValue: epersonService}, { provide: AuthorizationDataService, useValue: authorizationService}, { provide: DSONameService, useClass: DSONameServiceMock }, { provide: APP_CONFIG, useValue: environmentUseThumbs } @@ -229,7 +239,7 @@ describe('OrgUnitSearchResultListElementComponent', () => { {provide: NotificationsService, useValue: {}}, {provide: ResourcePolicyDataService, useValue: {}}, {provide: AuthService, useValue: authService}, - {provide: EPersonDataService, useValue: {}}, + {provide: EPersonDataService, useValue: epersonService}, {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 e8cb217cdf..25b3a37c83 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 @@ -14,7 +14,7 @@ import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; import { TranslateLoaderMock } from '../../../../../shared/mocks/translate-loader.mock'; import { SupervisionOrderDataService } from '../../../../../core/supervision-order/supervision-order-data.service'; import { NotificationsService } from '../../../../../shared/notifications/notifications.service'; -import { createSuccessfulRemoteDataObject } from '../../../../../shared/remote-data.utils'; +import { createSuccessfulRemoteDataObject, createSuccessfulRemoteDataObject$ } from '../../../../../shared/remote-data.utils'; import { hot } from 'jasmine-marbles'; import { PageInfo } from '../../../../../core/shared/page-info.model'; import { GroupMock } from '../../../../../shared/testing/group-mock'; @@ -25,6 +25,8 @@ import { ResourcePolicyDataService } from '../../../../../core/resource-policy/r 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 { EPerson } from '../../../../../core/eperson/models/eperson.model'; +import { createPaginatedList } from '../../../../../shared/testing/utils.test'; let personListElementComponent: PersonSearchResultListElementComponent; let fixture: ComponentFixture; @@ -40,6 +42,14 @@ const authService: AuthServiceStub = Object.assign(new AuthServiceStub(), { 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(), @@ -149,7 +159,7 @@ describe('PersonSearchResultListElementComponent', () => { { provide: NotificationsService, useValue: {} }, { provide: ResourcePolicyDataService, useValue: {}}, { provide: AuthService, useValue: authService}, - { provide: EPersonDataService, useValue: {}}, + { provide: EPersonDataService, useValue: epersonService}, { provide: AuthorizationDataService, useValue: authorizationService}, { provide: DSONameService, useClass: DSONameServiceMock }, { provide: APP_CONFIG, useValue: environmentUseThumbs } @@ -228,7 +238,7 @@ describe('PersonSearchResultListElementComponent', () => { {provide: NotificationsService, useValue: {}}, {provide: ResourcePolicyDataService, useValue: {}}, {provide: AuthService, useValue: authService}, - {provide: EPersonDataService, useValue: {}}, + {provide: EPersonDataService, useValue: epersonService}, {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/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 6af4f9c43b..60487af8c8 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 @@ -13,7 +13,7 @@ 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'; @@ -24,6 +24,8 @@ import { EPersonDataService } from '../../../../../core/eperson/eperson-data.ser 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 '../../../../../core/eperson/models/eperson.model'; +import { createPaginatedList } from '../../../../../shared/testing/utils.test'; let projectListElementComponent: ProjectSearchResultListElementComponent; let fixture: ComponentFixture; @@ -37,6 +39,15 @@ const authService: AuthServiceStub = Object.assign(new AuthServiceStub(), { } }); +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(), { @@ -144,7 +155,7 @@ describe('ProjectSearchResultListElementComponent', () => { { provide: TranslateService, useValue: {}}, { provide: ResourcePolicyDataService, useValue: {}}, { provide: AuthService, useValue: authService}, - { provide: EPersonDataService, useValue: {}}, + { provide: EPersonDataService, useValue: epersonService}, { provide: AuthorizationDataService, useValue: authorizationService}, { provide: DSONameService, useClass: DSONameServiceMock }, { provide: APP_CONFIG, useValue: environmentUseThumbs } @@ -217,7 +228,7 @@ describe('ProjectSearchResultListElementComponent', () => { {provide: TranslateService, useValue: {}}, {provide: ResourcePolicyDataService, useValue: {}}, {provide: AuthService, useValue: authService}, - {provide: EPersonDataService, useValue: {}}, + {provide: EPersonDataService, useValue: epersonService}, {provide: AuthorizationDataService, useValue: authorizationService}, {provide: DSONameService, useClass: DSONameServiceMock}, { provide: APP_CONFIG, useValue: enviromentNoThumbs } From 67d401cc77e52135043087a848dbb6ebd40e9d15 Mon Sep 17 00:00:00 2001 From: corrado lombardi Date: Mon, 6 Feb 2023 16:53:37 +0100 Subject: [PATCH 05/10] [CST-7755] updated PR to latest REST changes --- src/app/core/shared/context.model.ts | 2 +- src/app/my-dspace-page/my-dspace-configuration-value-type.ts | 2 +- src/assets/i18n/en.json5 | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/app/core/shared/context.model.ts b/src/app/core/shared/context.model.ts index 0f1130ebda..dbe5a64552 100644 --- a/src/app/core/shared/context.model.ts +++ b/src/app/core/shared/context.model.ts @@ -8,7 +8,7 @@ export enum Context { Search = 'search', Workflow = 'workflow', Workspace = 'workspace', - SupervisedItems = 'otherworkspace', + SupervisedItems = 'supervisedWorkspace', AdminMenu = 'adminMenu', EntitySearchModalWithNameVariants = 'EntitySearchModalWithNameVariants', EntitySearchModal = 'EntitySearchModal', diff --git a/src/app/my-dspace-page/my-dspace-configuration-value-type.ts b/src/app/my-dspace-page/my-dspace-configuration-value-type.ts index 52e6b01c11..c8484d97a0 100644 --- a/src/app/my-dspace-page/my-dspace-configuration-value-type.ts +++ b/src/app/my-dspace-page/my-dspace-configuration-value-type.ts @@ -1,5 +1,5 @@ export enum MyDSpaceConfigurationValueType { Workspace = 'workspace', - SupervisedItems = 'otherworkspace', + SupervisedItems = 'supervisedWorkspace', Workflow = 'workflow' } diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 4e068152ab..0251f171b7 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -2968,7 +2968,7 @@ "mydspace.show.workspace": "Your Submissions", - "mydspace.show.otherworkspace": "Supervised items", + "mydspace.show.supervisedWorkspace": "Supervised items", "mydspace.status.archived": "Archived", @@ -4665,7 +4665,7 @@ - "otherworkspace.search.results.head": "Supervised Items", + "supervisedWorkspace.search.results.head": "Supervised Items", "workspace.search.results.head": "Your submissions", From 800d3a90019a51f45e7d1b6f6b899231bf7fbd86 Mon Sep 17 00:00:00 2001 From: corrado lombardi Date: Thu, 9 Feb 2023 15:31:03 +0100 Subject: [PATCH 06/10] [CST-7755] added cancel button to modal and updated message returned when a supervision order already exists --- .../supervision-group-selector.component.html | 17 +++++++++++------ .../supervision-group-selector.component.ts | 6 +++--- ...item-search-result-list-element.component.ts | 2 +- src/assets/i18n/en.json5 | 4 ++++ 4 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/app/shared/dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component.html b/src/app/shared/dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component.html index f6a5c339ce..c6d45c8743 100644 --- a/src/app/shared/dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component.html +++ b/src/app/shared/dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component.html @@ -30,11 +30,16 @@ (select)="updateGroupObjectSelected($event)"> -
- + +
- \ No newline at end of file + 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 1ae2d496d2..88ffb13070 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 @@ -79,13 +79,13 @@ export class SupervisionGroupSelectorComponent { 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 })); + this.close(); } else { this.notificationsService.error( - this.translateService.get('supervision-group-selector.notification.create.failure.title'), - rd.errorMessage); + this.translateService.get('supervision-group-selector.notification.create.failure.title'), + rd.statusCode == 422 ? this.translateService.get('supervision-group-selector.notification.create.already-existing') : rd.errorMessage); } }); - this.close(); } } 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 41afab0ab8..2fa72d2ac0 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 @@ -100,7 +100,7 @@ export class ItemSearchResultListElementComponent extends SearchResultListElemen ).pipe( getAllSucceededRemoteData(), ).subscribe((result) => { - this.supervisionOrder$ = this.supervisionOrderDataService.searchByItem(this.dso.uuid, null, null, followLink('group')).pipe( + this.supervisionOrder$ = this.supervisionOrderDataService.searchByItem(this.dso.uuid, false, true, followLink('group')).pipe( getAllSucceededRemoteListPayload(), switchMap((supervisionOrders: SupervisionOrder[]) => { const supervisionOrdersArray = supervisionOrders.map((supervisionOrder: SupervisionOrder) => { diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 0251f171b7..47fbbaf518 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -1443,6 +1443,8 @@ "supervision-group-selector.select.group.label": "Select a Group", + "supervision-group-selector.button.cancel": "Cancel", + "supervision-group-selector.button.save": "Save", "supervision-group-selector.select.type-of-order.error": "Please select a type of order", @@ -1453,6 +1455,8 @@ "supervision-group-selector.notification.create.failure.title": "Error", + "supervision-group-selector.notification.create.already-existing" : "A supervision order already exists on this item for selected group", + "confirmation-modal.export-metadata.header": "Export metadata for {{ dsoName }}", "confirmation-modal.export-metadata.info": "Are you sure you want to export metadata for {{ dsoName }}", From 52cd98a7d3a41891b407971dba6fe529f9dc22b3 Mon Sep 17 00:00:00 2001 From: corrado lombardi Date: Thu, 9 Feb 2023 15:39:13 +0100 Subject: [PATCH 07/10] [CST-7755] lint fix --- .../supervision-group-selector.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 88ffb13070..da22fe0d44 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 @@ -83,7 +83,7 @@ export class SupervisionGroupSelectorComponent { } else { this.notificationsService.error( this.translateService.get('supervision-group-selector.notification.create.failure.title'), - rd.statusCode == 422 ? this.translateService.get('supervision-group-selector.notification.create.already-existing') : rd.errorMessage); + rd.statusCode === 422 ? this.translateService.get('supervision-group-selector.notification.create.already-existing') : rd.errorMessage); } }); } From d82526af8abd4d5c6be501fa045f509326015e8b Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Fri, 10 Feb 2023 19:47:20 +0100 Subject: [PATCH 08/10] [CST-7755] WIP refactoring --- ...admin-workflow-list-element.component.html | 6 +- ...t-admin-workflow-list-element.component.ts | 127 ++++++++++++++++-- .../models/submission-object.model.ts | 4 +- ...table-object-component-loader.component.ts | 14 +- .../abstract-listable-element.component.ts | 5 + .../item/item-list-element.component.html | 2 +- .../object-list/object-list.component.html | 7 +- .../object-list/object-list.component.ts | 5 + ...-search-result-list-element.component.html | 37 ++--- ...em-search-result-list-element.component.ts | 14 +- .../supervision-order-status.component.html | 13 ++ .../supervision-order-status.component.scss | 0 ...supervision-order-status.component.spec.ts | 25 ++++ .../supervision-order-status.component.ts | 88 ++++++++++++ src/app/shared/shared.module.ts | 42 +++--- src/assets/i18n/en.json5 | 16 +-- 16 files changed, 330 insertions(+), 75 deletions(-) create mode 100644 src/app/shared/object-list/supervision-order-status/supervision-order-status.component.html create mode 100644 src/app/shared/object-list/supervision-order-status/supervision-order-status.component.scss create mode 100644 src/app/shared/object-list/supervision-order-status/supervision-order-status.component.spec.ts create mode 100644 src/app/shared/object-list/supervision-order-status/supervision-order-status.component.ts 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 32ba7b9cc8..8963db01bd 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,9 +6,13 @@ +
+ +
+ 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.ts 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.ts index ee6cb16bbe..c57d918126 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.ts +++ 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.ts @@ -1,21 +1,46 @@ import { Component, Inject, OnInit } from '@angular/core'; + +import { BehaviorSubject, Observable } from 'rxjs'; +import { map, mergeMap, take, tap } from 'rxjs/operators'; +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateService } from '@ngx-translate/core'; + import { ViewMode } from '../../../../../core/shared/view-mode.model'; -import { listableObjectComponent } from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator'; +import { + listableObjectComponent +} from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator'; import { Context } from '../../../../../core/shared/context.model'; import { WorkflowItem } from '../../../../../core/submission/models/workflowitem.model'; -import { Observable } from 'rxjs'; import { LinkService } from '../../../../../core/cache/builders/link.service'; import { followLink } from '../../../../../shared/utils/follow-link-config.model'; import { RemoteData } from '../../../../../core/data/remote-data'; -import { getAllSucceededRemoteData, getRemoteDataPayload } from '../../../../../core/shared/operators'; +import { + getAllSucceededRemoteData, + getFirstCompletedRemoteData, + getRemoteDataPayload +} from '../../../../../core/shared/operators'; import { Item } from '../../../../../core/shared/item.model'; -import { SearchResultListElementComponent } from '../../../../../shared/object-list/search-result-list-element/search-result-list-element.component'; +import { + SearchResultListElementComponent +} from '../../../../../shared/object-list/search-result-list-element/search-result-list-element.component'; import { TruncatableService } from '../../../../../shared/truncatable/truncatable.service'; -import { WorkflowItemSearchResult } from '../../../../../shared/object-collection/shared/workflow-item-search-result.model'; +import { + WorkflowItemSearchResult +} from '../../../../../shared/object-collection/shared/workflow-item-search-result.model'; import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service'; import { APP_CONFIG, AppConfig } from '../../../../../../config/app-config.interface'; -import { WorkspaceItemSearchResult } from '../../../../../shared/object-collection/shared/workspace-item-search-result.model'; +import { + WorkspaceItemSearchResult +} from '../../../../../shared/object-collection/shared/workspace-item-search-result.model'; import { SupervisionOrder } from '../../../../../core/supervision-order/models/supervision-order.model'; +import { SupervisionOrderDataService } from '../../../../../core/supervision-order/supervision-order-data.service'; +import { PaginatedList } from '../../../../../core/data/paginated-list.model'; +import { ConfirmationModalComponent } from '../../../../../shared/confirmation-modal/confirmation-modal.component'; +import { hasValue } from '../../../../../shared/empty.util'; +import { + SupervisionOrderListEntry +} from '../../../../../shared/object-list/supervision-order-status/supervision-order-status.component'; +import { NotificationsService } from '../../../../../shared/notifications/notifications.service'; @listableObjectComponent(WorkflowItemSearchResult, ViewMode.ListElement, Context.AdminWorkflowSearch) @listableObjectComponent(WorkspaceItemSearchResult, ViewMode.ListElement, Context.AdminWorkflowSearch) @@ -25,7 +50,7 @@ import { SupervisionOrder } from '../../../../../core/supervision-order/models/s templateUrl: './workflow-item-search-result-admin-workflow-list-element.component.html' }) /** - * The component for displaying a list element for an workflow item on the admin workflow search page + * The component for displaying a list element for a workflow item on the admin workflow search page */ export class WorkflowItemSearchResultAdminWorkflowListElementComponent extends SearchResultListElementComponent implements OnInit { @@ -34,14 +59,25 @@ export class WorkflowItemSearchResultAdminWorkflowListElementComponent extends S */ public item$: Observable; + /** + * The id of the item linked to the workflow item + */ + public itemId: string; + /** * The supervision orders linked to the workflow item */ - public supervisionOrder$: Observable; + public supervisionOrder$: BehaviorSubject = new BehaviorSubject([]); + + private messagePrefix = 'workflow-item.search.result'; constructor(private linkService: LinkService, - protected truncatableService: TruncatableService, protected dsoNameService: DSONameService, + protected modalService: NgbModal, + protected notificationsService: NotificationsService, + protected supervisionOrderDataService: SupervisionOrderDataService, + protected translateService: TranslateService, + protected truncatableService: TruncatableService, @Inject(APP_CONFIG) protected appConfig: AppConfig ) { super(truncatableService, dsoNameService, appConfig); @@ -53,7 +89,78 @@ 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()); + + this.item$.pipe( + take(1), + tap((item: Item) => this.itemId = item.id), + mergeMap((item: Item) => this.retrieveSupervisorOrders(item.id)) + ).subscribe((supervisionOrderList: SupervisionOrder[]) => { + this.supervisionOrder$.next(supervisionOrderList); + }) + } + + /** + * Deletes the Group from the Repository. The Group will be the only that this form is showing. + * It'll either show a success or error message depending on whether the delete was successful or not. + */ + deleteSupervisionOrder(supervisionOrderEntry: SupervisionOrderListEntry) { + const modalRef = this.modalService.open(ConfirmationModalComponent); + modalRef.componentInstance.dso = supervisionOrderEntry.group; + modalRef.componentInstance.headerLabel = this.messagePrefix + '.delete-supervision.modal.header'; + modalRef.componentInstance.infoLabel = this.messagePrefix + '.delete-supervision.modal.info'; + modalRef.componentInstance.cancelLabel = this.messagePrefix + '.delete-supervision.modal.cancel'; + modalRef.componentInstance.confirmLabel = this.messagePrefix + '.delete-supervision.modal.confirm'; + modalRef.componentInstance.brandColor = 'danger'; + modalRef.componentInstance.confirmIcon = 'fas fa-trash'; + modalRef.componentInstance.response.pipe( + take(1), + mergeMap((confirm: boolean) => { + if (confirm && hasValue(supervisionOrderEntry.supervisionOrder.id)) { + return this.supervisionOrderDataService.delete(supervisionOrderEntry.supervisionOrder.id).pipe( + take(1), + tap((result: boolean) => { + if (result) { + this.notificationsService.success( + null, + this.translateService.get( + this.messagePrefix + '.notification.deleted.success', + { name: this.dsoNameService.getName(supervisionOrderEntry.group) } + ) + ); + } else { + this.notificationsService.error( + null, + this.translateService.get( + this.messagePrefix + '.notification.deleted.failure', + { name: this.dsoNameService.getName(supervisionOrderEntry.group) } + ) + ); + } + }), + mergeMap((result: boolean) => result ? this.retrieveSupervisorOrders(this.itemId) : this.supervisionOrder$.asObservable()) + ) + } else { + return this.supervisionOrder$.asObservable() + } + }) + ).subscribe((supervisionOrderList: SupervisionOrder[]) => { + this.supervisionOrder$.next(supervisionOrderList) + }) + } + + /** + * Retrieve the list of SupervisionOrder object related to the given item + * + * @param itemId + * @private + */ + private retrieveSupervisorOrders(itemId): Observable { + return this.supervisionOrderDataService.searchByItem( + itemId, false, true, followLink('group') + ).pipe( + getFirstCompletedRemoteData(), + map((soRD: RemoteData>) => soRD.hasSucceeded && !soRD.hasNoContent ? soRD.payload.page : []) + ); } } diff --git a/src/app/core/submission/models/submission-object.model.ts b/src/app/core/submission/models/submission-object.model.ts index 3d373d2522..e2d1a4396b 100644 --- a/src/app/core/submission/models/submission-object.model.ts +++ b/src/app/core/submission/models/submission-object.model.ts @@ -15,6 +15,8 @@ import { excludeFromEquals } from '../../utilities/equals.decorators'; import { WorkspaceitemSectionsObject } from './workspaceitem-sections.model'; import { CacheableObject } from '../../cache/cacheable-object.model'; import { SUPERVISION_ORDER } from '../../supervision-order/models/supervision-order.resource-type'; +import { PaginatedList } from '../../data/paginated-list.model'; +import { SupervisionOrder } from '../../supervision-order/models/supervision-order.model'; export interface SubmissionObjectError { message: string; @@ -101,6 +103,6 @@ export abstract class SubmissionObject extends DSpaceObject implements Cacheable */ @link(SUPERVISION_ORDER) /* This was changed from 'Observable> | WorkspaceItem' to 'any' to prevent issues in templates with async */ - supervisionOrders?: any; + supervisionOrders?: Observable>>; } 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 9779ecd830..59ce71ff6c 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 { Observable, Subscription } from 'rxjs'; +import { Subscription } from 'rxjs'; import { take } from 'rxjs/operators'; import { ListableObject } from '../listable-object.model'; @@ -41,11 +41,6 @@ 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 */ @@ -76,6 +71,11 @@ export class ListableObjectComponentLoaderComponent implements OnInit, OnChanges */ @Input() showLabel = true; + /** + * Whether to show the supervision orders badges or not + */ + @Input() showSupervisionOrderBadges = false; + /** * The value to display for this element */ @@ -128,7 +128,7 @@ export class ListableObjectComponentLoaderComponent implements OnInit, OnChanges */ protected inAndOutputNames: string[] = [ 'object', - 'supervisionOrders', + 'showSupervisionOrderBadges', '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 dde9cf61dc..f292ac5b76 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 @@ -46,6 +46,11 @@ export class AbstractListableElementComponent { */ @Input() showLabel = true; + /** + * Whether to show the supervision orders badges or not + */ + @Input() showSupervisionOrderBadges = false; + /** * The context we matched on to get this component */ 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 f244da97bd..4bf45e7f3b 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/object-list.component.html b/src/app/shared/object-list/object-list.component.html index 863d328a69..a0ef3e1cb9 100644 --- a/src/app/shared/object-list/object-list.component.html +++ b/src/app/shared/object-list/object-list.component.html @@ -25,8 +25,13 @@ - diff --git a/src/app/shared/object-list/object-list.component.ts b/src/app/shared/object-list/object-list.component.ts index 65e2b508da..9d064115e6 100644 --- a/src/app/shared/object-list/object-list.component.ts +++ b/src/app/shared/object-list/object-list.component.ts @@ -81,6 +81,11 @@ export class ObjectListComponent { */ @Input() showPaginator = true; + /** + * Whether to show the supervision orders badges or not + */ + @Input() showSupervisionOrderBadges = false; + /** * Emit when one of the listed object has changed. */ diff --git a/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.html b/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.html index 64108681f6..bf1d51bfc2 100644 --- a/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.html +++ b/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.html @@ -23,37 +23,24 @@ - - - ( - ) - - - - - ; + + + ( + ) + + + + + ; + - - - + +
- -
-
- {{'item.search.result.list.element.supervised-by' | translate}} -
-
- - {{supervisionOrder.group._name}} - X - -
-
-
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 2fa72d2ac0..7ed96fdc68 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 @@ -1,5 +1,7 @@ import { Component, Inject } from '@angular/core'; -import { listableObjectComponent } from '../../../../../object-collection/shared/listable-object/listable-object.decorator'; +import { + listableObjectComponent +} from '../../../../../object-collection/shared/listable-object/listable-object.decorator'; import { ViewMode } from '../../../../../../core/shared/view-mode.model'; import { ItemSearchResult } from '../../../../../object-collection/shared/item-search-result.model'; import { SearchResultListElementComponent } from '../../../search-result-list-element.component'; @@ -8,7 +10,7 @@ import { getItemPageRoute } from '../../../../../../item-page/item-page-routing- import { SupervisionOrderDataService } from '../../../../../../core/supervision-order/supervision-order-data.service'; import { TruncatableService } from '../../../../../../shared/truncatable/truncatable.service'; import { DSONameService } from '../../../../../../core/breadcrumbs/dso-name.service'; -import { AppConfig, APP_CONFIG } from '../../../../../../../config/app-config.interface'; +import { APP_CONFIG, AppConfig } from '../../../../../../../config/app-config.interface'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { combineLatest, filter, map, Observable, switchMap, take } from 'rxjs'; import { ConfirmationModalComponent } from '../../../../../../shared/confirmation-modal/confirmation-modal.component'; @@ -16,11 +18,15 @@ import { hasValue } from '../../../../../../shared/empty.util'; import { NotificationsService } from '../../../../../../shared/notifications/notifications.service'; import { TranslateService } from '@ngx-translate/core'; import { followLink } from '../../../../../../shared/utils/follow-link-config.model'; -import { getAllSucceededRemoteListPayload, getFirstSucceededRemoteDataPayload } from '../../../../../../core/shared/operators'; +import { + getAllSucceededRemoteData, + getAllSucceededRemoteListPayload, + getFirstSucceededRemoteDataPayload, + getRemoteDataPayload +} 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'; diff --git a/src/app/shared/object-list/supervision-order-status/supervision-order-status.component.html b/src/app/shared/object-list/supervision-order-status/supervision-order-status.component.html new file mode 100644 index 0000000000..2e4f8d39cd --- /dev/null +++ b/src/app/shared/object-list/supervision-order-status/supervision-order-status.component.html @@ -0,0 +1,13 @@ + +
+
+ {{'workflow-item.search.result.list.element.supervised-by' | translate}} +
+
+ + {{supervisionOrder.group.name}} + X + +
+
+
diff --git a/src/app/shared/object-list/supervision-order-status/supervision-order-status.component.scss b/src/app/shared/object-list/supervision-order-status/supervision-order-status.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/shared/object-list/supervision-order-status/supervision-order-status.component.spec.ts b/src/app/shared/object-list/supervision-order-status/supervision-order-status.component.spec.ts new file mode 100644 index 0000000000..9a5516b8e9 --- /dev/null +++ b/src/app/shared/object-list/supervision-order-status/supervision-order-status.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SupervisionOrderStatusComponent } from './supervision-order-status.component'; + +describe('SupervisionOrderStatusComponent', () => { + let component: SupervisionOrderStatusComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SupervisionOrderStatusComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SupervisionOrderStatusComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/shared/object-list/supervision-order-status/supervision-order-status.component.ts b/src/app/shared/object-list/supervision-order-status/supervision-order-status.component.ts new file mode 100644 index 0000000000..92cbf17885 --- /dev/null +++ b/src/app/shared/object-list/supervision-order-status/supervision-order-status.component.ts @@ -0,0 +1,88 @@ +import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core'; + +import { BehaviorSubject, from, Observable } from 'rxjs'; +import { map, mergeMap, reduce } from 'rxjs/operators'; + +import { SupervisionOrder } from '../../../core/supervision-order/models/supervision-order.model'; +import { Group } from '../../../core/eperson/models/group.model'; +import { getFirstCompletedRemoteData } from '../../../core/shared/operators'; +import { isNotEmpty } from '../../empty.util'; +import { RemoteData } from '../../../core/data/remote-data'; + +export interface SupervisionOrderListEntry { + supervisionOrder: SupervisionOrder; + group: Group +} + +@Component({ + selector: 'ds-supervision-order-status', + templateUrl: './supervision-order-status.component.html', + styleUrls: ['./supervision-order-status.component.scss'] +}) +export class SupervisionOrderStatusComponent implements OnChanges { + + /** + * The list of supervision order object to show + */ + @Input() supervisionOrderList: SupervisionOrder[] = []; + + /** + * The groups the user belongs to + */ + groups: Group[]; + + /** + * List of the supervision orders combined with the group + */ + supervisionOrderEntries$: BehaviorSubject = new BehaviorSubject([]); + + @Output() delete: EventEmitter = new EventEmitter(); + + ngOnChanges(changes: SimpleChanges): void { + if (changes && changes.supervisionOrderList) { + this.getSupervisionOrderEntries(changes.supervisionOrderList.currentValue) + .subscribe((supervisionOrderEntries: SupervisionOrderListEntry[]) => { + this.supervisionOrderEntries$.next(supervisionOrderEntries) + }) + } + console.log('ngOnChanges', changes); + } + + /** + * Create a list of SupervisionOrderListEntry by the given SupervisionOrder list + * + * @param supervisionOrderList + */ + private getSupervisionOrderEntries(supervisionOrderList: SupervisionOrder[]): Observable { + return from(supervisionOrderList).pipe( + mergeMap((so: SupervisionOrder) => so.group.pipe( + getFirstCompletedRemoteData(), + map((sogRD: RemoteData) => { + if (sogRD.hasSucceeded) { + const entry: SupervisionOrderListEntry = { + supervisionOrder: so, + group: sogRD.payload + }; + return entry; + } else { + return null; + } + }) + )), + reduce((acc: SupervisionOrderListEntry[], value: any) => { + if (isNotEmpty(value)) { + return [...acc, value] + } else { + return acc; + } + }, []), + ) + } + + /** + * Emit a delete event with the given SupervisionOrderListEntry. + */ + deleteSupervisionOrder(supervisionOrder: SupervisionOrderListEntry) { + this.delete.emit(supervisionOrder); + } +} diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index 3c985d46b9..624d519ad1 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -100,19 +100,19 @@ import { CreateCommunityParentSelectorComponent } from './dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component'; import { - ThemedCreateCommunityParentSelectorComponent + ThemedCreateCommunityParentSelectorComponent } from './dso-selector/modal-wrappers/create-community-parent-selector/themed-create-community-parent-selector.component'; import { CreateItemParentSelectorComponent } from './dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component'; import { - ThemedCreateItemParentSelectorComponent + ThemedCreateItemParentSelectorComponent } from './dso-selector/modal-wrappers/create-item-parent-selector/themed-create-item-parent-selector.component'; import { CreateCollectionParentSelectorComponent } from './dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component'; import { - ThemedCreateCollectionParentSelectorComponent + ThemedCreateCollectionParentSelectorComponent } from './dso-selector/modal-wrappers/create-collection-parent-selector/themed-create-collection-parent-selector.component'; import { CommunitySearchResultListElementComponent @@ -124,19 +124,19 @@ import { EditItemSelectorComponent } from './dso-selector/modal-wrappers/edit-item-selector/edit-item-selector.component'; import { - ThemedEditItemSelectorComponent + ThemedEditItemSelectorComponent } from './dso-selector/modal-wrappers/edit-item-selector/themed-edit-item-selector.component'; import { EditCommunitySelectorComponent } from './dso-selector/modal-wrappers/edit-community-selector/edit-community-selector.component'; import { - ThemedEditCommunitySelectorComponent + ThemedEditCommunitySelectorComponent } from './dso-selector/modal-wrappers/edit-community-selector/themed-edit-community-selector.component'; import { EditCollectionSelectorComponent } from './dso-selector/modal-wrappers/edit-collection-selector/edit-collection-selector.component'; import { - ThemedEditCollectionSelectorComponent + ThemedEditCollectionSelectorComponent } from './dso-selector/modal-wrappers/edit-collection-selector/themed-edit-collection-selector.component'; import { RoleDirective } from './roles/role.directive'; import { UserMenuComponent } from './auth-nav-menu/user-menu/user-menu.component'; @@ -242,14 +242,20 @@ import { MenuModule } from './menu/menu.module'; import { ListableNotificationObjectComponent } from './object-list/listable-notification-object/listable-notification-object.component'; -import { SupervisionGroupSelectorComponent } from './dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component'; +import { + SupervisionGroupSelectorComponent +} from './dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component'; import { EpersonGroupListComponent } from './form/eperson-group-list/eperson-group-list.component'; import { EpersonSearchBoxComponent } from './form/eperson-group-list/eperson-search-box/eperson-search-box.component'; import { GroupSearchBoxComponent } from './form/eperson-group-list/group-search-box/group-search-box.component'; import { ThemedCollectionDropdownComponent } from './collection-dropdown/themed-collection-dropdown.component'; import { MetadataFieldWrapperComponent } from './metadata-field-wrapper/metadata-field-wrapper.component'; -import { LogInExternalProviderComponent } from './log-in/methods/log-in-external-provider/log-in-external-provider.component'; - +import { + LogInExternalProviderComponent +} from './log-in/methods/log-in-external-provider/log-in-external-provider.component'; +import { + SupervisionOrderStatusComponent +} from './object-list/supervision-order-status/supervision-order-status.component'; const MODULES = [ @@ -452,18 +458,20 @@ const DIRECTIVES = [ ...COMPONENTS, ...ENTRY_COMPONENTS, ...DIRECTIVES, + SupervisionOrderStatusComponent, ], providers: [ ...PROVIDERS ], - exports: [ - ...MODULES, - ...PIPES, - ...COMPONENTS, - ...ENTRY_COMPONENTS, - ...DIRECTIVES, - TranslateModule, - ] + exports: [ + ...MODULES, + ...PIPES, + ...COMPONENTS, + ...ENTRY_COMPONENTS, + ...DIRECTIVES, + TranslateModule, + SupervisionOrderStatusComponent, + ] }) /** diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 47fbbaf518..892f686fb8 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -2271,21 +2271,21 @@ "item.truncatable-part.show-less": "Collapse", - "item.search.result.delete-supervision.modal.header": "Delete Supervision Order", + "workflow-item.search.result.delete-supervision.modal.header": "Delete Supervision Order", - "item.search.result.delete-supervision.modal.info": "Are you sure you want to delete Supervision Order", + "workflow-item.search.result.delete-supervision.modal.info": "Are you sure you want to delete Supervision Order", - "item.search.result.delete-supervision.modal.cancel": "Cancel", + "workflow-item.search.result.delete-supervision.modal.cancel": "Cancel", - "item.search.result.delete-supervision.modal.confirm": "Delete", + "workflow-item.search.result.delete-supervision.modal.confirm": "Delete", - "item.search.result.notification.deleted.success": "Successfully deleted supervision order \"{{name}}\"", + "workflow-item.search.result.notification.deleted.success": "Successfully deleted supervision order \"{{name}}\"", - "item.search.result.notification.deleted.failure.title": "Failed to delete supervision order \"{{name}}\"", + "workflow-item.search.result.notification.deleted.failure": "Failed to delete supervision order \"{{name}}\"", - "item.search.result.notification.deleted.failure.content": "Failed to delete supervision order", + "workflow-item.search.result.list.element.supervised-by": "Supervised by:", - "item.search.result.list.element.supervised-by": "Supervised by:", + "workflow-item.search.result.list.element.supervised.remove-tooltip": "Remove supervision group", From 363136027ec0e05d01e2a9d5c1ba6cbbc9dbba45 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Mon, 13 Feb 2023 10:36:13 +0100 Subject: [PATCH 09/10] [CST-7755] WIP revert changes on list components --- ...arch-result-list-element.component.spec.ts | 103 +------------ ...arch-result-list-element.component.spec.ts | 101 +------------ ...arch-result-list-element.component.spec.ts | 101 +------------ ...arch-result-list-element.component.spec.ts | 99 +------------ ...arch-result-list-element.component.spec.ts | 98 +------------ ...on-search-result-list-element.component.ts | 20 +-- ...arch-result-list-element.component.spec.ts | 103 +------------ ...table-object-component-loader.component.ts | 6 - .../abstract-listable-element.component.ts | 10 -- .../item/item-list-element.component.html | 2 +- .../object-list/object-list.component.html | 1 - .../object-list/object-list.component.ts | 5 - ...arch-result-list-element.component.spec.ts | 102 +------------ ...em-search-result-list-element.component.ts | 136 +----------------- 14 files changed, 16 insertions(+), 871 deletions(-) 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 3a0e73e46c..178ed86c40 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, of } from 'rxjs'; +import { of as observableOf } 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'; @@ -10,43 +10,9 @@ import { TruncatableService } from '../../../../../shared/truncatable/truncatabl import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service'; import { DSONameServiceMock } from '../../../../../shared/mocks/dso-name.service.mock'; 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, 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 '../../../../../core/eperson/models/eperson.model'; -import { createPaginatedList } from '../../../../../shared/testing/utils.test'; 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 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(), @@ -104,65 +70,12 @@ const enviromentNoThumbs = { } }; -const supervisionOrderDataService: any = jasmine.createSpyObj('supervisionOrderDataService', { - searchByItem: jasmine.createSpy('searchByItem'), -}); - -const supervisionOrder: any = { - id: '1', - type: 'supervisionOrder', - uuid: 'supervision-order-1', - _links: { - item: { - href: 'https://rest.api/rest/api/eperson' - }, - group: { - href: 'https://rest.api/rest/api/group' - }, - self: { - href: 'https://rest.api/rest/api/supervisionorders/1' - }, - }, - item: observableOf(createSuccessfulRemoteDataObject({})), - group: observableOf(createSuccessfulRemoteDataObject(GroupMock)) -}; -const anothersupervisionOrder: any = { - id: '2', - type: 'supervisionOrder', - uuid: 'supervision-order-2', - _links: { - item: { - href: 'https://rest.api/rest/api/eperson' - }, - group: { - href: 'https://rest.api/rest/api/group' - }, - self: { - href: 'https://rest.api/rest/api/supervisionorders/1' - }, - }, - item: observableOf(createSuccessfulRemoteDataObject({})), - group: observableOf(createSuccessfulRemoteDataObject(GroupMock)) -}; - -const pageInfo = new PageInfo(); -const array = [supervisionOrder, anothersupervisionOrder]; -const paginatedList = buildPaginatedList(pageInfo, array); -const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); - describe('JournalIssueSearchResultListElementComponent', () => { beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [JournalIssueSearchResultListElementComponent, TruncatePipe], providers: [ { provide: TruncatableService, useValue: {} }, - { 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 } ], @@ -174,9 +87,6 @@ describe('JournalIssueSearchResultListElementComponent', () => { })); beforeEach(waitForAsync(() => { - supervisionOrderDataService.searchByItem.and.returnValue(hot('a|', { - a: paginatedListRD - })); fixture = TestBed.createComponent(JournalIssueSearchResultListElementComponent); journalIssueListElementComponent = fixture.componentInstance; @@ -254,13 +164,6 @@ describe('JournalIssueSearchResultListElementComponent', () => { declarations: [JournalIssueSearchResultListElementComponent, TruncatePipe], providers: [ {provide: TruncatableService, useValue: {}}, - {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 } ], @@ -278,9 +181,7 @@ describe('JournalIssueSearchResultListElementComponent', () => { describe('with environment.browseBy.showThumbnails set to false', () => { beforeEach(() => { - supervisionOrderDataService.searchByItem.and.returnValue(hot('a|', { - a: paginatedListRD - })); + journalIssueListElementComponent.object = mockItemWithMetadata; fixture.detectChanges(); }); 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 67665403d1..71fa83a3b1 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, of } from 'rxjs'; +import { of as observableOf } 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'; @@ -10,43 +10,10 @@ import { TruncatableService } from '../../../../../shared/truncatable/truncatabl import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service'; import { DSONameServiceMock } from '../../../../../shared/mocks/dso-name.service.mock'; 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, 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 { 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'; -import { EPerson } from '../../../../../core/eperson/models/eperson.model'; -import { createPaginatedList } from '../../../../../shared/testing/utils.test'; 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 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(), { @@ -102,65 +69,12 @@ const enviromentNoThumbs = { } }; -const supervisionOrderDataService: any = jasmine.createSpyObj('supervisionOrderDataService', { - searchByItem: jasmine.createSpy('searchByItem'), -}); - -const supervisionOrder: any = { - id: '1', - type: 'supervisionOrder', - uuid: 'supervision-order-1', - _links: { - item: { - href: 'https://rest.api/rest/api/eperson' - }, - group: { - href: 'https://rest.api/rest/api/group' - }, - self: { - href: 'https://rest.api/rest/api/supervisionorders/1' - }, - }, - item: observableOf(createSuccessfulRemoteDataObject({})), - group: observableOf(createSuccessfulRemoteDataObject(GroupMock)) -}; -const anothersupervisionOrder: any = { - id: '2', - type: 'supervisionOrder', - uuid: 'supervision-order-2', - _links: { - item: { - href: 'https://rest.api/rest/api/eperson' - }, - group: { - href: 'https://rest.api/rest/api/group' - }, - self: { - href: 'https://rest.api/rest/api/supervisionorders/1' - }, - }, - item: observableOf(createSuccessfulRemoteDataObject({})), - group: observableOf(createSuccessfulRemoteDataObject(GroupMock)) -}; - -const pageInfo = new PageInfo(); -const array = [supervisionOrder, anothersupervisionOrder]; -const paginatedList = buildPaginatedList(pageInfo, array); -const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); - describe('JournalVolumeSearchResultListElementComponent', () => { beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [JournalVolumeSearchResultListElementComponent, TruncatePipe], providers: [ { provide: TruncatableService, useValue: {} }, - { 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 } ], @@ -172,9 +86,6 @@ describe('JournalVolumeSearchResultListElementComponent', () => { })); beforeEach(waitForAsync(() => { - supervisionOrderDataService.searchByItem.and.returnValue(hot('a|', { - a: paginatedListRD - })); fixture = TestBed.createComponent(JournalVolumeSearchResultListElementComponent); journalVolumeListElementComponent = fixture.componentInstance; @@ -251,13 +162,6 @@ describe('JournalVolumeSearchResultListElementComponent', () => { declarations: [JournalVolumeSearchResultListElementComponent, TruncatePipe], providers: [ {provide: TruncatableService, useValue: {}}, - {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 } ], @@ -269,9 +173,6 @@ describe('JournalVolumeSearchResultListElementComponent', () => { })); beforeEach(waitForAsync(() => { - supervisionOrderDataService.searchByItem.and.returnValue(hot('a|', { - a: paginatedListRD - })); fixture = TestBed.createComponent(JournalVolumeSearchResultListElementComponent); journalVolumeListElementComponent = fixture.componentInstance; })); 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 63e8abda28..07970d7128 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, of } from 'rxjs'; +import { of as observableOf } 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'; @@ -10,42 +10,9 @@ import { ItemSearchResult } from '../../../../../shared/object-collection/shared import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service'; import { DSONameServiceMock } from '../../../../../shared/mocks/dso-name.service.mock'; 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, 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 { 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'; -import { EPerson } from '../../../../../core/eperson/models/eperson.model'; -import { createPaginatedList } from '../../../../../shared/testing/utils.test'; 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 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(), @@ -98,65 +65,12 @@ const enviromentNoThumbs = { } }; -const supervisionOrderDataService: any = jasmine.createSpyObj('supervisionOrderDataService', { - searchByItem: jasmine.createSpy('searchByItem'), -}); - -const supervisionOrder: any = { - id: '1', - type: 'supervisionOrder', - uuid: 'supervision-order-1', - _links: { - item: { - href: 'https://rest.api/rest/api/eperson' - }, - group: { - href: 'https://rest.api/rest/api/group' - }, - self: { - href: 'https://rest.api/rest/api/supervisionorders/1' - }, - }, - item: observableOf(createSuccessfulRemoteDataObject({})), - group: observableOf(createSuccessfulRemoteDataObject(GroupMock)) -}; -const anothersupervisionOrder: any = { - id: '2', - type: 'supervisionOrder', - uuid: 'supervision-order-2', - _links: { - item: { - href: 'https://rest.api/rest/api/eperson' - }, - group: { - href: 'https://rest.api/rest/api/group' - }, - self: { - href: 'https://rest.api/rest/api/supervisionorders/1' - }, - }, - item: observableOf(createSuccessfulRemoteDataObject({})), - group: observableOf(createSuccessfulRemoteDataObject(GroupMock)) -}; - -const pageInfo = new PageInfo(); -const array = [supervisionOrder, anothersupervisionOrder]; -const paginatedList = buildPaginatedList(pageInfo, array); -const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); - describe('JournalSearchResultListElementComponent', () => { beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [JournalSearchResultListElementComponent, TruncatePipe], providers: [ { provide: TruncatableService, useValue: {} }, - { 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 } ], @@ -168,9 +82,6 @@ describe('JournalSearchResultListElementComponent', () => { })); beforeEach(waitForAsync(() => { - supervisionOrderDataService.searchByItem.and.returnValue(hot('a|', { - a: paginatedListRD - })); fixture = TestBed.createComponent(JournalSearchResultListElementComponent); journalListElementComponent = fixture.componentInstance; @@ -223,13 +134,6 @@ describe('JournalSearchResultListElementComponent', () => { declarations: [JournalSearchResultListElementComponent, TruncatePipe], providers: [ {provide: TruncatableService, useValue: {}}, - {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 } ], @@ -241,9 +145,6 @@ describe('JournalSearchResultListElementComponent', () => { })); beforeEach(waitForAsync(() => { - supervisionOrderDataService.searchByItem.and.returnValue(hot('a|', { - a: paginatedListRD - })); fixture = TestBed.createComponent(JournalSearchResultListElementComponent); journalListElementComponent = fixture.componentInstance; })); 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 102393ed8f..9609a9582a 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, of } from 'rxjs'; +import { of as observableOf } 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'; @@ -12,41 +12,9 @@ import { DSONameServiceMock } from '../../../../../shared/mocks/dso-name.service import { APP_CONFIG } from '../../../../../../config/app-config.interface'; import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; import { TranslateLoaderMock } from '../../../../../shared/mocks/translate-loader.mock'; -import { SupervisionOrderDataService } from '../../../../../core/supervision-order/supervision-order-data.service'; -import { NotificationsService } from '../../../../../shared/notifications/notifications.service'; -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 '../../../../../core/eperson/models/eperson.model'; -import { createPaginatedList } from '../../../../../shared/testing/utils.test'; 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 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(), @@ -97,52 +65,6 @@ const enviromentNoThumbs = { } }; -const supervisionOrderDataService: any = jasmine.createSpyObj('supervisionOrderDataService', { - searchByItem: jasmine.createSpy('searchByItem'), -}); - -const supervisionOrder: any = { - id: '1', - type: 'supervisionOrder', - uuid: 'supervision-order-1', - _links: { - item: { - href: 'https://rest.api/rest/api/eperson' - }, - group: { - href: 'https://rest.api/rest/api/group' - }, - self: { - href: 'https://rest.api/rest/api/supervisionorders/1' - }, - }, - item: observableOf(createSuccessfulRemoteDataObject({})), - group: observableOf(createSuccessfulRemoteDataObject(GroupMock)) -}; -const anothersupervisionOrder: any = { - id: '2', - type: 'supervisionOrder', - uuid: 'supervision-order-2', - _links: { - item: { - href: 'https://rest.api/rest/api/eperson' - }, - group: { - href: 'https://rest.api/rest/api/group' - }, - self: { - href: 'https://rest.api/rest/api/supervisionorders/1' - }, - }, - item: observableOf(createSuccessfulRemoteDataObject({})), - group: observableOf(createSuccessfulRemoteDataObject(GroupMock)) -}; - -const pageInfo = new PageInfo(); -const array = [supervisionOrder, anothersupervisionOrder]; -const paginatedList = buildPaginatedList(pageInfo, array); -const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); - describe('OrgUnitSearchResultListElementComponent', () => { beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ @@ -156,12 +78,6 @@ describe('OrgUnitSearchResultListElementComponent', () => { declarations: [ OrgUnitSearchResultListElementComponent , TruncatePipe], providers: [ { provide: TruncatableService, useValue: {} }, - { provide: SupervisionOrderDataService, useValue: supervisionOrderDataService }, - { provide: NotificationsService, 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 } ], @@ -173,9 +89,6 @@ describe('OrgUnitSearchResultListElementComponent', () => { })); beforeEach(waitForAsync(() => { - supervisionOrderDataService.searchByItem.and.returnValue(hot('a|', { - a: paginatedListRD - })); fixture = TestBed.createComponent(OrgUnitSearchResultListElementComponent); orgUnitListElementComponent = fixture.componentInstance; @@ -235,12 +148,6 @@ describe('OrgUnitSearchResultListElementComponent', () => { declarations: [OrgUnitSearchResultListElementComponent, TruncatePipe], providers: [ {provide: TruncatableService, useValue: {}}, - {provide: SupervisionOrderDataService, useValue: supervisionOrderDataService }, - {provide: NotificationsService, 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 } ], @@ -258,9 +165,7 @@ describe('OrgUnitSearchResultListElementComponent', () => { describe('with environment.browseBy.showThumbnails set to false', () => { beforeEach(() => { - supervisionOrderDataService.searchByItem.and.returnValue(hot('a|', { - a: paginatedListRD - })); + orgUnitListElementComponent.object = mockItemWithMetadata; fixture.detectChanges(); }); 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 25b3a37c83..31018520f6 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, of } from 'rxjs'; +import { of as observableOf } 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'; @@ -12,44 +12,9 @@ import { DSONameServiceMock } from '../../../../../shared/mocks/dso-name.service import { APP_CONFIG } from '../../../../../../config/app-config.interface'; import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; import { TranslateLoaderMock } from '../../../../../shared/mocks/translate-loader.mock'; -import { SupervisionOrderDataService } from '../../../../../core/supervision-order/supervision-order-data.service'; -import { NotificationsService } from '../../../../../shared/notifications/notifications.service'; -import { createSuccessfulRemoteDataObject, createSuccessfulRemoteDataObject$ } from '../../../../../shared/remote-data.utils'; -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'; -import { EPerson } from '../../../../../core/eperson/models/eperson.model'; -import { createPaginatedList } from '../../../../../shared/testing/utils.test'; 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 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(), @@ -100,48 +65,6 @@ const enviromentNoThumbs = { } }; -const supervisionOrder: any = { - id: '1', - type: 'supervisionOrder', - uuid: 'supervision-order-1', - _links: { - item: { - href: 'https://rest.api/rest/api/eperson' - }, - group: { - href: 'https://rest.api/rest/api/group' - }, - self: { - href: 'https://rest.api/rest/api/supervisionorders/1' - }, - }, - item: observableOf(createSuccessfulRemoteDataObject({})), - group: observableOf(createSuccessfulRemoteDataObject(GroupMock)) -}; -const anothersupervisionOrder: any = { - id: '2', - type: 'supervisionOrder', - uuid: 'supervision-order-2', - _links: { - item: { - href: 'https://rest.api/rest/api/eperson' - }, - group: { - href: 'https://rest.api/rest/api/group' - }, - self: { - href: 'https://rest.api/rest/api/supervisionorders/1' - }, - }, - item: observableOf(createSuccessfulRemoteDataObject({})), - group: observableOf(createSuccessfulRemoteDataObject(GroupMock)) -}; - -const pageInfo = new PageInfo(); -const array = [supervisionOrder, anothersupervisionOrder]; -const paginatedList = buildPaginatedList(pageInfo, array); -const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); - describe('PersonSearchResultListElementComponent', () => { beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ @@ -155,12 +78,6 @@ describe('PersonSearchResultListElementComponent', () => { declarations: [PersonSearchResultListElementComponent, TruncatePipe], providers: [ { provide: TruncatableService, useValue: {} }, - { provide: SupervisionOrderDataService, useValue: supervisionOrderDataService }, - { provide: NotificationsService, 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 } ], @@ -172,9 +89,6 @@ describe('PersonSearchResultListElementComponent', () => { })); beforeEach(waitForAsync(() => { - supervisionOrderDataService.searchByItem.and.returnValue(hot('a|', { - a: paginatedListRD - })); fixture = TestBed.createComponent(PersonSearchResultListElementComponent); personListElementComponent = fixture.componentInstance; @@ -234,12 +148,6 @@ describe('PersonSearchResultListElementComponent', () => { declarations: [PersonSearchResultListElementComponent, TruncatePipe], providers: [ {provide: TruncatableService, useValue: {}}, - {provide: SupervisionOrderDataService, useValue: supervisionOrderDataService}, - {provide: NotificationsService, 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 } ], @@ -257,9 +165,7 @@ describe('PersonSearchResultListElementComponent', () => { describe('with environment.browseBy.showThumbnails set to false', () => { beforeEach(() => { - supervisionOrderDataService.searchByItem.and.returnValue(hot('a|', { - a: paginatedListRD - })); + personListElementComponent.object = mockItemWithMetadata; fixture.detectChanges(); }); 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 09142fc02e..217d7baef9 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 @@ -9,14 +9,6 @@ import { import { TruncatableService } from '../../../../../shared/truncatable/truncatable.service'; import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service'; import { APP_CONFIG, AppConfig } from '../../../../../../config/app-config.interface'; -import { SupervisionOrderDataService } from '../../../../../core/supervision-order/supervision-order-data.service'; -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({ @@ -32,17 +24,9 @@ export class PersonSearchResultListElementComponent extends ItemSearchResultList public constructor( protected truncatableService: TruncatableService, protected dsoNameService: DSONameService, - @Inject(APP_CONFIG) protected appConfig: AppConfig, - protected supervisionOrderDataService: SupervisionOrderDataService, - protected modalService: NgbModal, - protected notificationsService: NotificationsService, - protected translateService: TranslateService, - protected resourcePolicyService: ResourcePolicyDataService, - protected authService: AuthService, - protected epersonService: EPersonDataService, - protected authorizationService: AuthorizationDataService + @Inject(APP_CONFIG) protected appConfig: AppConfig ) { - super(truncatableService, dsoNameService, appConfig, supervisionOrderDataService, modalService, notificationsService, translateService, resourcePolicyService, authService, epersonService, authorizationService); + super(truncatableService, dsoNameService, appConfig); } /** 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 60487af8c8..0cb3e63e87 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, of } from 'rxjs'; +import { of as observableOf } 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'; @@ -10,43 +10,9 @@ import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service import { DSONameServiceMock } from '../../../../../shared/mocks/dso-name.service.mock'; import { By } from '@angular/platform-browser'; 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, 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 '../../../../../core/eperson/models/eperson.model'; -import { createPaginatedList } from '../../../../../shared/testing/utils.test'; 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 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(), @@ -98,65 +64,12 @@ const enviromentNoThumbs = { } }; -const supervisionOrderDataService: any = jasmine.createSpyObj('supervisionOrderDataService', { - searchByItem: jasmine.createSpy('searchByItem'), -}); - -const supervisionOrder: any = { - id: '1', - type: 'supervisionOrder', - uuid: 'supervision-order-1', - _links: { - item: { - href: 'https://rest.api/rest/api/eperson' - }, - group: { - href: 'https://rest.api/rest/api/group' - }, - self: { - href: 'https://rest.api/rest/api/supervisionorders/1' - }, - }, - item: observableOf(createSuccessfulRemoteDataObject({})), - group: observableOf(createSuccessfulRemoteDataObject(GroupMock)) -}; -const anothersupervisionOrder: any = { - id: '2', - type: 'supervisionOrder', - uuid: 'supervision-order-2', - _links: { - item: { - href: 'https://rest.api/rest/api/eperson' - }, - group: { - href: 'https://rest.api/rest/api/group' - }, - self: { - href: 'https://rest.api/rest/api/supervisionorders/1' - }, - }, - item: observableOf(createSuccessfulRemoteDataObject({})), - group: observableOf(createSuccessfulRemoteDataObject(GroupMock)) -}; - -const pageInfo = new PageInfo(); -const array = [supervisionOrder, anothersupervisionOrder]; -const paginatedList = buildPaginatedList(pageInfo, array); -const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); - describe('ProjectSearchResultListElementComponent', () => { beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [ProjectSearchResultListElementComponent, TruncatePipe], providers: [ { provide: TruncatableService, useValue: {} }, - { 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 } ], @@ -168,9 +81,6 @@ describe('ProjectSearchResultListElementComponent', () => { })); beforeEach(waitForAsync(() => { - supervisionOrderDataService.searchByItem.and.returnValue(hot('a|', { - a: paginatedListRD - })); fixture = TestBed.createComponent(ProjectSearchResultListElementComponent); projectListElementComponent = fixture.componentInstance; @@ -223,13 +133,6 @@ describe('ProjectSearchResultListElementComponent', () => { declarations: [ProjectSearchResultListElementComponent, TruncatePipe], providers: [ {provide: TruncatableService, useValue: {}}, - {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 } @@ -248,9 +151,7 @@ describe('ProjectSearchResultListElementComponent', () => { describe('with environment.browseBy.showThumbnails set to false', () => { beforeEach(() => { - supervisionOrderDataService.searchByItem.and.returnValue(hot('a|', { - a: paginatedListRD - })); + projectListElementComponent.object = mockItemWithMetadata; fixture.detectChanges(); }); 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 59ce71ff6c..6b75c59181 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 @@ -71,11 +71,6 @@ export class ListableObjectComponentLoaderComponent implements OnInit, OnChanges */ @Input() showLabel = true; - /** - * Whether to show the supervision orders badges or not - */ - @Input() showSupervisionOrderBadges = false; - /** * The value to display for this element */ @@ -128,7 +123,6 @@ export class ListableObjectComponentLoaderComponent implements OnInit, OnChanges */ protected inAndOutputNames: string[] = [ 'object', - 'showSupervisionOrderBadges', '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 f292ac5b76..7d4e107b2b 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,11 +16,6 @@ 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 */ @@ -46,11 +41,6 @@ export class AbstractListableElementComponent { */ @Input() showLabel = true; - /** - * Whether to show the supervision orders badges or not - */ - @Input() showSupervisionOrderBadges = false; - /** * The context we matched on to get this component */ 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 4bf45e7f3b..3877e2f335 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/object-list.component.html b/src/app/shared/object-list/object-list.component.html index a0ef3e1cb9..b8712b85c5 100644 --- a/src/app/shared/object-list/object-list.component.html +++ b/src/app/shared/object-list/object-list.component.html @@ -31,7 +31,6 @@ [context]="context" [linkType]="linkType" [listID]="selectionConfig?.listId" - [showSupervisionOrderBadges]="showSupervisionOrderBadges" (contentChange)="contentChange.emit($event)">
diff --git a/src/app/shared/object-list/object-list.component.ts b/src/app/shared/object-list/object-list.component.ts index 9d064115e6..65e2b508da 100644 --- a/src/app/shared/object-list/object-list.component.ts +++ b/src/app/shared/object-list/object-list.component.ts @@ -81,11 +81,6 @@ export class ObjectListComponent { */ @Input() showPaginator = true; - /** - * Whether to show the supervision orders badges or not - */ - @Input() showSupervisionOrderBadges = false; - /** * Emit when one of the listed object has changed. */ 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 d4ca14c105..7665b7d64e 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, of } from 'rxjs'; +import { of as observableOf } from 'rxjs'; import { ItemSearchResultListElementComponent } from './item-search-result-list-element.component'; import { Item } from '../../../../../../core/shared/item.model'; import { TruncatePipe } from '../../../../../utils/truncate.pipe'; @@ -10,44 +10,10 @@ import { ItemSearchResult } from '../../../../../object-collection/shared/item-s import { DSONameService } from '../../../../../../core/breadcrumbs/dso-name.service'; import { DSONameServiceMock, UNDEFINED_NAME } from '../../../../../mocks/dso-name.service.mock'; 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, 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; const dcTitle = 'This is just another title'; -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(), { hitHighlights: { 'dc.title': [{ @@ -218,65 +184,12 @@ const enviromentNoThumbs = { } }; -const supervisionOrderDataService: any = jasmine.createSpyObj('supervisionOrderDataService', { - searchByItem: jasmine.createSpy('searchByItem'), -}); - -const supervisionOrder: any = { - id: '1', - type: 'supervisionOrder', - uuid: 'supervision-order-1', - _links: { - item: { - href: 'https://rest.api/rest/api/eperson' - }, - group: { - href: 'https://rest.api/rest/api/group' - }, - self: { - href: 'https://rest.api/rest/api/supervisionorders/1' - }, - }, - item: observableOf(createSuccessfulRemoteDataObject({})), - group: observableOf(createSuccessfulRemoteDataObject(GroupMock)) -}; -const anothersupervisionOrder: any = { - id: '2', - type: 'supervisionOrder', - uuid: 'supervision-order-2', - _links: { - item: { - href: 'https://rest.api/rest/api/eperson' - }, - group: { - href: 'https://rest.api/rest/api/group' - }, - self: { - href: 'https://rest.api/rest/api/supervisionorders/1' - }, - }, - item: observableOf(createSuccessfulRemoteDataObject({})), - group: observableOf(createSuccessfulRemoteDataObject(GroupMock)) -}; - -const pageInfo = new PageInfo(); -const array = [supervisionOrder, anothersupervisionOrder]; -const paginatedList = buildPaginatedList(pageInfo, array); -const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); - describe('ItemSearchResultListElementComponent', () => { beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [ItemSearchResultListElementComponent, TruncatePipe], providers: [ { provide: TruncatableService, useValue: {} }, - { 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,9 +201,6 @@ describe('ItemSearchResultListElementComponent', () => { })); beforeEach(waitForAsync(() => { - supervisionOrderDataService.searchByItem.and.returnValue(hot('a|', { - a: paginatedListRD - })); fixture = TestBed.createComponent(ItemSearchResultListElementComponent); publicationListElementComponent = fixture.componentInstance; @@ -463,13 +373,6 @@ describe('ItemSearchResultListElementComponent', () => { declarations: [ItemSearchResultListElementComponent, TruncatePipe], providers: [ {provide: TruncatableService, useValue: {}}, - {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 } ], @@ -481,9 +384,6 @@ describe('ItemSearchResultListElementComponent', () => { })); beforeEach(waitForAsync(() => { - supervisionOrderDataService.searchByItem.and.returnValue(hot('a|', { - a: paginatedListRD - })); fixture = TestBed.createComponent(ItemSearchResultListElementComponent); publicationListElementComponent = fixture.componentInstance; })); 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 7ed96fdc68..f84ae642ad 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 @@ -1,37 +1,10 @@ -import { Component, Inject } from '@angular/core'; -import { - listableObjectComponent -} from '../../../../../object-collection/shared/listable-object/listable-object.decorator'; +import { Component } from '@angular/core'; +import { listableObjectComponent } from '../../../../../object-collection/shared/listable-object/listable-object.decorator'; import { ViewMode } from '../../../../../../core/shared/view-mode.model'; import { ItemSearchResult } from '../../../../../object-collection/shared/item-search-result.model'; import { SearchResultListElementComponent } from '../../../search-result-list-element.component'; import { Item } from '../../../../../../core/shared/item.model'; import { getItemPageRoute } from '../../../../../../item-page/item-page-routing-paths'; -import { SupervisionOrderDataService } from '../../../../../../core/supervision-order/supervision-order-data.service'; -import { TruncatableService } from '../../../../../../shared/truncatable/truncatable.service'; -import { DSONameService } from '../../../../../../core/breadcrumbs/dso-name.service'; -import { APP_CONFIG, AppConfig } from '../../../../../../../config/app-config.interface'; -import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; -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'; -import { TranslateService } from '@ngx-translate/core'; -import { followLink } from '../../../../../../shared/utils/follow-link-config.model'; -import { - getAllSucceededRemoteData, - getAllSucceededRemoteListPayload, - getFirstSucceededRemoteDataPayload, - getRemoteDataPayload -} 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 { 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) @@ -44,8 +17,6 @@ import { FeatureID } from '../../../../../../core/data/feature-authorization/fea * The component for displaying a list element for an item search result of the type Publication */ export class ItemSearchResultListElementComponent extends SearchResultListElementComponent { - messagePrefix = 'item.search.result'; - /** * Route to the item's page */ @@ -56,112 +27,9 @@ export class ItemSearchResultListElementComponent extends SearchResultListElemen */ showThumbnails: boolean; - /** - * List of the supervision orders combined with the group - */ - supervisionOrder$: Observable<{ supervisionOrder: SupervisionOrder; group: Group; }[]>; - - /** - * The groups the user belongs to - */ - groups: Group[]; - - constructor( - protected truncatableService: TruncatableService, - protected dsoNameService: DSONameService, - @Inject(APP_CONFIG) protected appConfig: AppConfig, - protected supervisionOrderDataService: SupervisionOrderDataService, - 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); - 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, false, true, 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)) - ); - })); - }); - } - } - - /** - * Deletes the Group from the Repository. The Group will be the only that this form is showing. - * It'll either show a success or error message depending on whether the delete was successful or not. - */ - deleteSupervisionOrder(supervisionOrder) { - const modalRef = this.modalService.open(ConfirmationModalComponent); - modalRef.componentInstance.dso = supervisionOrder.group; - modalRef.componentInstance.headerLabel = this.messagePrefix + '.delete-supervision.modal.header'; - modalRef.componentInstance.infoLabel = this.messagePrefix + '.delete-supervision.modal.info'; - modalRef.componentInstance.cancelLabel = this.messagePrefix + '.delete-supervision.modal.cancel'; - modalRef.componentInstance.confirmLabel = this.messagePrefix + '.delete-supervision.modal.confirm'; - modalRef.componentInstance.brandColor = 'danger'; - modalRef.componentInstance.confirmIcon = 'fas fa-trash'; - modalRef.componentInstance.response.pipe(take(1)).subscribe((confirm: boolean) => { - if (confirm) { - if (hasValue(supervisionOrder.supervisionOrder.id)) { - 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( - this.translateService.get(this.messagePrefix + '.notification.deleted.failure.title', { name: supervisionOrder.group._name }), - this.translateService.get(this.messagePrefix + '.notification.deleted.failure.content')); - } - }); - } - } - }); } } From 75ebacf90ea34424e2af14f84878710277205cee Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Mon, 13 Feb 2023 20:55:30 +0100 Subject: [PATCH 10/10] [CST-7755] Complete refactoring --- ...item-admin-workflow-actions.component.html | 8 + ...item-admin-workflow-actions.component.scss | 0 ...m-admin-workflow-actions.component.spec.ts | 18 +- ...w-item-admin-workflow-actions.component.ts | 43 ++++ ...ision-order-group-selector.component.html} | 1 - ...ision-order-group-selector.component.scss} | 0 ...on-order-group-selector.component.spec.ts} | 20 +- ...rvision-order-group-selector.component.ts} | 27 ++- .../supervision-order-status.component.html | 15 ++ .../supervision-order-status.component.scss | 3 + ...supervision-order-status.component.spec.ts | 61 ++++++ .../supervision-order-status.component.ts | 24 +-- ...tem-admin-workflow-actions.component.html} | 13 +- ...item-admin-workflow-actions.component.scss | 1 + ...m-admin-workflow-actions.component.spec.ts | 156 ++++++++++++++ ...e-item-admin-workflow-actions.component.ts | 192 ++++++++++++++++++ ...in-workflow-grid-element.component.spec.ts | 18 +- ...admin-workflow-grid-element.component.html | 16 ++ ...dmin-workflow-grid-element.component.scss} | 0 ...in-workflow-grid-element.component.spec.ts | 127 ++++++++++++ ...t-admin-workflow-grid-element.component.ts | 158 ++++++++++++++ ...admin-workflow-list-element.component.html | 10 +- ...in-workflow-list-element.component.spec.ts | 10 +- ...t-admin-workflow-list-element.component.ts | 116 +---------- ...admin-workflow-list-element.component.html | 13 ++ ...dmin-workflow-list-element.component.scss} | 0 ...in-workflow-list-element.component.spec.ts | 111 ++++++++++ ...t-admin-workflow-list-element.component.ts | 109 ++++++++++ ...w-item-admin-workflow-actions.component.ts | 75 ------- .../admin-workflow.module.ts | 34 +++- .../detail/process-detail.component.ts | 1 - .../eperson-group-list.component.html | 0 .../eperson-group-list.component.scss | 0 .../eperson-group-list.component.spec.ts | 26 +-- .../eperson-group-list.component.ts | 32 +-- .../eperson-search-box.component.html | 0 .../eperson-search-box.component.spec.ts | 2 +- .../eperson-search-box.component.ts | 2 +- .../group-search-box.component.html | 0 .../group-search-box.component.spec.ts | 2 +- .../group-search-box.component.ts | 2 +- .../supervision-order-status.component.html | 13 -- ...supervision-order-status.component.spec.ts | 25 --- .../resource-policy-form.component.spec.ts | 4 +- src/app/shared/shared.module.ts | 34 ++-- .../shared/testing/supervision-order.mock.ts | 95 +++++++++ src/assets/i18n/en.json5 | 2 + 47 files changed, 1263 insertions(+), 356 deletions(-) create mode 100644 src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workflow-item/workflow-item-admin-workflow-actions.component.html rename src/app/admin/admin-workflow-page/admin-workflow-search-results/{ => actions/workflow-item}/workflow-item-admin-workflow-actions.component.scss (100%) rename src/app/admin/admin-workflow-page/admin-workflow-search-results/{ => actions/workflow-item}/workflow-item-admin-workflow-actions.component.spec.ts (75%) create mode 100644 src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workflow-item/workflow-item-admin-workflow-actions.component.ts rename src/app/{shared/dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component.html => admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/supervision-order-group-selector/supervision-order-group-selector.component.html} (95%) rename src/app/{shared/dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component.scss => admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/supervision-order-group-selector/supervision-order-group-selector.component.scss} (100%) rename src/app/{shared/dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component.spec.ts => admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/supervision-order-group-selector/supervision-order-group-selector.component.spec.ts} (69%) rename src/app/{shared/dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component.ts => admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/supervision-order-group-selector/supervision-order-group-selector.component.ts} (70%) create mode 100644 src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/supervision-order-status/supervision-order-status.component.html create mode 100644 src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/supervision-order-status/supervision-order-status.component.scss create mode 100644 src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/supervision-order-status/supervision-order-status.component.spec.ts rename src/app/{shared/object-list => admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item}/supervision-order-status/supervision-order-status.component.ts (82%) rename src/app/admin/admin-workflow-page/admin-workflow-search-results/{workflow-item-admin-workflow-actions.component.html => actions/workspace-item/workspace-item-admin-workflow-actions.component.html} (61%) create mode 100644 src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/workspace-item-admin-workflow-actions.component.scss create mode 100644 src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/workspace-item-admin-workflow-actions.component.spec.ts create mode 100644 src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/workspace-item-admin-workflow-actions.component.ts create mode 100644 src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-grid-element/workspace-item/workspace-item-search-result-admin-workflow-grid-element.component.html rename src/app/{shared/form/eperson-group-list/eperson-group-list.component.scss => admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-grid-element/workspace-item/workspace-item-search-result-admin-workflow-grid-element.component.scss} (100%) create mode 100644 src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-grid-element/workspace-item/workspace-item-search-result-admin-workflow-grid-element.component.spec.ts create mode 100644 src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-grid-element/workspace-item/workspace-item-search-result-admin-workflow-grid-element.component.ts create mode 100644 src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-list-element/workspace-item/workspace-item-search-result-admin-workflow-list-element.component.html rename src/app/{shared/object-list/supervision-order-status/supervision-order-status.component.scss => admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-list-element/workspace-item/workspace-item-search-result-admin-workflow-list-element.component.scss} (100%) create mode 100644 src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-list-element/workspace-item/workspace-item-search-result-admin-workflow-list-element.component.spec.ts create mode 100644 src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-list-element/workspace-item/workspace-item-search-result-admin-workflow-list-element.component.ts delete mode 100644 src/app/admin/admin-workflow-page/admin-workflow-search-results/workflow-item-admin-workflow-actions.component.ts rename src/app/shared/{form => }/eperson-group-list/eperson-group-list.component.html (100%) create mode 100644 src/app/shared/eperson-group-list/eperson-group-list.component.scss rename src/app/shared/{form => }/eperson-group-list/eperson-group-list.component.spec.ts (89%) rename src/app/shared/{form => }/eperson-group-list/eperson-group-list.component.ts (81%) rename src/app/shared/{form => }/eperson-group-list/eperson-search-box/eperson-search-box.component.html (100%) rename src/app/shared/{form => }/eperson-group-list/eperson-search-box/eperson-search-box.component.spec.ts (97%) rename src/app/shared/{form => }/eperson-group-list/eperson-search-box/eperson-search-box.component.ts (96%) rename src/app/shared/{form => }/eperson-group-list/group-search-box/group-search-box.component.html (100%) rename src/app/shared/{form => }/eperson-group-list/group-search-box/group-search-box.component.spec.ts (97%) rename src/app/shared/{form => }/eperson-group-list/group-search-box/group-search-box.component.ts (96%) delete mode 100644 src/app/shared/object-list/supervision-order-status/supervision-order-status.component.html delete mode 100644 src/app/shared/object-list/supervision-order-status/supervision-order-status.component.spec.ts create mode 100644 src/app/shared/testing/supervision-order.mock.ts diff --git a/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workflow-item/workflow-item-admin-workflow-actions.component.html b/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workflow-item/workflow-item-admin-workflow-actions.component.html new file mode 100644 index 0000000000..7f19ef3c2e --- /dev/null +++ b/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workflow-item/workflow-item-admin-workflow-actions.component.html @@ -0,0 +1,8 @@ + diff --git a/src/app/admin/admin-workflow-page/admin-workflow-search-results/workflow-item-admin-workflow-actions.component.scss b/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workflow-item/workflow-item-admin-workflow-actions.component.scss similarity index 100% rename from src/app/admin/admin-workflow-page/admin-workflow-search-results/workflow-item-admin-workflow-actions.component.scss rename to src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workflow-item/workflow-item-admin-workflow-actions.component.scss diff --git a/src/app/admin/admin-workflow-page/admin-workflow-search-results/workflow-item-admin-workflow-actions.component.spec.ts b/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workflow-item/workflow-item-admin-workflow-actions.component.spec.ts similarity index 75% rename from src/app/admin/admin-workflow-page/admin-workflow-search-results/workflow-item-admin-workflow-actions.component.spec.ts rename to src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workflow-item/workflow-item-admin-workflow-actions.component.spec.ts index 9b2bffffef..04377fcc81 100644 --- a/src/app/admin/admin-workflow-page/admin-workflow-search-results/workflow-item-admin-workflow-actions.component.spec.ts +++ b/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workflow-item/workflow-item-admin-workflow-actions.component.spec.ts @@ -4,17 +4,17 @@ import { NO_ERRORS_SCHEMA } from '@angular/core'; import { TranslateModule } from '@ngx-translate/core'; import { By } from '@angular/platform-browser'; import { RouterTestingModule } from '@angular/router/testing'; -import { URLCombiner } from '../../../core/url-combiner/url-combiner'; +import { URLCombiner } from '../../../../../core/url-combiner/url-combiner'; import { WorkflowItemAdminWorkflowActionsComponent } from './workflow-item-admin-workflow-actions.component'; -import { WorkflowItem } from '../../../core/submission/models/workflowitem.model'; +import { WorkflowItem } from '../../../../../core/submission/models/workflowitem.model'; import { getWorkflowItemDeleteRoute, getWorkflowItemSendBackRoute -} from '../../../workflowitems-edit-page/workflowitems-edit-page-routing-paths'; +} from '../../../../../workflowitems-edit-page/workflowitems-edit-page-routing-paths'; import { of } from 'rxjs'; -import { Item } from 'src/app/core/shared/item.model'; -import { RemoteData } from 'src/app/core/data/remote-data'; -import { RequestEntryState } from 'src/app/core/data/request-entry-state.model'; +import { Item } from '../../../../../core/shared/item.model'; +import { RemoteData } from '../../../../../core/data/remote-data'; +import { RequestEntryState } from '../../../../../core/data/request-entry-state.model'; describe('WorkflowItemAdminWorkflowActionsComponent', () => { let component: WorkflowItemAdminWorkflowActionsComponent; @@ -68,10 +68,4 @@ describe('WorkflowItemAdminWorkflowActionsComponent', () => { expect(link).toContain(new URLCombiner(getWorkflowItemSendBackRoute(wfi.id)).toString()); }); - it('should render a policies button with the correct link', () => { - const a = fixture.debugElement.query(By.css('a.policies-link')); - const link = a.nativeElement.href; - expect(link).toContain(new URLCombiner('/items/itemUUID1111/edit/bitstreams').toString()); - }); - }); diff --git a/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workflow-item/workflow-item-admin-workflow-actions.component.ts b/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workflow-item/workflow-item-admin-workflow-actions.component.ts new file mode 100644 index 0000000000..480c48f25e --- /dev/null +++ b/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workflow-item/workflow-item-admin-workflow-actions.component.ts @@ -0,0 +1,43 @@ +import { Component, Input } from '@angular/core'; + +import { WorkflowItem } from '../../../../../core/submission/models/workflowitem.model'; +import { + getWorkflowItemDeleteRoute, + getWorkflowItemSendBackRoute +} from '../../../../../workflowitems-edit-page/workflowitems-edit-page-routing-paths'; + +@Component({ + selector: 'ds-workflow-item-admin-workflow-actions-element', + styleUrls: ['./workflow-item-admin-workflow-actions.component.scss'], + templateUrl: './workflow-item-admin-workflow-actions.component.html' +}) +/** + * The component for displaying the actions for a list element for a workflow-item on the admin workflow search page + */ +export class WorkflowItemAdminWorkflowActionsComponent { + + /** + * The workflow item to perform the actions on + */ + @Input() public wfi: WorkflowItem; + + /** + * Whether to use small buttons or not + */ + @Input() public small: boolean; + + /** + * Returns the path to the delete page of this workflow item + */ + getDeleteRoute(): string { + return getWorkflowItemDeleteRoute(this.wfi.id); + } + + /** + * Returns the path to the send back page of this workflow item + */ + getSendBackRoute(): string { + return getWorkflowItemSendBackRoute(this.wfi.id); + } + +} diff --git a/src/app/shared/dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component.html b/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/supervision-order-group-selector/supervision-order-group-selector.component.html similarity index 95% rename from src/app/shared/dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component.html rename to src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/supervision-order-group-selector/supervision-order-group-selector.component.html index c6d45c8743..3ad1dce0b8 100644 --- a/src/app/shared/dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component.html +++ b/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/supervision-order-group-selector/supervision-order-group-selector.component.html @@ -11,7 +11,6 @@ diff --git a/src/app/shared/dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component.scss b/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/supervision-order-group-selector/supervision-order-group-selector.component.scss similarity index 100% rename from src/app/shared/dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component.scss rename to src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/supervision-order-group-selector/supervision-order-group-selector.component.scss diff --git a/src/app/shared/dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component.spec.ts b/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/supervision-order-group-selector/supervision-order-group-selector.component.spec.ts similarity index 69% rename from src/app/shared/dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component.spec.ts rename to src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/supervision-order-group-selector/supervision-order-group-selector.component.spec.ts index b5e62ef8ac..6e917ed088 100644 --- a/src/app/shared/dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component.spec.ts +++ b/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/supervision-order-group-selector/supervision-order-group-selector.component.spec.ts @@ -2,16 +2,16 @@ import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; import { TranslateModule } from '@ngx-translate/core'; import { DebugElement, NO_ERRORS_SCHEMA } from '@angular/core'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; -import { SupervisionGroupSelectorComponent } from './supervision-group-selector.component'; -import { SupervisionOrderDataService } from '../../../../core/supervision-order/supervision-order-data.service'; -import { NotificationsService } from '../../../../shared/notifications/notifications.service'; -import { Group } from '../../../../core/eperson/models/group.model'; -import { SupervisionOrder } from '../../../../core/supervision-order/models/supervision-order.model'; +import { SupervisionOrderGroupSelectorComponent } from './supervision-order-group-selector.component'; +import { SupervisionOrderDataService } from '../../../../../../core/supervision-order/supervision-order-data.service'; +import { NotificationsService } from '../../../../../../shared/notifications/notifications.service'; +import { Group } from '../../../../../../core/eperson/models/group.model'; +import { SupervisionOrder } from '../../../../../../core/supervision-order/models/supervision-order.model'; import { of } from 'rxjs'; -describe('SupervisionGroupSelectorComponent', () => { - let component: SupervisionGroupSelectorComponent; - let fixture: ComponentFixture; +describe('SupervisionOrderGroupSelectorComponent', () => { + let component: SupervisionOrderGroupSelectorComponent; + let fixture: ComponentFixture; let debugElement: DebugElement; const modalStub = jasmine.createSpyObj('modalStub', ['close']); @@ -32,7 +32,7 @@ describe('SupervisionGroupSelectorComponent', () => { beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [TranslateModule.forRoot()], - declarations: [SupervisionGroupSelectorComponent], + declarations: [SupervisionOrderGroupSelectorComponent], providers: [ { provide: NgbActiveModal, useValue: modalStub }, { provide: SupervisionOrderDataService, useValue: supervisionOrderDataService }, @@ -44,7 +44,7 @@ describe('SupervisionGroupSelectorComponent', () => { })); beforeEach(waitForAsync(() => { - fixture = TestBed.createComponent(SupervisionGroupSelectorComponent); + fixture = TestBed.createComponent(SupervisionOrderGroupSelectorComponent); component = fixture.componentInstance; })); diff --git a/src/app/shared/dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component.ts b/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/supervision-order-group-selector/supervision-order-group-selector.component.ts similarity index 70% rename from src/app/shared/dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component.ts rename to src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/supervision-order-group-selector/supervision-order-group-selector.component.ts index da22fe0d44..bbb1df3c49 100644 --- a/src/app/shared/dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component.ts +++ b/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/supervision-order-group-selector/supervision-order-group-selector.component.ts @@ -1,13 +1,13 @@ -import { Component } from '@angular/core'; +import { Component, EventEmitter, Output } from '@angular/core'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { TranslateService } from '@ngx-translate/core'; import { getFirstCompletedRemoteData } from 'src/app/core/shared/operators'; import { NotificationsService } from 'src/app/shared/notifications/notifications.service'; -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'; +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 { RemoteData } from '../../../../../../core/data/remote-data'; /** * Component to wrap a dropdown - for type of order - @@ -18,10 +18,10 @@ import { followLink } from '../../../../shared/utils/follow-link-config.model'; @Component({ selector: 'ds-supervision-group-selector', - styleUrls: ['./supervision-group-selector.component.scss'], - templateUrl: './supervision-group-selector.component.html', + styleUrls: ['./supervision-order-group-selector.component.scss'], + templateUrl: './supervision-order-group-selector.component.html', }) -export class SupervisionGroupSelectorComponent { +export class SupervisionOrderGroupSelectorComponent { /** * The item to perform the actions on @@ -43,6 +43,11 @@ export class SupervisionGroupSelectorComponent { */ isSubmitted = false; + /** + * Event emitted when a new SupervisionOrder has been created + */ + @Output() create: EventEmitter = new EventEmitter(); + constructor( public dsoNameService: DSONameService, private activeModal: NgbActiveModal, @@ -75,10 +80,10 @@ export class SupervisionGroupSelectorComponent { supervisionDataObject.ordertype = this.selectedOrderType; this.supervisionOrderDataService.create(supervisionDataObject, this.itemUUID, this.selectedGroup.uuid, this.selectedOrderType).pipe( getFirstCompletedRemoteData(), - ).subscribe(rd => { + ).subscribe((rd: RemoteData) => { 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 })); + this.create.emit(rd.payload); this.close(); } else { this.notificationsService.error( diff --git a/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/supervision-order-status/supervision-order-status.component.html b/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/supervision-order-status/supervision-order-status.component.html new file mode 100644 index 0000000000..fa6a2eafff --- /dev/null +++ b/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/supervision-order-status/supervision-order-status.component.html @@ -0,0 +1,15 @@ + +
+
+ {{'workflow-item.search.result.list.element.supervised-by' | translate}} +
+ +
+
diff --git a/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/supervision-order-status/supervision-order-status.component.scss b/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/supervision-order-status/supervision-order-status.component.scss new file mode 100644 index 0000000000..7818e34054 --- /dev/null +++ b/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/supervision-order-status/supervision-order-status.component.scss @@ -0,0 +1,3 @@ +.badge { + cursor: pointer; +} diff --git a/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/supervision-order-status/supervision-order-status.component.spec.ts b/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/supervision-order-status/supervision-order-status.component.spec.ts new file mode 100644 index 0000000000..2f4ed631cc --- /dev/null +++ b/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/supervision-order-status/supervision-order-status.component.spec.ts @@ -0,0 +1,61 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { NO_ERRORS_SCHEMA, SimpleChange } from '@angular/core'; +import { By } from '@angular/platform-browser'; + +import { NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; + +import { SupervisionOrderStatusComponent } from './supervision-order-status.component'; +import { VarDirective } from '../../../../../../shared/utils/var.directive'; +import { TranslateLoaderMock } from '../../../../../../shared/mocks/translate-loader.mock'; +import { supervisionOrderListMock } from '../../../../../../shared/testing/supervision-order.mock'; + +describe('SupervisionOrderStatusComponent', () => { + let component: SupervisionOrderStatusComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ + NgbTooltipModule, + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateLoaderMock + } + }) + ], + declarations: [ SupervisionOrderStatusComponent, VarDirective ], + schemas: [ + NO_ERRORS_SCHEMA + ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SupervisionOrderStatusComponent); + component = fixture.componentInstance; + component.supervisionOrderList = supervisionOrderListMock; + component.ngOnChanges( { + supervisionOrderList: new SimpleChange(null, supervisionOrderListMock, true) + }); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should render badges properly', () => { + const badges = fixture.debugElement.queryAll(By.css('[data-test="soBadge"]')); + expect(badges.length).toBe(2); + }); + + it('should emit delete event on click', () => { + spyOn(component.delete, 'emit'); + const badges = fixture.debugElement.queryAll(By.css('[data-test="soBadge"]')); + badges[0].nativeElement.click(); + expect(component.delete.emit).toHaveBeenCalled(); + }); +}); diff --git a/src/app/shared/object-list/supervision-order-status/supervision-order-status.component.ts b/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/supervision-order-status/supervision-order-status.component.ts similarity index 82% rename from src/app/shared/object-list/supervision-order-status/supervision-order-status.component.ts rename to src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/supervision-order-status/supervision-order-status.component.ts index 92cbf17885..11b6400ffd 100644 --- a/src/app/shared/object-list/supervision-order-status/supervision-order-status.component.ts +++ b/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/supervision-order-status/supervision-order-status.component.ts @@ -3,11 +3,11 @@ import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from import { BehaviorSubject, from, Observable } from 'rxjs'; import { map, mergeMap, reduce } from 'rxjs/operators'; -import { SupervisionOrder } from '../../../core/supervision-order/models/supervision-order.model'; -import { Group } from '../../../core/eperson/models/group.model'; -import { getFirstCompletedRemoteData } from '../../../core/shared/operators'; -import { isNotEmpty } from '../../empty.util'; -import { RemoteData } from '../../../core/data/remote-data'; +import { SupervisionOrder } from '../../../../../../core/supervision-order/models/supervision-order.model'; +import { Group } from '../../../../../../core/eperson/models/group.model'; +import { getFirstCompletedRemoteData } from '../../../../../../core/shared/operators'; +import { isNotEmpty } from '../../../../../../shared/empty.util'; +import { RemoteData } from '../../../../../../core/data/remote-data'; export interface SupervisionOrderListEntry { supervisionOrder: SupervisionOrder; @@ -26,11 +26,6 @@ export class SupervisionOrderStatusComponent implements OnChanges { */ @Input() supervisionOrderList: SupervisionOrder[] = []; - /** - * The groups the user belongs to - */ - groups: Group[]; - /** * List of the supervision orders combined with the group */ @@ -42,10 +37,9 @@ export class SupervisionOrderStatusComponent implements OnChanges { if (changes && changes.supervisionOrderList) { this.getSupervisionOrderEntries(changes.supervisionOrderList.currentValue) .subscribe((supervisionOrderEntries: SupervisionOrderListEntry[]) => { - this.supervisionOrderEntries$.next(supervisionOrderEntries) - }) + this.supervisionOrderEntries$.next(supervisionOrderEntries); + }); } - console.log('ngOnChanges', changes); } /** @@ -71,12 +65,12 @@ export class SupervisionOrderStatusComponent implements OnChanges { )), reduce((acc: SupervisionOrderListEntry[], value: any) => { if (isNotEmpty(value)) { - return [...acc, value] + return [...acc, value]; } else { return acc; } }, []), - ) + ); } /** diff --git a/src/app/admin/admin-workflow-page/admin-workflow-search-results/workflow-item-admin-workflow-actions.component.html b/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/workspace-item-admin-workflow-actions.component.html similarity index 61% rename from src/app/admin/admin-workflow-page/admin-workflow-search-results/workflow-item-admin-workflow-actions.component.html rename to src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/workspace-item-admin-workflow-actions.component.html index f458476bc5..2b904a5429 100644 --- a/src/app/admin/admin-workflow-page/admin-workflow-search-results/workflow-item-admin-workflow-actions.component.html +++ b/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/workspace-item-admin-workflow-actions.component.html @@ -1,15 +1,16 @@ +
+ +
+ diff --git a/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/workspace-item-admin-workflow-actions.component.scss b/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/workspace-item-admin-workflow-actions.component.scss new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/workspace-item-admin-workflow-actions.component.scss @@ -0,0 +1 @@ + diff --git a/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/workspace-item-admin-workflow-actions.component.spec.ts b/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/workspace-item-admin-workflow-actions.component.spec.ts new file mode 100644 index 0000000000..628fc3f89c --- /dev/null +++ b/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/workspace-item-admin-workflow-actions.component.spec.ts @@ -0,0 +1,156 @@ +import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { By } from '@angular/platform-browser'; +import { RouterTestingModule } from '@angular/router/testing'; + +import { of } from 'rxjs'; +import { NgbModalModule } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateModule } from '@ngx-translate/core'; + +import { URLCombiner } from '../../../../../core/url-combiner/url-combiner'; +import { WorkspaceItemAdminWorkflowActionsComponent } from './workspace-item-admin-workflow-actions.component'; +import { WorkspaceItem } from '../../../../../core/submission/models/workspaceitem.model'; +import { + getWorkflowItemDeleteRoute, +} from '../../../../../workflowitems-edit-page/workflowitems-edit-page-routing-paths'; +import { Item } from '../../../../../core/shared/item.model'; +import { RemoteData } from '../../../../../core/data/remote-data'; +import { RequestEntryState } from '../../../../../core/data/request-entry-state.model'; +import { NotificationsServiceStub } from '../../../../../shared/testing/notifications-service.stub'; +import { NotificationsService } from '../../../../../shared/notifications/notifications.service'; +import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service'; +import { DSONameServiceMock } from '../../../../../shared/mocks/dso-name.service.mock'; +import { SupervisionOrderDataService } from '../../../../../core/supervision-order/supervision-order-data.service'; +import { ConfirmationModalComponent } from '../../../../../shared/confirmation-modal/confirmation-modal.component'; +import { supervisionOrderEntryMock } from '../../../../../shared/testing/supervision-order.mock'; +import { + SupervisionOrderGroupSelectorComponent +} from './supervision-order-group-selector/supervision-order-group-selector.component'; + +describe('WorkspaceItemAdminWorkflowActionsComponent', () => { + let component: WorkspaceItemAdminWorkflowActionsComponent; + let fixture: ComponentFixture; + let id; + let wsi; + let item = new Item(); + item.uuid = 'itemUUID1111'; + const rd = new RemoteData(undefined, undefined, undefined, RequestEntryState.Success, undefined, item, 200); + let supervisionOrderDataService; + let notificationService: NotificationsServiceStub; + + function init() { + notificationService = new NotificationsServiceStub(); + supervisionOrderDataService = jasmine.createSpyObj('supervisionOrderDataService', { + searchByItem: jasmine.createSpy('searchByItem'), + delete: jasmine.createSpy('delete'), + }); + id = '780b2588-bda5-4112-a1cd-0b15000a5339'; + wsi = new WorkspaceItem(); + wsi.id = id; + wsi.item = of(rd); + } + + beforeEach(waitForAsync(() => { + init(); + TestBed.configureTestingModule({ + imports: [ + NgbModalModule, + TranslateModule.forRoot(), + RouterTestingModule.withRoutes([]) + ], + declarations: [WorkspaceItemAdminWorkflowActionsComponent], + providers: [ + { provide: DSONameService, useClass: DSONameServiceMock }, + { provide: NotificationsService, useValue: notificationService }, + { provide: SupervisionOrderDataService, useValue: supervisionOrderDataService } + ], + schemas: [NO_ERRORS_SCHEMA] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(WorkspaceItemAdminWorkflowActionsComponent); + component = fixture.componentInstance; + component.wsi = wsi; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should render a delete button with the correct link', () => { + const button = fixture.debugElement.query(By.css('a.delete-link')); + const link = button.nativeElement.href; + expect(link).toContain(new URLCombiner(getWorkflowItemDeleteRoute(wsi.id)).toString()); + }); + + it('should render a policies button with the correct link', () => { + const a = fixture.debugElement.query(By.css('a.policies-link')); + const link = a.nativeElement.href; + expect(link).toContain(new URLCombiner('/items/itemUUID1111/edit/authorizations').toString()); + }); + + describe('deleteSupervisionOrder', () => { + + beforeEach(() => { + spyOn(component.delete, 'emit'); + spyOn((component as any).modalService, 'open').and.returnValue({ + componentInstance: { response: of(true) } + }); + }); + + describe('when delete succeeded', () => { + + beforeEach(() => { + supervisionOrderDataService.delete.and.returnValue(of(true)); + }); + + it('should notify success', () => { + component.deleteSupervisionOrder(supervisionOrderEntryMock); + expect((component as any).modalService.open).toHaveBeenCalledWith(ConfirmationModalComponent); + expect(notificationService.success).toHaveBeenCalled(); + expect(component.delete.emit).toHaveBeenCalled(); + }); + + }); + + describe('when delete failed', () => { + + beforeEach(() => { + supervisionOrderDataService.delete.and.returnValue(of(false)); + }); + + it('should notify success', () => { + component.deleteSupervisionOrder(supervisionOrderEntryMock); + expect((component as any).modalService.open).toHaveBeenCalledWith(ConfirmationModalComponent); + expect(notificationService.error).toHaveBeenCalled(); + expect(component.delete.emit).not.toHaveBeenCalled(); + }); + + }); + + }); + + describe('openSupervisionModal', () => { + + beforeEach(() => { + spyOn(component.create, 'emit'); + spyOn((component as any).modalService, 'open').and.returnValue({ + componentInstance: { create: of(true) } + }); + }); + + it('should emit create event properly', () => { + component.openSupervisionModal(); + expect((component as any).modalService.open).toHaveBeenCalledWith(SupervisionOrderGroupSelectorComponent, { + size: 'lg', + backdrop: 'static' + }); + expect(component.create.emit).toHaveBeenCalled(); + }); + }); + + +}); diff --git a/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/workspace-item-admin-workflow-actions.component.ts b/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/workspace-item-admin-workflow-actions.component.ts new file mode 100644 index 0000000000..adbd421628 --- /dev/null +++ b/src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/workspace-item-admin-workflow-actions.component.ts @@ -0,0 +1,192 @@ +import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; + +import { map, Observable } from 'rxjs'; +import { switchMap, take, tap } from 'rxjs/operators'; +import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateService } from '@ngx-translate/core'; + +import { Item } from '../../../../../core/shared/item.model'; +import { getFirstSucceededRemoteDataPayload } from '../../../../../core/shared/operators'; +import { + SupervisionOrderGroupSelectorComponent +} from './supervision-order-group-selector/supervision-order-group-selector.component'; +import { + getWorkflowItemDeleteRoute +} from '../../../../../workflowitems-edit-page/workflowitems-edit-page-routing-paths'; +import { ITEM_EDIT_AUTHORIZATIONS_PATH } from '../../../../../item-page/edit-item-page/edit-item-page.routing-paths'; +import { WorkspaceItem } from '../../../../../core/submission/models/workspaceitem.model'; +import { SupervisionOrder } from '../../../../../core/supervision-order/models/supervision-order.model'; +import { SupervisionOrderListEntry } from './supervision-order-status/supervision-order-status.component'; +import { ConfirmationModalComponent } from '../../../../../shared/confirmation-modal/confirmation-modal.component'; +import { hasValue } from '../../../../../shared/empty.util'; +import { NotificationsService } from '../../../../../shared/notifications/notifications.service'; +import { SupervisionOrderDataService } from '../../../../../core/supervision-order/supervision-order-data.service'; +import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service'; +import { DSpaceObject } from '../../../../../core/shared/dspace-object.model'; +import { getSearchResultFor } from '../../../../../shared/search/search-result-element-decorator'; + +@Component({ + selector: 'ds-workspace-item-admin-workflow-actions-element', + styleUrls: ['./workspace-item-admin-workflow-actions.component.scss'], + templateUrl: './workspace-item-admin-workflow-actions.component.html' +}) +/** + * The component for displaying the actions for a list element for a workspace-item on the admin workflow search page + */ +export class WorkspaceItemAdminWorkflowActionsComponent implements OnInit { + + /** + * The workspace item to perform the actions on + */ + @Input() public wsi: WorkspaceItem; + + /** + * Whether to use small buttons or not + */ + @Input() public small: boolean; + + /** + * The list of supervision order object to show + */ + @Input() supervisionOrderList: SupervisionOrder[] = []; + + /** + * The item related to the workspace item + */ + item: Item; + + /** + * An array containing the route to the resource policies page + */ + resourcePoliciesPageRoute: string[]; + + /** + * The i18n keys prefix + * @private + */ + private messagePrefix = 'workflow-item.search.result'; + + /** + * Event emitted when a new SupervisionOrder has been created + */ + @Output() create: EventEmitter = new EventEmitter(); + + /** + * Event emitted when new SupervisionOrder has been deleted + */ + @Output() delete: EventEmitter = new EventEmitter(); + + /** + * Event emitted when a new SupervisionOrder has been created + */ + constructor( + protected dsoNameService: DSONameService, + protected modalService: NgbModal, + protected notificationsService: NotificationsService, + protected supervisionOrderDataService: SupervisionOrderDataService, + protected translateService: TranslateService, + ) { + } + + ngOnInit(): void { + const item$: Observable = this.wsi.item.pipe( + getFirstSucceededRemoteDataPayload(), + ); + + item$.pipe( + map((item: Item) => this.getPoliciesRoute(item)) + ).subscribe((route: string[]) => { + this.resourcePoliciesPageRoute = route; + }); + + item$.subscribe((item: Item) => { + this.item = item; + }); + } + + /** + * Returns the path to the delete page of this workflow item + */ + getDeleteRoute(): string { + return getWorkflowItemDeleteRoute(this.wsi.id); + } + + /** + * Returns the path to the administrative edit page policies tab + */ + getPoliciesRoute(item: Item): string[] { + return ['/items', item.uuid, 'edit', ITEM_EDIT_AUTHORIZATIONS_PATH]; + } + + /** + * Deletes the Group from the Repository. The Group will be the only that this form is showing. + * It'll either show a success or error message depending on whether delete was successful or not. + */ + deleteSupervisionOrder(supervisionOrderEntry: SupervisionOrderListEntry) { + const modalRef = this.modalService.open(ConfirmationModalComponent); + modalRef.componentInstance.dso = supervisionOrderEntry.group; + modalRef.componentInstance.headerLabel = this.messagePrefix + '.delete-supervision.modal.header'; + modalRef.componentInstance.infoLabel = this.messagePrefix + '.delete-supervision.modal.info'; + modalRef.componentInstance.cancelLabel = this.messagePrefix + '.delete-supervision.modal.cancel'; + modalRef.componentInstance.confirmLabel = this.messagePrefix + '.delete-supervision.modal.confirm'; + modalRef.componentInstance.brandColor = 'danger'; + modalRef.componentInstance.confirmIcon = 'fas fa-trash'; + modalRef.componentInstance.response.pipe( + take(1), + switchMap((confirm: boolean) => { + if (confirm && hasValue(supervisionOrderEntry.supervisionOrder.id)) { + return this.supervisionOrderDataService.delete(supervisionOrderEntry.supervisionOrder.id).pipe( + take(1), + tap((result: boolean) => { + if (result) { + this.notificationsService.success( + null, + this.translateService.get( + this.messagePrefix + '.notification.deleted.success', + { name: this.dsoNameService.getName(supervisionOrderEntry.group) } + ) + ); + } else { + this.notificationsService.error( + null, + this.translateService.get( + this.messagePrefix + '.notification.deleted.failure', + { name: this.dsoNameService.getName(supervisionOrderEntry.group) } + ) + ); + } + }) + ); + } + }) + ).subscribe((result: boolean) => { + if (result) { + this.delete.emit(this.convertReloadedObject()); + } + }); + } + + /** + * Opens the Supervision Modal to create a supervision order + */ + openSupervisionModal() { + const supervisionModal: NgbModalRef = this.modalService.open(SupervisionOrderGroupSelectorComponent, { + size: 'lg', + backdrop: 'static' + }); + supervisionModal.componentInstance.itemUUID = this.item.uuid; + supervisionModal.componentInstance.create.subscribe(() => { + this.create.emit(this.convertReloadedObject()); + }); + } + + /** + * Convert the reloadedObject to the Type required by this dso. + */ + private convertReloadedObject(): DSpaceObject { + const constructor = getSearchResultFor((this.wsi as any).constructor); + return Object.assign(new constructor(), this.wsi, { + indexableObject: this.wsi + }); + } +} diff --git a/src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-grid-element/workflow-item/workflow-item-search-result-admin-workflow-grid-element.component.spec.ts b/src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-grid-element/workflow-item/workflow-item-search-result-admin-workflow-grid-element.component.spec.ts index 0b933d0859..8035c53547 100644 --- a/src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-grid-element/workflow-item/workflow-item-search-result-admin-workflow-grid-element.component.spec.ts +++ b/src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-grid-element/workflow-item/workflow-item-search-result-admin-workflow-grid-element.component.spec.ts @@ -7,14 +7,22 @@ import { TruncatableService } from '../../../../../shared/truncatable/truncatabl import { CollectionElementLinkType } from '../../../../../shared/object-collection/collection-element-link.type'; import { ViewMode } from '../../../../../core/shared/view-mode.model'; import { RouterTestingModule } from '@angular/router/testing'; -import { WorkflowItemSearchResultAdminWorkflowGridElementComponent } from './workflow-item-search-result-admin-workflow-grid-element.component'; +import { + WorkflowItemSearchResultAdminWorkflowGridElementComponent +} from './workflow-item-search-result-admin-workflow-grid-element.component'; import { WorkflowItem } from '../../../../../core/submission/models/workflowitem.model'; import { LinkService } from '../../../../../core/cache/builders/link.service'; import { followLink } from '../../../../../shared/utils/follow-link-config.model'; import { Item } from '../../../../../core/shared/item.model'; -import { ItemGridElementComponent } from '../../../../../shared/object-grid/item-grid-element/item-types/item/item-grid-element.component'; -import { ListableObjectDirective } from '../../../../../shared/object-collection/shared/listable-object/listable-object.directive'; -import { WorkflowItemSearchResult } from '../../../../../shared/object-collection/shared/workflow-item-search-result.model'; +import { + ItemGridElementComponent +} from '../../../../../shared/object-grid/item-grid-element/item-types/item/item-grid-element.component'; +import { + ListableObjectDirective +} from '../../../../../shared/object-collection/shared/listable-object/listable-object.directive'; +import { + WorkflowItemSearchResult +} from '../../../../../shared/object-collection/shared/workflow-item-search-result.model'; import { BitstreamDataService } from '../../../../../core/data/bitstream-data.service'; import { createSuccessfulRemoteDataObject$ } from '../../../../../shared/remote-data.utils'; import { getMockLinkService } from '../../../../../shared/mocks/link-service.mock'; @@ -22,7 +30,7 @@ import { of as observableOf } from 'rxjs'; import { getMockThemeService } from '../../../../../shared/mocks/theme-service.mock'; import { ThemeService } from '../../../../../shared/theme-support/theme.service'; -describe('WorkflowItemAdminWorkflowGridElementComponent', () => { +describe('WorkflowItemSearchResultAdminWorkflowGridElementComponent', () => { let component: WorkflowItemSearchResultAdminWorkflowGridElementComponent; let fixture: ComponentFixture; let id; diff --git a/src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-grid-element/workspace-item/workspace-item-search-result-admin-workflow-grid-element.component.html b/src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-grid-element/workspace-item/workspace-item-search-result-admin-workflow-grid-element.component.html new file mode 100644 index 0000000000..767ad79786 --- /dev/null +++ b/src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-grid-element/workspace-item/workspace-item-search-result-admin-workflow-grid-element.component.html @@ -0,0 +1,16 @@ + + +
+
+ {{ "admin.workflow.item.workspace" | translate }} +
+
+
    +
  • + +
  • +
diff --git a/src/app/shared/form/eperson-group-list/eperson-group-list.component.scss b/src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-grid-element/workspace-item/workspace-item-search-result-admin-workflow-grid-element.component.scss similarity index 100% rename from src/app/shared/form/eperson-group-list/eperson-group-list.component.scss rename to src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-grid-element/workspace-item/workspace-item-search-result-admin-workflow-grid-element.component.scss diff --git a/src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-grid-element/workspace-item/workspace-item-search-result-admin-workflow-grid-element.component.spec.ts b/src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-grid-element/workspace-item/workspace-item-search-result-admin-workflow-grid-element.component.spec.ts new file mode 100644 index 0000000000..b9e752c104 --- /dev/null +++ b/src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-grid-element/workspace-item/workspace-item-search-result-admin-workflow-grid-element.component.spec.ts @@ -0,0 +1,127 @@ +import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { RouterTestingModule } from '@angular/router/testing'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; + +import { of as observableOf } from 'rxjs'; +import { TranslateModule } from '@ngx-translate/core'; + +import { TruncatableService } from '../../../../../shared/truncatable/truncatable.service'; +import { CollectionElementLinkType } from '../../../../../shared/object-collection/collection-element-link.type'; +import { ViewMode } from '../../../../../core/shared/view-mode.model'; +import { + WorkspaceItemSearchResultAdminWorkflowGridElementComponent +} from './workspace-item-search-result-admin-workflow-grid-element.component'; +import { WorkflowItem } from '../../../../../core/submission/models/workflowitem.model'; +import { LinkService } from '../../../../../core/cache/builders/link.service'; +import { followLink } from '../../../../../shared/utils/follow-link-config.model'; +import { Item } from '../../../../../core/shared/item.model'; +import { + ItemGridElementComponent +} from '../../../../../shared/object-grid/item-grid-element/item-types/item/item-grid-element.component'; +import { + ListableObjectDirective +} from '../../../../../shared/object-collection/shared/listable-object/listable-object.directive'; +import { + WorkflowItemSearchResult +} from '../../../../../shared/object-collection/shared/workflow-item-search-result.model'; +import { BitstreamDataService } from '../../../../../core/data/bitstream-data.service'; +import { createSuccessfulRemoteDataObject$ } from '../../../../../shared/remote-data.utils'; +import { getMockLinkService } from '../../../../../shared/mocks/link-service.mock'; +import { getMockThemeService } from '../../../../../shared/mocks/theme-service.mock'; +import { ThemeService } from '../../../../../shared/theme-support/theme.service'; +import { + supervisionOrderPaginatedListRD, + supervisionOrderPaginatedListRD$ +} from '../../../../../shared/testing/supervision-order.mock'; +import { SupervisionOrderDataService } from '../../../../../core/supervision-order/supervision-order-data.service'; +import { DSpaceObject } from '../../../../../core/shared/dspace-object.model'; + +describe('WorkspaceItemSearchResultAdminWorkflowGridElementComponent', () => { + let component: WorkspaceItemSearchResultAdminWorkflowGridElementComponent; + let fixture: ComponentFixture; + let id; + let wfi; + let itemRD$; + let linkService; + let object; + let themeService; + let supervisionOrderDataService; + + function init() { + itemRD$ = createSuccessfulRemoteDataObject$(new Item()); + id = '780b2588-bda5-4112-a1cd-0b15000a5339'; + object = new WorkflowItemSearchResult(); + wfi = new WorkflowItem(); + wfi.item = itemRD$; + object.indexableObject = wfi; + linkService = getMockLinkService(); + themeService = getMockThemeService(); + supervisionOrderDataService = jasmine.createSpyObj('supervisionOrderDataService', { + searchByItem: jasmine.createSpy('searchByItem'), + delete: jasmine.createSpy('delete'), + }); + } + + beforeEach(waitForAsync(() => { + init(); + TestBed.configureTestingModule( + { + declarations: [WorkspaceItemSearchResultAdminWorkflowGridElementComponent, ItemGridElementComponent, ListableObjectDirective], + imports: [ + NoopAnimationsModule, + TranslateModule.forRoot(), + RouterTestingModule.withRoutes([]), + ], + providers: [ + { provide: LinkService, useValue: linkService }, + { provide: ThemeService, useValue: themeService }, + { + provide: TruncatableService, useValue: { + isCollapsed: () => observableOf(true), + } + }, + { provide: BitstreamDataService, useValue: {} }, + { provide: SupervisionOrderDataService, useValue: supervisionOrderDataService } + ], + schemas: [NO_ERRORS_SCHEMA] + }) + .overrideComponent(WorkspaceItemSearchResultAdminWorkflowGridElementComponent, { + set: { + entryComponents: [ItemGridElementComponent] + } + }) + .compileComponents(); + })); + + beforeEach(() => { + linkService.resolveLink.and.callFake((a) => a); + fixture = TestBed.createComponent(WorkspaceItemSearchResultAdminWorkflowGridElementComponent); + component = fixture.componentInstance; + component.object = object; + component.linkTypes = CollectionElementLinkType; + component.index = 0; + component.viewModes = ViewMode; + supervisionOrderDataService.searchByItem.and.returnValue(supervisionOrderPaginatedListRD$); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should retrieve the item using the link service', () => { + expect(linkService.resolveLink).toHaveBeenCalledWith(wfi, followLink('item')); + }); + + it('should retrieve supervision order objects properly', () => { + expect(component.supervisionOrder$.value).toEqual(supervisionOrderPaginatedListRD.payload.page); + }); + + it('should emit reloadedObject properly ', () => { + spyOn(component.reloadedObject, 'emit'); + const dso = new DSpaceObject(); + component.reloadObject(dso); + expect(component.reloadedObject.emit).toHaveBeenCalledWith(dso); + }); +}); diff --git a/src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-grid-element/workspace-item/workspace-item-search-result-admin-workflow-grid-element.component.ts b/src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-grid-element/workspace-item/workspace-item-search-result-admin-workflow-grid-element.component.ts new file mode 100644 index 0000000000..f18c18ca1c --- /dev/null +++ b/src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-grid-element/workspace-item/workspace-item-search-result-admin-workflow-grid-element.component.ts @@ -0,0 +1,158 @@ +import { Component, ComponentFactoryResolver, ElementRef, ViewChild } from '@angular/core'; + +import { BehaviorSubject, Observable } from 'rxjs'; +import { map, mergeMap, take, tap } from 'rxjs/operators'; + +import { Item } from '../../../../../core/shared/item.model'; +import { ViewMode } from '../../../../../core/shared/view-mode.model'; +import { + getListableObjectComponent, + listableObjectComponent +} from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator'; +import { Context } from '../../../../../core/shared/context.model'; +import { + SearchResultGridElementComponent +} from '../../../../../shared/object-grid/search-result-grid-element/search-result-grid-element.component'; +import { TruncatableService } from '../../../../../shared/truncatable/truncatable.service'; +import { BitstreamDataService } from '../../../../../core/data/bitstream-data.service'; +import { GenericConstructor } from '../../../../../core/shared/generic-constructor'; +import { + ListableObjectDirective +} from '../../../../../shared/object-collection/shared/listable-object/listable-object.directive'; +import { WorkspaceItem } from '../../../../../core/submission/models/workspaceitem.model'; +import { LinkService } from '../../../../../core/cache/builders/link.service'; +import { followLink } from '../../../../../shared/utils/follow-link-config.model'; +import { RemoteData } from '../../../../../core/data/remote-data'; +import { + getAllSucceededRemoteData, + getFirstCompletedRemoteData, + getRemoteDataPayload +} from '../../../../../core/shared/operators'; +import { + WorkspaceItemSearchResult +} from '../../../../../shared/object-collection/shared/workspace-item-search-result.model'; +import { ThemeService } from '../../../../../shared/theme-support/theme.service'; +import { DSpaceObject } from '../../../../../core/shared/dspace-object.model'; +import { SupervisionOrder } from '../../../../../core/supervision-order/models/supervision-order.model'; +import { PaginatedList } from '../../../../../core/data/paginated-list.model'; +import { SupervisionOrderDataService } from '../../../../../core/supervision-order/supervision-order-data.service'; + +@listableObjectComponent(WorkspaceItemSearchResult, ViewMode.GridElement, Context.AdminWorkflowSearch) +@Component({ + selector: 'ds-workflow-item-search-result-admin-workflow-grid-element', + styleUrls: ['./workspace-item-search-result-admin-workflow-grid-element.component.scss'], + templateUrl: './workspace-item-search-result-admin-workflow-grid-element.component.html' +}) +/** + * The component for displaying a grid element for an workflow item on the admin workflow search page + */ +export class WorkspaceItemSearchResultAdminWorkflowGridElementComponent extends SearchResultGridElementComponent { + + /** + * The item linked to the workspace item + */ + public item$: Observable; + + /** + * The id of the item linked to the workflow item + */ + public itemId: string; + + /** + * The supervision orders linked to the workflow item + */ + public supervisionOrder$: BehaviorSubject = new BehaviorSubject([]); + + /** + * Directive used to render the dynamic component in + */ + @ViewChild(ListableObjectDirective, { static: true }) listableObjectDirective: ListableObjectDirective; + + /** + * The html child that contains the badges html + */ + @ViewChild('badges', { static: true }) badges: ElementRef; + + /** + * The html child that contains the button html + */ + @ViewChild('buttons', { static: true }) buttons: ElementRef; + + constructor( + private componentFactoryResolver: ComponentFactoryResolver, + private linkService: LinkService, + protected truncatableService: TruncatableService, + private themeService: ThemeService, + protected bitstreamDataService: BitstreamDataService, + protected supervisionOrderDataService: SupervisionOrderDataService, + ) { + super(truncatableService, bitstreamDataService); + } + + /** + * Setup the dynamic child component + * Initialize the item object from the workflow item + */ + ngOnInit(): void { + super.ngOnInit(); + this.dso = this.linkService.resolveLink(this.dso, followLink('item')); + this.item$ = (this.dso.item as Observable>).pipe(getAllSucceededRemoteData(), getRemoteDataPayload()); + this.item$.pipe(take(1)).subscribe((item: Item) => { + const componentFactory = this.componentFactoryResolver.resolveComponentFactory(this.getComponent(item)); + + const viewContainerRef = this.listableObjectDirective.viewContainerRef; + viewContainerRef.clear(); + + const componentRef = viewContainerRef.createComponent( + componentFactory, + 0, + undefined, + [ + [this.badges.nativeElement], + [this.buttons.nativeElement] + ]); + (componentRef.instance as any).object = item; + (componentRef.instance as any).index = this.index; + (componentRef.instance as any).linkType = this.linkType; + (componentRef.instance as any).listID = this.listID; + componentRef.changeDetectorRef.detectChanges(); + } + ); + + this.item$.pipe( + take(1), + tap((item: Item) => this.itemId = item.id), + mergeMap((item: Item) => this.retrieveSupervisorOrders(item.id)) + ).subscribe((supervisionOrderList: SupervisionOrder[]) => { + this.supervisionOrder$.next(supervisionOrderList); + }); + } + + /** + * Fetch the component depending on the item's entity type, view mode and context + * @returns {GenericConstructor} + */ + private getComponent(item: Item): GenericConstructor { + return getListableObjectComponent(item.getRenderTypes(), ViewMode.GridElement, undefined, this.themeService.getThemeName()); + } + + + /** + * Retrieve the list of SupervisionOrder object related to the given item + * + * @param itemId + * @private + */ + private retrieveSupervisorOrders(itemId): Observable { + return this.supervisionOrderDataService.searchByItem( + itemId, false, true, followLink('group') + ).pipe( + getFirstCompletedRemoteData(), + map((soRD: RemoteData>) => soRD.hasSucceeded && !soRD.hasNoContent ? soRD.payload.page : []) + ); + } + + reloadObject(dso: DSpaceObject) { + this.reloadedObject.emit(dso); + } +} 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 8963db01bd..192cc751f2 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 @@ -1,18 +1,10 @@ -
+
{{ "admin.workflow.item.workflow" | translate }}
-
- {{ "admin.workflow.item.workspace" | translate }} -
-
- -
- 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.spec.ts 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.spec.ts index a489cb0e57..ab5d8b79a8 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.spec.ts +++ 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.spec.ts @@ -9,11 +9,15 @@ import { CollectionElementLinkType } from '../../../../../shared/object-collecti import { ViewMode } from '../../../../../core/shared/view-mode.model'; import { RouterTestingModule } from '@angular/router/testing'; import { WorkflowItem } from '../../../../../core/submission/models/workflowitem.model'; -import { WorkflowItemSearchResultAdminWorkflowListElementComponent } from './workflow-item-search-result-admin-workflow-list-element.component'; +import { + WorkflowItemSearchResultAdminWorkflowListElementComponent +} from './workflow-item-search-result-admin-workflow-list-element.component'; import { LinkService } from '../../../../../core/cache/builders/link.service'; import { followLink } from '../../../../../shared/utils/follow-link-config.model'; import { Item } from '../../../../../core/shared/item.model'; -import { WorkflowItemSearchResult } from '../../../../../shared/object-collection/shared/workflow-item-search-result.model'; +import { + WorkflowItemSearchResult +} from '../../../../../shared/object-collection/shared/workflow-item-search-result.model'; import { createSuccessfulRemoteDataObject$ } from '../../../../../shared/remote-data.utils'; import { getMockLinkService } from '../../../../../shared/mocks/link-service.mock'; import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service'; @@ -21,7 +25,7 @@ import { DSONameServiceMock } from '../../../../../shared/mocks/dso-name.service import { APP_CONFIG } from '../../../../../../config/app-config.interface'; import { environment } from '../../../../../../environments/environment'; -describe('WorkflowItemAdminWorkflowListElementComponent', () => { +describe('WorkflowItemSearchResultAdminWorkflowListElementComponent', () => { let component: WorkflowItemSearchResultAdminWorkflowListElementComponent; let fixture: ComponentFixture; let id; 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.ts 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.ts index c57d918126..b1db3f99ce 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.ts +++ 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.ts @@ -1,24 +1,15 @@ import { Component, Inject, OnInit } from '@angular/core'; - -import { BehaviorSubject, Observable } from 'rxjs'; -import { map, mergeMap, take, tap } from 'rxjs/operators'; -import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; -import { TranslateService } from '@ngx-translate/core'; - import { ViewMode } from '../../../../../core/shared/view-mode.model'; import { listableObjectComponent } from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator'; import { Context } from '../../../../../core/shared/context.model'; import { WorkflowItem } from '../../../../../core/submission/models/workflowitem.model'; +import { Observable } from 'rxjs'; import { LinkService } from '../../../../../core/cache/builders/link.service'; import { followLink } from '../../../../../shared/utils/follow-link-config.model'; import { RemoteData } from '../../../../../core/data/remote-data'; -import { - getAllSucceededRemoteData, - getFirstCompletedRemoteData, - getRemoteDataPayload -} from '../../../../../core/shared/operators'; +import { getAllSucceededRemoteData, getRemoteDataPayload } from '../../../../../core/shared/operators'; import { Item } from '../../../../../core/shared/item.model'; import { SearchResultListElementComponent @@ -29,21 +20,8 @@ import { } from '../../../../../shared/object-collection/shared/workflow-item-search-result.model'; import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service'; import { APP_CONFIG, AppConfig } from '../../../../../../config/app-config.interface'; -import { - WorkspaceItemSearchResult -} from '../../../../../shared/object-collection/shared/workspace-item-search-result.model'; -import { SupervisionOrder } from '../../../../../core/supervision-order/models/supervision-order.model'; -import { SupervisionOrderDataService } from '../../../../../core/supervision-order/supervision-order-data.service'; -import { PaginatedList } from '../../../../../core/data/paginated-list.model'; -import { ConfirmationModalComponent } from '../../../../../shared/confirmation-modal/confirmation-modal.component'; -import { hasValue } from '../../../../../shared/empty.util'; -import { - SupervisionOrderListEntry -} from '../../../../../shared/object-list/supervision-order-status/supervision-order-status.component'; -import { NotificationsService } from '../../../../../shared/notifications/notifications.service'; @listableObjectComponent(WorkflowItemSearchResult, ViewMode.ListElement, Context.AdminWorkflowSearch) -@listableObjectComponent(WorkspaceItemSearchResult, ViewMode.ListElement, Context.AdminWorkflowSearch) @Component({ selector: 'ds-workflow-item-search-result-admin-workflow-list-element', styleUrls: ['./workflow-item-search-result-admin-workflow-list-element.component.scss'], @@ -59,25 +37,9 @@ export class WorkflowItemSearchResultAdminWorkflowListElementComponent extends S */ public item$: Observable; - /** - * The id of the item linked to the workflow item - */ - public itemId: string; - - /** - * The supervision orders linked to the workflow item - */ - public supervisionOrder$: BehaviorSubject = new BehaviorSubject([]); - - private messagePrefix = 'workflow-item.search.result'; - constructor(private linkService: LinkService, - protected dsoNameService: DSONameService, - protected modalService: NgbModal, - protected notificationsService: NotificationsService, - protected supervisionOrderDataService: SupervisionOrderDataService, - protected translateService: TranslateService, protected truncatableService: TruncatableService, + protected dsoNameService: DSONameService, @Inject(APP_CONFIG) protected appConfig: AppConfig ) { super(truncatableService, dsoNameService, appConfig); @@ -90,77 +52,5 @@ export class WorkflowItemSearchResultAdminWorkflowListElementComponent extends S super.ngOnInit(); this.dso = this.linkService.resolveLink(this.dso, followLink('item')); this.item$ = (this.dso.item as Observable>).pipe(getAllSucceededRemoteData(), getRemoteDataPayload()); - - this.item$.pipe( - take(1), - tap((item: Item) => this.itemId = item.id), - mergeMap((item: Item) => this.retrieveSupervisorOrders(item.id)) - ).subscribe((supervisionOrderList: SupervisionOrder[]) => { - this.supervisionOrder$.next(supervisionOrderList); - }) - } - - /** - * Deletes the Group from the Repository. The Group will be the only that this form is showing. - * It'll either show a success or error message depending on whether the delete was successful or not. - */ - deleteSupervisionOrder(supervisionOrderEntry: SupervisionOrderListEntry) { - const modalRef = this.modalService.open(ConfirmationModalComponent); - modalRef.componentInstance.dso = supervisionOrderEntry.group; - modalRef.componentInstance.headerLabel = this.messagePrefix + '.delete-supervision.modal.header'; - modalRef.componentInstance.infoLabel = this.messagePrefix + '.delete-supervision.modal.info'; - modalRef.componentInstance.cancelLabel = this.messagePrefix + '.delete-supervision.modal.cancel'; - modalRef.componentInstance.confirmLabel = this.messagePrefix + '.delete-supervision.modal.confirm'; - modalRef.componentInstance.brandColor = 'danger'; - modalRef.componentInstance.confirmIcon = 'fas fa-trash'; - modalRef.componentInstance.response.pipe( - take(1), - mergeMap((confirm: boolean) => { - if (confirm && hasValue(supervisionOrderEntry.supervisionOrder.id)) { - return this.supervisionOrderDataService.delete(supervisionOrderEntry.supervisionOrder.id).pipe( - take(1), - tap((result: boolean) => { - if (result) { - this.notificationsService.success( - null, - this.translateService.get( - this.messagePrefix + '.notification.deleted.success', - { name: this.dsoNameService.getName(supervisionOrderEntry.group) } - ) - ); - } else { - this.notificationsService.error( - null, - this.translateService.get( - this.messagePrefix + '.notification.deleted.failure', - { name: this.dsoNameService.getName(supervisionOrderEntry.group) } - ) - ); - } - }), - mergeMap((result: boolean) => result ? this.retrieveSupervisorOrders(this.itemId) : this.supervisionOrder$.asObservable()) - ) - } else { - return this.supervisionOrder$.asObservable() - } - }) - ).subscribe((supervisionOrderList: SupervisionOrder[]) => { - this.supervisionOrder$.next(supervisionOrderList) - }) - } - - /** - * Retrieve the list of SupervisionOrder object related to the given item - * - * @param itemId - * @private - */ - private retrieveSupervisorOrders(itemId): Observable { - return this.supervisionOrderDataService.searchByItem( - itemId, false, true, followLink('group') - ).pipe( - getFirstCompletedRemoteData(), - map((soRD: RemoteData>) => soRD.hasSucceeded && !soRD.hasNoContent ? soRD.payload.page : []) - ); } } diff --git a/src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-list-element/workspace-item/workspace-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/workspace-item/workspace-item-search-result-admin-workflow-list-element.component.html new file mode 100644 index 0000000000..ed877706c6 --- /dev/null +++ b/src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-list-element/workspace-item/workspace-item-search-result-admin-workflow-list-element.component.html @@ -0,0 +1,13 @@ +{{ "admin.workflow.item.workspace" | translate }} + + + diff --git a/src/app/shared/object-list/supervision-order-status/supervision-order-status.component.scss b/src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-list-element/workspace-item/workspace-item-search-result-admin-workflow-list-element.component.scss similarity index 100% rename from src/app/shared/object-list/supervision-order-status/supervision-order-status.component.scss rename to src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-list-element/workspace-item/workspace-item-search-result-admin-workflow-list-element.component.scss diff --git a/src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-list-element/workspace-item/workspace-item-search-result-admin-workflow-list-element.component.spec.ts b/src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-list-element/workspace-item/workspace-item-search-result-admin-workflow-list-element.component.spec.ts new file mode 100644 index 0000000000..19eefc9c48 --- /dev/null +++ b/src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-list-element/workspace-item/workspace-item-search-result-admin-workflow-list-element.component.spec.ts @@ -0,0 +1,111 @@ +import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { RouterTestingModule } from '@angular/router/testing'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; + +import { TranslateModule } from '@ngx-translate/core'; + +import { mockTruncatableService } from '../../../../../shared/mocks/mock-trucatable.service'; +import { TruncatableService } from '../../../../../shared/truncatable/truncatable.service'; +import { CollectionElementLinkType } from '../../../../../shared/object-collection/collection-element-link.type'; +import { ViewMode } from '../../../../../core/shared/view-mode.model'; +import { WorkflowItem } from '../../../../../core/submission/models/workflowitem.model'; +import { + WorkspaceItemSearchResultAdminWorkflowListElementComponent +} from './workspace-item-search-result-admin-workflow-list-element.component'; +import { LinkService } from '../../../../../core/cache/builders/link.service'; +import { followLink } from '../../../../../shared/utils/follow-link-config.model'; +import { Item } from '../../../../../core/shared/item.model'; +import { + WorkflowItemSearchResult +} from '../../../../../shared/object-collection/shared/workflow-item-search-result.model'; +import { createSuccessfulRemoteDataObject$ } from '../../../../../shared/remote-data.utils'; +import { getMockLinkService } from '../../../../../shared/mocks/link-service.mock'; +import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service'; +import { DSONameServiceMock } from '../../../../../shared/mocks/dso-name.service.mock'; +import { APP_CONFIG } from '../../../../../../config/app-config.interface'; +import { environment } from '../../../../../../environments/environment'; +import { SupervisionOrderDataService } from '../../../../../core/supervision-order/supervision-order-data.service'; +import { + supervisionOrderPaginatedListRD, + supervisionOrderPaginatedListRD$ +} from '../../../../../shared/testing/supervision-order.mock'; +import { DSpaceObject } from '../../../../../core/shared/dspace-object.model'; + +describe('WorkspaceItemSearchResultAdminWorkflowListElementComponent', () => { + let component: WorkspaceItemSearchResultAdminWorkflowListElementComponent; + let fixture: ComponentFixture; + let id; + let wfi; + let itemRD$; + let linkService; + let object; + let supervisionOrderDataService; + + function init() { + itemRD$ = createSuccessfulRemoteDataObject$(new Item()); + id = '780b2588-bda5-4112-a1cd-0b15000a5339'; + object = new WorkflowItemSearchResult(); + wfi = new WorkflowItem(); + wfi.item = itemRD$; + object.indexableObject = wfi; + linkService = getMockLinkService(); + supervisionOrderDataService = jasmine.createSpyObj('supervisionOrderDataService', { + searchByItem: jasmine.createSpy('searchByItem'), + delete: jasmine.createSpy('delete'), + }); + } + + beforeEach(waitForAsync(() => { + init(); + TestBed.configureTestingModule( + { + declarations: [WorkspaceItemSearchResultAdminWorkflowListElementComponent], + imports: [ + NoopAnimationsModule, + TranslateModule.forRoot(), + RouterTestingModule.withRoutes([]), + ], + providers: [ + { provide: TruncatableService, useValue: mockTruncatableService }, + { provide: LinkService, useValue: linkService }, + { provide: DSONameService, useClass: DSONameServiceMock }, + { provide: SupervisionOrderDataService, useValue: supervisionOrderDataService }, + { provide: APP_CONFIG, useValue: environment } + ], + schemas: [NO_ERRORS_SCHEMA] + }) + .compileComponents(); + })); + + beforeEach(() => { + linkService.resolveLink.and.callFake((a) => a); + fixture = TestBed.createComponent(WorkspaceItemSearchResultAdminWorkflowListElementComponent); + component = fixture.componentInstance; + component.object = object; + component.linkTypes = CollectionElementLinkType; + component.index = 0; + component.viewModes = ViewMode; + supervisionOrderDataService.searchByItem.and.returnValue(supervisionOrderPaginatedListRD$); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should retrieve the item using the link service', () => { + expect(linkService.resolveLink).toHaveBeenCalledWith(wfi, followLink('item')); + }); + + it('should retrieve supervision order objects properly', () => { + expect(component.supervisionOrder$.value).toEqual(supervisionOrderPaginatedListRD.payload.page); + }); + + it('should emit reloadedObject properly ', () => { + spyOn(component.reloadedObject, 'emit'); + const dso = new DSpaceObject(); + component.reloadObject(dso); + expect(component.reloadedObject.emit).toHaveBeenCalledWith(dso); + }); +}); diff --git a/src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-list-element/workspace-item/workspace-item-search-result-admin-workflow-list-element.component.ts b/src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-list-element/workspace-item/workspace-item-search-result-admin-workflow-list-element.component.ts new file mode 100644 index 0000000000..597ed8bbe7 --- /dev/null +++ b/src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-list-element/workspace-item/workspace-item-search-result-admin-workflow-list-element.component.ts @@ -0,0 +1,109 @@ +import { Component, Inject, OnInit } from '@angular/core'; + +import { BehaviorSubject, Observable } from 'rxjs'; +import { map, mergeMap, take, tap } from 'rxjs/operators'; + +import { ViewMode } from '../../../../../core/shared/view-mode.model'; +import { + listableObjectComponent +} from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator'; +import { Context } from '../../../../../core/shared/context.model'; +import { WorkspaceItem } from '../../../../../core/submission/models/workspaceitem.model'; +import { LinkService } from '../../../../../core/cache/builders/link.service'; +import { followLink } from '../../../../../shared/utils/follow-link-config.model'; +import { RemoteData } from '../../../../../core/data/remote-data'; +import { + getAllSucceededRemoteData, + getFirstCompletedRemoteData, + getRemoteDataPayload +} from '../../../../../core/shared/operators'; +import { Item } from '../../../../../core/shared/item.model'; +import { + SearchResultListElementComponent +} from '../../../../../shared/object-list/search-result-list-element/search-result-list-element.component'; +import { TruncatableService } from '../../../../../shared/truncatable/truncatable.service'; +import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service'; +import { APP_CONFIG, AppConfig } from '../../../../../../config/app-config.interface'; +import { + WorkspaceItemSearchResult +} from '../../../../../shared/object-collection/shared/workspace-item-search-result.model'; +import { SupervisionOrder } from '../../../../../core/supervision-order/models/supervision-order.model'; +import { SupervisionOrderDataService } from '../../../../../core/supervision-order/supervision-order-data.service'; +import { PaginatedList } from '../../../../../core/data/paginated-list.model'; +import { DSpaceObject } from '../../../../../core/shared/dspace-object.model'; + +@listableObjectComponent(WorkspaceItemSearchResult, ViewMode.ListElement, Context.AdminWorkflowSearch) +@Component({ + selector: 'ds-workflow-item-search-result-admin-workflow-list-element', + styleUrls: ['./workspace-item-search-result-admin-workflow-list-element.component.scss'], + templateUrl: './workspace-item-search-result-admin-workflow-list-element.component.html' +}) +/** + * The component for displaying a list element for a workflow item on the admin workflow search page + */ +export class WorkspaceItemSearchResultAdminWorkflowListElementComponent extends SearchResultListElementComponent implements OnInit { + + /** + * The item linked to the workflow item + */ + public item$: Observable; + + /** + * The id of the item linked to the workflow item + */ + public itemId: string; + + /** + * The supervision orders linked to the workflow item + */ + public supervisionOrder$: BehaviorSubject = new BehaviorSubject([]); + + constructor(private linkService: LinkService, + protected dsoNameService: DSONameService, + protected supervisionOrderDataService: SupervisionOrderDataService, + protected truncatableService: TruncatableService, + @Inject(APP_CONFIG) protected appConfig: AppConfig + ) { + super(truncatableService, dsoNameService, appConfig); + } + + /** + * Initialize the item object from the workflow item + */ + ngOnInit(): void { + super.ngOnInit(); + this.dso = this.linkService.resolveLink(this.dso, followLink('item')); + this.item$ = (this.dso.item as Observable>).pipe(getAllSucceededRemoteData(), getRemoteDataPayload()); + + this.item$.pipe( + take(1), + tap((item: Item) => this.itemId = item.id), + mergeMap((item: Item) => this.retrieveSupervisorOrders(item.id)) + ).subscribe((supervisionOrderList: SupervisionOrder[]) => { + this.supervisionOrder$.next(supervisionOrderList); + }); + } + + /** + * Retrieve the list of SupervisionOrder object related to the given item + * + * @param itemId + * @private + */ + private retrieveSupervisorOrders(itemId): Observable { + return this.supervisionOrderDataService.searchByItem( + itemId, false, true, followLink('group') + ).pipe( + getFirstCompletedRemoteData(), + map((soRD: RemoteData>) => soRD.hasSucceeded && !soRD.hasNoContent ? soRD.payload.page : []) + ); + } + + /** + * Reload list element after supervision order change. + */ + reloadObject(dso: DSpaceObject) { + this.reloadedObject.emit(dso); + } + +} diff --git a/src/app/admin/admin-workflow-page/admin-workflow-search-results/workflow-item-admin-workflow-actions.component.ts b/src/app/admin/admin-workflow-page/admin-workflow-search-results/workflow-item-admin-workflow-actions.component.ts deleted file mode 100644 index 924f24e738..0000000000 --- a/src/app/admin/admin-workflow-page/admin-workflow-search-results/workflow-item-admin-workflow-actions.component.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { Component, Input } from '@angular/core'; -import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; -import { map, Observable } from 'rxjs'; -import { Item } from '../../../core/shared/item.model'; -import { getFirstSucceededRemoteDataPayload } from '../../../core/shared/operators'; -import { SupervisionGroupSelectorComponent } from '../../../shared/dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component'; -import { WorkflowItem } from '../../../core/submission/models/workflowitem.model'; -import { - getWorkflowItemSendBackRoute, - getWorkflowItemDeleteRoute -} from '../../../workflowitems-edit-page/workflowitems-edit-page-routing-paths'; - -@Component({ - selector: 'ds-workflow-item-admin-workflow-actions-element', - styleUrls: ['./workflow-item-admin-workflow-actions.component.scss'], - templateUrl: './workflow-item-admin-workflow-actions.component.html' -}) -/** - * The component for displaying the actions for a list element for an item on the admin workflow search page - */ -export class WorkflowItemAdminWorkflowActionsComponent { - - /** - * The workflow item to perform the actions on - */ - @Input() public wfi: WorkflowItem; - - /** - * Whether or not to use small buttons - */ - @Input() public small: boolean; - - constructor( - private modalService: NgbModal - ) { } - - /** - * Returns the path to the delete page of this workflow item - */ - getDeleteRoute(): string { - - return getWorkflowItemDeleteRoute(this.wfi.id); - } - - /** - * Returns the path to the send back page of this workflow item - */ - getSendBackRoute(): string { - return getWorkflowItemSendBackRoute(this.wfi.id); - } - - /** - * Returns the path to the to administrative edit page policies tab - */ - getPoliciesRoute(): Observable { - return this.wfi.item.pipe( - getFirstSucceededRemoteDataPayload(), - map((item: Item) => { - return '/items/' + item.uuid + '/edit/bitstreams'; - }) - ); - } - - /** - * Opens the Supervision Modal to create a supervision order - */ - openSupervisionModal() { - this.wfi.item.pipe( - getFirstSucceededRemoteDataPayload(), - ).subscribe((item: Item) => { - const supervisionModal = this.modalService.open(SupervisionGroupSelectorComponent, { size: 'lg', backdrop: 'static' }); - supervisionModal.componentInstance.itemUUID = item.uuid; - }); - } -} diff --git a/src/app/admin/admin-workflow-page/admin-workflow.module.ts b/src/app/admin/admin-workflow-page/admin-workflow.module.ts index 85e8f00a46..21990c1ea9 100644 --- a/src/app/admin/admin-workflow-page/admin-workflow.module.ts +++ b/src/app/admin/admin-workflow-page/admin-workflow.module.ts @@ -1,16 +1,39 @@ import { NgModule } from '@angular/core'; -import { SharedModule } from '../../shared/shared.module'; -import { WorkflowItemSearchResultAdminWorkflowGridElementComponent } from './admin-workflow-search-results/admin-workflow-search-result-grid-element/workflow-item/workflow-item-search-result-admin-workflow-grid-element.component'; -import { WorkflowItemAdminWorkflowActionsComponent } from './admin-workflow-search-results/workflow-item-admin-workflow-actions.component'; -import { WorkflowItemSearchResultAdminWorkflowListElementComponent } from './admin-workflow-search-results/admin-workflow-search-result-list-element/workflow-item/workflow-item-search-result-admin-workflow-list-element.component'; +import { SharedModule } from '../../shared/shared.module'; +import { + WorkflowItemSearchResultAdminWorkflowGridElementComponent +} from './admin-workflow-search-results/admin-workflow-search-result-grid-element/workflow-item/workflow-item-search-result-admin-workflow-grid-element.component'; +import { + WorkflowItemAdminWorkflowActionsComponent +} from './admin-workflow-search-results/actions/workflow-item/workflow-item-admin-workflow-actions.component'; +import { + WorkflowItemSearchResultAdminWorkflowListElementComponent +} from './admin-workflow-search-results/admin-workflow-search-result-list-element/workflow-item/workflow-item-search-result-admin-workflow-list-element.component'; import { AdminWorkflowPageComponent } from './admin-workflow-page.component'; import { SearchModule } from '../../shared/search/search.module'; +import { + WorkspaceItemAdminWorkflowActionsComponent +} from './admin-workflow-search-results/actions/workspace-item/workspace-item-admin-workflow-actions.component'; +import { + WorkspaceItemSearchResultAdminWorkflowListElementComponent +} from './admin-workflow-search-results/admin-workflow-search-result-list-element/workspace-item/workspace-item-search-result-admin-workflow-list-element.component'; +import { + WorkspaceItemSearchResultAdminWorkflowGridElementComponent +} from './admin-workflow-search-results/admin-workflow-search-result-grid-element/workspace-item/workspace-item-search-result-admin-workflow-grid-element.component'; +import { + SupervisionOrderGroupSelectorComponent +} from './admin-workflow-search-results/actions/workspace-item/supervision-order-group-selector/supervision-order-group-selector.component'; +import { + SupervisionOrderStatusComponent +} from './admin-workflow-search-results/actions/workspace-item/supervision-order-status/supervision-order-status.component'; const ENTRY_COMPONENTS = [ // put only entry components that use custom decorator WorkflowItemSearchResultAdminWorkflowListElementComponent, WorkflowItemSearchResultAdminWorkflowGridElementComponent, + WorkspaceItemSearchResultAdminWorkflowListElementComponent, + WorkspaceItemSearchResultAdminWorkflowGridElementComponent ]; @NgModule({ @@ -20,7 +43,10 @@ const ENTRY_COMPONENTS = [ ], declarations: [ AdminWorkflowPageComponent, + SupervisionOrderGroupSelectorComponent, + SupervisionOrderStatusComponent, WorkflowItemAdminWorkflowActionsComponent, + WorkspaceItemAdminWorkflowActionsComponent, ...ENTRY_COMPONENTS ], exports: [ diff --git a/src/app/process-page/detail/process-detail.component.ts b/src/app/process-page/detail/process-detail.component.ts index 9d92dece61..2e7dea5def 100644 --- a/src/app/process-page/detail/process-detail.component.ts +++ b/src/app/process-page/detail/process-detail.component.ts @@ -128,7 +128,6 @@ export class ProcessDetailComponent implements OnInit { * Sets the outputLogs when retrieved and sets the showOutputLogs boolean to show them and hide the button. */ showProcessOutputLogs() { - console.log('showProcessOutputLogs'); this.retrievingOutputLogs$.next(true); this.zone.runOutsideAngular(() => { const processOutputRD$: Observable> = this.processRD$.pipe( diff --git a/src/app/shared/form/eperson-group-list/eperson-group-list.component.html b/src/app/shared/eperson-group-list/eperson-group-list.component.html similarity index 100% rename from src/app/shared/form/eperson-group-list/eperson-group-list.component.html rename to src/app/shared/eperson-group-list/eperson-group-list.component.html diff --git a/src/app/shared/eperson-group-list/eperson-group-list.component.scss b/src/app/shared/eperson-group-list/eperson-group-list.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/shared/form/eperson-group-list/eperson-group-list.component.spec.ts b/src/app/shared/eperson-group-list/eperson-group-list.component.spec.ts similarity index 89% rename from src/app/shared/form/eperson-group-list/eperson-group-list.component.spec.ts rename to src/app/shared/eperson-group-list/eperson-group-list.component.spec.ts index 399080c0ef..8c5fc88137 100644 --- a/src/app/shared/form/eperson-group-list/eperson-group-list.component.spec.ts +++ b/src/app/shared/eperson-group-list/eperson-group-list.component.spec.ts @@ -6,21 +6,21 @@ import { TranslateModule } from '@ngx-translate/core'; import { cold } from 'jasmine-marbles'; import uniqueId from 'lodash/uniqueId'; -import { createSuccessfulRemoteDataObject } from '../../remote-data.utils'; -import { createTestComponent } from '../../testing/utils.test'; -import { EPersonDataService } from '../../../core/eperson/eperson-data.service'; -import { GroupDataService } from '../../../core/eperson/group-data.service'; -import { RequestService } from '../../../core/data/request.service'; -import { getMockRequestService } from '../../mocks/request.service.mock'; +import { createSuccessfulRemoteDataObject } from '../remote-data.utils'; +import { createTestComponent } from '../testing/utils.test'; +import { EPersonDataService } from '../../core/eperson/eperson-data.service'; +import { GroupDataService } from '../../core/eperson/group-data.service'; +import { RequestService } from '../../core/data/request.service'; +import { getMockRequestService } from '../mocks/request.service.mock'; import { EpersonGroupListComponent, SearchEvent } from './eperson-group-list.component'; -import { EPersonMock } from '../../testing/eperson.mock'; -import { GroupMock } from '../../testing/group-mock'; -import { PaginationComponentOptions } from '../../pagination/pagination-component-options.model'; -import { buildPaginatedList } from '../../../core/data/paginated-list.model'; -import { PageInfo } from '../../../core/shared/page-info.model'; +import { EPersonMock } from '../testing/eperson.mock'; +import { GroupMock } from '../testing/group-mock'; +import { PaginationComponentOptions } from '../pagination/pagination-component-options.model'; +import { buildPaginatedList } from '../../core/data/paginated-list.model'; +import { PageInfo } from '../../core/shared/page-info.model'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { PaginationService } from '../../../core/pagination/pagination.service'; -import { PaginationServiceStub } from '../../testing/pagination-service.stub'; +import { PaginationService } from '../../core/pagination/pagination.service'; +import { PaginationServiceStub } from '../testing/pagination-service.stub'; describe('EpersonGroupListComponent test suite', () => { let comp: EpersonGroupListComponent; diff --git a/src/app/shared/form/eperson-group-list/eperson-group-list.component.ts b/src/app/shared/eperson-group-list/eperson-group-list.component.ts similarity index 81% rename from src/app/shared/form/eperson-group-list/eperson-group-list.component.ts rename to src/app/shared/eperson-group-list/eperson-group-list.component.ts index e2b56859dc..7cad7a9783 100644 --- a/src/app/shared/form/eperson-group-list/eperson-group-list.component.ts +++ b/src/app/shared/eperson-group-list/eperson-group-list.component.ts @@ -4,22 +4,22 @@ import { BehaviorSubject, Observable, Subscription } from 'rxjs'; import { map } from 'rxjs/operators'; import uniqueId from 'lodash/uniqueId'; -import { RemoteData } from '../../../core/data/remote-data'; -import { PaginatedList } from '../../../core/data/paginated-list.model'; -import { DSpaceObject } from '../../../core/shared/dspace-object.model'; -import { PaginationComponentOptions } from '../../pagination/pagination-component-options.model'; -import { hasValue, isNotEmpty } from '../../empty.util'; -import { DSONameService } from '../../../core/breadcrumbs/dso-name.service'; -import { EPERSON } from '../../../core/eperson/models/eperson.resource-type'; -import { GROUP } from '../../../core/eperson/models/group.resource-type'; -import { ResourceType } from '../../../core/shared/resource-type'; -import { EPersonDataService } from '../../../core/eperson/eperson-data.service'; -import { GroupDataService } from '../../../core/eperson/group-data.service'; -import { fadeInOut } from '../../animations/fade'; -import { getFirstCompletedRemoteData } from '../../../core/shared/operators'; -import { PaginationService } from '../../../core/pagination/pagination.service'; -import { FindListOptions } from '../../../core/data/find-list-options.model'; -import { getDataServiceFor } from '../../../core/data/base/data-service.decorator'; +import { RemoteData } from '../../core/data/remote-data'; +import { PaginatedList } from '../../core/data/paginated-list.model'; +import { DSpaceObject } from '../../core/shared/dspace-object.model'; +import { PaginationComponentOptions } from '../pagination/pagination-component-options.model'; +import { hasValue, isNotEmpty } from '../empty.util'; +import { DSONameService } from '../../core/breadcrumbs/dso-name.service'; +import { EPERSON } from '../../core/eperson/models/eperson.resource-type'; +import { GROUP } from '../../core/eperson/models/group.resource-type'; +import { ResourceType } from '../../core/shared/resource-type'; +import { EPersonDataService } from '../../core/eperson/eperson-data.service'; +import { GroupDataService } from '../../core/eperson/group-data.service'; +import { fadeInOut } from '../animations/fade'; +import { getFirstCompletedRemoteData } from '../../core/shared/operators'; +import { PaginationService } from '../../core/pagination/pagination.service'; +import { FindListOptions } from '../../core/data/find-list-options.model'; +import { getDataServiceFor } from '../../core/data/base/data-service.decorator'; export interface SearchEvent { scope: string; diff --git a/src/app/shared/form/eperson-group-list/eperson-search-box/eperson-search-box.component.html b/src/app/shared/eperson-group-list/eperson-search-box/eperson-search-box.component.html similarity index 100% rename from src/app/shared/form/eperson-group-list/eperson-search-box/eperson-search-box.component.html rename to src/app/shared/eperson-group-list/eperson-search-box/eperson-search-box.component.html diff --git a/src/app/shared/form/eperson-group-list/eperson-search-box/eperson-search-box.component.spec.ts b/src/app/shared/eperson-group-list/eperson-search-box/eperson-search-box.component.spec.ts similarity index 97% rename from src/app/shared/form/eperson-group-list/eperson-search-box/eperson-search-box.component.spec.ts rename to src/app/shared/eperson-group-list/eperson-search-box/eperson-search-box.component.spec.ts index db16af5edf..5a9e74055a 100644 --- a/src/app/shared/form/eperson-group-list/eperson-search-box/eperson-search-box.component.spec.ts +++ b/src/app/shared/eperson-group-list/eperson-search-box/eperson-search-box.component.spec.ts @@ -4,7 +4,7 @@ import { FormBuilder, FormsModule, ReactiveFormsModule } from '@angular/forms'; import { TranslateModule } from '@ngx-translate/core'; -import { createTestComponent } from '../../../testing/utils.test'; +import { createTestComponent } from '../../testing/utils.test'; import { EpersonSearchBoxComponent } from './eperson-search-box.component'; import { SearchEvent } from '../eperson-group-list.component'; diff --git a/src/app/shared/form/eperson-group-list/eperson-search-box/eperson-search-box.component.ts b/src/app/shared/eperson-group-list/eperson-search-box/eperson-search-box.component.ts similarity index 96% rename from src/app/shared/form/eperson-group-list/eperson-search-box/eperson-search-box.component.ts rename to src/app/shared/eperson-group-list/eperson-search-box/eperson-search-box.component.ts index 6ae3200d0b..2aa4891c03 100644 --- a/src/app/shared/form/eperson-group-list/eperson-search-box/eperson-search-box.component.ts +++ b/src/app/shared/eperson-group-list/eperson-search-box/eperson-search-box.component.ts @@ -4,7 +4,7 @@ import { FormBuilder } from '@angular/forms'; import { Subscription } from 'rxjs'; import { SearchEvent } from '../eperson-group-list.component'; -import { isNotNull } from '../../../empty.util'; +import { isNotNull } from '../../empty.util'; /** * A component used to show a search box for epersons. diff --git a/src/app/shared/form/eperson-group-list/group-search-box/group-search-box.component.html b/src/app/shared/eperson-group-list/group-search-box/group-search-box.component.html similarity index 100% rename from src/app/shared/form/eperson-group-list/group-search-box/group-search-box.component.html rename to src/app/shared/eperson-group-list/group-search-box/group-search-box.component.html diff --git a/src/app/shared/form/eperson-group-list/group-search-box/group-search-box.component.spec.ts b/src/app/shared/eperson-group-list/group-search-box/group-search-box.component.spec.ts similarity index 97% rename from src/app/shared/form/eperson-group-list/group-search-box/group-search-box.component.spec.ts rename to src/app/shared/eperson-group-list/group-search-box/group-search-box.component.spec.ts index 17e96fc71c..d28a144245 100644 --- a/src/app/shared/form/eperson-group-list/group-search-box/group-search-box.component.spec.ts +++ b/src/app/shared/eperson-group-list/group-search-box/group-search-box.component.spec.ts @@ -4,7 +4,7 @@ import { FormBuilder, FormsModule, ReactiveFormsModule } from '@angular/forms'; import { TranslateModule } from '@ngx-translate/core'; -import { createTestComponent } from '../../../testing/utils.test'; +import { createTestComponent } from '../../testing/utils.test'; import { GroupSearchBoxComponent } from './group-search-box.component'; import { SearchEvent } from '../eperson-group-list.component'; diff --git a/src/app/shared/form/eperson-group-list/group-search-box/group-search-box.component.ts b/src/app/shared/eperson-group-list/group-search-box/group-search-box.component.ts similarity index 96% rename from src/app/shared/form/eperson-group-list/group-search-box/group-search-box.component.ts rename to src/app/shared/eperson-group-list/group-search-box/group-search-box.component.ts index ad181bdb64..3e45bb0336 100644 --- a/src/app/shared/form/eperson-group-list/group-search-box/group-search-box.component.ts +++ b/src/app/shared/eperson-group-list/group-search-box/group-search-box.component.ts @@ -4,7 +4,7 @@ import { FormBuilder } from '@angular/forms'; import { Subscription } from 'rxjs'; import { SearchEvent } from '../eperson-group-list.component'; -import { isNotNull } from '../../../empty.util'; +import { isNotNull } from '../../empty.util'; /** * A component used to show a search box for groups. diff --git a/src/app/shared/object-list/supervision-order-status/supervision-order-status.component.html b/src/app/shared/object-list/supervision-order-status/supervision-order-status.component.html deleted file mode 100644 index 2e4f8d39cd..0000000000 --- a/src/app/shared/object-list/supervision-order-status/supervision-order-status.component.html +++ /dev/null @@ -1,13 +0,0 @@ - -
-
- {{'workflow-item.search.result.list.element.supervised-by' | translate}} -
-
- - {{supervisionOrder.group.name}} - X - -
-
-
diff --git a/src/app/shared/object-list/supervision-order-status/supervision-order-status.component.spec.ts b/src/app/shared/object-list/supervision-order-status/supervision-order-status.component.spec.ts deleted file mode 100644 index 9a5516b8e9..0000000000 --- a/src/app/shared/object-list/supervision-order-status/supervision-order-status.component.spec.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { SupervisionOrderStatusComponent } from './supervision-order-status.component'; - -describe('SupervisionOrderStatusComponent', () => { - let component: SupervisionOrderStatusComponent; - let fixture: ComponentFixture; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ SupervisionOrderStatusComponent ] - }) - .compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(SupervisionOrderStatusComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/app/shared/resource-policies/form/resource-policy-form.component.spec.ts b/src/app/shared/resource-policies/form/resource-policy-form.component.spec.ts index 1a84270f1b..1cc908cc6d 100644 --- a/src/app/shared/resource-policies/form/resource-policy-form.component.spec.ts +++ b/src/app/shared/resource-policies/form/resource-policy-form.component.spec.ts @@ -24,9 +24,9 @@ import { ResourcePolicyEvent, ResourcePolicyFormComponent } from './resource-pol import { FormService } from '../../form/form.service'; import { getMockFormService } from '../../mocks/form-service.mock'; import { FormBuilderService } from '../../form/builder/form-builder.service'; -import { EpersonGroupListComponent } from '../../form/eperson-group-list/eperson-group-list.component'; +import { EpersonGroupListComponent } from '../../eperson-group-list/eperson-group-list.component'; import { FormComponent } from '../../form/form.component'; -import { stringToNgbDateStruct, dateToISOFormat } from '../../date.util'; +import { dateToISOFormat, stringToNgbDateStruct } from '../../date.util'; import { ResourcePolicy } from '../../../core/resource-policy/models/resource-policy.model'; import { RESOURCE_POLICY } from '../../../core/resource-policy/models/resource-policy.resource-type'; import { EPersonMock } from '../../testing/eperson.mock'; diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index c2e5600604..751075ae5f 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -84,8 +84,9 @@ import { LangSwitchComponent } from './lang-switch/lang-switch.component'; import { PlainTextMetadataListElementComponent } from './object-list/metadata-representation-list-element/plain-text/plain-text-metadata-list-element.component'; -import { BrowseLinkMetadataListElementComponent } - from './object-list/metadata-representation-list-element/browse-link/browse-link-metadata-list-element.component'; +import { + BrowseLinkMetadataListElementComponent +} from './object-list/metadata-representation-list-element/browse-link/browse-link-metadata-list-element.component'; import { ItemMetadataListElementComponent } from './object-list/metadata-representation-list-element/item/item-metadata-list-element.component'; @@ -246,21 +247,21 @@ import { import { ThemedCollectionDropdownComponent } from './collection-dropdown/themed-collection-dropdown.component'; import { MetadataFieldWrapperComponent } from './metadata-field-wrapper/metadata-field-wrapper.component'; import { ShortNumberPipe } from './utils/short-number.pipe'; -import { LogInExternalProviderComponent } from './log-in/methods/log-in-external-provider/log-in-external-provider.component'; -import { AdvancedClaimedTaskActionSelectReviewerComponent } from './mydspace-actions/claimed-task/select-reviewer/advanced-claimed-task-action-select-reviewer.component'; +import { + LogInExternalProviderComponent +} from './log-in/methods/log-in-external-provider/log-in-external-provider.component'; +import { + AdvancedClaimedTaskActionSelectReviewerComponent +} from './mydspace-actions/claimed-task/select-reviewer/advanced-claimed-task-action-select-reviewer.component'; import { AdvancedClaimedTaskActionRatingComponent } from './mydspace-actions/claimed-task/rating/advanced-claimed-task-action-rating.component'; -import { ClaimedTaskActionsDeclineTaskComponent } from './mydspace-actions/claimed-task/decline-task/claimed-task-actions-decline-task.component'; import { - SupervisionOrderStatusComponent -} from './object-list/supervision-order-status/supervision-order-status.component'; -import { - SupervisionGroupSelectorComponent -} from './dso-selector/modal-wrappers/supervision-group-selector/supervision-group-selector.component'; -import { EpersonGroupListComponent } from './form/eperson-group-list/eperson-group-list.component'; -import { EpersonSearchBoxComponent } from './form/eperson-group-list/eperson-search-box/eperson-search-box.component'; -import { GroupSearchBoxComponent } from './form/eperson-group-list/group-search-box/group-search-box.component'; + ClaimedTaskActionsDeclineTaskComponent +} from './mydspace-actions/claimed-task/decline-task/claimed-task-actions-decline-task.component'; +import { EpersonGroupListComponent } from './eperson-group-list/eperson-group-list.component'; +import { EpersonSearchBoxComponent } from './eperson-group-list/eperson-search-box/eperson-search-box.component'; +import { GroupSearchBoxComponent } from './eperson-group-list/group-search-box/group-search-box.component'; const MODULES = [ CommonModule, @@ -364,9 +365,7 @@ const COMPONENTS = [ ContextHelpWrapperComponent, EpersonGroupListComponent, EpersonSearchBoxComponent, - GroupSearchBoxComponent, - SupervisionGroupSelectorComponent, - SupervisionOrderStatusComponent + GroupSearchBoxComponent ]; const ENTRY_COMPONENTS = [ @@ -427,8 +426,7 @@ const ENTRY_COMPONENTS = [ AdvancedClaimedTaskActionRatingComponent, EpersonGroupListComponent, EpersonSearchBoxComponent, - GroupSearchBoxComponent, - SupervisionGroupSelectorComponent + GroupSearchBoxComponent ]; const PROVIDERS = [ diff --git a/src/app/shared/testing/supervision-order.mock.ts b/src/app/shared/testing/supervision-order.mock.ts new file mode 100644 index 0000000000..850486016d --- /dev/null +++ b/src/app/shared/testing/supervision-order.mock.ts @@ -0,0 +1,95 @@ +import { Item } from '../../core/shared/item.model'; +import { SupervisionOrder } from '../../core/supervision-order/models/supervision-order.model'; +import { createSuccessfulRemoteDataObject, createSuccessfulRemoteDataObject$ } from '../remote-data.utils'; +import { GroupMock, GroupMock2 } from './group-mock'; +import { buildPaginatedList } from '../../core/data/paginated-list.model'; +import { PageInfo } from '../../core/shared/page-info.model'; + +const itemMock = Object.assign(new Item(), { + metadata: { + 'dc.title': [ + { + value: 'Item one' + } + ], + 'dc.contributor.author': [ + { + value: 'Smith, Donald' + } + ], + 'dc.publisher': [ + { + value: 'a publisher' + } + ], + 'dc.date.issued': [ + { + value: '2015-06-26' + } + ], + 'dc.description.abstract': [ + { + value: 'This is the abstract' + } + ] + } +}); + +const anotherItemMock = Object.assign(new Item(), { + metadata: { + 'dc.title': [ + { + value: 'Item two' + } + ], + 'dc.contributor.author': [ + { + value: 'Smith, Donald' + } + ], + 'dc.publisher': [ + { + value: 'a publisher' + } + ], + 'dc.date.issued': [ + { + value: '2015-06-26' + } + ], + 'dc.description.abstract': [ + { + value: 'This is the abstract' + } + ] + } +}); + +export const supervisionOrderMock: any = Object.assign(new SupervisionOrder(),{ + id: '1', + item: createSuccessfulRemoteDataObject$(itemMock), + group: createSuccessfulRemoteDataObject$(GroupMock) +}); + +export const anotherSupervisionOrderMock: any = { + id: '2', + item: createSuccessfulRemoteDataObject$(anotherItemMock), + group: createSuccessfulRemoteDataObject$(GroupMock2) +}; + +export const supervisionOrderListMock = [supervisionOrderMock, anotherSupervisionOrderMock]; +export const supervisionOrderEntryMock = { + supervisionOrder: supervisionOrderMock, + group: GroupMock +}; + +const pageInfo = new PageInfo({ + elementsPerPage: 10, + totalElements: 2, + totalPages: 1, + currentPage: 1 +}); +const array = [supervisionOrderMock, anotherSupervisionOrderMock]; +const paginatedList = buildPaginatedList(pageInfo, array); +export const supervisionOrderPaginatedListRD = createSuccessfulRemoteDataObject(paginatedList); +export const supervisionOrderPaginatedListRD$ = createSuccessfulRemoteDataObject$(paginatedList); diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 70bd245ea5..37554b3da7 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -3745,6 +3745,8 @@ "search.filters.applied.f.birthDate.min": "Start birth date", + "search.filters.applied.f.supervisedBy": "Supervised by", + "search.filters.applied.f.withdrawn": "Withdrawn",