From d5484e5c89afd86629eb43a05cf1a6fdd7d13c40 Mon Sep 17 00:00:00 2001 From: lotte Date: Fri, 6 Mar 2020 13:54:46 +0100 Subject: [PATCH] created admin search page --- resources/i18n/en.json5 | 28 ++++ resources/i18n/nl.json5 | 2 +- src/app/+admin/admin-routing.module.ts | 4 +- .../admin-search-page.component.html | 1 + .../admin-search-page.component.scss | 0 .../admin-search-page.component.spec.ts | 27 ++++ .../admin-search-page.component.ts | 18 +++ src/app/+admin/admin.module.ts | 4 + .../edit-item-page.routing.module.ts | 12 +- src/app/+search-page/search.component.html | 83 ++++++------ src/app/+search-page/search.component.ts | 7 + src/app/core/services/route.reducer.ts | 4 +- src/app/core/services/route.service.ts | 6 +- src/app/core/shared/context.model.ts | 1 + .../abstract-listable-element.component.ts | 17 +++ ...-search-result-list-element.component.html | 8 ++ ...-search-result-list-element.component.scss | 0 ...arch-result-list-element.component.spec.ts | 60 +++++++++ ...in-search-result-list-element.component.ts | 27 ++++ ...-search-result-list-element.component.html | 8 ++ ...-search-result-list-element.component.scss | 0 ...arch-result-list-element.component.spec.ts | 60 +++++++++ ...in-search-result-list-element.component.ts | 27 ++++ ...-search-result-list-element.component.html | 39 ++++++ ...-search-result-list-element.component.scss | 0 ...arch-result-list-element.component.spec.ts | 120 ++++++++++++++++++ ...in-search-result-list-element.component.ts | 77 +++++++++++ src/app/shared/shared.module.ts | 13 +- 28 files changed, 600 insertions(+), 53 deletions(-) create mode 100644 src/app/+admin/admin-search-page/admin-search-page.component.html create mode 100644 src/app/+admin/admin-search-page/admin-search-page.component.scss create mode 100644 src/app/+admin/admin-search-page/admin-search-page.component.spec.ts create mode 100644 src/app/+admin/admin-search-page/admin-search-page.component.ts create mode 100644 src/app/shared/object-list/admin-search-result-list-element/collection-search-result/collection-admin-search-result-list-element.component.html create mode 100644 src/app/shared/object-list/admin-search-result-list-element/collection-search-result/collection-admin-search-result-list-element.component.scss create mode 100644 src/app/shared/object-list/admin-search-result-list-element/collection-search-result/collection-admin-search-result-list-element.component.spec.ts create mode 100644 src/app/shared/object-list/admin-search-result-list-element/collection-search-result/collection-admin-search-result-list-element.component.ts create mode 100644 src/app/shared/object-list/admin-search-result-list-element/community-search-result/community-admin-search-result-list-element.component.html create mode 100644 src/app/shared/object-list/admin-search-result-list-element/community-search-result/community-admin-search-result-list-element.component.scss create mode 100644 src/app/shared/object-list/admin-search-result-list-element/community-search-result/community-admin-search-result-list-element.component.spec.ts create mode 100644 src/app/shared/object-list/admin-search-result-list-element/community-search-result/community-admin-search-result-list-element.component.ts create mode 100644 src/app/shared/object-list/admin-search-result-list-element/item-search-result/item-admin-search-result-list-element.component.html create mode 100644 src/app/shared/object-list/admin-search-result-list-element/item-search-result/item-admin-search-result-list-element.component.scss create mode 100644 src/app/shared/object-list/admin-search-result-list-element/item-search-result/item-admin-search-result-list-element.component.spec.ts create mode 100644 src/app/shared/object-list/admin-search-result-list-element/item-search-result/item-admin-search-result-list-element.component.ts diff --git a/resources/i18n/en.json5 b/resources/i18n/en.json5 index cfa202fe4a..497dc8db54 100644 --- a/resources/i18n/en.json5 +++ b/resources/i18n/en.json5 @@ -170,6 +170,32 @@ + "admin.search.collection.edit": "Edit", + + "admin.search.community.edit": "Edit", + + "admin.search.item.delete": "Delete", + + "admin.search.item.edit": "Edit", + + "admin.search.item.make-private": "Make Private", + + "admin.search.item.make-public": "Make Public", + + "admin.search.item.move": "Move", + + "admin.search.item.private": "Private", + + "admin.search.item.reinstate": "Reinstate", + + "admin.search.item.withdraw": "Withdraw", + + "admin.search.item.withdrawn": "Withdrawn", + + "admin.search.title": "Admin Search", + + + "auth.errors.invalid-user": "Invalid email address or password.", "auth.messages.expired": "Your session has expired. Please log in again.", @@ -1984,6 +2010,8 @@ "title": "DSpace", + "undiscoverable.search.results.head": "Admin Search", + "uploader.browse": "browse", diff --git a/resources/i18n/nl.json5 b/resources/i18n/nl.json5 index 344a36e2e8..871efcbd04 100644 --- a/resources/i18n/nl.json5 +++ b/resources/i18n/nl.json5 @@ -1248,7 +1248,7 @@ // "journalissue.listelement.badge": "Journal Issue", - "journalissue.listelement.badge": "Tijdschrift aflevering", + "journalissue.listelement.badge": "Tijdschriftaflevering", // "journalissue.page.description": "Description", "journalissue.page.description": "Beschrijving", diff --git a/src/app/+admin/admin-routing.module.ts b/src/app/+admin/admin-routing.module.ts index 2003ecf124..d750d22058 100644 --- a/src/app/+admin/admin-routing.module.ts +++ b/src/app/+admin/admin-routing.module.ts @@ -2,6 +2,7 @@ import { RouterModule } from '@angular/router'; import { NgModule } from '@angular/core'; import { URLCombiner } from '../core/url-combiner/url-combiner'; import { getAdminModulePath } from '../app-routing.module'; +import { AdminSearchPageComponent } from './admin-search-page/admin-search-page.component'; const REGISTRIES_MODULE_PATH = 'registries'; @@ -15,7 +16,8 @@ export function getRegistriesModulePath() { { path: REGISTRIES_MODULE_PATH, loadChildren: './admin-registries/admin-registries.module#AdminRegistriesModule' - } + }, + { path: 'search', component: AdminSearchPageComponent, data: { title: 'admin.search.title' } }, ]) ] }) diff --git a/src/app/+admin/admin-search-page/admin-search-page.component.html b/src/app/+admin/admin-search-page/admin-search-page.component.html new file mode 100644 index 0000000000..15fa71e4d5 --- /dev/null +++ b/src/app/+admin/admin-search-page/admin-search-page.component.html @@ -0,0 +1 @@ + diff --git a/src/app/+admin/admin-search-page/admin-search-page.component.scss b/src/app/+admin/admin-search-page/admin-search-page.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/+admin/admin-search-page/admin-search-page.component.spec.ts b/src/app/+admin/admin-search-page/admin-search-page.component.spec.ts new file mode 100644 index 0000000000..05546d180b --- /dev/null +++ b/src/app/+admin/admin-search-page/admin-search-page.component.spec.ts @@ -0,0 +1,27 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AdminSearchPageComponent } from './admin-search-page.component'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; + +describe('AdminSearchPageComponent', () => { + let component: AdminSearchPageComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ AdminSearchPageComponent ], + schemas: [NO_ERRORS_SCHEMA] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(AdminSearchPageComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/+admin/admin-search-page/admin-search-page.component.ts b/src/app/+admin/admin-search-page/admin-search-page.component.ts new file mode 100644 index 0000000000..cbbc65a489 --- /dev/null +++ b/src/app/+admin/admin-search-page/admin-search-page.component.ts @@ -0,0 +1,18 @@ +import { Component, OnInit } from '@angular/core'; +import { Context } from '../../core/shared/context.model'; + +@Component({ + selector: 'ds-admin-search-page', + templateUrl: './admin-search-page.component.html', + styleUrls: ['./admin-search-page.component.scss'] +}) + +/** + * Component that represents a search page for administrators + */ +export class AdminSearchPageComponent { + /** + * The context of this page + */ + context: Context = Context.AdminSearch; +} diff --git a/src/app/+admin/admin.module.ts b/src/app/+admin/admin.module.ts index 1495d0fd8c..b3617cdf4d 100644 --- a/src/app/+admin/admin.module.ts +++ b/src/app/+admin/admin.module.ts @@ -2,13 +2,17 @@ import { NgModule } from '@angular/core'; import { AdminRegistriesModule } from './admin-registries/admin-registries.module'; import { AdminRoutingModule } from './admin-routing.module'; import { SharedModule } from '../shared/shared.module'; +import { AdminSearchPageComponent } from './admin-search-page/admin-search-page.component'; +import { SearchPageModule } from '../+search-page/search-page.module'; @NgModule({ imports: [ AdminRegistriesModule, AdminRoutingModule, SharedModule, + SearchPageModule ], + declarations: [AdminSearchPageComponent], }) export class AdminModule { diff --git a/src/app/+item-page/edit-item-page/edit-item-page.routing.module.ts b/src/app/+item-page/edit-item-page/edit-item-page.routing.module.ts index da667847f7..84cdeec3d0 100644 --- a/src/app/+item-page/edit-item-page/edit-item-page.routing.module.ts +++ b/src/app/+item-page/edit-item-page/edit-item-page.routing.module.ts @@ -15,12 +15,12 @@ import { ItemMoveComponent } from './item-move/item-move.component'; import { ItemRelationshipsComponent } from './item-relationships/item-relationships.component'; import { I18nBreadcrumbResolver } from '../../core/breadcrumbs/i18n-breadcrumb.resolver'; -const ITEM_EDIT_WITHDRAW_PATH = 'withdraw'; -const ITEM_EDIT_REINSTATE_PATH = 'reinstate'; -const ITEM_EDIT_PRIVATE_PATH = 'private'; -const ITEM_EDIT_PUBLIC_PATH = 'public'; -const ITEM_EDIT_DELETE_PATH = 'delete'; -const ITEM_EDIT_MOVE_PATH = 'move'; +export const ITEM_EDIT_WITHDRAW_PATH = 'withdraw'; +export const ITEM_EDIT_REINSTATE_PATH = 'reinstate'; +export const ITEM_EDIT_PRIVATE_PATH = 'private'; +export const ITEM_EDIT_PUBLIC_PATH = 'public'; +export const ITEM_EDIT_DELETE_PATH = 'delete'; +export const ITEM_EDIT_MOVE_PATH = 'move'; /** * Routing module that handles the routing for the Edit Item page administrator functionality diff --git a/src/app/+search-page/search.component.html b/src/app/+search-page/search.component.html index 36879f33d4..ee96f703f2 100644 --- a/src/app/+search-page/search.component.html +++ b/src/app/+search-page/search.component.html @@ -1,54 +1,55 @@
-
-
- +
+
+ +
-
-
-
- +
+
+ +
+
+
+ + +
+ +
-
-
- - -
- -
-
- - - + + + - - -
-
- + + +
+
+ +
-
diff --git a/src/app/+search-page/search.component.ts b/src/app/+search-page/search.component.ts index b27ebf625f..bbbfdba513 100644 --- a/src/app/+search-page/search.component.ts +++ b/src/app/+search-page/search.component.ts @@ -17,6 +17,7 @@ import { SearchConfigurationService } from '../core/shared/search/search-configu import { SearchService } from '../core/shared/search/search.service'; import { currentPath } from '../shared/utils/route.utils'; import { Router } from '@angular/router'; +import { Context } from '../core/shared/context.model'; @Component({ selector: 'ds-search', @@ -84,6 +85,12 @@ export class SearchComponent implements OnInit { @Input() configuration$: Observable; + /** + * The current context + */ + @Input() + context: Context; + /** * Link to the search page */ diff --git a/src/app/core/services/route.reducer.ts b/src/app/core/services/route.reducer.ts index 2d5356a5db..5a56fd3d9b 100644 --- a/src/app/core/services/route.reducer.ts +++ b/src/app/core/services/route.reducer.ts @@ -9,6 +9,7 @@ import { SetQueryParameterAction, SetQueryParametersAction } from './route.actions'; +import { isNotEmpty } from '../../shared/empty.util'; /** * Interface to represent the parameter state of a current route in the store @@ -81,7 +82,8 @@ function addParameter(state: RouteState, action: AddParameterAction | AddQueryPa * @param paramType The type of parameter to set: route or query parameter */ function setParameters(state: RouteState, action: SetParametersAction | SetQueryParametersAction, paramType: string): RouteState { - return Object.assign({}, state, { [paramType]: { [action.payload.key]: action.payload.value } }); + const param = isNotEmpty(action.payload) ? { [paramType]: { [action.payload.key]: action.payload.value } } : {}; + return Object.assign({}, state, param); } /** diff --git a/src/app/core/services/route.service.ts b/src/app/core/services/route.service.ts index 661f4acf94..441d058c4c 100644 --- a/src/app/core/services/route.service.ts +++ b/src/app/core/services/route.service.ts @@ -6,7 +6,7 @@ import { combineLatest, Observable } from 'rxjs'; import { createSelector, MemoizedSelector, select, Store } from '@ngrx/store'; import { isEqual } from 'lodash'; -import { AddParameterAction, SetParameterAction, SetParametersAction, SetQueryParametersAction } from './route.actions'; +import { AddParameterAction, SetParameterAction, SetParametersAction, SetQueryParameterAction, SetQueryParametersAction } from './route.actions'; import { CoreState } from '../core.reducers'; import { coreSelector } from '../core.selectors'; import { hasValue } from '../../shared/empty.util'; @@ -194,6 +194,10 @@ export class RouteService { this.store.dispatch(new SetParameterAction(key, value)); } + public setQueryParameter(key, value) { + this.store.dispatch(new SetQueryParameterAction(key, value)); + } + /** * Sets the current route parameters and query parameters in the store */ diff --git a/src/app/core/shared/context.model.ts b/src/app/core/shared/context.model.ts index 7bfd613b65..6bb3d77140 100644 --- a/src/app/core/shared/context.model.ts +++ b/src/app/core/shared/context.model.ts @@ -10,4 +10,5 @@ export enum Context { Workspace = 'workspace', AdminMenu = 'adminMenu', SubmissionModal = 'submissionModal', + AdminSearch = 'adminSearch', } diff --git a/src/app/shared/object-collection/shared/object-collection-element/abstract-listable-element.component.ts b/src/app/shared/object-collection/shared/object-collection-element/abstract-listable-element.component.ts index d27fb331de..3602f45ede 100644 --- a/src/app/shared/object-collection/shared/object-collection-element/abstract-listable-element.component.ts +++ b/src/app/shared/object-collection/shared/object-collection-element/abstract-listable-element.component.ts @@ -1,6 +1,8 @@ import { Component, Input } from '@angular/core'; import { ListableObject } from '../listable-object.model'; import { CollectionElementLinkType } from '../../collection-element-link.type'; +import { Context } from '../../../../core/shared/context.model'; +import { ViewMode } from '../../../../core/shared/view-mode.model'; @Component({ selector: 'ds-abstract-object-element', @@ -22,8 +24,23 @@ export class AbstractListableElementComponent { */ @Input() listID: string; + /** + * The index of this element + */ + @Input() index: number; + /** * The available link types */ linkTypes = CollectionElementLinkType; + + /** + * The available view modes + */ + viewModes = ViewMode; + + /** + * The available contexts + */ + contexts = Context; } diff --git a/src/app/shared/object-list/admin-search-result-list-element/collection-search-result/collection-admin-search-result-list-element.component.html b/src/app/shared/object-list/admin-search-result-list-element/collection-search-result/collection-admin-search-result-list-element.component.html new file mode 100644 index 0000000000..8cf98b6680 --- /dev/null +++ b/src/app/shared/object-list/admin-search-result-list-element/collection-search-result/collection-admin-search-result-list-element.component.html @@ -0,0 +1,8 @@ + + + {{"admin.search.collection.edit" | translate}} + diff --git a/src/app/shared/object-list/admin-search-result-list-element/collection-search-result/collection-admin-search-result-list-element.component.scss b/src/app/shared/object-list/admin-search-result-list-element/collection-search-result/collection-admin-search-result-list-element.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/shared/object-list/admin-search-result-list-element/collection-search-result/collection-admin-search-result-list-element.component.spec.ts b/src/app/shared/object-list/admin-search-result-list-element/collection-search-result/collection-admin-search-result-list-element.component.spec.ts new file mode 100644 index 0000000000..9e932db81c --- /dev/null +++ b/src/app/shared/object-list/admin-search-result-list-element/collection-search-result/collection-admin-search-result-list-element.component.spec.ts @@ -0,0 +1,60 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { CollectionAdminSearchResultListElementComponent } from './collection-admin-search-result-list-element.component'; +import { TranslateModule } from '@ngx-translate/core'; +import { TruncatableService } from '../../../truncatable/truncatable.service'; +import { CollectionElementLinkType } from '../../../object-collection/collection-element-link.type'; +import { ViewMode } from '../../../../core/shared/view-mode.model'; +import { CollectionSearchResult } from '../../../object-collection/shared/collection-search-result.model'; +import { Collection } from '../../../../core/shared/collection.model'; +import { By } from '@angular/platform-browser'; +import { RouterTestingModule } from '@angular/router/testing'; +import { getCollectionEditPath } from '../../../../+collection-page/collection-page-routing.module'; + +describe('CollectionAdminSearchResultListElementComponent', () => { + let component: CollectionAdminSearchResultListElementComponent; + let fixture: ComponentFixture; + let id; + let searchResult; + + function init() { + id = '780b2588-bda5-4112-a1cd-0b15000a5339'; + searchResult = new CollectionSearchResult(); + searchResult.indexableObject = new Collection(); + searchResult.indexableObject.uuid = id; + } + beforeEach(async(() => { + init(); + TestBed.configureTestingModule({ + imports: [ + TranslateModule.forRoot(), + RouterTestingModule.withRoutes([]) + ], + declarations: [CollectionAdminSearchResultListElementComponent], + providers: [{ provide: TruncatableService, useValue: {} }], + schemas: [NO_ERRORS_SCHEMA] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(CollectionAdminSearchResultListElementComponent); + component = fixture.componentInstance; + component.object = searchResult; + component.linkTypes = CollectionElementLinkType; + component.index = 0; + component.viewModes = ViewMode; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should render an edit button with the correct link', () => { + const a = fixture.debugElement.query(By.css('a')); + const link = a.nativeElement.href; + expect(link).toContain(getCollectionEditPath(id)); + }) +}); diff --git a/src/app/shared/object-list/admin-search-result-list-element/collection-search-result/collection-admin-search-result-list-element.component.ts b/src/app/shared/object-list/admin-search-result-list-element/collection-search-result/collection-admin-search-result-list-element.component.ts new file mode 100644 index 0000000000..6077db58b3 --- /dev/null +++ b/src/app/shared/object-list/admin-search-result-list-element/collection-search-result/collection-admin-search-result-list-element.component.ts @@ -0,0 +1,27 @@ +import { Component } from '@angular/core'; +import { ViewMode } from '../../../../core/shared/view-mode.model'; +import { listableObjectComponent } from '../../../object-collection/shared/listable-object/listable-object.decorator'; +import { Context } from '../../../../core/shared/context.model'; +import { SearchResultListElementComponent } from '../../search-result-list-element/search-result-list-element.component'; +import { CollectionSearchResult } from '../../../object-collection/shared/collection-search-result.model'; +import { Collection } from '../../../../core/shared/collection.model'; +import { getCollectionEditPath } from '../../../../+collection-page/collection-page-routing.module'; + +@listableObjectComponent(CollectionSearchResult, ViewMode.ListElement, Context.AdminSearch) +@Component({ + selector: 'ds-collection-admin-search-result-list-element', + styleUrls: ['./collection-admin-search-result-list-element.component.scss'], + templateUrl: './collection-admin-search-result-list-element.component.html' +}) +/** + * The component for displaying a list element for a collection search result on the admin search page + */ +export class CollectionAdminSearchResultListElementComponent extends SearchResultListElementComponent { + + /** + * Returns the path to the edit page of this collection + */ + getEditPath(): string { + return getCollectionEditPath(this.dso.uuid) + } +} diff --git a/src/app/shared/object-list/admin-search-result-list-element/community-search-result/community-admin-search-result-list-element.component.html b/src/app/shared/object-list/admin-search-result-list-element/community-search-result/community-admin-search-result-list-element.component.html new file mode 100644 index 0000000000..43917e0399 --- /dev/null +++ b/src/app/shared/object-list/admin-search-result-list-element/community-search-result/community-admin-search-result-list-element.component.html @@ -0,0 +1,8 @@ + + + {{"admin.search.community.edit" | translate}} + diff --git a/src/app/shared/object-list/admin-search-result-list-element/community-search-result/community-admin-search-result-list-element.component.scss b/src/app/shared/object-list/admin-search-result-list-element/community-search-result/community-admin-search-result-list-element.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/shared/object-list/admin-search-result-list-element/community-search-result/community-admin-search-result-list-element.component.spec.ts b/src/app/shared/object-list/admin-search-result-list-element/community-search-result/community-admin-search-result-list-element.component.spec.ts new file mode 100644 index 0000000000..79e7350437 --- /dev/null +++ b/src/app/shared/object-list/admin-search-result-list-element/community-search-result/community-admin-search-result-list-element.component.spec.ts @@ -0,0 +1,60 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { TranslateModule } from '@ngx-translate/core'; +import { TruncatableService } from '../../../truncatable/truncatable.service'; +import { CollectionElementLinkType } from '../../../object-collection/collection-element-link.type'; +import { ViewMode } from '../../../../core/shared/view-mode.model'; +import { Collection } from '../../../../core/shared/collection.model'; +import { By } from '@angular/platform-browser'; +import { RouterTestingModule } from '@angular/router/testing'; +import { CommunityAdminSearchResultListElementComponent } from './community-admin-search-result-list-element.component'; +import { CommunitySearchResult } from '../../../object-collection/shared/community-search-result.model'; +import { getCommunityEditPath } from '../../../../+community-page/community-page-routing.module'; + +describe('CommunityAdminSearchResultListElementComponent', () => { + let component: CommunityAdminSearchResultListElementComponent; + let fixture: ComponentFixture; + let id; + let searchResult; + + function init() { + id = '780b2588-bda5-4112-a1cd-0b15000a5339'; + searchResult = new CommunitySearchResult(); + searchResult.indexableObject = new Collection(); + searchResult.indexableObject.uuid = id; + } + beforeEach(async(() => { + init(); + TestBed.configureTestingModule({ + imports: [ + TranslateModule.forRoot(), + RouterTestingModule.withRoutes([]) + ], + declarations: [CommunityAdminSearchResultListElementComponent], + providers: [{ provide: TruncatableService, useValue: {} }], + schemas: [NO_ERRORS_SCHEMA] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(CommunityAdminSearchResultListElementComponent); + component = fixture.componentInstance; + component.object = searchResult; + component.linkTypes = CollectionElementLinkType; + component.index = 0; + component.viewModes = ViewMode; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should render an edit button with the correct link', () => { + const a = fixture.debugElement.query(By.css('a')); + const link = a.nativeElement.href; + expect(link).toContain(getCommunityEditPath(id)); + }) +}); diff --git a/src/app/shared/object-list/admin-search-result-list-element/community-search-result/community-admin-search-result-list-element.component.ts b/src/app/shared/object-list/admin-search-result-list-element/community-search-result/community-admin-search-result-list-element.component.ts new file mode 100644 index 0000000000..2ba298e596 --- /dev/null +++ b/src/app/shared/object-list/admin-search-result-list-element/community-search-result/community-admin-search-result-list-element.component.ts @@ -0,0 +1,27 @@ +import { Component } from '@angular/core'; +import { ViewMode } from '../../../../core/shared/view-mode.model'; +import { listableObjectComponent } from '../../../object-collection/shared/listable-object/listable-object.decorator'; +import { Context } from '../../../../core/shared/context.model'; +import { SearchResultListElementComponent } from '../../search-result-list-element/search-result-list-element.component'; +import { CommunitySearchResult } from '../../../object-collection/shared/community-search-result.model'; +import { Community } from '../../../../core/shared/community.model'; +import { getCommunityEditPath } from '../../../../+community-page/community-page-routing.module'; + +@listableObjectComponent(CommunitySearchResult, ViewMode.ListElement, Context.AdminSearch) +@Component({ + selector: 'ds-community-admin-search-result-list-element', + styleUrls: ['./community-admin-search-result-list-element.component.scss'], + templateUrl: './community-admin-search-result-list-element.component.html' +}) +/** + * The component for displaying a list element for a community search result on the admin search page + */ +export class CommunityAdminSearchResultListElementComponent extends SearchResultListElementComponent { + + /** + * Returns the path to the edit page of this community + */ + getEditPath(): string { + return getCommunityEditPath(this.dso.uuid) + } +} diff --git a/src/app/shared/object-list/admin-search-result-list-element/item-search-result/item-admin-search-result-list-element.component.html b/src/app/shared/object-list/admin-search-result-list-element/item-search-result/item-admin-search-result-list-element.component.html new file mode 100644 index 0000000000..5730e3f859 --- /dev/null +++ b/src/app/shared/object-list/admin-search-result-list-element/item-search-result/item-admin-search-result-list-element.component.html @@ -0,0 +1,39 @@ +
+ {{ "admin.search.item.private" | translate }} +
+
+ {{ "admin.search.item.withdrawn" | translate }} +
+ + + + {{"admin.search.item.edit" | translate}} + + + + {{"admin.search.item.withdraw" | translate}} + + + + {{"admin.search.item.reinstate" | translate}} + + + + {{"admin.search.item.make-private" | translate}} + + + + {{"admin.search.item.make-public" | translate}} + + + + {{"admin.search.item.delete" | translate}} + + + + {{"admin.search.item.move" | translate}} + diff --git a/src/app/shared/object-list/admin-search-result-list-element/item-search-result/item-admin-search-result-list-element.component.scss b/src/app/shared/object-list/admin-search-result-list-element/item-search-result/item-admin-search-result-list-element.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/shared/object-list/admin-search-result-list-element/item-search-result/item-admin-search-result-list-element.component.spec.ts b/src/app/shared/object-list/admin-search-result-list-element/item-search-result/item-admin-search-result-list-element.component.spec.ts new file mode 100644 index 0000000000..e75244ff3e --- /dev/null +++ b/src/app/shared/object-list/admin-search-result-list-element/item-search-result/item-admin-search-result-list-element.component.spec.ts @@ -0,0 +1,120 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { TranslateModule } from '@ngx-translate/core'; +import { TruncatableService } from '../../../truncatable/truncatable.service'; +import { CollectionElementLinkType } from '../../../object-collection/collection-element-link.type'; +import { ViewMode } from '../../../../core/shared/view-mode.model'; +import { Collection } from '../../../../core/shared/collection.model'; +import { By } from '@angular/platform-browser'; +import { RouterTestingModule } from '@angular/router/testing'; +import { ItemSearchResult } from '../../../object-collection/shared/item-search-result.model'; +import { ItemAdminSearchResultListElementComponent } from './item-admin-search-result-list-element.component'; +import { getItemEditPath } from '../../../../+item-page/item-page-routing.module'; +import { URLCombiner } from '../../../../core/url-combiner/url-combiner'; +import { ITEM_EDIT_DELETE_PATH, ITEM_EDIT_MOVE_PATH, ITEM_EDIT_REINSTATE_PATH, ITEM_EDIT_WITHDRAW_PATH } from '../../../../+item-page/edit-item-page/edit-item-page.routing.module'; + +describe('ItemAdminSearchResultListElementComponent', () => { + let component: ItemAdminSearchResultListElementComponent; + let fixture: ComponentFixture; + let id; + let searchResult; + + function init() { + id = '780b2588-bda5-4112-a1cd-0b15000a5339'; + searchResult = new ItemSearchResult(); + searchResult.indexableObject = new Collection(); + searchResult.indexableObject.uuid = id; + } + beforeEach(async(() => { + init(); + TestBed.configureTestingModule({ + imports: [ + TranslateModule.forRoot(), + RouterTestingModule.withRoutes([]) + ], + declarations: [ItemAdminSearchResultListElementComponent], + providers: [{ provide: TruncatableService, useValue: {} }], + schemas: [NO_ERRORS_SCHEMA] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ItemAdminSearchResultListElementComponent); + component = fixture.componentInstance; + component.object = searchResult; + component.linkTypes = CollectionElementLinkType; + component.index = 0; + component.viewModes = ViewMode; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should render an edit button with the correct link', () => { + const button = fixture.debugElement.query(By.css('a.edit-link')); + const link = button.nativeElement.href; + expect(link).toContain(getItemEditPath(id)); + }); + + it('should render a delete button with the correct link', () => { + const button = fixture.debugElement.query(By.css('a.delete-link')); + const link = button.nativeElement.href; + expect(link).toContain(new URLCombiner(getItemEditPath(id), ITEM_EDIT_DELETE_PATH).toString()); + }); + + it('should render a move button with the correct link', () => { + const a = fixture.debugElement.query(By.css('a.move-link')); + const link = a.nativeElement.href; + expect(link).toContain(new URLCombiner(getItemEditPath(id), ITEM_EDIT_MOVE_PATH).toString()); + }); + + describe('when the item is not withdrawn', () => { + beforeEach(() => { + component.dso.isWithdrawn = false; + fixture.detectChanges(); + }); + + it('should not show the withdrawn badge', () => { + const badge = fixture.debugElement.query(By.css('div.withdrawn-badge')); + expect(badge).toBeNull(); + }); + + it('should render a withdraw button with the correct link', () => { + const a = fixture.debugElement.query(By.css('a.withdraw-link')); + const link = a.nativeElement.href; + expect(link).toContain(new URLCombiner(getItemEditPath(id), ITEM_EDIT_WITHDRAW_PATH).toString()); + }); + + it('should not render a reinstate button with the correct link', () => { + const a = fixture.debugElement.query(By.css('a.reinstate-link')); + expect(a).toBeNull(); + }); + }); + + describe('when the item is withdrawn', () => { + beforeEach(() => { + component.dso.isWithdrawn = true; + fixture.detectChanges(); + }); + + it('should show the withdrawn badge', () => { + const badge = fixture.debugElement.query(By.css('div.withdrawn-badge')); + expect(badge).not.toBeNull(); + }); + + it('should render a withdraw button with the correct link', () => { + const a = fixture.debugElement.query(By.css('a.withdraw-link')); + expect(a).toBeNull(); + }); + + it('should not render a reinstate button with the correct link', () => { + const a = fixture.debugElement.query(By.css('a.reinstate-link')); + const link = a.nativeElement.href; + expect(link).toContain(new URLCombiner(getItemEditPath(id), ITEM_EDIT_REINSTATE_PATH).toString()); + }); + }) +}); diff --git a/src/app/shared/object-list/admin-search-result-list-element/item-search-result/item-admin-search-result-list-element.component.ts b/src/app/shared/object-list/admin-search-result-list-element/item-search-result/item-admin-search-result-list-element.component.ts new file mode 100644 index 0000000000..3eb84e08ad --- /dev/null +++ b/src/app/shared/object-list/admin-search-result-list-element/item-search-result/item-admin-search-result-list-element.component.ts @@ -0,0 +1,77 @@ +import { Component } from '@angular/core'; +import { Item } from '../../../../core/shared/item.model'; +import { ViewMode } from '../../../../core/shared/view-mode.model'; +import { listableObjectComponent } from '../../../object-collection/shared/listable-object/listable-object.decorator'; +import { Context } from '../../../../core/shared/context.model'; +import { ItemSearchResult } from '../../../object-collection/shared/item-search-result.model'; +import { SearchResultListElementComponent } from '../../search-result-list-element/search-result-list-element.component'; +import { getItemEditPath } from '../../../../+item-page/item-page-routing.module'; +import { URLCombiner } from '../../../../core/url-combiner/url-combiner'; +import { + ITEM_EDIT_DELETE_PATH, + ITEM_EDIT_MOVE_PATH, + ITEM_EDIT_PRIVATE_PATH, ITEM_EDIT_PUBLIC_PATH, + ITEM_EDIT_REINSTATE_PATH, + ITEM_EDIT_WITHDRAW_PATH +} from '../../../../+item-page/edit-item-page/edit-item-page.routing.module'; + +@listableObjectComponent(ItemSearchResult, ViewMode.ListElement, Context.AdminSearch) +@Component({ + selector: 'ds-item-admin-search-result-list-element', + styleUrls: ['./item-admin-search-result-list-element.component.scss'], + templateUrl: './item-admin-search-result-list-element.component.html' +}) +/** + * The component for displaying a list element for an item search result on the admin search page + */ +export class ItemAdminSearchResultListElementComponent extends SearchResultListElementComponent { + + /** + * Returns the path to the edit page of this item + */ + getEditPath(): string { + return getItemEditPath(this.dso.uuid) + } + + /** + * Returns the path to the move page of this item + */ + getMovePath(): string { + return new URLCombiner(this.getEditPath(), ITEM_EDIT_MOVE_PATH).toString(); + } + + /** + * Returns the path to the delete page of this item + */ + getDeletePath(): string { + return new URLCombiner(this.getEditPath(), ITEM_EDIT_DELETE_PATH).toString(); + } + + /** + * Returns the path to the withdraw page of this item + */ + getWithdrawPath(): string { + return new URLCombiner(this.getEditPath(), ITEM_EDIT_WITHDRAW_PATH).toString(); + } + + /** + * Returns the path to the reinstate page of this item + */ + getReinstatePath(): string { + return new URLCombiner(this.getEditPath(), ITEM_EDIT_REINSTATE_PATH).toString(); + } + + /** + * Returns the path to the page where the user can make this item private + */ + getPrivatePath(): string { + return new URLCombiner(this.getEditPath(), ITEM_EDIT_PRIVATE_PATH).toString(); + } + + /** + * Returns the path to the page where the user can make this item public + */ + getPublicPath(): string { + return new URLCombiner(this.getEditPath(), ITEM_EDIT_PUBLIC_PATH).toString(); + } +} diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index c6180e3a3b..c64fb51edc 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -177,6 +177,9 @@ import { ImportableListItemControlComponent } from './object-collection/shared/i import { DragDropModule } from '@angular/cdk/drag-drop'; import { ExistingMetadataListElementComponent } from './form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component'; import { SortablejsModule } from 'ngx-sortablejs'; +import { ItemAdminSearchResultListElementComponent } from './object-list/admin-search-result-list-element/item-search-result/item-admin-search-result-list-element.component'; +import { CommunityAdminSearchResultListElementComponent } from './object-list/admin-search-result-list-element/community-search-result/community-admin-search-result-list-element.component'; +import { CollectionAdminSearchResultListElementComponent } from './object-list/admin-search-result-list-element/collection-search-result/collection-admin-search-result-list-element.component'; const MODULES = [ // Do NOT include UniversalModule, HttpModule, or JsonpModule here @@ -339,7 +342,10 @@ const COMPONENTS = [ SelectableListItemControlComponent, ExternalSourceEntryImportModalComponent, ImportableListItemControlComponent, - ExistingMetadataListElementComponent + ExistingMetadataListElementComponent, + ItemAdminSearchResultListElementComponent, + CommunityAdminSearchResultListElementComponent, + CollectionAdminSearchResultListElementComponent ]; const ENTRY_COMPONENTS = [ @@ -402,7 +408,10 @@ const ENTRY_COMPONENTS = [ DsDynamicLookupRelationSearchTabComponent, DsDynamicLookupRelationSelectionTabComponent, DsDynamicLookupRelationExternalSourceTabComponent, - ExternalSourceEntryImportModalComponent + ExternalSourceEntryImportModalComponent, + ItemAdminSearchResultListElementComponent, + CommunityAdminSearchResultListElementComponent, + CollectionAdminSearchResultListElementComponent ]; const SHARED_ITEM_PAGE_COMPONENTS = [