created admin search page

This commit is contained in:
lotte
2020-03-06 13:54:46 +01:00
parent 01231ef105
commit d5484e5c89
28 changed files with 600 additions and 53 deletions

View File

@@ -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.errors.invalid-user": "Invalid email address or password.",
"auth.messages.expired": "Your session has expired. Please log in again.", "auth.messages.expired": "Your session has expired. Please log in again.",
@@ -1984,6 +2010,8 @@
"title": "DSpace", "title": "DSpace",
"undiscoverable.search.results.head": "Admin Search",
"uploader.browse": "browse", "uploader.browse": "browse",

View File

@@ -2,6 +2,7 @@ import { RouterModule } from '@angular/router';
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { URLCombiner } from '../core/url-combiner/url-combiner'; import { URLCombiner } from '../core/url-combiner/url-combiner';
import { getAdminModulePath } from '../app-routing.module'; import { getAdminModulePath } from '../app-routing.module';
import { AdminSearchPageComponent } from './admin-search-page/admin-search-page.component';
const REGISTRIES_MODULE_PATH = 'registries'; const REGISTRIES_MODULE_PATH = 'registries';
@@ -15,7 +16,8 @@ export function getRegistriesModulePath() {
{ {
path: REGISTRIES_MODULE_PATH, path: REGISTRIES_MODULE_PATH,
loadChildren: './admin-registries/admin-registries.module#AdminRegistriesModule' loadChildren: './admin-registries/admin-registries.module#AdminRegistriesModule'
} },
{ path: 'search', component: AdminSearchPageComponent, data: { title: 'admin.search.title' } },
]) ])
] ]
}) })

View File

@@ -0,0 +1 @@
<ds-configuration-search-page configuration="undiscoverable" [context]="context"></ds-configuration-search-page>

View File

@@ -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<AdminSearchPageComponent>;
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();
});
});

View File

@@ -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;
}

View File

@@ -2,13 +2,17 @@ import { NgModule } from '@angular/core';
import { AdminRegistriesModule } from './admin-registries/admin-registries.module'; import { AdminRegistriesModule } from './admin-registries/admin-registries.module';
import { AdminRoutingModule } from './admin-routing.module'; import { AdminRoutingModule } from './admin-routing.module';
import { SharedModule } from '../shared/shared.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({ @NgModule({
imports: [ imports: [
AdminRegistriesModule, AdminRegistriesModule,
AdminRoutingModule, AdminRoutingModule,
SharedModule, SharedModule,
SearchPageModule
], ],
declarations: [AdminSearchPageComponent],
}) })
export class AdminModule { export class AdminModule {

View File

@@ -15,12 +15,12 @@ import { ItemMoveComponent } from './item-move/item-move.component';
import { ItemRelationshipsComponent } from './item-relationships/item-relationships.component'; import { ItemRelationshipsComponent } from './item-relationships/item-relationships.component';
import { I18nBreadcrumbResolver } from '../../core/breadcrumbs/i18n-breadcrumb.resolver'; import { I18nBreadcrumbResolver } from '../../core/breadcrumbs/i18n-breadcrumb.resolver';
const ITEM_EDIT_WITHDRAW_PATH = 'withdraw'; export const ITEM_EDIT_WITHDRAW_PATH = 'withdraw';
const ITEM_EDIT_REINSTATE_PATH = 'reinstate'; export const ITEM_EDIT_REINSTATE_PATH = 'reinstate';
const ITEM_EDIT_PRIVATE_PATH = 'private'; export const ITEM_EDIT_PRIVATE_PATH = 'private';
const ITEM_EDIT_PUBLIC_PATH = 'public'; export const ITEM_EDIT_PUBLIC_PATH = 'public';
const ITEM_EDIT_DELETE_PATH = 'delete'; export const ITEM_EDIT_DELETE_PATH = 'delete';
const ITEM_EDIT_MOVE_PATH = 'move'; export const ITEM_EDIT_MOVE_PATH = 'move';
/** /**
* Routing module that handles the routing for the Edit Item page administrator functionality * Routing module that handles the routing for the Edit Item page administrator functionality

View File

@@ -22,7 +22,8 @@
<ds-search-results [searchResults]="resultsRD$ | async" <ds-search-results [searchResults]="resultsRD$ | async"
[searchConfig]="searchOptions$ | async" [searchConfig]="searchOptions$ | async"
[configuration]="configuration$ | async" [configuration]="configuration$ | async"
[disableHeader]="!searchEnabled"></ds-search-results> [disableHeader]="!searchEnabled"
[context]="context"></ds-search-results>
</div> </div>
</div> </div>
</ds-page-with-sidebar> </ds-page-with-sidebar>

View File

@@ -17,6 +17,7 @@ import { SearchConfigurationService } from '../core/shared/search/search-configu
import { SearchService } from '../core/shared/search/search.service'; import { SearchService } from '../core/shared/search/search.service';
import { currentPath } from '../shared/utils/route.utils'; import { currentPath } from '../shared/utils/route.utils';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { Context } from '../core/shared/context.model';
@Component({ @Component({
selector: 'ds-search', selector: 'ds-search',
@@ -84,6 +85,12 @@ export class SearchComponent implements OnInit {
@Input() @Input()
configuration$: Observable<string>; configuration$: Observable<string>;
/**
* The current context
*/
@Input()
context: Context;
/** /**
* Link to the search page * Link to the search page
*/ */

View File

@@ -9,6 +9,7 @@ import {
SetQueryParameterAction, SetQueryParameterAction,
SetQueryParametersAction SetQueryParametersAction
} from './route.actions'; } from './route.actions';
import { isNotEmpty } from '../../shared/empty.util';
/** /**
* Interface to represent the parameter state of a current route in the store * 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 * @param paramType The type of parameter to set: route or query parameter
*/ */
function setParameters(state: RouteState, action: SetParametersAction | SetQueryParametersAction, paramType: string): RouteState { 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);
} }
/** /**

View File

@@ -6,7 +6,7 @@ import { combineLatest, Observable } from 'rxjs';
import { createSelector, MemoizedSelector, select, Store } from '@ngrx/store'; import { createSelector, MemoizedSelector, select, Store } from '@ngrx/store';
import { isEqual } from 'lodash'; 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 { CoreState } from '../core.reducers';
import { coreSelector } from '../core.selectors'; import { coreSelector } from '../core.selectors';
import { hasValue } from '../../shared/empty.util'; import { hasValue } from '../../shared/empty.util';
@@ -194,6 +194,10 @@ export class RouteService {
this.store.dispatch(new SetParameterAction(key, value)); 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 * Sets the current route parameters and query parameters in the store
*/ */

