From 878db5be752595277e68bd71ceb221a416801e63 Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Tue, 20 Sep 2022 15:45:04 +0200 Subject: [PATCH 001/257] 94390: Replace DSO page edit buttons with a menu --- .../admin-sidebar-section.component.html | 4 +- .../admin-sidebar-section.component.spec.ts | 106 +++++++--- .../admin-sidebar-section.component.ts | 13 +- ...dable-admin-sidebar-section.component.html | 1 + .../collection-page-routing.module.ts | 7 +- .../collection-page.component.html | 4 +- .../community-page-routing.module.ts | 7 +- .../community-page.component.html | 4 +- .../journal-issue.component.html | 5 +- .../journal-volume.component.html | 4 +- .../item-pages/journal/journal.component.html | 5 +- .../org-unit/org-unit.component.html | 5 +- .../item-pages/person/person.component.html | 5 +- .../item-pages/project/project.component.html | 5 +- .../full/full-item-page.component.html | 5 +- src/app/item-page/item-page-routing.module.ts | 5 +- src/app/item-page/item-page.module.ts | 2 - .../publication/publication.component.html | 4 +- .../untyped-item/untyped-item.component.html | 8 +- .../untyped-item/untyped-item.component.ts | 4 +- .../versioned-item.component.scss | 0 .../versioned-item.component.spec.ts | 95 --------- .../versioned-item.component.ts | 80 -------- .../expandable-navbar-section.component.html | 1 + .../dso-page/dso-edit-menu.resolver.spec.ts | 190 ++++++++++++++++++ .../shared/dso-page/dso-edit-menu.resolver.ts | 164 +++++++++++++++ ...dit-menu-expandable-section.component.html | 18 ++ ...dit-menu-expandable-section.component.scss | 26 +++ ...-menu-expandable-section.component.spec.ts | 75 +++++++ ...-edit-menu-expandable-section.component.ts | 39 ++++ .../dso-edit-menu-section.component.html | 25 +++ .../dso-edit-menu-section.component.scss | 3 + .../dso-edit-menu-section.component.spec.ts | 173 ++++++++++++++++ .../dso-edit-menu-section.component.ts | 51 +++++ .../dso-edit-menu.component.html | 6 + .../dso-edit-menu.component.scss} | 0 .../dso-edit-menu.component.spec.ts | 78 +++++++ .../dso-edit-menu/dso-edit-menu.component.ts | 36 ++++ .../dso-page-edit-button.component.html | 7 - .../dso-page-edit-button.component.scss | 3 - .../dso-page-edit-button.component.spec.ts | 76 ------- .../dso-page-edit-button.component.ts | 43 ---- .../dso-page-version-button.component.html | 8 - .../dso-page-version-button.component.scss | 3 - .../dso-page-version-button.component.spec.ts | 96 --------- .../dso-page-version-button.component.ts | 77 ------- .../dso-versioning-modal.service.spec.ts | 92 +++++++++ .../dso-versioning-modal.service.ts | 98 +++++++++ src/app/shared/menu/initial-menus-state.ts | 14 +- .../menu-item/link-menu-item.component.html | 4 +- .../menu-item/link-menu-item.component.ts | 2 +- .../menu/menu-item/models/altmetric.model.ts | 1 + .../menu/menu-item/models/link.model.ts | 1 + .../menu/menu-item/models/menu-item.model.ts | 1 + .../menu/menu-item/models/onclick.model.ts | 1 + .../menu/menu-item/models/search.model.ts | 1 + .../menu/menu-item/models/text.model.ts | 1 + .../onclick-menu-item.component.html | 4 +- .../menu-item/onclick-menu-item.component.ts | 9 +- .../menu-item/text-menu-item.component.html | 2 +- .../menu-section/menu-section.component.ts | 8 +- src/app/shared/shared.module.ts | 17 +- 62 files changed, 1247 insertions(+), 585 deletions(-) delete mode 100644 src/app/item-page/simple/item-types/versioned-item/versioned-item.component.scss delete mode 100644 src/app/item-page/simple/item-types/versioned-item/versioned-item.component.spec.ts delete mode 100644 src/app/item-page/simple/item-types/versioned-item/versioned-item.component.ts create mode 100644 src/app/shared/dso-page/dso-edit-menu.resolver.spec.ts create mode 100644 src/app/shared/dso-page/dso-edit-menu.resolver.ts create mode 100644 src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.html create mode 100644 src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.scss create mode 100644 src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.spec.ts create mode 100644 src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.ts create mode 100644 src/app/shared/dso-page/dso-edit-menu/dso-edit-menu-section/dso-edit-menu-section.component.html create mode 100644 src/app/shared/dso-page/dso-edit-menu/dso-edit-menu-section/dso-edit-menu-section.component.scss create mode 100644 src/app/shared/dso-page/dso-edit-menu/dso-edit-menu-section/dso-edit-menu-section.component.spec.ts create mode 100644 src/app/shared/dso-page/dso-edit-menu/dso-edit-menu-section/dso-edit-menu-section.component.ts create mode 100644 src/app/shared/dso-page/dso-edit-menu/dso-edit-menu.component.html rename src/app/{item-page/simple/item-types/versioned-item/versioned-item.component.html => shared/dso-page/dso-edit-menu/dso-edit-menu.component.scss} (100%) create mode 100644 src/app/shared/dso-page/dso-edit-menu/dso-edit-menu.component.spec.ts create mode 100644 src/app/shared/dso-page/dso-edit-menu/dso-edit-menu.component.ts delete mode 100644 src/app/shared/dso-page/dso-page-edit-button/dso-page-edit-button.component.html delete mode 100644 src/app/shared/dso-page/dso-page-edit-button/dso-page-edit-button.component.scss delete mode 100644 src/app/shared/dso-page/dso-page-edit-button/dso-page-edit-button.component.spec.ts delete mode 100644 src/app/shared/dso-page/dso-page-edit-button/dso-page-edit-button.component.ts delete mode 100644 src/app/shared/dso-page/dso-page-version-button/dso-page-version-button.component.html delete mode 100644 src/app/shared/dso-page/dso-page-version-button/dso-page-version-button.component.scss delete mode 100644 src/app/shared/dso-page/dso-page-version-button/dso-page-version-button.component.spec.ts delete mode 100644 src/app/shared/dso-page/dso-page-version-button/dso-page-version-button.component.ts create mode 100644 src/app/shared/dso-page/dso-versioning-modal-service/dso-versioning-modal.service.spec.ts create mode 100644 src/app/shared/dso-page/dso-versioning-modal-service/dso-versioning-modal.service.ts diff --git a/src/app/admin/admin-sidebar/admin-sidebar-section/admin-sidebar-section.component.html b/src/app/admin/admin-sidebar/admin-sidebar-section/admin-sidebar-section.component.html index 8706b40ee0..7f1e8716ba 100644 --- a/src/app/admin/admin-sidebar/admin-sidebar-section/admin-sidebar-section.component.html +++ b/src/app/admin/admin-sidebar/admin-sidebar-section/admin-sidebar-section.component.html @@ -1,7 +1,7 @@
diff --git a/src/app/community-page/community-page-routing.module.ts b/src/app/community-page/community-page-routing.module.ts index ad1b1fd2f2..ac90f3618c 100644 --- a/src/app/community-page/community-page-routing.module.ts +++ b/src/app/community-page/community-page-routing.module.ts @@ -14,6 +14,7 @@ import { CommunityPageAdministratorGuard } from './community-page-administrator. import { MenuItemType } from '../shared/menu/initial-menus-state'; import { LinkMenuItemModel } from '../shared/menu/menu-item/models/link.model'; import { ThemedCommunityPageComponent } from './themed-community-page.component'; +import { DSOEditMenuResolver } from '../shared/dso-page/dso-edit-menu.resolver'; @NgModule({ imports: [ @@ -27,7 +28,8 @@ import { ThemedCommunityPageComponent } from './themed-community-page.component' path: ':id', resolve: { dso: CommunityPageResolver, - breadcrumb: CommunityBreadcrumbResolver + breadcrumb: CommunityBreadcrumbResolver, + menu: DSOEditMenuResolver }, runGuardsAndResolvers: 'always', children: [ @@ -72,7 +74,8 @@ import { ThemedCommunityPageComponent } from './themed-community-page.component' DSOBreadcrumbsService, LinkService, CreateCommunityPageGuard, - CommunityPageAdministratorGuard + CommunityPageAdministratorGuard, + DSOEditMenuResolver ] }) export class CommunityPageRoutingModule { diff --git a/src/app/community-page/community-page.component.html b/src/app/community-page/community-page.component.html index cf7282eb4b..cee13eadd6 100644 --- a/src/app/community-page/community-page.component.html +++ b/src/app/community-page/community-page.component.html @@ -20,9 +20,7 @@ [title]="'community.page.news'"> -
- -
+
diff --git a/src/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.html b/src/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.html index 5847be7dd2..94dc81fc8f 100644 --- a/src/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.html +++ b/src/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.html @@ -2,9 +2,8 @@

{{'journalissue.page.titleprefix' | translate}}

-
- -
+ +
diff --git a/src/app/entity-groups/journal-entities/item-pages/journal-volume/journal-volume.component.html b/src/app/entity-groups/journal-entities/item-pages/journal-volume/journal-volume.component.html index a0a25766ef..b472f4e648 100644 --- a/src/app/entity-groups/journal-entities/item-pages/journal-volume/journal-volume.component.html +++ b/src/app/entity-groups/journal-entities/item-pages/journal-volume/journal-volume.component.html @@ -2,9 +2,7 @@

{{'journalvolume.page.titleprefix' | translate}}

-
- -
+
diff --git a/src/app/entity-groups/journal-entities/item-pages/journal/journal.component.html b/src/app/entity-groups/journal-entities/item-pages/journal/journal.component.html index af3ac85959..9b11409a31 100644 --- a/src/app/entity-groups/journal-entities/item-pages/journal/journal.component.html +++ b/src/app/entity-groups/journal-entities/item-pages/journal/journal.component.html @@ -2,9 +2,8 @@

{{'journal.page.titleprefix' | translate}}

-
- -
+ +
diff --git a/src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.html b/src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.html index c9ea8fb549..21b36de722 100644 --- a/src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.html +++ b/src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.html @@ -2,9 +2,8 @@

{{'orgunit.page.titleprefix' | translate}}

-
- -
+ +
diff --git a/src/app/entity-groups/research-entities/item-pages/person/person.component.html b/src/app/entity-groups/research-entities/item-pages/person/person.component.html index 5c2fd227fd..c23b543011 100644 --- a/src/app/entity-groups/research-entities/item-pages/person/person.component.html +++ b/src/app/entity-groups/research-entities/item-pages/person/person.component.html @@ -2,9 +2,8 @@

{{'person.page.titleprefix' | translate}}

-
- -
+ +
diff --git a/src/app/entity-groups/research-entities/item-pages/project/project.component.html b/src/app/entity-groups/research-entities/item-pages/project/project.component.html index 8f2ff6adcd..b9a1a30225 100644 --- a/src/app/entity-groups/research-entities/item-pages/project/project.component.html +++ b/src/app/entity-groups/research-entities/item-pages/project/project.component.html @@ -2,9 +2,8 @@

{{'project.page.titleprefix' | translate}}

-
- -
+ +
diff --git a/src/app/item-page/full/full-item-page.component.html b/src/app/item-page/full/full-item-page.component.html index d2655c4ad0..8bb7860aaa 100644 --- a/src/app/item-page/full/full-item-page.component.html +++ b/src/app/item-page/full/full-item-page.component.html @@ -6,9 +6,8 @@
-
- -
+ +
diff --git a/src/app/item-page/simple/item-types/untyped-item/untyped-item.component.html b/src/app/item-page/simple/item-types/untyped-item/untyped-item.component.html index 04794717f1..c9c88fa085 100644 --- a/src/app/item-page/simple/item-types/untyped-item/untyped-item.component.html +++ b/src/app/item-page/simple/item-types/untyped-item/untyped-item.component.html @@ -11,12 +11,8 @@

