diff --git a/src/app/shared/mydspace-actions/item/item-actions.component.html b/src/app/shared/mydspace-actions/item/item-actions.component.html index 0f085c453e1..ff38c3463a7 100644 --- a/src/app/shared/mydspace-actions/item/item-actions.component.html +++ b/src/app/shared/mydspace-actions/item/item-actions.component.html @@ -3,3 +3,12 @@ [routerLink]="[itemPageRoute]"> {{"submission.workflow.generic.view" | translate}} + + diff --git a/src/app/shared/mydspace-actions/item/item-actions.component.spec.ts b/src/app/shared/mydspace-actions/item/item-actions.component.spec.ts index e6abfa76a1c..ce219907d91 100644 --- a/src/app/shared/mydspace-actions/item/item-actions.component.spec.ts +++ b/src/app/shared/mydspace-actions/item/item-actions.component.spec.ts @@ -1,5 +1,6 @@ import { ChangeDetectionStrategy, Injector, NO_ERRORS_SCHEMA } from '@angular/core'; import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { By } from '@angular/platform-browser'; import { Router } from '@angular/router'; import { of as observableOf } from 'rxjs'; @@ -16,6 +17,8 @@ import { RequestService } from '../../../core/data/request.service'; import { getMockSearchService } from '../../mocks/search-service.mock'; import { getMockRequestService } from '../../mocks/request.service.mock'; import { SearchService } from '../../../core/shared/search/search.service'; +import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service'; +import { DsoVersioningModalService } from '../../dso-page/dso-versioning-modal-service/dso-versioning-modal.service'; let component: ItemActionsComponent; let fixture: ComponentFixture; @@ -24,7 +27,25 @@ let mockObject: Item; const mockDataService = {}; +const authorizationService = jasmine.createSpyObj('authorizationService', { + isAuthorized: observableOf(true), +}); + +const dsoVersioningModalService = jasmine.createSpyObj('dsoVersioningModalService', { + isNewVersionButtonDisabled: observableOf(false), + getVersioningTooltipMessage: observableOf('item.page.version.create'), + openCreateVersionModal: undefined, +}); + mockObject = Object.assign(new Item(), { + _links: { + self: { + href: 'https://rest.test/server/api/core/items/item-id' + }, + version: { + href: 'https://rest.test/server/api/core/versions/1' + } + }, bundles: observableOf({}), metadata: { 'dc.title': [ @@ -76,7 +97,9 @@ describe('ItemActionsComponent', () => { { provide: ItemDataService, useValue: mockDataService }, { provide: NotificationsService, useValue: new NotificationsServiceStub() }, { provide: SearchService, useValue: searchService }, - { provide: RequestService, useValue: requestServce } + { provide: RequestService, useValue: requestServce }, + { provide: AuthorizationDataService, useValue: authorizationService }, + { provide: DsoVersioningModalService, useValue: dsoVersioningModalService } ], schemas: [NO_ERRORS_SCHEMA] }).overrideComponent(ItemActionsComponent, { @@ -85,6 +108,14 @@ describe('ItemActionsComponent', () => { })); beforeEach(() => { + authorizationService.isAuthorized.calls.reset(); + authorizationService.isAuthorized.and.returnValue(observableOf(true)); + dsoVersioningModalService.isNewVersionButtonDisabled.calls.reset(); + dsoVersioningModalService.isNewVersionButtonDisabled.and.returnValue(observableOf(false)); + dsoVersioningModalService.getVersioningTooltipMessage.calls.reset(); + dsoVersioningModalService.getVersioningTooltipMessage.and.returnValue(observableOf('item.page.version.create')); + dsoVersioningModalService.openCreateVersionModal.calls.reset(); + fixture = TestBed.createComponent(ItemActionsComponent); component = fixture.componentInstance; component.object = mockObject; @@ -103,4 +134,70 @@ describe('ItemActionsComponent', () => { expect(component.object).toEqual(mockObject); }); + it('should show the New version button when version creation is authorized', () => { + fixture.detectChanges(); + + const newVersionButton = fixture.debugElement.query(By.css('button.btn-outline-primary')); + + expect(newVersionButton).toBeTruthy(); + }); + + it('should hide the New version button when version creation is not authorized', () => { + authorizationService.isAuthorized.and.returnValue(observableOf(false)); + + fixture = TestBed.createComponent(ItemActionsComponent); + component = fixture.componentInstance; + component.object = mockObject; + fixture.detectChanges(); + + const newVersionButton = fixture.debugElement.query(By.css('button.btn-outline-primary')); + + expect(newVersionButton).toBeNull(); + }); + + it('should mark the New version button as disabled when version creation is disabled', () => { + dsoVersioningModalService.isNewVersionButtonDisabled.and.returnValue(observableOf(true)); + + fixture = TestBed.createComponent(ItemActionsComponent); + component = fixture.componentInstance; + component.object = mockObject; + fixture.detectChanges(); + + let isDisabled: boolean; + component.disableNewVersion$.subscribe((value) => { + isDisabled = value; + }); + + expect(isDisabled).toBeTrue(); + }); + + it('should use getVersioningTooltipMessage to derive tooltip key', () => { + dsoVersioningModalService.isNewVersionButtonDisabled.and.returnValue(observableOf(true)); + dsoVersioningModalService.getVersioningTooltipMessage.and.returnValue(observableOf('item.page.version.hasDraft')); + + fixture = TestBed.createComponent(ItemActionsComponent); + component = fixture.componentInstance; + component.object = mockObject; + fixture.detectChanges(); + + let tooltipKey: string; + component.newVersionTooltip$.subscribe((value) => { + tooltipKey = value; + }); + + expect(tooltipKey).toBe('item.page.version.hasDraft'); + expect(dsoVersioningModalService.getVersioningTooltipMessage) + .toHaveBeenCalledWith(mockObject, 'item.page.version.hasDraft', 'item.page.version.create'); + }); + + it('should open the create version modal when the New version button is clicked', () => { + fixture.detectChanges(); + + const newVersionButton = fixture.debugElement.query(By.css('button.btn-outline-primary')); + + newVersionButton.triggerEventHandler('click'); + + expect(dsoVersioningModalService.openCreateVersionModal).toHaveBeenCalledWith(mockObject); + }); + }); diff --git a/src/app/shared/mydspace-actions/item/item-actions.component.ts b/src/app/shared/mydspace-actions/item/item-actions.component.ts index 4df11d65d91..4c232e54c01 100644 --- a/src/app/shared/mydspace-actions/item/item-actions.component.ts +++ b/src/app/shared/mydspace-actions/item/item-actions.component.ts @@ -1,6 +1,8 @@ import { Component, Injector, Input, OnInit } from '@angular/core'; import { Router } from '@angular/router'; import { TranslateService } from '@ngx-translate/core'; +import { Observable, of as observableOf } from 'rxjs'; +import { shareReplay } from 'rxjs/operators'; import { MyDSpaceActionsComponent } from '../mydspace-actions'; import { ItemDataService } from '../../../core/data/item-data.service'; import { Item } from '../../../core/shared/item.model'; @@ -8,6 +10,10 @@ import { NotificationsService } from '../../notifications/notifications.service' import { RequestService } from '../../../core/data/request.service'; import { SearchService } from '../../../core/shared/search/search.service'; import { getItemPageRoute } from '../../../item-page/item-page-routing-paths'; +import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service'; +import { FeatureID } from '../../../core/data/feature-authorization/feature-id'; +import { DsoVersioningModalService } from '../../dso-page/dso-versioning-modal-service/dso-versioning-modal.service'; +import { hasValue } from '../../empty.util'; /** * This component represents mydspace actions related to Item object. @@ -30,6 +36,21 @@ export class ItemActionsComponent extends MyDSpaceActionsComponent; + + /** + * Whether the New version button should be disabled. + */ + disableNewVersion$: Observable; + + /** + * Tooltip key for the New version button. + */ + newVersionTooltip$: Observable; + /** * Initialize instance variables * @@ -45,12 +66,15 @@ export class ItemActionsComponent extends MyDSpaceActionsComponent