View File

@@ -10,4 +10,5 @@ export enum Context {
Workspace = 'workspace', Workspace = 'workspace',
AdminMenu = 'adminMenu', AdminMenu = 'adminMenu',
SubmissionModal = 'submissionModal', SubmissionModal = 'submissionModal',
AdminSearch = 'adminSearch',
} }

View File

@@ -1,6 +1,8 @@
import { Component, Input } from '@angular/core'; import { Component, Input } from '@angular/core';
import { ListableObject } from '../listable-object.model'; import { ListableObject } from '../listable-object.model';
import { CollectionElementLinkType } from '../../collection-element-link.type'; import { CollectionElementLinkType } from '../../collection-element-link.type';
import { Context } from '../../../../core/shared/context.model';
import { ViewMode } from '../../../../core/shared/view-mode.model';
@Component({ @Component({
selector: 'ds-abstract-object-element', selector: 'ds-abstract-object-element',
@@ -22,8 +24,23 @@ export class AbstractListableElementComponent<T extends ListableObject> {
*/ */
@Input() listID: string; @Input() listID: string;
/**
* The index of this element
*/
@Input() index: number;
/** /**
* The available link types * The available link types
*/ */
linkTypes = CollectionElementLinkType; linkTypes = CollectionElementLinkType;
/**
* The available view modes
*/
viewModes = ViewMode;
/**
* The available contexts
*/
contexts = Context;
} }

View File

@@ -0,0 +1,8 @@
<ds-listable-object-component-loader [object]="object"
[viewMode]="viewModes.ListElement"
[index]="index"
[linkType]="linkType"
[listID]="listID"></ds-listable-object-component-loader>
<a class="btn btn-primary mt-1 mb-3" [routerLink]="[getEditPath()]">
<i class="fa fa-edit"></i> {{"admin.search.collection.edit" | translate}}
</a>

View File

@@ -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<CollectionAdminSearchResultListElementComponent>;
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));
})
});

View File

@@ -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<CollectionSearchResult, Collection> {
/**
* Returns the path to the edit page of this collection
*/
getEditPath(): string {
return getCollectionEditPath(this.dso.uuid)
}
}

View File

@@ -0,0 +1,8 @@
<ds-listable-object-component-loader [object]="object"
[viewMode]="viewModes.ListElement"
[index]="index"
[linkType]="linkType"
[listID]="listID"></ds-listable-object-component-loader>
<a class="btn btn-primary mt-1 mb-3" [routerLink]="[getEditPath()]">
<i class="fa fa-edit"></i> {{"admin.search.community.edit" | translate}}
</a>

View File

@@ -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<CommunityAdminSearchResultListElementComponent>;
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));
})
});

View File