-
- - -
+ +
diff --git a/src/app/item-page/simple/item-types/untyped-item/untyped-item.component.ts b/src/app/item-page/simple/item-types/untyped-item/untyped-item.component.ts index 3ce33dc90a..ead62008de 100644 --- a/src/app/item-page/simple/item-types/untyped-item/untyped-item.component.ts +++ b/src/app/item-page/simple/item-types/untyped-item/untyped-item.component.ts @@ -2,7 +2,7 @@ import { ChangeDetectionStrategy, Component } from '@angular/core'; import { Item } from '../../../../core/shared/item.model'; import { ViewMode } from '../../../../core/shared/view-mode.model'; import { listableObjectComponent } from '../../../../shared/object-collection/shared/listable-object/listable-object.decorator'; -import { VersionedItemComponent } from '../versioned-item/versioned-item.component'; +import { ItemComponent } from '../shared/item.component'; /** * Component that represents a publication Item page @@ -15,6 +15,6 @@ import { VersionedItemComponent } from '../versioned-item/versioned-item.compone templateUrl: './untyped-item.component.html', changeDetection: ChangeDetectionStrategy.OnPush, }) -export class UntypedItemComponent extends VersionedItemComponent { +export class UntypedItemComponent extends ItemComponent { } diff --git a/src/app/item-page/simple/item-types/versioned-item/versioned-item.component.scss b/src/app/item-page/simple/item-types/versioned-item/versioned-item.component.scss deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/app/item-page/simple/item-types/versioned-item/versioned-item.component.spec.ts b/src/app/item-page/simple/item-types/versioned-item/versioned-item.component.spec.ts deleted file mode 100644 index eff51b1019..0000000000 --- a/src/app/item-page/simple/item-types/versioned-item/versioned-item.component.spec.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { VersionedItemComponent } from './versioned-item.component'; -import { VersionHistoryDataService } from '../../../../core/data/version-history-data.service'; -import { TranslateService } from '@ngx-translate/core'; -import { VersionDataService } from '../../../../core/data/version-data.service'; -import { NotificationsService } from '../../../../shared/notifications/notifications.service'; -import { ItemVersionsSharedService } from '../../../../shared/item/item-versions/item-versions-shared.service'; -import { Item } from '../../../../core/shared/item.model'; -import { createSuccessfulRemoteDataObject$ } from '../../../../shared/remote-data.utils'; -import { buildPaginatedList } from '../../../../core/data/paginated-list.model'; -import { PageInfo } from '../../../../core/shared/page-info.model'; -import { MetadataMap } from '../../../../core/shared/metadata.models'; -import { createRelationshipsObservable, mockRouteService } from '../shared/item.component.spec'; -import { RouterTestingModule } from '@angular/router/testing'; -import { Component } from '@angular/core'; -import { WorkspaceitemDataService } from '../../../../core/submission/workspaceitem-data.service'; -import { SearchService } from '../../../../core/shared/search/search.service'; -import { ItemDataService } from '../../../../core/data/item-data.service'; -import { Version } from '../../../../core/shared/version.model'; -import { RouteService } from '../../../../core/services/route.service'; - -const mockItem: Item = Object.assign(new Item(), { - bundles: createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), [])), - metadata: new MetadataMap(), - relationships: createRelationshipsObservable(), - _links: { - self: { - href: 'item-href' - }, - version: { - href: 'version-href' - } - } -}); - - -@Component({template: ''}) -class DummyComponent { -} - -describe('VersionedItemComponent', () => { - let component: VersionedItemComponent; - let fixture: ComponentFixture; - - let versionService: VersionDataService; - let versionHistoryService: VersionHistoryDataService; - - const versionServiceSpy = jasmine.createSpyObj('versionService', { - findByHref: createSuccessfulRemoteDataObject$(new Version()), - }); - - const versionHistoryServiceSpy = jasmine.createSpyObj('versionHistoryService', { - createVersion: createSuccessfulRemoteDataObject$(new Version()), - }); - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [VersionedItemComponent, DummyComponent], - imports: [RouterTestingModule], - providers: [ - { provide: VersionHistoryDataService, useValue: versionHistoryServiceSpy }, - { provide: TranslateService, useValue: {} }, - { provide: VersionDataService, useValue: versionServiceSpy }, - { provide: NotificationsService, useValue: {} }, - { provide: ItemVersionsSharedService, useValue: {} }, - { provide: WorkspaceitemDataService, useValue: {} }, - { provide: SearchService, useValue: {} }, - { provide: ItemDataService, useValue: {} }, - { provide: RouteService, useValue: mockRouteService } - ] - }).compileComponents(); - versionService = TestBed.inject(VersionDataService); - versionHistoryService = TestBed.inject(VersionHistoryDataService); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(VersionedItemComponent); - component = fixture.componentInstance; - component.object = mockItem; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('when onCreateNewVersion() is called', () => { - it('should call versionService.findByHref', () => { - component.onCreateNewVersion(); - expect(versionService.findByHref).toHaveBeenCalledWith('version-href'); - }); - }); - -}); diff --git a/src/app/item-page/simple/item-types/versioned-item/versioned-item.component.ts b/src/app/item-page/simple/item-types/versioned-item/versioned-item.component.ts deleted file mode 100644 index cd2eb3a19b..0000000000 --- a/src/app/item-page/simple/item-types/versioned-item/versioned-item.component.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { Component } from '@angular/core'; -import { ItemComponent } from '../shared/item.component'; -import { ItemVersionsSummaryModalComponent } from '../../../../shared/item/item-versions/item-versions-summary-modal/item-versions-summary-modal.component'; -import { getFirstCompletedRemoteData, getFirstSucceededRemoteDataPayload } from '../../../../core/shared/operators'; -import { RemoteData } from '../../../../core/data/remote-data'; -import { Version } from '../../../../core/shared/version.model'; -import { switchMap, tap } from 'rxjs/operators'; -import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; -import { VersionHistoryDataService } from '../../../../core/data/version-history-data.service'; -import { TranslateService } from '@ngx-translate/core'; -import { VersionDataService } from '../../../../core/data/version-data.service'; -import { ItemVersionsSharedService } from '../../../../shared/item/item-versions/item-versions-shared.service'; -import { Router } from '@angular/router'; -import { WorkspaceitemDataService } from '../../../../core/submission/workspaceitem-data.service'; -import { SearchService } from '../../../../core/shared/search/search.service'; -import { Item } from '../../../../core/shared/item.model'; -import { ItemDataService } from '../../../../core/data/item-data.service'; -import { WorkspaceItem } from '../../../../core/submission/models/workspaceitem.model'; -import { RouteService } from '../../../../core/services/route.service'; - -@Component({ - selector: 'ds-versioned-item', - templateUrl: './versioned-item.component.html', - styleUrls: ['./versioned-item.component.scss'] -}) -export class VersionedItemComponent extends ItemComponent { - - constructor( - private modalService: NgbModal, - private versionHistoryService: VersionHistoryDataService, - private translateService: TranslateService, - private versionService: VersionDataService, - private itemVersionShared: ItemVersionsSharedService, - private router: Router, - private workspaceItemDataService: WorkspaceitemDataService, - private searchService: SearchService, - private itemService: ItemDataService, - protected routeService: RouteService - ) { - super(routeService); - } - - /** - * Open a modal that allows to create a new version starting from the specified item, with optional summary - */ - onCreateNewVersion(): void { - - const item = this.object; - const versionHref = item._links.version.href; - - // Open modal - const activeModal = this.modalService.open(ItemVersionsSummaryModalComponent); - - // Show current version in modal - this.versionService.findByHref(versionHref).pipe(getFirstCompletedRemoteData()).subscribe((res: RemoteData) => { - // if res.hasNoContent then the item is unversioned - activeModal.componentInstance.firstVersion = res.hasNoContent; - activeModal.componentInstance.versionNumber = (res.hasNoContent ? undefined : res.payload.version); - }); - - // On createVersionEvent emitted create new version and notify - activeModal.componentInstance.createVersionEvent.pipe( - switchMap((summary: string) => this.versionHistoryService.createVersion(item._links.self.href, summary)), - getFirstCompletedRemoteData(), - // show success/failure notification - tap((res: RemoteData) => { this.itemVersionShared.notifyCreateNewVersion(res); }), - // get workspace item - getFirstSucceededRemoteDataPayload(), - switchMap((newVersion: Version) => this.itemService.findByHref(newVersion._links.item.href)), - getFirstSucceededRemoteDataPayload(), - switchMap((newVersionItem: Item) => this.workspaceItemDataService.findByItem(newVersionItem.uuid, true, false)), - getFirstSucceededRemoteDataPayload(), - ).subscribe((wsItem) => { - const wsiId = wsItem.id; - const route = 'workspaceitems/' + wsiId + '/edit'; - this.router.navigateByUrl(route); - }); - - } -} diff --git a/src/app/navbar/expandable-navbar-section/expandable-navbar-section.component.html b/src/app/navbar/expandable-navbar-section/expandable-navbar-section.component.html index d8a517dc55..a77b6bc253 100644 --- a/src/app/navbar/expandable-navbar-section/expandable-navbar-section.component.html +++ b/src/app/navbar/expandable-navbar-section/expandable-navbar-section.component.html @@ -6,6 +6,7 @@ (mouseenter)="activateSection($event)" (mouseleave)="deactivateSection($event)"> { + + const MENU_STATE = { + id: 'some menu' + }; + + let resolver: DSOEditMenuResolver; + + let dSpaceObjectDataService; + let menuService; + let authorizationService; + let dsoVersioningModalService; + + const route = { + data: { + menu: { + 'statistics': [{ + id: 'statistics-dummy-1', + active: false, + visible: true, + model: null + }] + } + }, + params: {id: 'test-uuid'}, + }; + + const state = { + url: 'test-url' + }; + + const testObject = Object.assign(new Item(), {uuid: 'test-uuid', type: 'item', _links: {self: {href: 'self-link'}}}); + + const dummySections1 = [{ + id: 'dummy-1', + active: false, + visible: true, + model: null + }, + { + id: 'dummy-2', + active: false, + visible: true, + model: null + }]; + + const dummySections2 = [{ + id: 'dummy-3', + active: false, + visible: true, + model: null + }, + { + id: 'dummy-4', + active: false, + visible: true, + model: null + }, + { + id: 'dummy-5', + active: false, + visible: true, + model: null + }]; + + beforeEach(waitForAsync(() => { + menuService = new MenuServiceStub(); + spyOn(menuService, 'getMenu').and.returnValue(observableOf(MENU_STATE)); + + dSpaceObjectDataService = jasmine.createSpyObj('dSpaceObjectDataService', { + findById: createSuccessfulRemoteDataObject$(testObject) + }); + authorizationService = jasmine.createSpyObj('authorizationService', { + isAuthorized: observableOf(true) + }); + dsoVersioningModalService = jasmine.createSpyObj('dsoVersioningModalService', { + isNewVersionButtonDisabled: observableOf(false), + getVersioningTooltipMessage: observableOf('message'), + openCreateVersionModal: {} + }); + + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot(), NoopAnimationsModule, RouterTestingModule], + declarations: [AdminSidebarComponent], + providers: [ + {provide: DSpaceObjectDataService, useValue: dSpaceObjectDataService}, + {provide: MenuService, useValue: menuService}, + {provide: AuthorizationDataService, useValue: authorizationService}, + {provide: DsoVersioningModalService, useValue: dsoVersioningModalService}, + { + provide: NgbModal, useValue: { + open: () => {/*comment*/ + } + } + } + ], + schemas: [NO_ERRORS_SCHEMA] + }); + resolver = TestBed.inject(DSOEditMenuResolver); + + spyOn(menuService, 'addSection'); + })); + + it('should be created', () => { + expect(resolver).toBeTruthy(); + }); + + describe('resolve', () => { + it('should create all menus when a dso is found', (done) => { + spyOn(resolver, 'getDsoMenus').and.returnValue( + [observableOf(dummySections1), observableOf(dummySections2)] + ); + resolver.resolve(route as any, null).subscribe(resolved => { + expect(resolved).toEqual( + { + ...route.data.menu, + [MenuID.DSO_EDIT]: [ + ...dummySections1.map((menu) => Object.assign(menu, {id: menu.id + '-test-uuid'})), + ...dummySections2.map((menu) => Object.assign(menu, {id: menu.id + '-test-uuid'})) + ] + } + ); + expect(resolver.getDsoMenus).toHaveBeenCalled(); + done(); + }); + }); + it('should return the statistics menu when no dso is found', (done) => { + (dSpaceObjectDataService.findById as jasmine.Spy).and.returnValue(createFailedRemoteDataObject$()); + + resolver.resolve(route as any, null).subscribe(resolved => { + expect(resolved).toEqual( + { + ...route.data.menu + } + ); + done(); + }); + }); + }); + describe('getDsoMenus', () => { + it('should return as first part the item version list ', (done) => { + const result = resolver.getDsoMenus(testObject, route, state); + result[0].subscribe((menuList) => { + expect(menuList.length).toEqual(1); + expect(menuList[0].id).toEqual('version-dso'); + expect(menuList[0].active).toEqual(false); + expect(menuList[0].visible).toEqual(true); + expect(menuList[0].model.type).toEqual(MenuItemType.ONCLICK); + expect(menuList[0].model.text).toEqual('message'); + expect(menuList[0].model.disabled).toEqual(false); + expect(menuList[0].icon).toEqual('code-branch'); + done(); + }); + + }); + it('should return as second part the common list ', (done) => { + const result = resolver.getDsoMenus(testObject, route, state); + result[1].subscribe((menuList) => { + expect(menuList.length).toEqual(1); + expect(menuList[0].id).toEqual('edit-dso'); + expect(menuList[0].active).toEqual(false); + expect(menuList[0].visible).toEqual(true); + expect(menuList[0].model.type).toEqual(MenuItemType.LINK); + expect(menuList[0].model.text).toEqual('item.page.edit'); + expect(menuList[0].model.link).toEqual('test-url/edit/metadata'); + expect(menuList[0].icon).toEqual('pencil-alt'); + done(); + }); + + }); + }); +}); diff --git a/src/app/shared/dso-page/dso-edit-menu.resolver.ts b/src/app/shared/dso-page/dso-edit-menu.resolver.ts new file mode 100644 index 0000000000..003e61df95 --- /dev/null +++ b/src/app/shared/dso-page/dso-edit-menu.resolver.ts @@ -0,0 +1,164 @@ +import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router'; +import { combineLatest, Observable, of as observableOf } from 'rxjs'; +import { FeatureID } from '../../core/data/feature-authorization/feature-id'; +import { MenuID, MenuItemType } from '../menu/initial-menus-state'; +import { MenuService } from '../menu/menu.service'; +import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service'; +import { Injectable } from '@angular/core'; +import { LinkMenuItemModel } from '../menu/menu-item/models/link.model'; +import { Item } from '../../core/shared/item.model'; +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { OnClickMenuItemModel } from '../menu/menu-item/models/onclick.model'; +import { getFirstCompletedRemoteData } from '../../core/shared/operators'; +import { map, switchMap } from 'rxjs/operators'; +import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.service'; +import { URLCombiner } from '../../core/url-combiner/url-combiner'; +import { DsoVersioningModalService } from './dso-versioning-modal-service/dso-versioning-modal.service'; +import { hasValue } from '../empty.util'; +import { MenuSection } from '../menu/menu.reducer'; + +/** + * Creates the menus for the dspace object pages + */ +@Injectable({ + providedIn: 'root' +}) +export class DSOEditMenuResolver implements Resolve<{ [key: string]: MenuSection[] }> { + + constructor( + protected dSpaceObjectDataService: DSpaceObjectDataService, + protected menuService: MenuService, + protected authorizationService: AuthorizationDataService, + protected modalService: NgbModal, + protected dsoVersioningModalService: DsoVersioningModalService, + ) { + } + + /** + * Initialise all dspace object related menus + */ + resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<{ [key: string]: MenuSection[] }> { + const uuid = route.params.id; + return this.dSpaceObjectDataService.findById(uuid, true, false).pipe( + getFirstCompletedRemoteData(), + switchMap((dsoRD) => { + if (dsoRD.hasSucceeded) { + const dso = dsoRD.payload; + return combineLatest(this.getDsoMenus(dso, route, state)).pipe( + map((combinedMenus) => [].concat.apply([], combinedMenus)), + map((menus) => this.addDsoUuidToMenuIDs(menus, dso)), + map((menus) => { + return { + ...route.data?.menu, + [MenuID.DSO_EDIT]: menus + }; + }) + ); + } else { + return observableOf({...route.data?.menu}); + } + }) + ); + } + + /** + * Return all the menus for a dso based on the route and state + */ + getDsoMenus(dso, route, state) { + return [ + this.getItemMenu(dso), + this.getCommonMenu(dso, state) + ]; + } + + /** + * Get the common menus between all dspace objects + */ + protected getCommonMenu(dso, state): Observable { + return combineLatest([ + this.authorizationService.isAuthorized(FeatureID.CanEditMetadata, dso.self), + ]).pipe( + map(([canEditItem]) => { + return [ + { + id: 'edit-dso', + active: false, + visible: canEditItem, + model: { + type: MenuItemType.LINK, + text: this.getDsoType(dso) + '.page.edit', + link: new URLCombiner(state.url, 'edit', 'metadata').toString() + } as LinkMenuItemModel, + icon: 'pencil-alt', + index: 1 + }, + ]; + + }) + ); + } + + /** + * Get item sepcific menus + */ + protected getItemMenu(dso): Observable { + if (dso instanceof Item) { + return combineLatest([ + this.authorizationService.isAuthorized(FeatureID.CanCreateVersion, dso.self), + this.dsoVersioningModalService.isNewVersionButtonDisabled(dso), + this.dsoVersioningModalService.getVersioningTooltipMessage(dso, 'item.page.version.hasDraft', 'item.page.version.create') + ]).pipe( + map(([canCreateVersion, disableVersioning, versionTooltip]) => { + return [ + { + id: 'version-dso', + active: false, + visible: canCreateVersion, + model: { + type: MenuItemType.ONCLICK, + text: versionTooltip, + disabled: disableVersioning, + function: () => { + this.dsoVersioningModalService.openCreateVersionModal(dso); + } + } as OnClickMenuItemModel, + icon: 'code-branch', + index: 0 + }, + ]; + }), + ); + } else { + return observableOf([]); + } + } + + /** + * Retrieve the dso or entity type for an object to be used in generic messages + */ + protected getDsoType(dso) { + const renderType = dso.getRenderTypes()[0]; + if (typeof renderType === 'string' || renderType instanceof String) { + return renderType.toLowerCase(); + } else { + return dso.type.toString().toLowerCase(); + } + } + + /** + * Add the dso uuid to all provided menu ids and parent ids + */ + protected addDsoUuidToMenuIDs(menus, dso) { + return menus.map((menu) => { + Object.assign(menu, { + id: menu.id + '-' + dso.uuid + }); + if (hasValue(menu.parentID)) { + Object.assign(menu, { + parentID: menu.parentID + '-' + dso.uuid + }); + } + return menu; + }); + } +} diff --git a/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.html b/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.html new file mode 100644 index 0000000000..b330b1e87d --- /dev/null +++ b/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.html @@ -0,0 +1,18 @@ +
+
+ +
    + + + +
+
+
+ + + + diff --git a/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.scss b/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.scss new file mode 100644 index 0000000000..61ec6347f9 --- /dev/null +++ b/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.scss @@ -0,0 +1,26 @@ +.btn-dark { + background-color: var(--ds-admin-sidebar-bg); +} + +.dso-button-menu { + .dropdown-toggle::after { + display: none; + } +} + +ul.dropdown-menu { + background-color: var(--ds-admin-sidebar-bg); + color: white; + + ::ng-deep a { + color: white; + + &.disabled { + color: $btn-link-disabled-color; + } + } + + .disabled { + color: $btn-link-disabled-color; + } +} diff --git a/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.spec.ts b/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.spec.ts new file mode 100644 index 0000000000..211fd0bdf0 --- /dev/null +++ b/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.spec.ts @@ -0,0 +1,75 @@ +import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { MenuServiceStub } from '../../../testing/menu-service.stub'; +import { TranslateModule } from '@ngx-translate/core'; +import { MenuService } from '../../../menu/menu.service'; +import { CSSVariableService } from '../../../sass-helper/sass-helper.service'; +import { CSSVariableServiceStub } from '../../../testing/css-variable-service.stub'; +import { Router } from '@angular/router'; +import { RouterStub } from '../../../testing/router.stub'; +import { of as observableOf } from 'rxjs'; +import { Component } from '@angular/core'; +import { DsoEditMenuExpandableSectionComponent } from './dso-edit-menu-expandable-section.component'; +import { MenuItemType } from '../../../menu/initial-menus-state'; +import { By } from '@angular/platform-browser'; + +describe('DsoEditMenuExpandableSectionComponent', () => { + let component: DsoEditMenuExpandableSectionComponent; + let fixture: ComponentFixture; + const menuService = new MenuServiceStub(); + const iconString = 'test'; + + const dummySection = { + id: 'dummy', + active: false, + visible: true, + model: { + type: MenuItemType.TEXT, + disabled: false, + text: 'text' + }, + icon: iconString + }; + + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot()], + declarations: [DsoEditMenuExpandableSectionComponent, TestComponent], + providers: [ + {provide: 'sectionDataProvider', useValue: dummySection}, + {provide: MenuService, useValue: menuService}, + {provide: CSSVariableService, useClass: CSSVariableServiceStub}, + {provide: Router, useValue: new RouterStub()}, + ] + }).overrideComponent(DsoEditMenuExpandableSectionComponent, { + set: { + entryComponents: [TestComponent] + } + }) + .compileComponents(); + })); + + beforeEach(() => { + spyOn(menuService, 'getSubSectionsByParentID').and.returnValue(observableOf([])); + fixture = TestBed.createComponent(DsoEditMenuExpandableSectionComponent); + component = fixture.componentInstance; + spyOn(component as any, 'getMenuItemComponent').and.returnValue(TestComponent); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should show a button with the icon', () => { + const button = fixture.debugElement.query(By.css('.btn-dark')); + expect(button.nativeElement.innerHTML).toContain('fa-' + iconString); + }); +}); + +// declare a test component +@Component({ + selector: 'ds-test-cmp', + template: `` +}) +class TestComponent { +} diff --git a/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.ts b/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.ts new file mode 100644 index 0000000000..e0ad28617b --- /dev/null +++ b/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.ts @@ -0,0 +1,39 @@ +import { Component, Inject, Injector } from '@angular/core'; +import { MenuID } from 'src/app/shared/menu/initial-menus-state'; +import { rendersSectionForMenu } from 'src/app/shared/menu/menu-section.decorator'; +import { MenuSectionComponent } from 'src/app/shared/menu/menu-section/menu-section.component'; +import { MenuService } from '../../../menu/menu.service'; +import { MenuSection } from '../../../menu/menu.reducer'; +import { Router } from '@angular/router'; + +/** + * Represents an expandable section in the dso edit menus + */ +@Component({ + /* tslint:disable:component-selector */ + selector: 'ds-dso-edit-menu-expandable-section', + templateUrl: './dso-edit-menu-expandable-section.component.html', + styleUrls: ['./dso-edit-menu-expandable-section.component.scss'], +}) +@rendersSectionForMenu(MenuID.DSO_EDIT, true) +export class DsoEditMenuExpandableSectionComponent extends MenuSectionComponent { + + menuID: MenuID = MenuID.DSO_EDIT; + itemModel; + + constructor( + @Inject('sectionDataProvider') menuSection: MenuSection, + protected menuService: MenuService, + protected injector: Injector, + protected router: Router, + ) { + super(menuSection, menuService, injector); + this.itemModel = menuSection.model; + } + + ngOnInit(): void { + this.menuService.activateSection(this.menuID, this.section.id); + super.ngOnInit(); + } + +} diff --git a/src/app/shared/dso-page/dso-edit-menu/dso-edit-menu-section/dso-edit-menu-section.component.html b/src/app/shared/dso-page/dso-edit-menu/dso-edit-menu-section/dso-edit-menu-section.component.html new file mode 100644 index 0000000000..0fc6d19667 --- /dev/null +++ b/src/app/shared/dso-page/dso-edit-menu/dso-edit-menu-section/dso-edit-menu-section.component.html @@ -0,0 +1,25 @@ +
+ + + +
+ +
+
+ +
+ +
diff --git a/src/app/shared/dso-page/dso-edit-menu/dso-edit-menu-section/dso-edit-menu-section.component.scss b/src/app/shared/dso-page/dso-edit-menu/dso-edit-menu-section/dso-edit-menu-section.component.scss new file mode 100644 index 0000000000..cf0e81c553 --- /dev/null +++ b/src/app/shared/dso-page/dso-edit-menu/dso-edit-menu-section/dso-edit-menu-section.component.scss @@ -0,0 +1,3 @@ +.btn-dark { + background-color: var(--ds-admin-sidebar-bg); +} diff --git a/src/app/shared/dso-page/dso-edit-menu/dso-edit-menu-section/dso-edit-menu-section.component.spec.ts b/src/app/shared/dso-page/dso-edit-menu/dso-edit-menu-section/dso-edit-menu-section.component.spec.ts new file mode 100644 index 0000000000..bcfeab8180 --- /dev/null +++ b/src/app/shared/dso-page/dso-edit-menu/dso-edit-menu-section/dso-edit-menu-section.component.spec.ts @@ -0,0 +1,173 @@ +import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { MenuServiceStub } from '../../../testing/menu-service.stub'; +import { TranslateModule } from '@ngx-translate/core'; +import { MenuService } from '../../../menu/menu.service'; +import { CSSVariableService } from '../../../sass-helper/sass-helper.service'; +import { CSSVariableServiceStub } from '../../../testing/css-variable-service.stub'; +import { Router } from '@angular/router'; +import { RouterStub } from '../../../testing/router.stub'; +import { of as observableOf } from 'rxjs'; +import { Component } from '@angular/core'; +import { MenuItemType } from '../../../menu/initial-menus-state'; +import { By } from '@angular/platform-browser'; +import { DsoEditMenuSectionComponent } from './dso-edit-menu-section.component'; +import { OnClickMenuItemModel } from '../../../menu/menu-item/models/onclick.model'; + +function initAsync(dummySectionText: { visible: boolean; icon: string; active: boolean; model: { disabled: boolean; text: string; type: MenuItemType }; id: string }, menuService: MenuServiceStub) { + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot()], + declarations: [DsoEditMenuSectionComponent, TestComponent], + providers: [ + {provide: 'sectionDataProvider', useValue: dummySectionText}, + {provide: MenuService, useValue: menuService}, + {provide: CSSVariableService, useClass: CSSVariableServiceStub}, + {provide: Router, useValue: new RouterStub()}, + ] + }).overrideComponent(DsoEditMenuSectionComponent, { + set: { + entryComponents: [TestComponent] + } + }) + .compileComponents(); + })); +} + +describe('DsoEditMenuSectionComponent', () => { + let component: DsoEditMenuSectionComponent; + let fixture: ComponentFixture; + const menuService = new MenuServiceStub(); + const iconString = 'test'; + + const dummySectionText = { + id: 'dummy', + active: false, + visible: true, + model: { + type: MenuItemType.TEXT, + disabled: false, + text: 'text' + }, + icon: iconString + }; + const dummySectionLink = { + id: 'dummy', + active: false, + visible: true, + model: { + type: MenuItemType.LINK, + disabled: false, + text: 'text', + link: 'link' + }, + icon: iconString + }; + + const dummySectionClick = { + id: 'dummy', + active: false, + visible: true, + model: { + type: MenuItemType.ONCLICK, + disabled: false, + text: 'text', + function: () => 'test' + }, + icon: iconString + }; + + describe('text model', () => { + initAsync(dummySectionText, menuService); + beforeEach(() => { + spyOn(menuService, 'getSubSectionsByParentID').and.returnValue(observableOf([])); + fixture = TestBed.createComponent(DsoEditMenuSectionComponent); + component = fixture.componentInstance; + spyOn(component as any, 'getMenuItemComponent').and.returnValue(TestComponent); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should show a button with the icon', () => { + const button = fixture.debugElement.query(By.css('.btn-dark')); + expect(button.nativeElement.innerHTML).toContain('fa-' + iconString); + }); + describe('when the section model in a disabled link or text', () => { + it('should show just the button', () => { + const textButton = fixture.debugElement.query(By.css('div div button')); + expect(textButton.nativeElement.innerHTML).toContain('fa-' + iconString); + }); + }); + }); + describe('on click model', () => { + initAsync(dummySectionClick, menuService); + beforeEach(() => { + spyOn(menuService, 'getSubSectionsByParentID').and.returnValue(observableOf([])); + fixture = TestBed.createComponent(DsoEditMenuSectionComponent); + component = fixture.componentInstance; + spyOn(component as any, 'getMenuItemComponent').and.returnValue(TestComponent); + fixture.detectChanges(); + }); + + describe('when the section model in an on click menu', () => { + it('should call the activate method when clicking the button', () => { + spyOn(component, 'activate'); + + const button = fixture.debugElement.query(By.css('.btn-dark')); + button.triggerEventHandler('click', null); + + expect(component.activate).toHaveBeenCalled(); + }); + }); + describe('activate', () => { + const mockEvent = jasmine.createSpyObj('event', { + preventDefault: jasmine.createSpy('preventDefault'), + stopPropagation: jasmine.createSpy('stopPropagation'), + }); + it('should call the item model function when not disabled', () => { + spyOn(component.section.model as OnClickMenuItemModel, 'function'); + component.activate(mockEvent); + + expect((component.section.model as OnClickMenuItemModel).function).toHaveBeenCalled(); + }); + it('should call not the item model function when disabled', () => { + spyOn(component.section.model as OnClickMenuItemModel, 'function'); + component.itemModel.disabled = true; + component.activate(mockEvent); + + expect((component.section.model as OnClickMenuItemModel).function).not.toHaveBeenCalled(); + component.itemModel.disabled = false; + }); + }); + + }); + + describe('link model', () => { + initAsync(dummySectionLink, menuService); + beforeEach(() => { + spyOn(menuService, 'getSubSectionsByParentID').and.returnValue(observableOf([])); + fixture = TestBed.createComponent(DsoEditMenuSectionComponent); + component = fixture.componentInstance; + spyOn(component as any, 'getMenuItemComponent').and.returnValue(TestComponent); + fixture.detectChanges(); + }); + + describe('when the section model in a non disabled link', () => { + it('should show a link element with the button in it', () => { + const link = fixture.debugElement.query(By.css('a')); + expect(link.nativeElement.innerHTML).toContain('button'); + }); + }); + + }); +}); + +// declare a test component +@Component({ + selector: 'ds-test-cmp', + template: `` +}) +class TestComponent { +} diff --git a/src/app/shared/dso-page/dso-edit-menu/dso-edit-menu-section/dso-edit-menu-section.component.ts b/src/app/shared/dso-page/dso-edit-menu/dso-edit-menu-section/dso-edit-menu-section.component.ts new file mode 100644 index 0000000000..63354e9749 --- /dev/null +++ b/src/app/shared/dso-page/dso-edit-menu/dso-edit-menu-section/dso-edit-menu-section.component.ts @@ -0,0 +1,51 @@ +import { Component, Inject, Injector, OnInit } from '@angular/core'; +import { MenuID } from 'src/app/shared/menu/initial-menus-state'; +import { rendersSectionForMenu } from 'src/app/shared/menu/menu-section.decorator'; +import { MenuSectionComponent } from 'src/app/shared/menu/menu-section/menu-section.component'; +import { MenuService } from '../../../menu/menu.service'; +import { MenuSection } from '../../../menu/menu.reducer'; +import { isNotEmpty } from '../../../empty.util'; + +/** + * Represents a non-expandable section in the dso edit menus + */ +@Component({ + /* tslint:disable:component-selector */ + selector: 'ds-dso-edit-menu-section', + templateUrl: './dso-edit-menu-section.component.html', + styleUrls: ['./dso-edit-menu-section.component.scss'] +}) +@rendersSectionForMenu(MenuID.DSO_EDIT, false) +export class DsoEditMenuSectionComponent extends MenuSectionComponent implements OnInit { + + menuID: MenuID = MenuID.DSO_EDIT; + itemModel; + hasLink: boolean; + canActivate: boolean; + + constructor( + @Inject('sectionDataProvider') menuSection: MenuSection, + protected menuService: MenuService, + protected injector: Injector, + ) { + super(menuSection, menuService, injector); + this.itemModel = menuSection.model; + } + + ngOnInit(): void { + this.hasLink = isNotEmpty(this.itemModel?.link); + this.canActivate = isNotEmpty(this.itemModel?.function); + super.ngOnInit(); + } + + /** + * Activate the section's model funtion + */ + public activate(event: any) { + event.preventDefault(); + if (!this.itemModel.disabled) { + this.itemModel.function(); + } + event.stopPropagation(); + } +} diff --git a/src/app/shared/dso-page/dso-edit-menu/dso-edit-menu.component.html b/src/app/shared/dso-page/dso-edit-menu/dso-edit-menu.component.html new file mode 100644 index 0000000000..9ef6fff1dc --- /dev/null +++ b/src/app/shared/dso-page/dso-edit-menu/dso-edit-menu.component.html @@ -0,0 +1,6 @@ +
+
+ +
+
diff --git a/src/app/item-page/simple/item-types/versioned-item/versioned-item.component.html b/src/app/shared/dso-page/dso-edit-menu/dso-edit-menu.component.scss similarity index 100% rename from src/app/item-page/simple/item-types/versioned-item/versioned-item.component.html rename to src/app/shared/dso-page/dso-edit-menu/dso-edit-menu.component.scss diff --git a/src/app/shared/dso-page/dso-edit-menu/dso-edit-menu.component.spec.ts b/src/app/shared/dso-page/dso-edit-menu/dso-edit-menu.component.spec.ts new file mode 100644 index 0000000000..f2fb656ecc --- /dev/null +++ b/src/app/shared/dso-page/dso-edit-menu/dso-edit-menu.component.spec.ts @@ -0,0 +1,78 @@ +import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { TranslateModule } from '@ngx-translate/core'; +import { ChangeDetectionStrategy, Injector, NO_ERRORS_SCHEMA } from '@angular/core'; +import { of as observableOf } from 'rxjs'; +import { RouterTestingModule } from '@angular/router/testing'; +import { ActivatedRoute } from '@angular/router'; +import { DsoEditMenuComponent } from './dso-edit-menu.component'; +import { MenuServiceStub } from '../../testing/menu-service.stub'; +import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service'; +import { AuthService } from '../../../core/auth/auth.service'; +import { AuthServiceStub } from '../../testing/auth-service.stub'; +import { MenuService } from '../../menu/menu.service'; +import { + ExpandableNavbarSectionComponent +} from '../../../navbar/expandable-navbar-section/expandable-navbar-section.component'; +import { MenuItemModel } from '../../menu/menu-item/models/menu-item.model'; + +describe('DsoEditMenuComponent', () => { + let comp: DsoEditMenuComponent; + let fixture: ComponentFixture; + const menuService = new MenuServiceStub(); + let authorizationService: AuthorizationDataService; + + const routeStub = { + children: [] + }; + + const section = { + id: 'edit-dso', + active: false, + visible: true, + model: { + type: null, + disabled: false, + } as MenuItemModel, + icon: 'pencil-alt', + index: 1 + }; + + + beforeEach(waitForAsync(() => { + authorizationService = jasmine.createSpyObj('authorizationService', { + isAuthorized: observableOf(true) + }); + spyOn(menuService, 'getMenuTopSections').and.returnValue(observableOf([section])); + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot(), RouterTestingModule], + declarations: [DsoEditMenuComponent], + providers: [ + Injector, + {provide: MenuService, useValue: menuService}, + {provide: AuthService, useClass: AuthServiceStub}, + {provide: ActivatedRoute, useValue: routeStub}, + {provide: AuthorizationDataService, useValue: authorizationService}, + ], + schemas: [NO_ERRORS_SCHEMA] + }).overrideComponent(ExpandableNavbarSectionComponent, { + set: { + changeDetection: ChangeDetectionStrategy.Default, + } + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(DsoEditMenuComponent); + comp = fixture.componentInstance; + comp.sections = observableOf([]); + fixture.detectChanges(); + }); + + describe('onInit', () => { + it('should create', () => { + expect(comp).toBeTruthy(); + }); + }); +}); + diff --git a/src/app/shared/dso-page/dso-edit-menu/dso-edit-menu.component.ts b/src/app/shared/dso-page/dso-edit-menu/dso-edit-menu.component.ts new file mode 100644 index 0000000000..d754e07b32 --- /dev/null +++ b/src/app/shared/dso-page/dso-edit-menu/dso-edit-menu.component.ts @@ -0,0 +1,36 @@ +import { Component, Injector } from '@angular/core'; +import { AuthorizationDataService } from 'src/app/core/data/feature-authorization/authorization-data.service'; +import { MenuID } from '../../menu/initial-menus-state'; +import { MenuComponent } from '../../menu/menu.component'; +import { MenuService } from '../../menu/menu.service'; +import { ActivatedRoute } from '@angular/router'; +import { AuthService } from '../../../core/auth/auth.service'; + +/** + * Component representing the edit menu and other menus on the dspace object pages + */ +@Component({ + selector: 'ds-dso-edit-menu', + styleUrls: ['./dso-edit-menu.component.scss'], + templateUrl: './dso-edit-menu.component.html', +}) +export class DsoEditMenuComponent extends MenuComponent { + /** + * The menu ID of this component is DSO_EDIT + * @type {MenuID.DSO_EDIT} + */ + menuID = MenuID.DSO_EDIT; + + constructor(protected menuService: MenuService, + protected injector: Injector, + public authorizationService: AuthorizationDataService, + public route: ActivatedRoute, + private authService: AuthService, + ) { + super(menuService, injector, authorizationService, route); + } + + ngOnInit(): void { + super.ngOnInit(); + } +} diff --git a/src/app/shared/dso-page/dso-page-edit-button/dso-page-edit-button.component.html b/src/app/shared/dso-page/dso-page-edit-button/dso-page-edit-button.component.html deleted file mode 100644 index d680c140d8..0000000000 --- a/src/app/shared/dso-page/dso-page-edit-button/dso-page-edit-button.component.html +++ /dev/null @@ -1,7 +0,0 @@ -
- - diff --git a/src/app/shared/dso-page/dso-page-edit-button/dso-page-edit-button.component.scss b/src/app/shared/dso-page/dso-page-edit-button/dso-page-edit-button.component.scss deleted file mode 100644 index e8b7d689a3..0000000000 --- a/src/app/shared/dso-page/dso-page-edit-button/dso-page-edit-button.component.scss +++ /dev/null @@ -1,3 +0,0 @@ -.btn-dark { - background-color: var(--ds-admin-sidebar-bg); -} diff --git a/src/app/shared/dso-page/dso-page-edit-button/dso-page-edit-button.component.spec.ts b/src/app/shared/dso-page/dso-page-edit-button/dso-page-edit-button.component.spec.ts deleted file mode 100644 index 5949a98f71..0000000000 --- a/src/app/shared/dso-page/dso-page-edit-button/dso-page-edit-button.component.spec.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; -import { DsoPageEditButtonComponent } from './dso-page-edit-button.component'; -import { DSpaceObject } from '../../../core/shared/dspace-object.model'; -import { Item } from '../../../core/shared/item.model'; -import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service'; -import { of as observableOf } from 'rxjs'; -import { TranslateModule } from '@ngx-translate/core'; -import { RouterTestingModule } from '@angular/router/testing'; -import { FeatureID } from '../../../core/data/feature-authorization/feature-id'; -import { By } from '@angular/platform-browser'; -import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; - -describe('DsoPageEditButtonComponent', () => { - let component: DsoPageEditButtonComponent; - let fixture: ComponentFixture; - - let authorizationService: AuthorizationDataService; - let dso: DSpaceObject; - - beforeEach(waitForAsync(() => { - dso = Object.assign(new Item(), { - id: 'test-item', - _links: { - self: { href: 'test-item-selflink' } - } - }); - authorizationService = jasmine.createSpyObj('authorizationService', { - isAuthorized: observableOf(true) - }); - TestBed.configureTestingModule({ - declarations: [DsoPageEditButtonComponent], - imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([]), NgbModule], - providers: [ - { provide: AuthorizationDataService, useValue: authorizationService } - ] - }).compileComponents(); - })); - - beforeEach(() => { - fixture = TestBed.createComponent(DsoPageEditButtonComponent); - component = fixture.componentInstance; - component.dso = dso; - component.pageRoute = 'test'; - fixture.detectChanges(); - }); - - it('should check the authorization of the current user', () => { - expect(authorizationService.isAuthorized).toHaveBeenCalledWith(FeatureID.CanEditMetadata, dso.self); - }); - - describe('when the user is authorized', () => { - beforeEach(() => { - (authorizationService.isAuthorized as jasmine.Spy).and.returnValue(observableOf(true)); - component.ngOnInit(); - fixture.detectChanges(); - }); - - it('should render a link', () => { - const link = fixture.debugElement.query(By.css('a')); - expect(link).not.toBeNull(); - }); - }); - - describe('when the user is not authorized', () => { - beforeEach(() => { - (authorizationService.isAuthorized as jasmine.Spy).and.returnValue(observableOf(false)); - component.ngOnInit(); - fixture.detectChanges(); - }); - - it('should not render a link', () => { - const link = fixture.debugElement.query(By.css('a')); - expect(link).toBeNull(); - }); - }); -}); diff --git a/src/app/shared/dso-page/dso-page-edit-button/dso-page-edit-button.component.ts b/src/app/shared/dso-page/dso-page-edit-button/dso-page-edit-button.component.ts deleted file mode 100644 index 1879581d23..0000000000 --- a/src/app/shared/dso-page/dso-page-edit-button/dso-page-edit-button.component.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { Component, Input, OnInit } from '@angular/core'; -import { DSpaceObject } from '../../../core/shared/dspace-object.model'; -import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service'; -import { Observable } from 'rxjs'; -import { FeatureID } from '../../../core/data/feature-authorization/feature-id'; - -@Component({ - selector: 'ds-dso-page-edit-button', - templateUrl: './dso-page-edit-button.component.html', - styleUrls: ['./dso-page-edit-button.component.scss'] -}) -/** - * Display a button linking to the edit page of a DSpaceObject - */ -export class DsoPageEditButtonComponent implements OnInit { - /** - * The DSpaceObject to display a button to the edit page for - */ - @Input() dso: DSpaceObject; - - /** - * The prefix of the route to the edit page (before the object's UUID, e.g. "items") - */ - @Input() pageRoute: string; - - /** - * A message for the tooltip on the button - * Supports i18n keys - */ - @Input() tooltipMsg: string; - - /** - * Whether or not the current user is authorized to edit the DSpaceObject - */ - isAuthorized$: Observable; - - constructor(protected authorizationService: AuthorizationDataService) { } - - ngOnInit() { - this.isAuthorized$ = this.authorizationService.isAuthorized(FeatureID.CanEditMetadata, this.dso.self); - } - -} diff --git a/src/app/shared/dso-page/dso-page-version-button/dso-page-version-button.component.html b/src/app/shared/dso-page/dso-page-version-button/dso-page-version-button.component.html deleted file mode 100644 index 0e2e35dcb7..0000000000 --- a/src/app/shared/dso-page/dso-page-version-button/dso-page-version-button.component.html +++ /dev/null @@ -1,8 +0,0 @@ - diff --git a/src/app/shared/dso-page/dso-page-version-button/dso-page-version-button.component.scss b/src/app/shared/dso-page/dso-page-version-button/dso-page-version-button.component.scss deleted file mode 100644 index e8b7d689a3..0000000000 --- a/src/app/shared/dso-page/dso-page-version-button/dso-page-version-button.component.scss +++ /dev/null @@ -1,3 +0,0 @@ -.btn-dark { - background-color: var(--ds-admin-sidebar-bg); -} diff --git a/src/app/shared/dso-page/dso-page-version-button/dso-page-version-button.component.spec.ts b/src/app/shared/dso-page/dso-page-version-button/dso-page-version-button.component.spec.ts deleted file mode 100644 index 9839507d57..0000000000 --- a/src/app/shared/dso-page/dso-page-version-button/dso-page-version-button.component.spec.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; -import { DsoPageVersionButtonComponent } from './dso-page-version-button.component'; -import { Item } from '../../../core/shared/item.model'; -import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service'; -import { Observable, of, of as observableOf } from 'rxjs'; -import { TranslateModule } from '@ngx-translate/core'; -import { RouterTestingModule } from '@angular/router/testing'; -import { FeatureID } from '../../../core/data/feature-authorization/feature-id'; -import { By } from '@angular/platform-browser'; -import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; -import { VersionHistoryDataService } from '../../../core/data/version-history-data.service'; - -describe('DsoPageVersionButtonComponent', () => { - let component: DsoPageVersionButtonComponent; - let fixture: ComponentFixture; - - let authorizationService: AuthorizationDataService; - let versionHistoryService: VersionHistoryDataService; - - let dso: Item; - let tooltipMsg: Observable; - - const authorizationServiceSpy = jasmine.createSpyObj('authorizationService', ['isAuthorized']); - - const versionHistoryServiceSpy = jasmine.createSpyObj('versionHistoryService', - ['getVersions', 'getLatestVersionFromHistory$', 'isLatest$', 'hasDraftVersion$'] - ); - - beforeEach(waitForAsync(() => { - dso = Object.assign(new Item(), { - id: 'test-item', - _links: { - self: { href: 'test-item-selflink' }, - version: { href: 'test-item-version-selflink' }, - }, - }); - tooltipMsg = of('tooltip-msg'); - - TestBed.configureTestingModule({ - declarations: [DsoPageVersionButtonComponent], - imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([]), NgbModule], - providers: [ - { provide: AuthorizationDataService, useValue: authorizationServiceSpy }, - { provide: VersionHistoryDataService, useValue: versionHistoryServiceSpy }, - ] - }).compileComponents(); - - authorizationService = TestBed.inject(AuthorizationDataService); - versionHistoryService = TestBed.inject(VersionHistoryDataService); - - versionHistoryServiceSpy.hasDraftVersion$.and.returnValue(observableOf(true)); - })); - - beforeEach(() => { - fixture = TestBed.createComponent(DsoPageVersionButtonComponent); - component = fixture.componentInstance; - component.dso = dso; - component.tooltipMsg$ = tooltipMsg; - fixture.detectChanges(); - }); - - it('should check the authorization of the current user', () => { - expect(authorizationService.isAuthorized).toHaveBeenCalledWith(FeatureID.CanCreateVersion, dso.self); - }); - - it('should check if the item has a draft version', () => { - expect(versionHistoryServiceSpy.hasDraftVersion$).toHaveBeenCalledWith(dso._links.version.href); - }); - - describe('when the user is authorized', () => { - beforeEach(() => { - authorizationServiceSpy.isAuthorized.and.returnValue(observableOf(true)); - component.ngOnInit(); - fixture.detectChanges(); - }); - - it('should render a button', () => { - const button = fixture.debugElement.query(By.css('button')); - expect(button).not.toBeNull(); - }); - }); - - describe('when the user is not authorized', () => { - beforeEach(() => { - authorizationServiceSpy.isAuthorized.and.returnValue(observableOf(false)); - component.ngOnInit(); - fixture.detectChanges(); - }); - - it('should render a button', () => { - const button = fixture.debugElement.query(By.css('button')); - expect(button).toBeNull(); - }); - }); - -}); diff --git a/src/app/shared/dso-page/dso-page-version-button/dso-page-version-button.component.ts b/src/app/shared/dso-page/dso-page-version-button/dso-page-version-button.component.ts deleted file mode 100644 index cf07953c75..0000000000 --- a/src/app/shared/dso-page/dso-page-version-button/dso-page-version-button.component.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; -import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service'; -import { Observable, of } from 'rxjs'; -import { FeatureID } from '../../../core/data/feature-authorization/feature-id'; -import { VersionHistoryDataService } from '../../../core/data/version-history-data.service'; -import { Item } from '../../../core/shared/item.model'; -import { map, startWith, switchMap } from 'rxjs/operators'; - -@Component({ - selector: 'ds-dso-page-version-button', - templateUrl: './dso-page-version-button.component.html', - styleUrls: ['./dso-page-version-button.component.scss'] -}) -/** - * Display a button linking to the edit page of a DSpaceObject - */ -export class DsoPageVersionButtonComponent implements OnInit { - /** - * The item for which display a button to create a new version - */ - @Input() dso: Item; - - /** - * A message for the tooltip on the button - * Supports i18n keys - */ - @Input() tooltipMsgCreate: string; - - /** - * A message for the tooltip on the button (when is disabled) - * Supports i18n keys - */ - @Input() tooltipMsgHasDraft: string; - - /** - * Emits an event that triggers the creation of the new version - */ - @Output() newVersionEvent = new EventEmitter(); - - /** - * Whether or not the current user is authorized to create a new version of the DSpaceObject - */ - isAuthorized$: Observable; - - disableNewVersionButton$: Observable; - - tooltipMsg$: Observable; - - constructor( - protected authorizationService: AuthorizationDataService, - protected versionHistoryService: VersionHistoryDataService, - ) { - } - - /** - * Creates a new version for the current item - */ - createNewVersion() { - this.newVersionEvent.emit(); - } - - ngOnInit() { - this.isAuthorized$ = this.authorizationService.isAuthorized(FeatureID.CanCreateVersion, this.dso.self); - - this.disableNewVersionButton$ = this.versionHistoryService.hasDraftVersion$(this.dso._links.version.href).pipe( - // button is disabled if hasDraftVersion = true, and enabled if hasDraftVersion = false or null - // (hasDraftVersion is null when a version history does not exist) - map((res) => Boolean(res)), - startWith(true), - ); - - this.tooltipMsg$ = this.disableNewVersionButton$.pipe( - switchMap((hasDraftVersion) => of(hasDraftVersion ? this.tooltipMsgHasDraft : this.tooltipMsgCreate)), - ); - } - -} diff --git a/src/app/shared/dso-page/dso-versioning-modal-service/dso-versioning-modal.service.spec.ts b/src/app/shared/dso-page/dso-versioning-modal-service/dso-versioning-modal.service.spec.ts new file mode 100644 index 0000000000..0a02481d58 --- /dev/null +++ b/src/app/shared/dso-page/dso-versioning-modal-service/dso-versioning-modal.service.spec.ts @@ -0,0 +1,92 @@ +import { DsoVersioningModalService } from './dso-versioning-modal.service'; +import { waitForAsync } from '@angular/core/testing'; +import { createSuccessfulRemoteDataObject$ } from '../../remote-data.utils'; +import { Version } from '../../../core/shared/version.model'; +import { Item } from '../../../core/shared/item.model'; +import { MetadataMap } from '../../../core/shared/metadata.models'; +import { createRelationshipsObservable } from '../../../item-page/simple/item-types/shared/item.component.spec'; +import { buildPaginatedList } from '../../../core/data/paginated-list.model'; +import { PageInfo } from '../../../core/shared/page-info.model'; +import { EMPTY, of as observableOf } from 'rxjs'; + +fdescribe('DsoVersioningModalService', () => { + let service: DsoVersioningModalService; + let modalService; + let versionService; + let versionHistoryService; + let itemVersionShared; + let router; + let workspaceItemDataService; + let itemService; + + const mockItem: Item = Object.assign(new Item(), { + bundles: createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), [])), + metadata: new MetadataMap(), + relationships: createRelationshipsObservable(), + _links: { + self: { + href: 'item-href' + }, + version: { + href: 'version-href' + } + } + }); + + beforeEach(waitForAsync(() => { + modalService = jasmine.createSpyObj('modalService', { + open: {componentInstance: {firstVersion: {}, versionNumber: {}, createVersionEvent: EMPTY}} + }); + versionService = jasmine.createSpyObj('versionService', { + findByHref: createSuccessfulRemoteDataObject$(new Version()), + }); + versionHistoryService = jasmine.createSpyObj('versionHistoryService', { + createVersion: createSuccessfulRemoteDataObject$(new Version()), + hasDraftVersion$: observableOf(false) + }); + itemVersionShared = jasmine.createSpyObj('itemVersionShared', ['notifyCreateNewVersion']); + router = jasmine.createSpyObj('router', ['navigateByUrl']); + workspaceItemDataService = jasmine.createSpyObj('workspaceItemDataService', ['findByItem']); + itemService = jasmine.createSpyObj('itemService', ['findByHref']); + + service = new DsoVersioningModalService( + modalService, + versionService, + versionHistoryService, + itemVersionShared, + router, + workspaceItemDataService, + itemService + ); + })); + describe('when onCreateNewVersion() is called', () => { + it('should call versionService.findByHref', () => { + service.openCreateVersionModal(mockItem); + expect(versionService.findByHref).toHaveBeenCalledWith('version-href'); + }); + }); + + describe('isNewVersionButtonDisabled', () => { + it('should call versionHistoryService.hasDraftVersion$', () => { + service.isNewVersionButtonDisabled(mockItem); + expect(versionHistoryService.hasDraftVersion$).toHaveBeenCalledWith(mockItem._links.version.href); + }); + }); + + describe('getVersioningTooltipMessage', () => { + it('should return the create message when isNewVersionButtonDisabled returns false', (done) => { + spyOn(service, 'isNewVersionButtonDisabled').and.returnValue(observableOf(false)); + service.getVersioningTooltipMessage(mockItem, 'draft-message', 'create-message').subscribe((message) => { + expect(message).toEqual('create-message'); + done(); + }); + }); + it('should return the draft message when isNewVersionButtonDisabled returns true', (done) => { + spyOn(service, 'isNewVersionButtonDisabled').and.returnValue(observableOf(true)); + service.getVersioningTooltipMessage(mockItem, 'draft-message', 'create-message').subscribe((message) => { + expect(message).toEqual('draft-message'); + done(); + }); + }); + }); +}); diff --git a/src/app/shared/dso-page/dso-versioning-modal-service/dso-versioning-modal.service.ts b/src/app/shared/dso-page/dso-versioning-modal-service/dso-versioning-modal.service.ts new file mode 100644 index 0000000000..e1b827a50b --- /dev/null +++ b/src/app/shared/dso-page/dso-versioning-modal-service/dso-versioning-modal.service.ts @@ -0,0 +1,98 @@ +import { + ItemVersionsSummaryModalComponent +} from '../../item/item-versions/item-versions-summary-modal/item-versions-summary-modal.component'; +import { getFirstCompletedRemoteData, getFirstSucceededRemoteDataPayload } from '../../../core/shared/operators'; +import { RemoteData } from '../../../core/data/remote-data'; +import { Version } from '../../../core/shared/version.model'; +import { map, startWith, switchMap, tap } from 'rxjs/operators'; +import { Item } from '../../../core/shared/item.model'; +import { WorkspaceItem } from '../../../core/submission/models/workspaceitem.model'; +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { VersionDataService } from '../../../core/data/version-data.service'; +import { VersionHistoryDataService } from '../../../core/data/version-history-data.service'; +import { ItemVersionsSharedService } from '../../item/item-versions/item-versions-shared.service'; +import { Router } from '@angular/router'; +import { WorkspaceitemDataService } from '../../../core/submission/workspaceitem-data.service'; +import { ItemDataService } from '../../../core/data/item-data.service'; +import { Injectable } from '@angular/core'; +import { Observable, of } from 'rxjs'; + +/** + * Service to take care of all the functionality related to the version creation modal + */ +@Injectable({ + providedIn: 'root' +}) +export class DsoVersioningModalService { + + constructor( + protected modalService: NgbModal, + protected versionService: VersionDataService, + protected versionHistoryService: VersionHistoryDataService, + protected itemVersionShared: ItemVersionsSharedService, + protected router: Router, + protected workspaceItemDataService: WorkspaceitemDataService, + protected itemService: ItemDataService, + ) { + } + + /** + * Open the create version modal for the provided dso + */ + openCreateVersionModal(dso): void { + + const item = dso; + const versionHref = item._links.version.href; + + // Open modal + const activeModal = this.modalService.open(ItemVersionsSummaryModalComponent); + + // Show current version in modal + this.versionService.findByHref(versionHref).pipe(getFirstCompletedRemoteData()).subscribe((res: RemoteData) => { + // if res.hasNoContent then the item is unversioned + activeModal.componentInstance.firstVersion = res.hasNoContent; + activeModal.componentInstance.versionNumber = (res.hasNoContent ? undefined : res.payload.version); + }); + + // On createVersionEvent emitted create new version and notify + activeModal.componentInstance.createVersionEvent.pipe( + switchMap((summary: string) => this.versionHistoryService.createVersion(item._links.self.href, summary)), + getFirstCompletedRemoteData(), + // show success/failure notification + tap((res: RemoteData) => { + this.itemVersionShared.notifyCreateNewVersion(res); + }), + // get workspace item + getFirstSucceededRemoteDataPayload(), + switchMap((newVersion: Version) => this.itemService.findByHref(newVersion._links.item.href)), + getFirstSucceededRemoteDataPayload(), + switchMap((newVersionItem: Item) => this.workspaceItemDataService.findByItem(newVersionItem.uuid, true, false)), + getFirstSucceededRemoteDataPayload(), + ).subscribe((wsItem) => { + const wsiId = wsItem.id; + const route = 'workspaceitems/' + wsiId + '/edit'; + this.router.navigateByUrl(route); + }); + } + + /** + * Checks if the new version button should be disabled for the provided dso + */ + isNewVersionButtonDisabled(dso): Observable { + return this.versionHistoryService.hasDraftVersion$(dso._links.version.href).pipe( + // button is disabled if hasDraftVersion = true, and enabled if hasDraftVersion = false or null + // (hasDraftVersion is null when a version history does not exist) + map((res) => Boolean(res)), + startWith(true), + ); + } + + /** + * Checks and returns the tooltip that needs to be used for the create version button tooltip + */ + getVersioningTooltipMessage(dso, tooltipMsgHasDraft, tooltipMsgCreate): Observable { + return this.isNewVersionButtonDisabled(dso).pipe( + switchMap((hasDraftVersion) => of(hasDraftVersion ? tooltipMsgHasDraft : tooltipMsgCreate)), + ); + } +} diff --git a/src/app/shared/menu/initial-menus-state.ts b/src/app/shared/menu/initial-menus-state.ts index 7b900540b6..086c7c30fa 100644 --- a/src/app/shared/menu/initial-menus-state.ts +++ b/src/app/shared/menu/initial-menus-state.ts @@ -5,7 +5,8 @@ import { MenusState } from './menu.reducer'; */ export enum MenuID { ADMIN = 'admin-sidebar', - PUBLIC = 'public' + PUBLIC = 'public', + DSO_EDIT = 'dso-edit' } /** @@ -36,5 +37,14 @@ export const initialMenusState: MenusState = { visible: true, sections: {}, sectionToSubsectionIndex: {} - } + }, + [MenuID.DSO_EDIT]: + { + id: MenuID.DSO_EDIT, + collapsed: true, + previewCollapsed: true, + visible: false, + sections: {}, + sectionToSubsectionIndex: {} + }, }; diff --git a/src/app/shared/menu/menu-item/link-menu-item.component.html b/src/app/shared/menu/menu-item/link-menu-item.component.html index b2cc73bcf4..4dacc14cbe 100644 --- a/src/app/shared/menu/menu-item/link-menu-item.component.html +++ b/src/app/shared/menu/menu-item/link-menu-item.component.html @@ -1,6 +1,6 @@ {}; } diff --git a/src/app/shared/menu/menu-item/models/search.model.ts b/src/app/shared/menu/menu-item/models/search.model.ts index e8eeda5501..d2f728ba9f 100644 --- a/src/app/shared/menu/menu-item/models/search.model.ts +++ b/src/app/shared/menu/menu-item/models/search.model.ts @@ -6,6 +6,7 @@ import { MenuItemModel } from './menu-item.model'; */ export class SearchMenuItemModel implements MenuItemModel { type = MenuItemType.SEARCH; + disabled: boolean; placeholder: string; action: string; } diff --git a/src/app/shared/menu/menu-item/models/text.model.ts b/src/app/shared/menu/menu-item/models/text.model.ts index bbaf7804d9..d50ec821ad 100644 --- a/src/app/shared/menu/menu-item/models/text.model.ts +++ b/src/app/shared/menu/menu-item/models/text.model.ts @@ -6,5 +6,6 @@ import { MenuItemModel } from './menu-item.model'; */ export class TextMenuItemModel implements MenuItemModel { type = MenuItemType.TEXT; + disabled: boolean; text: string; } diff --git a/src/app/shared/menu/menu-item/onclick-menu-item.component.html b/src/app/shared/menu/menu-item/onclick-menu-item.component.html index fd0192ad5f..5e8aecbd44 100644 --- a/src/app/shared/menu/menu-item/onclick-menu-item.component.html +++ b/src/app/shared/menu/menu-item/onclick-menu-item.component.html @@ -1,4 +1,5 @@ -{{item.text | translate}} +{{item.text | translate}} diff --git a/src/app/shared/menu/menu-item/onclick-menu-item.component.ts b/src/app/shared/menu/menu-item/onclick-menu-item.component.ts index 002bfbc819..ba47e2ad4a 100644 --- a/src/app/shared/menu/menu-item/onclick-menu-item.component.ts +++ b/src/app/shared/menu/menu-item/onclick-menu-item.component.ts @@ -14,13 +14,16 @@ import { OnClickMenuItemModel } from './models/onclick.model'; @rendersMenuItemForType(MenuItemType.ONCLICK) export class OnClickMenuItemComponent { item: OnClickMenuItemModel; + constructor(@Inject('itemModelProvider') item: OnClickMenuItemModel) { this.item = item; } public activate(event: any) { - event.preventDefault(); - this.item.function(); - event.stopPropagation(); + if (!this.item.disabled) { + event.preventDefault(); + this.item.function(); + event.stopPropagation(); + } } } diff --git a/src/app/shared/menu/menu-item/text-menu-item.component.html b/src/app/shared/menu/menu-item/text-menu-item.component.html index 7ba353e5e7..11c4420402 100644 --- a/src/app/shared/menu/menu-item/text-menu-item.component.html +++ b/src/app/shared/menu/menu-item/text-menu-item.component.html @@ -1 +1 @@ -{{item.text | translate}} \ No newline at end of file +{{item.text | translate}} diff --git a/src/app/shared/menu/menu-section/menu-section.component.ts b/src/app/shared/menu/menu-section/menu-section.component.ts index fcd96c65f1..8c845a58d6 100644 --- a/src/app/shared/menu/menu-section/menu-section.component.ts +++ b/src/app/shared/menu/menu-section/menu-section.component.ts @@ -64,7 +64,9 @@ export class MenuSectionComponent implements OnInit, OnDestroy { */ toggleSection(event: Event) { event.preventDefault(); - this.menuService.toggleActiveSection(this.menuID, this.section.id); + if (!this.section.model?.disabled) { + this.menuService.toggleActiveSection(this.menuID, this.section.id); + } } /** @@ -73,7 +75,9 @@ export class MenuSectionComponent implements OnInit, OnDestroy { */ activateSection(event: Event) { event.preventDefault(); - this.menuService.activateSection(this.menuID, this.section.id); + if (!this.section.model?.disabled) { + this.menuService.activateSection(this.menuID, this.section.id); + } } /** diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index 715ee66a99..0454646c96 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -157,8 +157,6 @@ import { SidebarSearchListElementComponent } from './object-list/sidebar-search- import { CollectionSidebarSearchListElementComponent } from './object-list/sidebar-search-list-element/collection/collection-sidebar-search-list-element.component'; import { CommunitySidebarSearchListElementComponent } from './object-list/sidebar-search-list-element/community/community-sidebar-search-list-element.component'; import { AuthorizedCollectionSelectorComponent } from './dso-selector/dso-selector/authorized-collection-selector/authorized-collection-selector.component'; -import { DsoPageEditButtonComponent } from './dso-page/dso-page-edit-button/dso-page-edit-button.component'; -import { DsoPageVersionButtonComponent } from './dso-page/dso-page-version-button/dso-page-version-button.component'; import { HoverClassDirective } from './hover-class.directive'; import { ValidationSuggestionsComponent } from './input-suggestions/validation-suggestions/validation-suggestions.component'; import { ItemAlertsComponent } from './item/item-alerts/item-alerts.component'; @@ -177,6 +175,13 @@ import { ScopeSelectorModalComponent } from './search-form/scope-selector-modal/ import { BitstreamRequestACopyPageComponent } from './bitstream-request-a-copy-page/bitstream-request-a-copy-page.component'; import { DsSelectComponent } from './ds-select/ds-select.component'; import { LogInOidcComponent } from './log-in/methods/oidc/log-in-oidc.component'; +import { + DsoEditMenuSectionComponent +} from './dso-page/dso-edit-menu/dso-edit-menu-section/dso-edit-menu-section.component'; +import { DsoEditMenuComponent } from './dso-page/dso-edit-menu/dso-edit-menu.component'; +import { + DsoEditMenuExpandableSectionComponent +} from './dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component'; const MODULES = [ // Do NOT include UniversalModule, HttpModule, or JsonpModule here @@ -402,18 +407,20 @@ const ENTRY_COMPONENTS = [ OnClickMenuItemComponent, TextMenuItemComponent, ScopeSelectorModalComponent, + DsoEditMenuSectionComponent, + DsoEditMenuExpandableSectionComponent, ]; const SHARED_ITEM_PAGE_COMPONENTS = [ MetadataFieldWrapperComponent, MetadataValuesComponent, - DsoPageEditButtonComponent, - DsoPageVersionButtonComponent, ItemAlertsComponent, GenericItemPageFieldComponent, MetadataRepresentationListComponent, RelatedItemsComponent, - + DsoEditMenuSectionComponent, + DsoEditMenuComponent, + DsoEditMenuExpandableSectionComponent, ]; const PROVIDERS = [ From 96ba1c931992340dbc5e611e26a9acf9b736ad2b Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Wed, 21 Sep 2022 14:28:53 +0200 Subject: [PATCH 002/257] 94390: Implement feedback --- .../admin-sidebar-section.component.ts | 2 +- src/app/collection-page/collection-page-routing.module.ts | 1 - src/app/community-page/community-page-routing.module.ts | 1 - src/app/item-page/item-page-routing.module.ts | 1 - .../dso-edit-menu-expandable-section.component.scss | 4 ++-- .../dso-page/dso-edit-menu/dso-edit-menu.component.ts | 6 +----- 6 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/app/admin/admin-sidebar/admin-sidebar-section/admin-sidebar-section.component.ts b/src/app/admin/admin-sidebar/admin-sidebar-section/admin-sidebar-section.component.ts index 620681c654..97b16c0522 100644 --- a/src/app/admin/admin-sidebar/admin-sidebar-section/admin-sidebar-section.component.ts +++ b/src/app/admin/admin-sidebar/admin-sidebar-section/admin-sidebar-section.component.ts @@ -49,7 +49,7 @@ export class AdminSidebarSectionComponent extends MenuSectionComponent implement navigate(event: any): void { event.preventDefault(); - if (this.isDisabled) { + if (!this.isDisabled) { this.router.navigate(this.itemModel.link); } } diff --git a/src/app/collection-page/collection-page-routing.module.ts b/src/app/collection-page/collection-page-routing.module.ts index c5759f833f..3101347990 100644 --- a/src/app/collection-page/collection-page-routing.module.ts +++ b/src/app/collection-page/collection-page-routing.module.ts @@ -93,7 +93,6 @@ import { DSOEditMenuResolver } from '../shared/dso-page/dso-edit-menu.resolver'; LinkService, CreateCollectionPageGuard, CollectionPageAdministratorGuard, - DSOEditMenuResolver ] }) export class CollectionPageRoutingModule { diff --git a/src/app/community-page/community-page-routing.module.ts b/src/app/community-page/community-page-routing.module.ts index ac90f3618c..2c97c99081 100644 --- a/src/app/community-page/community-page-routing.module.ts +++ b/src/app/community-page/community-page-routing.module.ts @@ -75,7 +75,6 @@ import { DSOEditMenuResolver } from '../shared/dso-page/dso-edit-menu.resolver'; LinkService, CreateCommunityPageGuard, CommunityPageAdministratorGuard, - DSOEditMenuResolver ] }) export class CommunityPageRoutingModule { diff --git a/src/app/item-page/item-page-routing.module.ts b/src/app/item-page/item-page-routing.module.ts index 1c4da9a267..069936ebd3 100644 --- a/src/app/item-page/item-page-routing.module.ts +++ b/src/app/item-page/item-page-routing.module.ts @@ -90,7 +90,6 @@ import { DSOEditMenuResolver } from '../shared/dso-page/dso-edit-menu.resolver'; LinkService, ItemPageAdministratorGuard, VersionResolver, - DSOEditMenuResolver ] }) diff --git a/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.scss b/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.scss index 61ec6347f9..ad6166398c 100644 --- a/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.scss +++ b/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.scss @@ -16,11 +16,11 @@ ul.dropdown-menu { color: white; &.disabled { - color: $btn-link-disabled-color; + color: var(--bs-btn-link-disabled-color); } } .disabled { - color: $btn-link-disabled-color; + color: var(--bs-btn-link-disabled-color); } } diff --git a/src/app/shared/dso-page/dso-edit-menu/dso-edit-menu.component.ts b/src/app/shared/dso-page/dso-edit-menu/dso-edit-menu.component.ts index d754e07b32..f222966ed8 100644 --- a/src/app/shared/dso-page/dso-edit-menu/dso-edit-menu.component.ts +++ b/src/app/shared/dso-page/dso-edit-menu/dso-edit-menu.component.ts @@ -24,13 +24,9 @@ export class DsoEditMenuComponent extends MenuComponent { constructor(protected menuService: MenuService, protected injector: Injector, public authorizationService: AuthorizationDataService, - public route: ActivatedRoute, - private authService: AuthService, + public route: ActivatedRoute ) { super(menuService, injector, authorizationService, route); } - ngOnInit(): void { - super.ngOnInit(); - } } From a92060c45ac9b2caca449a0a9f75fadde8997543 Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Thu, 22 Sep 2022 12:15:34 +0200 Subject: [PATCH 003/257] 94390: Add comment to array flattening --- src/app/shared/dso-page/dso-edit-menu.resolver.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/shared/dso-page/dso-edit-menu.resolver.ts b/src/app/shared/dso-page/dso-edit-menu.resolver.ts index 003e61df95..d461584358 100644 --- a/src/app/shared/dso-page/dso-edit-menu.resolver.ts +++ b/src/app/shared/dso-page/dso-edit-menu.resolver.ts @@ -45,6 +45,7 @@ export class DSOEditMenuResolver implements Resolve<{ [key: string]: MenuSection if (dsoRD.hasSucceeded) { const dso = dsoRD.payload; return combineLatest(this.getDsoMenus(dso, route, state)).pipe( + // Menu sections are retrieved as an array of arrays and flattened into a single array map((combinedMenus) => [].concat.apply([], combinedMenus)), map((menus) => this.addDsoUuidToMenuIDs(menus, dso)), map((menus) => { From b7c1e76b7f70894660843285d48324226d220a91 Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Thu, 22 Sep 2022 16:10:43 +0200 Subject: [PATCH 004/257] 94390: Remove fdescribe --- .../dso-versioning-modal.service.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/shared/dso-page/dso-versioning-modal-service/dso-versioning-modal.service.spec.ts b/src/app/shared/dso-page/dso-versioning-modal-service/dso-versioning-modal.service.spec.ts index 0a02481d58..fc5c1dafc9 100644 --- a/src/app/shared/dso-page/dso-versioning-modal-service/dso-versioning-modal.service.spec.ts +++ b/src/app/shared/dso-page/dso-versioning-modal-service/dso-versioning-modal.service.spec.ts @@ -9,7 +9,7 @@ import { buildPaginatedList } from '../../../core/data/paginated-list.model'; import { PageInfo } from '../../../core/shared/page-info.model'; import { EMPTY, of as observableOf } from 'rxjs'; -fdescribe('DsoVersioningModalService', () => { +describe('DsoVersioningModalService', () => { let service: DsoVersioningModalService; let modalService; let versionService; From 6a932ec6ac65ef6794b3945fc6be0dbd0fd30af1 Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Tue, 27 Sep 2022 16:21:56 +0200 Subject: [PATCH 005/257] 94390: Remove unused import --- .../research-entities/item-pages/person/person.component.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/app/entity-groups/research-entities/item-pages/person/person.component.ts b/src/app/entity-groups/research-entities/item-pages/person/person.component.ts index 1ac70bad9d..e5e2a52338 100644 --- a/src/app/entity-groups/research-entities/item-pages/person/person.component.ts +++ b/src/app/entity-groups/research-entities/item-pages/person/person.component.ts @@ -1,7 +1,6 @@ import { Component } from '@angular/core'; import { ViewMode } from '../../../../core/shared/view-mode.model'; import { listableObjectComponent } from '../../../../shared/object-collection/shared/listable-object/listable-object.decorator'; -import { MetadataValue } from '../../../../core/shared/metadata.models'; import { ItemComponent } from '../../../../item-page/simple/item-types/shared/item.component'; @listableObjectComponent('Person', ViewMode.StandalonePage) From 4489b3417c633386b82ee5de1126465bf5ba4234 Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Wed, 28 Sep 2022 18:09:30 +0200 Subject: [PATCH 006/257] 94391: intermittent commit --- ...expandable-admin-sidebar-section.component.html | 2 +- .../shared/dso-page/dso-edit-menu.resolver.spec.ts | 8 +++++--- src/app/shared/dso-page/dso-edit-menu.resolver.ts | 9 +++++---- ...dso-edit-menu-expandable-section.component.html | 14 ++++++++------ src/styles/_global-styles.scss | 5 +++++ 5 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/app/admin/admin-sidebar/expandable-admin-sidebar-section/expandable-admin-sidebar-section.component.html b/src/app/admin/admin-sidebar/expandable-admin-sidebar-section/expandable-admin-sidebar-section.component.html index 259dbd1060..1f4666bbd0 100644 --- a/src/app/admin/admin-sidebar/expandable-admin-sidebar-section/expandable-admin-sidebar-section.component.html +++ b/src/app/admin/admin-sidebar/expandable-admin-sidebar-section/expandable-admin-sidebar-section.component.html @@ -7,7 +7,7 @@ [attr.aria-labelledby]="'sidebarName-' + section.id" [attr.aria-expanded]="expanded | async" [title]="('menu.section.icon.' + section.id) | translate" - [class.disabled]="section.model.disabled" + [class.disabled]="section.model?.disabled" (click)="toggleSection($event)" (keyup.space)="toggleSection($event)" (keyup.enter)="toggleSection($event)" diff --git a/src/app/shared/dso-page/dso-edit-menu.resolver.spec.ts b/src/app/shared/dso-page/dso-edit-menu.resolver.spec.ts index 3f1e34b0e0..ac4c4dae17 100644 --- a/src/app/shared/dso-page/dso-edit-menu.resolver.spec.ts +++ b/src/app/shared/dso-page/dso-edit-menu.resolver.spec.ts @@ -15,6 +15,8 @@ import { DsoVersioningModalService } from './dso-versioning-modal-service/dso-ve import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.service'; import { Item } from '../../core/shared/item.model'; import { createFailedRemoteDataObject$, createSuccessfulRemoteDataObject$ } from '../remote-data.utils'; +import { TextMenuItemModel } from '../menu/menu-item/models/text.model'; +import { LinkMenuItemModel } from '../menu/menu-item/models/link.model'; describe('DSOEditMenuResolver', () => { @@ -164,7 +166,7 @@ describe('DSOEditMenuResolver', () => { expect(menuList[0].active).toEqual(false); expect(menuList[0].visible).toEqual(true); expect(menuList[0].model.type).toEqual(MenuItemType.ONCLICK); - expect(menuList[0].model.text).toEqual('message'); + expect((menuList[0].model as TextMenuItemModel).text).toEqual('message'); expect(menuList[0].model.disabled).toEqual(false); expect(menuList[0].icon).toEqual('code-branch'); done(); @@ -179,8 +181,8 @@ describe('DSOEditMenuResolver', () => { expect(menuList[0].active).toEqual(false); expect(menuList[0].visible).toEqual(true); expect(menuList[0].model.type).toEqual(MenuItemType.LINK); - expect(menuList[0].model.text).toEqual('item.page.edit'); - expect(menuList[0].model.link).toEqual('test-url/edit/metadata'); + expect((menuList[0].model as LinkMenuItemModel).text).toEqual('item.page.edit'); + expect((menuList[0].model as LinkMenuItemModel).link).toEqual('test-url/edit/metadata'); expect(menuList[0].icon).toEqual('pencil-alt'); done(); }); diff --git a/src/app/shared/dso-page/dso-edit-menu.resolver.ts b/src/app/shared/dso-page/dso-edit-menu.resolver.ts index d461584358..ceedda7b60 100644 --- a/src/app/shared/dso-page/dso-edit-menu.resolver.ts +++ b/src/app/shared/dso-page/dso-edit-menu.resolver.ts @@ -16,6 +16,7 @@ import { URLCombiner } from '../../core/url-combiner/url-combiner'; import { DsoVersioningModalService } from './dso-versioning-modal-service/dso-versioning-modal.service'; import { hasValue } from '../empty.util'; import { MenuSection } from '../menu/menu.reducer'; +import { TextMenuItemModel } from '../menu/menu-item/models/text.model'; /** * Creates the menus for the dspace object pages @@ -65,17 +66,17 @@ export class DSOEditMenuResolver implements Resolve<{ [key: string]: MenuSection /** * Return all the menus for a dso based on the route and state */ - getDsoMenus(dso, route, state) { + getDsoMenus(dso, route, state): Observable[] { return [ this.getItemMenu(dso), - this.getCommonMenu(dso, state) + this.getCommonMenu(dso, state), ]; } /** * Get the common menus between all dspace objects */ - protected getCommonMenu(dso, state): Observable { + protected getCommonMenu(dso, state): Observable { return combineLatest([ this.authorizationService.isAuthorized(FeatureID.CanEditMetadata, dso.self), ]).pipe( @@ -102,7 +103,7 @@ export class DSOEditMenuResolver implements Resolve<{ [key: string]: MenuSection /** * Get item sepcific menus */ - protected getItemMenu(dso): Observable { + protected getItemMenu(dso): Observable { if (dso instanceof Item) { return combineLatest([ this.authorizationService.isAuthorized(FeatureID.CanCreateVersion, dso.self), diff --git a/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.html b/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.html index b330b1e87d..d44238eb6e 100644 --- a/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.html +++ b/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.html @@ -1,14 +1,16 @@ -
+
- -
    - +
      +
diff --git a/src/styles/_global-styles.scss b/src/styles/_global-styles.scss index e337539c15..c71a9695f9 100644 --- a/src/styles/_global-styles.scss +++ b/src/styles/_global-styles.scss @@ -92,3 +92,8 @@ ngb-modal-backdrop { hyphens: auto; } + +ul.dso-edit-dropdown-menu li.nav-item ng-deep a.nav-link { + padding: 0; + display: inline; +} From 785e4085fcb4432d26997e51fa7287037cf3e75e Mon Sep 17 00:00:00 2001 From: Yury Bondarenko Date: Wed, 28 Sep 2022 18:28:41 +0200 Subject: [PATCH 007/257] 94389: Fix icon alignment & dropdown styles --- src/app/shared/dso-page/dso-edit-menu.resolver.ts | 2 -- .../dso-edit-menu-expandable-section.component.html | 9 ++++++--- .../dso-edit-menu-expandable-section.component.scss | 4 ++++ .../dso-edit-menu-expandable-section.component.ts | 12 +++++++++++- src/styles/_global-styles.scss | 3 ++- 5 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/app/shared/dso-page/dso-edit-menu.resolver.ts b/src/app/shared/dso-page/dso-edit-menu.resolver.ts index ceedda7b60..2bf1aa08b5 100644 --- a/src/app/shared/dso-page/dso-edit-menu.resolver.ts +++ b/src/app/shared/dso-page/dso-edit-menu.resolver.ts @@ -16,7 +16,6 @@ import { URLCombiner } from '../../core/url-combiner/url-combiner'; import { DsoVersioningModalService } from './dso-versioning-modal-service/dso-versioning-modal.service'; import { hasValue } from '../empty.util'; import { MenuSection } from '../menu/menu.reducer'; -import { TextMenuItemModel } from '../menu/menu-item/models/text.model'; /** * Creates the menus for the dspace object pages @@ -95,7 +94,6 @@ export class DSOEditMenuResolver implements Resolve<{ [key: string]: MenuSection index: 1 }, ]; - }) ); } diff --git a/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.html b/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.html index d44238eb6e..a119cf0327 100644 --- a/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.html +++ b/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.html @@ -4,9 +4,12 @@ -
    -