@@ -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<CommunitySearchResult, Community> {
/**
* Returns the path to the edit page of this community
*/
getEditPath(): string {
return getCommunityEditPath(this.dso.uuid)
}
}

View File

@@ -0,0 +1,39 @@
<div *ngIf="dso && !dso.isDiscoverable" class="private-badge">
<span class="badge badge-danger">{{ "admin.search.item.private" | translate }}</span>
</div>
<div *ngIf="dso && dso.isWithdrawn" class="withdrawn-badge">
<span class="badge badge-warning">{{ "admin.search.item.withdrawn" | translate }}</span>
</div>
<ds-listable-object-component-loader [object]="object"
[viewMode]="viewModes.ListElement"
[index]="index"
[linkType]="linkType"
[listID]="listID"></ds-listable-object-component-loader>
<a class="btn btn-light my-1 edit-link" [routerLink]="[getEditPath()]">
<i class="fa fa-edit"></i><span class="d-none d-sm-inline"> {{"admin.search.item.edit" | translate}}</span>
</a>
<a *ngIf="dso && !dso.isWithdrawn" class="btn btn-light my-1 withdraw-link" [routerLink]="[getWithdrawPath()]">
<i class="fa fa-box"></i><span class="d-none d-sm-inline"> {{"admin.search.item.withdraw" | translate}}</span>
</a>
<a *ngIf="dso && dso.isWithdrawn" class="btn btn-light my-1 reinstate-link" [routerLink]="[getReinstatePath()]">
<i class="fa fa-box-open"></i><span class="d-none d-sm-inline"> {{"admin.search.item.reinstate" | translate}}</span>
</a>
<a *ngIf="dso && dso.isDiscoverable" class="btn btn-light my-1 private-link" [routerLink]="[getPrivatePath()]">
<i class="fa fa-eye-slash"></i><span class="d-none d-sm-inline"> {{"admin.search.item.make-private" | translate}}</span>
</a>
<a *ngIf="dso && !dso.isDiscoverable" class="btn btn-light my-1 public-link" [routerLink]="[getPublicPath()]">
<i class="fa fa-eye"></i><span class="d-none d-sm-inline"> {{"admin.search.item.make-public" | translate}}</span>
</a>
<a class="btn btn-light my-1 delete-link" [routerLink]="[getDeletePath()]">
<i class="fa fa-trash"></i><span class="d-none d-sm-inline"> {{"admin.search.item.delete" | translate}}</span>
</a>
<a class="btn btn-light my-1 move-link" [routerLink]="[getMovePath()]">
<i class="fa fa-arrow-circle-right"></i><span class="d-none d-sm-inline"> {{"admin.search.item.move" | translate}}</span>
</a>

View File

@@ -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<ItemAdminSearchResultListElementComponent>;
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());
});
})
});

View File

@@ -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<ItemSearchResult, Item> {
/**
* 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();
}
}

View File

@@ -177,6 +177,9 @@ import { ImportableListItemControlComponent } from './object-collection/shared/i
import { DragDropModule } from '@angular/cdk/drag-drop'; 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 { ExistingMetadataListElementComponent } from './form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component';
import { SortablejsModule } from 'ngx-sortablejs'; 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 = [ const MODULES = [
// Do NOT include UniversalModule, HttpModule, or JsonpModule here // Do NOT include UniversalModule, HttpModule, or JsonpModule here
@@ -339,7 +342,10 @@ const COMPONENTS = [
SelectableListItemControlComponent, SelectableListItemControlComponent,
ExternalSourceEntryImportModalComponent, ExternalSourceEntryImportModalComponent,
ImportableListItemControlComponent, ImportableListItemControlComponent,
ExistingMetadataListElementComponent ExistingMetadataListElementComponent,
ItemAdminSearchResultListElementComponent,
CommunityAdminSearchResultListElementComponent,
CollectionAdminSearchResultListElementComponent
]; ];
const ENTRY_COMPONENTS = [ const ENTRY_COMPONENTS = [
@@ -402,7 +408,10 @@ const ENTRY_COMPONENTS = [
DsDynamicLookupRelationSearchTabComponent, DsDynamicLookupRelationSearchTabComponent,
DsDynamicLookupRelationSelectionTabComponent, DsDynamicLookupRelationSelectionTabComponent,
DsDynamicLookupRelationExternalSourceTabComponent, DsDynamicLookupRelationExternalSourceTabComponent,
ExternalSourceEntryImportModalComponent ExternalSourceEntryImportModalComponent,
ItemAdminSearchResultListElementComponent,
CommunityAdminSearchResultListElementComponent,
CollectionAdminSearchResultListElementComponent
]; ];
const SHARED_ITEM_PAGE_COMPONENTS = [ const SHARED_ITEM_PAGE_COMPONENTS = [