mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
Merge pull request #615 from atmire/administrative_search
Add Administrative search
This commit is contained in:
@@ -170,6 +170,34 @@
|
||||
|
||||
|
||||
|
||||
"admin.search.breadcrumbs": "Administrative Search",
|
||||
|
||||
"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": "Administrative Search",
|
||||
|
||||
|
||||
|
||||
"auth.errors.invalid-user": "Invalid email address or password.",
|
||||
|
||||
"auth.messages.expired": "Your session has expired. Please log in again.",
|
||||
@@ -1117,6 +1145,10 @@
|
||||
|
||||
|
||||
|
||||
"menu.section.admin_search": "Admin Search",
|
||||
|
||||
|
||||
|
||||
"menu.section.browse_community": "This Community",
|
||||
|
||||
"menu.section.browse_community_by_author": "By Author",
|
||||
@@ -1167,18 +1199,10 @@
|
||||
|
||||
|
||||
|
||||
"menu.section.find": "Find",
|
||||
|
||||
"menu.section.find_items": "Items",
|
||||
|
||||
"menu.section.find_private_items": "Private Items",
|
||||
|
||||
"menu.section.find_withdrawn_items": "Withdrawn Items",
|
||||
|
||||
|
||||
|
||||
"menu.section.icon.access_control": "Access Control menu section",
|
||||
|
||||
"menu.section.icon.admin_search": "Admin search menu section",
|
||||
|
||||
"menu.section.icon.control_panel": "Control Panel menu section",
|
||||
|
||||
"menu.section.icon.curation_task": "Curation Task menu section",
|
||||
@@ -1498,6 +1522,8 @@
|
||||
|
||||
"search.filters.applied.f.dateSubmitted": "Date submitted",
|
||||
|
||||
"search.filters.applied.f.discoverable": "Private",
|
||||
|
||||
"search.filters.applied.f.entityType": "Item Type",
|
||||
|
||||
"search.filters.applied.f.has_content_in_original_bundle": "Has files",
|
||||
@@ -1509,10 +1535,15 @@
|
||||
"search.filters.applied.f.subject": "Subject",
|
||||
|
||||
"search.filters.applied.f.submitter": "Submitter",
|
||||
|
||||
"search.filters.applied.f.jobTitle": "Job Title",
|
||||
|
||||
"search.filters.applied.f.birthDate.max": "End birth date",
|
||||
|
||||
"search.filters.applied.f.birthDate.min": "Start birth date",
|
||||
|
||||
"search.filters.applied.f.withdrawn": "Withdrawn",
|
||||
|
||||
|
||||
|
||||
"search.filters.filter.author.head": "Author",
|
||||
@@ -1549,6 +1580,10 @@
|
||||
|
||||
"search.filters.filter.dateSubmitted.placeholder": "Date submitted",
|
||||
|
||||
"search.filters.filter.discoverable.head": "Private",
|
||||
|
||||
"search.filters.filter.withdrawn.head": "Withdrawn",
|
||||
|
||||
"search.filters.filter.entityType.head": "Item Type",
|
||||
|
||||
"search.filters.filter.entityType.placeholder": "Item Type",
|
||||
@@ -1605,6 +1640,25 @@
|
||||
|
||||
|
||||
|
||||
"search.filters.entityType.JournalIssue": "Journal Issue",
|
||||
|
||||
"search.filters.entityType.JournalVolume": "Journal Volume",
|
||||
|
||||
"search.filters.entityType.OrgUnit": "Organizational Unit",
|
||||
|
||||
"search.filters.has_content_in_original_bundle.true": "Yes",
|
||||
|
||||
"search.filters.has_content_in_original_bundle.false": "No",
|
||||
|
||||
"search.filters.discoverable.true": "No",
|
||||
|
||||
"search.filters.discoverable.false": "Yes",
|
||||
|
||||
"search.filters.withdrawn.true": "Yes",
|
||||
|
||||
"search.filters.withdrawn.false": "No",
|
||||
|
||||
|
||||
"search.filters.head": "Filters",
|
||||
|
||||
"search.filters.reset": "Reset filters",
|
||||
@@ -1984,6 +2038,8 @@
|
||||
"title": "DSpace",
|
||||
|
||||
|
||||
"administrativeView.search.results.head": "Administrative Search",
|
||||
|
||||
|
||||
"uploader.browse": "browse",
|
||||
|
||||
|
@@ -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",
|
||||
|
@@ -2,6 +2,8 @@ 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';
|
||||
import { I18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.resolver';
|
||||
|
||||
const REGISTRIES_MODULE_PATH = 'registries';
|
||||
|
||||
@@ -15,7 +17,13 @@ export function getRegistriesModulePath() {
|
||||
{
|
||||
path: REGISTRIES_MODULE_PATH,
|
||||
loadChildren: './admin-registries/admin-registries.module#AdminRegistriesModule'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'search',
|
||||
resolve: { breadcrumb: I18nBreadcrumbResolver },
|
||||
component: AdminSearchPageComponent,
|
||||
data: { title: 'admin.search.title', breadcrumbKey: 'admin.search' }
|
||||
},
|
||||
])
|
||||
]
|
||||
})
|
||||
|
@@ -0,0 +1 @@
|
||||
<ds-configuration-search-page configuration="administrativeView" [context]="context"></ds-configuration-search-page>
|
@@ -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();
|
||||
});
|
||||
});
|
@@ -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;
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
<ds-collection-search-result-grid-element [object]="object"
|
||||
[index]="index"
|
||||
[linkType]="linkType"
|
||||
[listID]="listID">
|
||||
<ul class="list-group list-group-flush">
|
||||
<li class="list-group-item text-center">
|
||||
<a class="btn btn-light btn-sm btn-auto my-1 edit-link" [routerLink]="[editPath]">
|
||||
<i class="fa fa-edit"></i>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</ds-collection-search-result-grid-element>
|
||||
|
@@ -0,0 +1,66 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { BitstreamDataService } from '../../../../../core/data/bitstream-data.service';
|
||||
import { mockTruncatableService } from '../../../../../shared/mocks/mock-trucatable.service';
|
||||
import { SharedModule } from '../../../../../shared/shared.module';
|
||||
import { CollectionAdminSearchResultGridElementComponent } from './collection-admin-search-result-grid-element.component';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { TruncatableService } from '../../../../../shared/truncatable/truncatable.service';
|
||||
import { CollectionElementLinkType } from '../../../../../shared/object-collection/collection-element-link.type';
|
||||
import { ViewMode } from '../../../../../core/shared/view-mode.model';
|
||||
import { CollectionSearchResult } from '../../../../../shared/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('CollectionAdminSearchResultGridElementComponent', () => {
|
||||
let component: CollectionAdminSearchResultGridElementComponent;
|
||||
let fixture: ComponentFixture<CollectionAdminSearchResultGridElementComponent>;
|
||||
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: [
|
||||
NoopAnimationsModule,
|
||||
TranslateModule.forRoot(),
|
||||
RouterTestingModule.withRoutes([]),
|
||||
SharedModule
|
||||
],
|
||||
declarations: [CollectionAdminSearchResultGridElementComponent],
|
||||
providers: [
|
||||
{ provide: TruncatableService, useValue: mockTruncatableService },
|
||||
{ provide: BitstreamDataService, useValue: {} },
|
||||
]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(CollectionAdminSearchResultGridElementComponent);
|
||||
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.edit-link'));
|
||||
const link = a.nativeElement.href;
|
||||
expect(link).toContain(getCollectionEditPath(id));
|
||||
})
|
||||
});
|
@@ -0,0 +1,26 @@
|
||||
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 { Context } from '../../../../../core/shared/context.model';
|
||||
import { CollectionSearchResult } from '../../../../../shared/object-collection/shared/collection-search-result.model';
|
||||
import { Collection } from '../../../../../core/shared/collection.model';
|
||||
import { getCollectionEditPath } from '../../../../../+collection-page/collection-page-routing.module';
|
||||
import { SearchResultGridElementComponent } from '../../../../../shared/object-grid/search-result-grid-element/search-result-grid-element.component';
|
||||
|
||||
@listableObjectComponent(CollectionSearchResult, ViewMode.GridElement, Context.AdminSearch)
|
||||
@Component({
|
||||
selector: 'ds-collection-admin-search-result-list-element',
|
||||
styleUrls: ['./collection-admin-search-result-grid-element.component.scss'],
|
||||
templateUrl: './collection-admin-search-result-grid-element.component.html'
|
||||
})
|
||||
/**
|
||||
* The component for displaying a list element for a collection search result on the admin search page
|
||||
*/
|
||||
export class CollectionAdminSearchResultGridElementComponent extends SearchResultGridElementComponent<CollectionSearchResult, Collection> {
|
||||
editPath: string;
|
||||
|
||||
ngOnInit() {
|
||||
super.ngOnInit();
|
||||
this.editPath = getCollectionEditPath(this.dso.uuid);
|
||||
}
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
<ds-community-search-result-grid-element [object]="object"
|
||||
[index]="index"
|
||||
[linkType]="linkType"
|
||||
[listID]="listID">
|
||||
<ul class="list-group list-group-flush">
|
||||
<li class="list-group-item text-center">
|
||||
<a class="btn btn-light btn-sm btn-auto my-1 edit-link" [routerLink]="[editPath]">
|
||||
<i class="fa fa-edit"></i>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</ds-community-search-result-grid-element>
|
||||
|
@@ -0,0 +1,70 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { BitstreamDataService } from '../../../../../core/data/bitstream-data.service';
|
||||
import { mockTruncatableService } from '../../../../../shared/mocks/mock-trucatable.service';
|
||||
import { SharedModule } from '../../../../../shared/shared.module';
|
||||
import { TruncatableService } from '../../../../../shared/truncatable/truncatable.service';
|
||||
import { CollectionElementLinkType } from '../../../../../shared/object-collection/collection-element-link.type';
|
||||
import { ViewMode } from '../../../../../core/shared/view-mode.model';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { CommunityAdminSearchResultGridElementComponent } from './community-admin-search-result-grid-element.component';
|
||||
import { CommunitySearchResult } from '../../../../../shared/object-collection/shared/community-search-result.model';
|
||||
import { getCommunityEditPath } from '../../../../../+community-page/community-page-routing.module';
|
||||
import { Community } from '../../../../../core/shared/community.model';
|
||||
import { CommunityAdminSearchResultListElementComponent } from '../../admin-search-result-list-element/community-search-result/community-admin-search-result-list-element.component';
|
||||
|
||||
describe('CommunityAdminSearchResultGridElementComponent', () => {
|
||||
let component: CommunityAdminSearchResultGridElementComponent;
|
||||
let fixture: ComponentFixture<CommunityAdminSearchResultGridElementComponent>;
|
||||
let id;
|
||||
let searchResult;
|
||||
|
||||
function init() {
|
||||
id = '780b2588-bda5-4112-a1cd-0b15000a5339';
|
||||
searchResult = new CommunitySearchResult();
|
||||
searchResult.indexableObject = new Community();
|
||||
searchResult.indexableObject.uuid = id;
|
||||
}
|
||||
beforeEach(async(() => {
|
||||
init();
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
NoopAnimationsModule,
|
||||
TranslateModule.forRoot(),
|
||||
RouterTestingModule.withRoutes([]),
|
||||
SharedModule
|
||||
],
|
||||
declarations: [CommunityAdminSearchResultGridElementComponent],
|
||||
providers: [
|
||||
{ provide: TruncatableService, useValue: mockTruncatableService },
|
||||
{ provide: BitstreamDataService, useValue: {} },
|
||||
],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(CommunityAdminSearchResultGridElementComponent);
|
||||
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.edit-link'));
|
||||
const link = a.nativeElement.href;
|
||||
expect(link).toContain(getCommunityEditPath(id));
|
||||
})
|
||||
});
|
@@ -0,0 +1,26 @@
|
||||
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 { Context } from '../../../../../core/shared/context.model';
|
||||
import { CommunitySearchResult } from '../../../../../shared/object-collection/shared/community-search-result.model';
|
||||
import { Community } from '../../../../../core/shared/community.model';
|
||||
import { getCommunityEditPath } from '../../../../../+community-page/community-page-routing.module';
|
||||
import { SearchResultGridElementComponent } from '../../../../../shared/object-grid/search-result-grid-element/search-result-grid-element.component';
|
||||
|
||||
@listableObjectComponent(CommunitySearchResult, ViewMode.GridElement, Context.AdminSearch)
|
||||
@Component({
|
||||
selector: 'ds-community-admin-search-result-grid-element',
|
||||
styleUrls: ['./community-admin-search-result-grid-element.component.scss'],
|
||||
templateUrl: './community-admin-search-result-grid-element.component.html'
|
||||
})
|
||||
/**
|
||||
* The component for displaying a list element for a community search result on the admin search page
|
||||
*/
|
||||
export class CommunityAdminSearchResultGridElementComponent extends SearchResultGridElementComponent<CommunitySearchResult, Community> {
|
||||
editPath: string;
|
||||
|
||||
ngOnInit() {
|
||||
super.ngOnInit();
|
||||
this.editPath = getCommunityEditPath(this.dso.uuid);
|
||||
}
|
||||
}
|
@@ -0,0 +1,15 @@
|
||||
<ng-template dsListableObject>
|
||||
</ng-template>
|
||||
<div #badges class="position-absolute ml-1">
|
||||
<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>
|
||||
</div>
|
||||
<ul #buttons class="list-group list-group-flush">
|
||||
<li class="list-group-item">
|
||||
<ds-item-admin-search-result-actions-element class="d-flex justify-content-between" [item]="dso" [small]="true"></ds-item-admin-search-result-actions-element>
|
||||
</li>
|
||||
</ul>
|
@@ -0,0 +1,121 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { Observable } from 'rxjs/internal/Observable';
|
||||
import { BitstreamDataService } from '../../../../../core/data/bitstream-data.service';
|
||||
import { RemoteData } from '../../../../../core/data/remote-data';
|
||||
import { Bitstream } from '../../../../../core/shared/bitstream.model';
|
||||
import { Item } from '../../../../../core/shared/item.model';
|
||||
import { mockTruncatableService } from '../../../../../shared/mocks/mock-trucatable.service';
|
||||
import { SharedModule } from '../../../../../shared/shared.module';
|
||||
import { createSuccessfulRemoteDataObject$ } from '../../../../../shared/testing/utils';
|
||||
import { TruncatableService } from '../../../../../shared/truncatable/truncatable.service';
|
||||
import { CollectionElementLinkType } from '../../../../../shared/object-collection/collection-element-link.type';
|
||||
import { ViewMode } from '../../../../../core/shared/view-mode.model';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model';
|
||||
import { ItemAdminSearchResultGridElementComponent } from './item-admin-search-result-grid-element.component';
|
||||
|
||||
describe('ItemAdminSearchResultGridElementComponent', () => {
|
||||
let component: ItemAdminSearchResultGridElementComponent;
|
||||
let fixture: ComponentFixture<ItemAdminSearchResultGridElementComponent>;
|
||||
let id;
|
||||
let searchResult;
|
||||
|
||||
const mockBitstreamDataService = {
|
||||
getThumbnailFor(item: Item): Observable<RemoteData<Bitstream>> {
|
||||
return createSuccessfulRemoteDataObject$(new Bitstream());
|
||||
}
|
||||
};
|
||||
|
||||
function init() {
|
||||
id = '780b2588-bda5-4112-a1cd-0b15000a5339';
|
||||
searchResult = new ItemSearchResult();
|
||||
searchResult.indexableObject = new Item();
|
||||
searchResult.indexableObject.uuid = id;
|
||||
}
|
||||
|
||||
beforeEach(async(() => {
|
||||
init();
|
||||
TestBed.configureTestingModule(
|
||||
{
|
||||
declarations: [ItemAdminSearchResultGridElementComponent],
|
||||
imports: [
|
||||
NoopAnimationsModule,
|
||||
TranslateModule.forRoot(),
|
||||
RouterTestingModule.withRoutes([]),
|
||||
SharedModule
|
||||
],
|
||||
providers: [
|
||||
{ provide: TruncatableService, useValue: mockTruncatableService },
|
||||
{ provide: BitstreamDataService, useValue: mockBitstreamDataService },
|
||||
],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ItemAdminSearchResultGridElementComponent);
|
||||
component = fixture.componentInstance;
|
||||
component.object = searchResult;
|
||||
component.linkTypes = CollectionElementLinkType;
|
||||
component.index = 0;
|
||||
component.viewModes = ViewMode;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
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();
|
||||
});
|
||||
});
|
||||
|
||||
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();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the item is not private', () => {
|
||||
beforeEach(() => {
|
||||
component.dso.isDiscoverable = true;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
it('should not show the private badge', () => {
|
||||
const badge = fixture.debugElement.query(By.css('div.private-badge'));
|
||||
expect(badge).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the item is private', () => {
|
||||
beforeEach(() => {
|
||||
component.dso.isDiscoverable = false;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should show the private badge', () => {
|
||||
const badge = fixture.debugElement.query(By.css('div.private-badge'));
|
||||
expect(badge).not.toBeNull();
|
||||
});
|
||||
})
|
||||
});
|
@@ -0,0 +1,75 @@
|
||||
import { Component, ComponentFactoryResolver, ElementRef, OnInit, ViewChild, ViewContainerRef } from '@angular/core';
|
||||
import { Item } from '../../../../../core/shared/item.model';
|
||||
import { ViewMode } from '../../../../../core/shared/view-mode.model';
|
||||
import { getListableObjectComponent, listableObjectComponent } from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator';
|
||||
import { Context } from '../../../../../core/shared/context.model';
|
||||
import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model';
|
||||
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';
|
||||
import { SearchResultGridElementComponent } from '../../../../../shared/object-grid/search-result-grid-element/search-result-grid-element.component';
|
||||
import { TruncatableService } from '../../../../../shared/truncatable/truncatable.service';
|
||||
import { BitstreamDataService } from '../../../../../core/data/bitstream-data.service';
|
||||
import { GenericConstructor } from '../../../../../core/shared/generic-constructor';
|
||||
import { ListableObjectDirective } from '../../../../../shared/object-collection/shared/listable-object/listable-object.directive';
|
||||
|
||||
@listableObjectComponent(ItemSearchResult, ViewMode.GridElement, Context.AdminSearch)
|
||||
@Component({
|
||||
selector: 'ds-item-admin-search-result-grid-element',
|
||||
styleUrls: ['./item-admin-search-result-grid-element.component.scss'],
|
||||
templateUrl: './item-admin-search-result-grid-element.component.html'
|
||||
})
|
||||
/**
|
||||
* The component for displaying a list element for an item search result on the admin search page
|
||||
*/
|
||||
export class ItemAdminSearchResultGridElementComponent extends SearchResultGridElementComponent<ItemSearchResult, Item> implements OnInit {
|
||||
@ViewChild(ListableObjectDirective, { static: true }) listableObjectDirective: ListableObjectDirective;
|
||||
@ViewChild('badges', { static: true }) badges: ElementRef;
|
||||
@ViewChild('buttons', { static: true }) buttons: ElementRef;
|
||||
|
||||
constructor(protected truncatableService: TruncatableService,
|
||||
protected bitstreamDataService: BitstreamDataService,
|
||||
private componentFactoryResolver: ComponentFactoryResolver
|
||||
) {
|
||||
super(truncatableService, bitstreamDataService);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the dynamic child component
|
||||
*/
|
||||
ngOnInit(): void {
|
||||
super.ngOnInit();
|
||||
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(this.getComponent());
|
||||
|
||||
const viewContainerRef = this.listableObjectDirective.viewContainerRef;
|
||||
viewContainerRef.clear();
|
||||
|
||||
const componentRef = viewContainerRef.createComponent(
|
||||
componentFactory,
|
||||
0,
|
||||
undefined,
|
||||
[
|
||||
[this.badges.nativeElement],
|
||||
[this.buttons.nativeElement]
|
||||
]);
|
||||
(componentRef.instance as any).object = this.object;
|
||||
(componentRef.instance as any).index = this.index;
|
||||
(componentRef.instance as any).linkType = this.linkType;
|
||||
(componentRef.instance as any).listID = this.listID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the component depending on the item's relationship type, view mode and context
|
||||
* @returns {GenericConstructor<Component>}
|
||||
*/
|
||||
private getComponent(): GenericConstructor<Component> {
|
||||
return getListableObjectComponent(this.object.getRenderTypes(), ViewMode.GridElement, undefined)
|
||||
}
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
<ds-collection-search-result-list-element [object]="object"
|
||||
[index]="index"
|
||||
[linkType]="linkType"
|
||||
[listID]="listID"></ds-collection-search-result-list-element>
|
||||
<div>
|
||||
<a class="btn btn-light mt-1" [routerLink]="[editPath]">
|
||||
<i class="fa fa-edit"></i> {{"admin.search.collection.edit" | translate}}
|
||||
</a>
|
||||
</div>
|
@@ -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 '../../../../../shared/truncatable/truncatable.service';
|
||||
import { CollectionElementLinkType } from '../../../../../shared/object-collection/collection-element-link.type';
|
||||
import { ViewMode } from '../../../../../core/shared/view-mode.model';
|
||||
import { CollectionSearchResult } from '../../../../../shared/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));
|
||||
})
|
||||
});
|
@@ -0,0 +1,26 @@
|
||||
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 { Context } from '../../../../../core/shared/context.model';
|
||||
import { SearchResultListElementComponent } from '../../../../../shared/object-list/search-result-list-element/search-result-list-element.component';
|
||||
import { CollectionSearchResult } from '../../../../../shared/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> {
|
||||
editPath: string;
|
||||
|
||||
ngOnInit() {
|
||||
super.ngOnInit();
|
||||
this.editPath = getCollectionEditPath(this.dso.uuid);
|
||||
}
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
<ds-community-search-result-list-element [object]="object"
|
||||
[index]="index"
|
||||
[linkType]="linkType"
|
||||
[listID]="listID"></ds-community-search-result-list-element>
|
||||
<div>
|
||||
<a class="btn btn-light mt-1" [routerLink]="[editPath]">
|
||||
<i class="fa fa-edit"></i> {{"admin.search.community.edit" | translate}}
|
||||
</a>
|
||||
</div>
|
@@ -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 '../../../../../shared/truncatable/truncatable.service';
|
||||
import { CollectionElementLinkType } from '../../../../../shared/object-collection/collection-element-link.type';
|
||||
import { ViewMode } from '../../../../../core/shared/view-mode.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 '../../../../../shared/object-collection/shared/community-search-result.model';
|
||||
import { getCommunityEditPath } from '../../../../../+community-page/community-page-routing.module';
|
||||
import { Community } from '../../../../../core/shared/community.model';
|
||||
|
||||
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 Community();
|
||||
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));
|
||||
})
|
||||
});
|
@@ -0,0 +1,26 @@
|
||||
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 { Context } from '../../../../../core/shared/context.model';
|
||||
import { SearchResultListElementComponent } from '../../../../../shared/object-list/search-result-list-element/search-result-list-element.component';
|
||||
import { CommunitySearchResult } from '../../../../../shared/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> {
|
||||
editPath: string;
|
||||
|
||||
ngOnInit() {
|
||||
super.ngOnInit();
|
||||
this.editPath = getCommunityEditPath(this.dso.uuid);
|
||||
}
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
<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>
|
||||
<ds-item-admin-search-result-actions-element [item]="dso" [small]="false"></ds-item-admin-search-result-actions-element>
|
@@ -0,0 +1,101 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { TruncatableService } from '../../../../../shared/truncatable/truncatable.service';
|
||||
import { CollectionElementLinkType } from '../../../../../shared/object-collection/collection-element-link.type';
|
||||
import { ViewMode } from '../../../../../core/shared/view-mode.model';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model';
|
||||
import { ItemAdminSearchResultListElementComponent } from './item-admin-search-result-list-element.component';
|
||||
import { Item } from '../../../../../core/shared/item.model';
|
||||
|
||||
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 Item();
|
||||
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();
|
||||
});
|
||||
|
||||
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();
|
||||
});
|
||||
});
|
||||
|
||||
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();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the item is not private', () => {
|
||||
beforeEach(() => {
|
||||
component.dso.isDiscoverable = true;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
it('should not show the private badge', () => {
|
||||
const badge = fixture.debugElement.query(By.css('div.private-badge'));
|
||||
expect(badge).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the item is private', () => {
|
||||
beforeEach(() => {
|
||||
component.dso.isDiscoverable = false;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should show the private badge', () => {
|
||||
const badge = fixture.debugElement.query(By.css('div.private-badge'));
|
||||
expect(badge).not.toBeNull();
|
||||
});
|
||||
})
|
||||
});
|
@@ -0,0 +1,20 @@
|
||||
import { 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 { Context } from '../../../../../core/shared/context.model';
|
||||
import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model';
|
||||
import { SearchResultListElementComponent } from '../../../../../shared/object-list/search-result-list-element/search-result-list-element.component';
|
||||
|
||||
@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> {
|
||||
|
||||
}
|
@@ -0,0 +1,27 @@
|
||||
<a [ngClass]="{'btn-sm': small}" class="btn btn-light my-1 edit-link" [routerLink]="[getEditPath()]" [title]="'admin.search.item.edit' | translate">
|
||||
<i class="fa fa-edit"></i><span *ngIf="!small" class="d-none d-sm-inline"> {{"admin.search.item.edit" | translate}}</span>
|
||||
</a>
|
||||
|
||||
<a [ngClass]="{'btn-sm': small}" *ngIf="item && !item.isWithdrawn" class="btn btn-light my-1 withdraw-link" [routerLink]="[getWithdrawPath()]" [title]="'admin.search.item.withdraw' | translate">
|
||||
<i class="fa fa-ban"></i><span *ngIf="!small" class="d-none d-sm-inline"> {{"admin.search.item.withdraw" | translate}}</span>
|
||||
</a>
|
||||
|
||||
<a [ngClass]="{'btn-sm': small}" *ngIf="item && item.isWithdrawn" class="btn btn-light my-1 reinstate-link" [routerLink]="[getReinstatePath()]" [title]="'admin.search.item.reinstate' | translate">
|
||||
<i class="fa fa-undo"></i><span *ngIf="!small" class="d-none d-sm-inline"> {{"admin.search.item.reinstate" | translate}}</span>
|
||||
</a>
|
||||
|
||||
<a [ngClass]="{'btn-sm': small}" *ngIf="item && item.isDiscoverable" class="btn btn-light my-1 private-link" [routerLink]="[getPrivatePath()]" [title]="'admin.search.item.make-private' | translate">
|
||||
<i class="fa fa-eye-slash"></i><span *ngIf="!small" class="d-none d-sm-inline"> {{"admin.search.item.make-private" | translate}}</span>
|
||||
</a>
|
||||
|
||||
<a [ngClass]="{'btn-sm': small}" *ngIf="item && !item.isDiscoverable" class="btn btn-light my-1 public-link" [routerLink]="[getPublicPath()]" [title]="'admin.search.item.make-public' | translate">
|
||||
<i class="fa fa-eye"></i><span *ngIf="!small" class="d-none d-sm-inline"> {{"admin.search.item.make-public" | translate}}</span>
|
||||
</a>
|
||||
|
||||
<a [ngClass]="{'btn-sm': small}" class="btn btn-light my-1 delete-link" [routerLink]="[getDeletePath()]" [title]="'admin.search.item.delete' | translate">
|
||||
<i class="fa fa-trash"></i><span *ngIf="!small" class="d-none d-sm-inline"> {{"admin.search.item.delete" | translate}}</span>
|
||||
</a>
|
||||
|
||||
<a [ngClass]="{'btn-sm': small}" class="btn btn-light my-1 move-link" [routerLink]="[getMovePath()]" [title]="'admin.search.item.move' | translate">
|
||||
<i class="fa fa-arrow-circle-right"></i><span *ngIf="!small" class="d-none d-sm-inline"> {{"admin.search.item.move" | translate}}</span>
|
||||
</a>
|
@@ -0,0 +1 @@
|
||||
|
@@ -0,0 +1,144 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { ItemAdminSearchResultActionsComponent } from './item-admin-search-result-actions.component';
|
||||
import { Item } from '../../../core/shared/item.model';
|
||||
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';
|
||||
import { getItemEditPath } from '../../../+item-page/item-page-routing.module';
|
||||
import { URLCombiner } from '../../../core/url-combiner/url-combiner';
|
||||
|
||||
describe('ItemAdminSearchResultActionsComponent', () => {
|
||||
let component: ItemAdminSearchResultActionsComponent;
|
||||
let fixture: ComponentFixture<ItemAdminSearchResultActionsComponent>;
|
||||
let id;
|
||||
let item;
|
||||
|
||||
function init() {
|
||||
id = '780b2588-bda5-4112-a1cd-0b15000a5339';
|
||||
item = new Item();
|
||||
item.uuid = id;
|
||||
}
|
||||
beforeEach(async(() => {
|
||||
init();
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
TranslateModule.forRoot(),
|
||||
RouterTestingModule.withRoutes([])
|
||||
],
|
||||
declarations: [ItemAdminSearchResultActionsComponent],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ItemAdminSearchResultActionsComponent);
|
||||
component = fixture.componentInstance;
|
||||
component.item = item;
|
||||
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.item.isWithdrawn = false;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
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.item.isWithdrawn = true;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should not render a withdraw button with the correct link', () => {
|
||||
const a = fixture.debugElement.query(By.css('a.withdraw-link'));
|
||||
expect(a).toBeNull();
|
||||
});
|
||||
|
||||
it('should 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());
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the item is not private', () => {
|
||||
beforeEach(() => {
|
||||
component.item.isDiscoverable = true;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should render a make private button with the correct link', () => {
|
||||
const a = fixture.debugElement.query(By.css('a.private-link'));
|
||||
const link = a.nativeElement.href;
|
||||
expect(link).toContain(new URLCombiner(getItemEditPath(id), ITEM_EDIT_PRIVATE_PATH).toString());
|
||||
});
|
||||
|
||||
it('should not render a make public button with the correct link', () => {
|
||||
const a = fixture.debugElement.query(By.css('a.public-link'));
|
||||
expect(a).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the item is private', () => {
|
||||
beforeEach(() => {
|
||||
component.item.isDiscoverable = false;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should not render a make private button with the correct link', () => {
|
||||
const a = fixture.debugElement.query(By.css('a.private-link'));
|
||||
expect(a).toBeNull();
|
||||
});
|
||||
|
||||
it('should render a make private button with the correct link', () => {
|
||||
const a = fixture.debugElement.query(By.css('a.public-link'));
|
||||
const link = a.nativeElement.href;
|
||||
expect(link).toContain(new URLCombiner(getItemEditPath(id), ITEM_EDIT_PUBLIC_PATH).toString());
|
||||
});
|
||||
})
|
||||
});
|
@@ -0,0 +1,81 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { Item } from '../../../core/shared/item.model';
|
||||
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';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-item-admin-search-result-actions-element',
|
||||
styleUrls: ['./item-admin-search-result-actions.component.scss'],
|
||||
templateUrl: './item-admin-search-result-actions.component.html'
|
||||
})
|
||||
/**
|
||||
* The component for displaying the actions for a list element for an item search result on the admin search page
|
||||
*/
|
||||
export class ItemAdminSearchResultActionsComponent {
|
||||
/**
|
||||
* The item to perform the actions on
|
||||
*/
|
||||
@Input() public item: Item;
|
||||
|
||||
/**
|
||||
* Whether or not to use small buttons
|
||||
*/
|
||||
@Input() public small: boolean;
|
||||
|
||||
/**
|
||||
* Returns the path to the edit page of this item
|
||||
*/
|
||||
getEditPath(): string {
|
||||
return getItemEditPath(this.item.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();
|
||||
}
|
||||
}
|
@@ -350,53 +350,19 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit {
|
||||
link: ''
|
||||
} as LinkMenuItemModel,
|
||||
},
|
||||
|
||||
/* Search */
|
||||
/* Admin Search */
|
||||
{
|
||||
id: 'find',
|
||||
id: 'admin_search',
|
||||
active: false,
|
||||
visible: true,
|
||||
model: {
|
||||
type: MenuItemType.TEXT,
|
||||
text: 'menu.section.find'
|
||||
} as TextMenuItemModel,
|
||||
type: MenuItemType.LINK,
|
||||
text: 'menu.section.admin_search',
|
||||
link: '/admin/search'
|
||||
} as LinkMenuItemModel,
|
||||
icon: 'search',
|
||||
index: 5
|
||||
},
|
||||
{
|
||||
id: 'find_items',
|
||||
parentID: 'find',
|
||||
active: false,
|
||||
visible: true,
|
||||
model: {
|
||||
type: MenuItemType.LINK,
|
||||
text: 'menu.section.find_items',
|
||||
link: '/search'
|
||||
} as LinkMenuItemModel,
|
||||
},
|
||||
{
|
||||
id: 'find_withdrawn_items',
|
||||
parentID: 'find',
|
||||
active: false,
|
||||
visible: true,
|
||||
model: {
|
||||
type: MenuItemType.LINK,
|
||||
text: 'menu.section.find_withdrawn_items',
|
||||
link: ''
|
||||
} as LinkMenuItemModel,
|
||||
},
|
||||
{
|
||||
id: 'find_private_items',
|
||||
parentID: 'find',
|
||||
active: false,
|
||||
visible: true,
|
||||
model: {
|
||||
type: MenuItemType.LINK,
|
||||
text: 'menu.section.find_private_items',
|
||||
link: ''
|
||||
} as LinkMenuItemModel,
|
||||
},
|
||||
|
||||
/* Registries */
|
||||
{
|
||||
id: 'registries',
|
||||
|
@@ -2,13 +2,42 @@ 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';
|
||||
import { ItemAdminSearchResultListElementComponent } from './admin-search-page/admin-search-results/admin-search-result-list-element/item-search-result/item-admin-search-result-list-element.component';
|
||||
import { CommunityAdminSearchResultListElementComponent } from './admin-search-page/admin-search-results/admin-search-result-list-element/community-search-result/community-admin-search-result-list-element.component';
|
||||
import { CollectionAdminSearchResultListElementComponent } from './admin-search-page/admin-search-results/admin-search-result-list-element/collection-search-result/collection-admin-search-result-list-element.component';
|
||||
import { ItemAdminSearchResultGridElementComponent } from './admin-search-page/admin-search-results/admin-search-result-grid-element/item-search-result/item-admin-search-result-grid-element.component';
|
||||
import { CommunityAdminSearchResultGridElementComponent } from './admin-search-page/admin-search-results/admin-search-result-grid-element/community-search-result/community-admin-search-result-grid-element.component';
|
||||
import { CollectionAdminSearchResultGridElementComponent } from './admin-search-page/admin-search-results/admin-search-result-grid-element/collection-search-result/collection-admin-search-result-grid-element.component';
|
||||
import { ItemAdminSearchResultActionsComponent } from './admin-search-page/admin-search-results/item-admin-search-result-actions.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
AdminRegistriesModule,
|
||||
AdminRoutingModule,
|
||||
SharedModule,
|
||||
SearchPageModule
|
||||
],
|
||||
declarations: [
|
||||
AdminSearchPageComponent,
|
||||
ItemAdminSearchResultListElementComponent,
|
||||
CommunityAdminSearchResultListElementComponent,
|
||||
CollectionAdminSearchResultListElementComponent,
|
||||
ItemAdminSearchResultGridElementComponent,
|
||||
CommunityAdminSearchResultGridElementComponent,
|
||||
CollectionAdminSearchResultGridElementComponent,
|
||||
ItemAdminSearchResultActionsComponent
|
||||
],
|
||||
entryComponents: [
|
||||
ItemAdminSearchResultListElementComponent,
|
||||
CommunityAdminSearchResultListElementComponent,
|
||||
CollectionAdminSearchResultListElementComponent,
|
||||
ItemAdminSearchResultGridElementComponent,
|
||||
CommunityAdminSearchResultGridElementComponent,
|
||||
CollectionAdminSearchResultGridElementComponent,
|
||||
ItemAdminSearchResultActionsComponent
|
||||
]
|
||||
})
|
||||
export class AdminModule {
|
||||
|
||||
|
@@ -40,6 +40,7 @@ const COLLECTION_EDIT_PATH = 'edit';
|
||||
dso: CollectionPageResolver,
|
||||
breadcrumb: CollectionBreadcrumbResolver
|
||||
},
|
||||
runGuardsAndResolvers: 'always',
|
||||
children: [
|
||||
{
|
||||
path: COLLECTION_EDIT_PATH,
|
||||
|
@@ -39,6 +39,7 @@ const COMMUNITY_EDIT_PATH = 'edit';
|
||||
dso: CommunityPageResolver,
|
||||
breadcrumb: CommunityBreadcrumbResolver
|
||||
},
|
||||
runGuardsAndResolvers: 'always',
|
||||
children: [
|
||||
{
|
||||
path: COMMUNITY_EDIT_PATH,
|
||||
|
@@ -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
|
||||
|
@@ -30,6 +30,7 @@ const ITEM_EDIT_PATH = 'edit';
|
||||
item: ItemPageResolver,
|
||||
breadcrumb: ItemBreadcrumbResolver
|
||||
},
|
||||
runGuardsAndResolvers: 'always',
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import { switchMap } from 'rxjs/operators';
|
||||
import { HostWindowService } from '../shared/host-window.service';
|
||||
import { SidebarService } from '../shared/sidebar/sidebar.service';
|
||||
import { SearchComponent } from './search.component';
|
||||
|
@@ -14,6 +14,7 @@ import { SearchPageComponent } from './search-page.component';
|
||||
import { SidebarFilterService } from '../shared/sidebar/filter/sidebar-filter.service';
|
||||
import { SearchFilterService } from '../core/shared/search/search-filter.service';
|
||||
import { SearchConfigurationService } from '../core/shared/search/search-configuration.service';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
|
||||
const components = [
|
||||
SearchPageComponent,
|
||||
@@ -28,7 +29,7 @@ const components = [
|
||||
CommonModule,
|
||||
SharedModule,
|
||||
CoreModule.forRoot(),
|
||||
StatisticsModule.forRoot(),
|
||||
StatisticsModule.forRoot()
|
||||
],
|
||||
declarations: components,
|
||||
providers: [
|
||||
|
@@ -1,54 +1,55 @@
|
||||
<div class="container" *ngIf="(isXsOrSm$ | async)">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<ng-template *ngTemplateOutlet="searchForm"></ng-template>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<ng-template *ngTemplateOutlet="searchForm"></ng-template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ds-page-with-sidebar [id]="'search-page'" [sidebarContent]="sidebarContent">
|
||||
<div class="row">
|
||||
<div class="col-12" *ngIf="!(isXsOrSm$ | async)">
|
||||
<ng-template *ngTemplateOutlet="searchForm"></ng-template>
|
||||
<div class="row">
|
||||
<div class="col-12" *ngIf="!(isXsOrSm$ | async)">
|
||||
<ng-template *ngTemplateOutlet="searchForm"></ng-template>
|
||||
</div>
|
||||
<div id="search-content" class="col-12">
|
||||
<div class="d-block d-md-none search-controls clearfix">
|
||||
<ds-view-mode-switch [inPlaceSearch]="inPlaceSearch"></ds-view-mode-switch>
|
||||
<button (click)="openSidebar()" aria-controls="#search-body"
|
||||
class="btn btn-outline-primary float-right open-sidebar"><i
|
||||
class="fas fa-sliders"></i> {{"search.sidebar.open"
|
||||
| translate}}
|
||||
</button>
|
||||
</div>
|
||||
<ds-search-results [searchResults]="resultsRD$ | async"
|
||||
[searchConfig]="searchOptions$ | async"
|
||||
[configuration]="configuration$ | async"
|
||||
[disableHeader]="!searchEnabled"
|
||||
[context]="context"></ds-search-results>
|
||||
</div>
|
||||
</div>
|
||||
<div id="search-content" class="col-12">
|
||||
<div class="d-block d-md-none search-controls clearfix">
|
||||
<ds-view-mode-switch [inPlaceSearch]="inPlaceSearch"></ds-view-mode-switch>
|
||||
<button (click)="openSidebar()" aria-controls="#search-body"
|
||||
class="btn btn-outline-primary float-right open-sidebar"><i
|
||||
class="fas fa-sliders"></i> {{"search.sidebar.open"
|
||||
| translate}}
|
||||
</button>
|
||||
</div>
|
||||
<ds-search-results [searchResults]="resultsRD$ | async"
|
||||
[searchConfig]="searchOptions$ | async"
|
||||
[configuration]="configuration$ | async"
|
||||
[disableHeader]="!searchEnabled"></ds-search-results>
|
||||
</div>
|
||||
</div>
|
||||
</ds-page-with-sidebar>
|
||||
|
||||
<ng-template #sidebarContent>
|
||||
<ds-search-sidebar id="search-sidebar" *ngIf="!(isXsOrSm$ | async)"
|
||||
[resultCount]="(resultsRD$ | async)?.payload?.totalElements"
|
||||
[inPlaceSearch]="inPlaceSearch"></ds-search-sidebar>
|
||||
<ds-search-sidebar id="search-sidebar-sm" *ngIf="(isXsOrSm$ | async)"
|
||||
[resultCount]="(resultsRD$ | async)?.payload.totalElements"
|
||||
(toggleSidebar)="closeSidebar()"
|
||||
>
|
||||
</ds-search-sidebar>
|
||||
<ds-search-sidebar id="search-sidebar" *ngIf="!(isXsOrSm$ | async)"
|
||||
[resultCount]="(resultsRD$ | async)?.payload?.totalElements"
|
||||
[inPlaceSearch]="inPlaceSearch"></ds-search-sidebar>
|
||||
<ds-search-sidebar id="search-sidebar-sm" *ngIf="(isXsOrSm$ | async)"
|
||||
[resultCount]="(resultsRD$ | async)?.payload.totalElements"
|
||||
(toggleSidebar)="closeSidebar()"
|
||||
>
|
||||
</ds-search-sidebar>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #searchForm>
|
||||
<ds-search-form *ngIf="searchEnabled" id="search-form"
|
||||
[query]="(searchOptions$ | async)?.query"
|
||||
[scope]="(searchOptions$ | async)?.scope"
|
||||
[currentUrl]="searchLink"
|
||||
[scopes]="(scopeListRD$ | async)"
|
||||
[inPlaceSearch]="inPlaceSearch">
|
||||
</ds-search-form>
|
||||
<div class="row mb-3 mb-md-1">
|
||||
<div class="labels col-sm-9 offset-sm-3">
|
||||
<ds-search-labels *ngIf="searchEnabled" [inPlaceSearch]="inPlaceSearch"></ds-search-labels>
|
||||
<ds-search-form *ngIf="searchEnabled" id="search-form"
|
||||
[query]="(searchOptions$ | async)?.query"
|
||||
[scope]="(searchOptions$ | async)?.scope"
|
||||
[currentUrl]="searchLink"
|
||||
[scopes]="(scopeListRD$ | async)"
|
||||
[inPlaceSearch]="inPlaceSearch">
|
||||
</ds-search-form>
|
||||
<div class="row mb-3 mb-md-1">
|
||||
<div class="labels col-sm-9 offset-sm-3">
|
||||
<ds-search-labels *ngIf="searchEnabled" [inPlaceSearch]="inPlaceSearch"></ds-search-labels>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
@@ -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<string>;
|
||||
|
||||
/**
|
||||
* The current context
|
||||
*/
|
||||
@Input()
|
||||
context: Context;
|
||||
|
||||
/**
|
||||
* Link to the search page
|
||||
*/
|
||||
|
@@ -3,7 +3,6 @@ import { RouterModule } from '@angular/router';
|
||||
|
||||
import { PageNotFoundComponent } from './pagenotfound/pagenotfound.component';
|
||||
import { AuthenticatedGuard } from './core/auth/authenticated.guard';
|
||||
import { Breadcrumb } from './breadcrumbs/breadcrumb/breadcrumb.model';
|
||||
import { DSpaceObject } from './core/shared/dspace-object.model';
|
||||
import { Community } from './core/shared/community.model';
|
||||
import { getCommunityPageRoute } from './+community-page/community-page-routing.module';
|
||||
@@ -11,7 +10,6 @@ import { Collection } from './core/shared/collection.model';
|
||||
import { Item } from './core/shared/item.model';
|
||||
import { getItemPageRoute } from './+item-page/item-page-routing.module';
|
||||
import { getCollectionPageRoute } from './+collection-page/collection-page-routing.module';
|
||||
import { BrowseByDSOBreadcrumbResolver } from './+browse-by/browse-by-dso-breadcrumb.resolver';
|
||||
|
||||
const ITEM_MODULE_PATH = 'items';
|
||||
|
||||
@@ -69,7 +67,10 @@ export function getDSOPath(dso: DSpaceObject): string {
|
||||
{ path: 'workspaceitems', loadChildren: './+workspaceitems-edit-page/workspaceitems-edit-page.module#WorkspaceitemsEditPageModule' },
|
||||
{ path: 'workflowitems', loadChildren: './+workflowitems-edit-page/workflowitems-edit-page.module#WorkflowItemsEditPageModule' },
|
||||
{ path: '**', pathMatch: 'full', component: PageNotFoundComponent },
|
||||
])
|
||||
],
|
||||
{
|
||||
onSameUrlNavigation: 'reload',
|
||||
})
|
||||
],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
|
@@ -20,7 +20,7 @@ import { ITEM } from '../shared/item.resource-type';
|
||||
import {
|
||||
configureRequest,
|
||||
filterSuccessfulResponses,
|
||||
getRequestFromRequestHref,
|
||||
getRequestFromRequestHref, getRequestFromRequestUUID,
|
||||
getResponseFromEntry
|
||||
} from '../shared/operators';
|
||||
import { URLCombiner } from '../url-combiner/url-combiner';
|
||||
@@ -180,14 +180,17 @@ export class ItemDataService extends DataService<Item> {
|
||||
const patchOperation = [{
|
||||
op: 'replace', path: '/withdrawn', value: withdrawn
|
||||
}];
|
||||
this.requestService.removeByHrefSubstring('/discover');
|
||||
|
||||
return this.getItemWithdrawEndpoint(itemId).pipe(
|
||||
distinctUntilChanged(),
|
||||
map((endpointURL: string) =>
|
||||
new PatchRequest(this.requestService.generateRequestId(), endpointURL, patchOperation)
|
||||
),
|
||||
configureRequest(this.requestService),
|
||||
map((request: RestRequest) => request.href),
|
||||
getRequestFromRequestHref(this.requestService),
|
||||
map((request: RestRequest) => request.uuid),
|
||||
getRequestFromRequestUUID(this.requestService),
|
||||
filter((requestEntry: RequestEntry) => requestEntry.completed),
|
||||
map((requestEntry: RequestEntry) => requestEntry.response)
|
||||
);
|
||||
}
|
||||
@@ -201,14 +204,17 @@ export class ItemDataService extends DataService<Item> {
|
||||
const patchOperation = [{
|
||||
op: 'replace', path: '/discoverable', value: discoverable
|
||||
}];
|
||||
this.requestService.removeByHrefSubstring('/discover');
|
||||
|
||||
return this.getItemDiscoverableEndpoint(itemId).pipe(
|
||||
distinctUntilChanged(),
|
||||
map((endpointURL: string) =>
|
||||
new PatchRequest(this.requestService.generateRequestId(), endpointURL, patchOperation)
|
||||
),
|
||||
configureRequest(this.requestService),
|
||||
map((request: RestRequest) => request.href),
|
||||
getRequestFromRequestHref(this.requestService),
|
||||
map((request: RestRequest) => request.uuid),
|
||||
getRequestFromRequestUUID(this.requestService),
|
||||
filter((requestEntry: RequestEntry) => requestEntry.completed),
|
||||
map((requestEntry: RequestEntry) => requestEntry.response)
|
||||
);
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -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
|
||||
*/
|
||||
|
@@ -10,4 +10,5 @@ export enum Context {
|
||||
Workspace = 'workspace',
|
||||
AdminMenu = 'adminMenu',
|
||||
SubmissionModal = 'submissionModal',
|
||||
AdminSearch = 'adminSearch',
|
||||
}
|
||||
|
@@ -1,36 +1,43 @@
|
||||
<ds-truncatable [id]="dso.id">
|
||||
<div class="card" [@focusShadow]="(isCollapsed$ | async)?'blur':'focus'">
|
||||
<a *ngIf="linkType != linkTypes.None" [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]" class="card-img-top full-width">
|
||||
<div>
|
||||
<ds-grid-thumbnail [thumbnail]="getThumbnail() | async">
|
||||
</ds-grid-thumbnail>
|
||||
</div>
|
||||
</a>
|
||||
<span *ngIf="linkType == linkTypes.None" class="card-img-top full-width">
|
||||
<div class="card" [@focusShadow]="(isCollapsed$ | async)?'blur':'focus'">
|
||||
<ds-truncatable [id]="dso.id">
|
||||
<ng-content></ng-content>
|
||||
<a *ngIf="linkType != linkTypes.None"
|
||||
[target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'"
|
||||
rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||
class="card-img-top full-width">
|
||||
<div>
|
||||
<ds-grid-thumbnail [thumbnail]="getThumbnail() | async">
|
||||
</ds-grid-thumbnail>
|
||||
</div>
|
||||
</a>
|
||||
<span *ngIf="linkType == linkTypes.None" class="card-img-top full-width">
|
||||
<div>
|
||||
<ds-grid-thumbnail [thumbnail]="getThumbnail() | async">
|
||||
</ds-grid-thumbnail>
|
||||
</div>
|
||||
</span>
|
||||
<div class="card-body">
|
||||
<ds-item-type-badge [object]="dso"></ds-item-type-badge>
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="3" type="h4">
|
||||
<h4 class="card-title" [innerHTML]="firstMetadataValue('dc.title')"></h4>
|
||||
</ds-truncatable-part>
|
||||
<p *ngIf="dso.hasMetadata('creativework.datePublished')" class="item-date card-text text-muted">
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="1">
|
||||
<span [innerHTML]="firstMetadataValue('creativework.datePublished')"></span>
|
||||
</ds-truncatable-part>
|
||||
</p>
|
||||
<p *ngIf="dso.hasMetadata('journal.title')" class="item-journal-title card-text">
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="3">
|
||||
<span [innerHTML]="firstMetadataValue('journal.title')"></span>
|
||||
</ds-truncatable-part>
|
||||
</p>
|
||||
<div *ngIf="linkType != linkTypes.None" class="text-center">
|
||||
<a [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||
class="lead btn btn-primary viewButton">View</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<ds-item-type-badge [object]="dso"></ds-item-type-badge>
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="3" type="h4">
|
||||
<h4 class="card-title" [innerHTML]="firstMetadataValue('dc.title')"></h4>
|
||||
</ds-truncatable-part>
|
||||
<p *ngIf="dso.hasMetadata('creativework.datePublished')"
|
||||
class="item-date card-text text-muted">
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="1">
|
||||
<span [innerHTML]="firstMetadataValue('creativework.datePublished')"></span>
|
||||
</ds-truncatable-part>
|
||||
</p>
|
||||
<p *ngIf="dso.hasMetadata('journal.title')" class="item-journal-title card-text">
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="3">
|
||||
<span [innerHTML]="firstMetadataValue('journal.title')"></span>
|
||||
</ds-truncatable-part>
|
||||
</p>
|
||||
<div *ngIf="linkType != linkTypes.None" class="text-center">
|
||||
<a [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'"
|
||||
rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||
class="lead btn btn-primary viewButton">View</a>
|
||||
</div>
|
||||
</div>
|
||||
</ds-truncatable>
|
||||
</ds-truncatable>
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
|
@@ -1,36 +1,43 @@
|
||||
<ds-truncatable [id]="dso.id">
|
||||
<div class="card" [@focusShadow]="(isCollapsed$ | async)?'blur':'focus'">
|
||||
<a *ngIf="linkType != linkTypes.None" [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]" class="card-img-top full-width">
|
||||
<div>
|
||||
<ds-grid-thumbnail [thumbnail]="getThumbnail() | async">
|
||||
</ds-grid-thumbnail>
|
||||
</div>
|
||||
</a>
|
||||
<span *ngIf="linkType == linkTypes.None" class="card-img-top full-width">
|
||||
<div class="card" [@focusShadow]="(isCollapsed$ | async)?'blur':'focus'">
|
||||
<ds-truncatable [id]="dso.id">
|
||||
<ng-content></ng-content>
|
||||
<a *ngIf="linkType != linkTypes.None"
|
||||
[target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'"
|
||||
rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||
class="card-img-top full-width">
|
||||
<div>
|
||||
<ds-grid-thumbnail [thumbnail]="getThumbnail() | async">
|
||||
</ds-grid-thumbnail>
|
||||
</div>
|
||||
</a>
|
||||
<span *ngIf="linkType == linkTypes.None" class="card-img-top full-width">
|
||||
<div>
|
||||
<ds-grid-thumbnail [thumbnail]="getThumbnail() | async">
|
||||
</ds-grid-thumbnail>
|
||||
</div>
|
||||
</span>
|
||||
<div class="card-body">
|
||||
<ds-item-type-badge [object]="dso"></ds-item-type-badge>
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="3" type="h4">
|
||||
<h4 class="card-title" [innerHTML]="dso.firstMetadataValue('dc.title')"></h4>
|
||||
</ds-truncatable-part>
|
||||
<p *ngIf="dso.hasMetadata('creativework.datePublished')" class="item-date card-text text-muted">
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="1">
|
||||
<span [innerHTML]="firstMetadataValue('creativework.datePublished')"></span>
|
||||
</ds-truncatable-part>
|
||||
</p>
|
||||
<p *ngIf="dso.hasMetadata('dc.description')" class="item-description card-text">
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="3">
|
||||
<span [innerHTML]="firstMetadataValue('dc.description')"></span>
|
||||
</ds-truncatable-part>
|
||||
</p>
|
||||
<div *ngIf="linkType != linkTypes.None" class="text-center">
|
||||
<a [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||
class="lead btn btn-primary viewButton">View</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ds-truncatable>
|
||||
<div class="card-body">
|
||||
<ds-item-type-badge [object]="dso"></ds-item-type-badge>
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="3" type="h4">
|
||||
<h4 class="card-title" [innerHTML]="dso.firstMetadataValue('dc.title')"></h4>
|
||||
</ds-truncatable-part>
|
||||
<p *ngIf="dso.hasMetadata('creativework.datePublished')"
|
||||
class="item-date card-text text-muted">
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="1">
|
||||
<span [innerHTML]="firstMetadataValue('creativework.datePublished')"></span>
|
||||
</ds-truncatable-part>
|
||||
</p>
|
||||
<p *ngIf="dso.hasMetadata('dc.description')" class="item-description card-text">
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="3">
|
||||
<span [innerHTML]="firstMetadataValue('dc.description')"></span>
|
||||
</ds-truncatable-part>
|
||||
</p>
|
||||
<div *ngIf="linkType != linkTypes.None" class="text-center">
|
||||
<a [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'"
|
||||
rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||
class="lead btn btn-primary viewButton">View</a>
|
||||
</div>
|
||||
</div>
|
||||
</ds-truncatable>
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
|
@@ -1,41 +1,47 @@
|
||||
<ds-truncatable [id]="dso.id">
|
||||
<div class="card" [@focusShadow]="(isCollapsed$ | async)?'blur':'focus'">
|
||||
<a *ngIf="linkType != linkTypes.None" [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]" class="card-img-top full-width">
|
||||
<div>
|
||||
<ds-grid-thumbnail [thumbnail]="getThumbnail() | async">
|
||||
</ds-grid-thumbnail>
|
||||
</div>
|
||||
</a>
|
||||
<span *ngIf="linkType == linkTypes.None" class="card-img-top full-width">
|
||||
<div class="card" [@focusShadow]="(isCollapsed$ | async)?'blur':'focus'">
|
||||
<ds-truncatable [id]="dso.id">
|
||||
<ng-content></ng-content>
|
||||
<a *ngIf="linkType != linkTypes.None"
|
||||
[target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'"
|
||||
rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||
class="card-img-top full-width">
|
||||
<div>
|
||||
<ds-grid-thumbnail [thumbnail]="getThumbnail() | async">
|
||||
</ds-grid-thumbnail>
|
||||
</div>
|
||||
</a>
|
||||
<span *ngIf="linkType == linkTypes.None" class="card-img-top full-width">
|
||||
<div>
|
||||
<ds-grid-thumbnail [thumbnail]="getThumbnail() | async">
|
||||
</ds-grid-thumbnail>
|
||||
</div>
|
||||
</span>
|
||||
<div class="card-body">
|
||||
<ds-item-type-badge [object]="dso"></ds-item-type-badge>
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="3" type="h4">
|
||||
<h4 class="card-title" [innerHTML]="firstMetadataValue('dc.title')"></h4>
|
||||
</ds-truncatable-part>
|
||||
<p *ngIf="dso.hasMetadata('creativework.editor')"
|
||||
class="item-publisher card-text text-muted">
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="1">
|
||||
<span class="item-editor">{{firstMetadataValue('creativework.editor')}}</span>
|
||||
<span *ngIf="dso.hasMetadata('creativework.publisher')" class="item-publisher">
|
||||
<div class="card-body">
|
||||
<ds-item-type-badge [object]="dso"></ds-item-type-badge>
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="3" type="h4">
|
||||
<h4 class="card-title" [innerHTML]="firstMetadataValue('dc.title')"></h4>
|
||||
</ds-truncatable-part>
|
||||
<p *ngIf="dso.hasMetadata('creativework.editor')"
|
||||
class="item-publisher card-text text-muted">
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="1">
|
||||
<span class="item-editor">{{firstMetadataValue('creativework.editor')}}</span>
|
||||
<span *ngIf="dso.hasMetadata('creativework.publisher')" class="item-publisher">
|
||||
<span>, </span>
|
||||
{{firstMetadataValue('creativework.publisher')}}
|
||||
{{firstMetadataValue('creativework.publisher')}}
|
||||
</span>
|
||||
</ds-truncatable-part>
|
||||
</p>
|
||||
<p *ngIf="dso.hasMetadata('dc.description')" class="item-description card-text">
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="3">
|
||||
<span [innerHTML]="firstMetadataValue('dc.description')"></span>
|
||||
</ds-truncatable-part>
|
||||
</p>
|
||||
<div *ngIf="linkType != linkTypes.None" class="text-center">
|
||||
<a [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||
class="lead btn btn-primary viewButton">View</a>
|
||||
</div>
|
||||
</div>
|
||||
</ds-truncatable-part>
|
||||
</p>
|
||||
<p *ngIf="dso.hasMetadata('dc.description')" class="item-description card-text">
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="3">
|
||||
<span [innerHTML]="firstMetadataValue('dc.description')"></span>
|
||||
</ds-truncatable-part>
|
||||
</p>
|
||||
<div *ngIf="linkType != linkTypes.None" class="text-center">
|
||||
<a [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'"
|
||||
rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||
class="lead btn btn-primary viewButton">View</a>
|
||||
</div>
|
||||
</div>
|
||||
</ds-truncatable>
|
||||
</ds-truncatable>
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
|
@@ -1,41 +1,49 @@
|
||||
<ds-truncatable [id]="dso.id">
|
||||
<div class="card" [@focusShadow]="(isCollapsed$ | async)?'blur':'focus'">
|
||||
<a *ngIf="linkType != linkTypes.None" [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]" class="card-img-top full-width">
|
||||
<div>
|
||||
<ds-grid-thumbnail [thumbnail]="getThumbnail() | async">
|
||||
</ds-grid-thumbnail>
|
||||
</div>
|
||||
</a>
|
||||
<span *ngIf="linkType == linkTypes.None" class="card-img-top full-width">
|
||||
<div class="card" [@focusShadow]="(isCollapsed$ | async)?'blur':'focus'">
|
||||
<ds-truncatable [id]="dso.id">
|
||||
<ng-content></ng-content>
|
||||
<a *ngIf="linkType != linkTypes.None"
|
||||
[target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'"
|
||||
rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||
class="card-img-top full-width">
|
||||
<div>
|
||||
<ds-grid-thumbnail [thumbnail]="getThumbnail() | async">
|
||||
</ds-grid-thumbnail>
|
||||
</div>
|
||||
</a>
|
||||
<span *ngIf="linkType == linkTypes.None" class="card-img-top full-width">
|
||||
<div>
|
||||
<ds-grid-thumbnail [thumbnail]="getThumbnail() | async">
|
||||
</ds-grid-thumbnail>
|
||||
</div>
|
||||
</span>
|
||||
<div class="card-body">
|
||||
<ds-item-type-badge [object]="dso"></ds-item-type-badge>
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="3" type="h4">
|
||||
<h4 class="card-title" [innerHTML]="firstMetadataValue('organization.legalName')"></h4>
|
||||
</ds-truncatable-part>
|
||||
<p *ngIf="dso.hasMetadata('organization.foundingDate')" class="item-date card-text text-muted">
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="1">
|
||||
<span [innerHTML]="firstMetadataValue('organization.foundingDate')"></span>
|
||||
</ds-truncatable-part>
|
||||
</p>
|
||||
<p *ngIf="dso.hasMetadata('organization.address.addressCountry')"
|
||||
class="item-location card-text">
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="3">
|
||||
<span class="item-country">{{firstMetadataValue('organization.address.addressCountry')}}</span>
|
||||
<span *ngIf="dso.hasMetadata('organization.address.addressLocality')" class="item-city">
|
||||
<div class="card-body">
|
||||
<ds-item-type-badge [object]="dso"></ds-item-type-badge>
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="3" type="h4">
|
||||
<h4 class="card-title" [innerHTML]="firstMetadataValue('organization.legalName')"></h4>
|
||||
</ds-truncatable-part>
|
||||
<p *ngIf="dso.hasMetadata('organization.foundingDate')"
|
||||
class="item-date card-text text-muted">
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="1">
|
||||
<span [innerHTML]="firstMetadataValue('organization.foundingDate')"></span>
|
||||
</ds-truncatable-part>
|
||||
</p>
|
||||
<p *ngIf="dso.hasMetadata('organization.address.addressCountry')"
|
||||
class="item-location card-text">
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="3">
|
||||
<span
|
||||
class="item-country">{{firstMetadataValue('organization.address.addressCountry')}}</span>
|
||||
<span *ngIf="dso.hasMetadata('organization.address.addressLocality')" class="item-city">
|
||||
<span>, </span>
|
||||
{{firstMetadataValue('organization.address.addressLocality')}}
|
||||
{{firstMetadataValue('organization.address.addressLocality')}}
|
||||
</span>
|
||||
</ds-truncatable-part>
|
||||
</p>
|
||||
<div *ngIf="linkType != linkTypes.None" class="text-center">
|
||||
<a [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||
class="lead btn btn-primary viewButton">View</a>
|
||||
</div>
|
||||
</div>
|
||||
</ds-truncatable-part>
|
||||
</p>
|
||||
<div *ngIf="linkType != linkTypes.None" class="text-center">
|
||||
<a [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'"
|
||||
rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||
class="lead btn btn-primary viewButton">View</a>
|
||||
</div>
|
||||
</div>
|
||||
</ds-truncatable>
|
||||
</ds-truncatable>
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
|
@@ -1,37 +1,43 @@
|
||||
<ds-truncatable [id]="dso.id">
|
||||
<div class="card" [@focusShadow]="(isCollapsed$ | async)?'blur':'focus'">
|
||||
<a *ngIf="linkType != linkTypes.None" [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||
class="card-img-top full-width">
|
||||
<div>
|
||||
<ds-grid-thumbnail [thumbnail]="getThumbnail() | async">
|
||||
</ds-grid-thumbnail>
|
||||
</div>
|
||||
</a>
|
||||
<span *ngIf="linkType == linkTypes.None" class="card-img-top full-width">
|
||||
<div class="card" [@focusShadow]="(isCollapsed$ | async)?'blur':'focus'">
|
||||
<ds-truncatable [id]="dso.id">
|
||||
<ng-content></ng-content>
|
||||
<a *ngIf="linkType != linkTypes.None"
|
||||
[target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'"
|
||||
rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||
class="card-img-top full-width">
|
||||
<div>
|
||||
<ds-grid-thumbnail [thumbnail]="getThumbnail() | async">
|
||||
</ds-grid-thumbnail>
|
||||
</div>
|
||||
</a>
|
||||
<span *ngIf="linkType == linkTypes.None" class="card-img-top full-width">
|
||||
<div>
|
||||
<ds-grid-thumbnail [thumbnail]="getThumbnail() | async">
|
||||
</ds-grid-thumbnail>
|
||||
</div>
|
||||
</span>
|
||||
<div class="card-body">
|
||||
<ds-item-type-badge [object]="dso"></ds-item-type-badge>
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="3" type="h4">
|
||||
<h4 class="card-title" [innerHTML]="firstMetadataValue('person.familyName') + ', ' + firstMetadataValue('person.givenName')"></h4>
|
||||
</ds-truncatable-part>
|
||||
<p *ngIf="dso.hasMetadata('person.email')" class="item-email card-text text-muted">
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="1">
|
||||
<span [innerHTML]="firstMetadataValue('person.email')"></span>
|
||||
</ds-truncatable-part>
|
||||
</p>
|
||||
<p *ngIf="dso.hasMetadata('person.jobTitle')" class="item-jobtitle card-text">
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="3">
|
||||
<span [innerHTML]="firstMetadataValue('person.jobTitle')"></span>
|
||||
</ds-truncatable-part>
|
||||
</p>
|
||||
<div *ngIf="linkType != linkTypes.None" class="text-center">
|
||||
<a [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||
class="lead btn btn-primary viewButton">View</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<ds-item-type-badge [object]="dso"></ds-item-type-badge>
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="3" type="h4">
|
||||
<h4 class="card-title"
|
||||
[innerHTML]="firstMetadataValue('person.familyName') + ', ' + firstMetadataValue('person.givenName')"></h4>
|
||||
</ds-truncatable-part>
|
||||
<p *ngIf="dso.hasMetadata('person.email')" class="item-email card-text text-muted">
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="1">
|
||||
<span [innerHTML]="firstMetadataValue('person.email')"></span>
|
||||
</ds-truncatable-part>
|
||||
</p>
|
||||
<p *ngIf="dso.hasMetadata('person.jobTitle')" class="item-jobtitle card-text">
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="3">
|
||||
<span [innerHTML]="firstMetadataValue('person.jobTitle')"></span>
|
||||
</ds-truncatable-part>
|
||||
</p>
|
||||
<div *ngIf="linkType != linkTypes.None" class="text-center">
|
||||
<a [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'"
|
||||
rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||
class="lead btn btn-primary viewButton">View</a>
|
||||
</div>
|
||||
</div>
|
||||
</ds-truncatable>
|
||||
</ds-truncatable>
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
|
@@ -1,31 +1,37 @@
|
||||
<ds-truncatable [id]="dso.id">
|
||||
<div class="card" [@focusShadow]="(isCollapsed$ | async)?'blur':'focus'">
|
||||
<a *ngIf="linkType != linkTypes.None" [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]" class="card-img-top full-width">
|
||||
<div>
|
||||
<ds-grid-thumbnail [thumbnail]="getThumbnail() | async">
|
||||
</ds-grid-thumbnail>
|
||||
</div>
|
||||
</a>
|
||||
<span *ngIf="linkType == linkTypes.None" class="card-img-top full-width">
|
||||
<div class="card" [@focusShadow]="(isCollapsed$ | async)?'blur':'focus'">
|
||||
<ds-truncatable [id]="dso.id">
|
||||
<ng-content></ng-content>
|
||||
<a *ngIf="linkType != linkTypes.None"
|
||||
[target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'"
|
||||
rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||
class="card-img-top full-width">
|
||||
<div>
|
||||
<ds-grid-thumbnail [thumbnail]="getThumbnail() | async">
|
||||
</ds-grid-thumbnail>
|
||||
</div>
|
||||
</a>
|
||||
<span *ngIf="linkType == linkTypes.None" class="card-img-top full-width">
|
||||
<div>
|
||||
<ds-grid-thumbnail [thumbnail]="getThumbnail() | async">
|
||||
</ds-grid-thumbnail>
|
||||
</div>
|
||||
</span>
|
||||
<div class="card-body">
|
||||
<ds-item-type-badge [object]="dso"></ds-item-type-badge>
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="3" type="h4">
|
||||
<h4 class="card-title" [innerHTML]="firstMetadataValue('dc.title')"></h4>
|
||||
</ds-truncatable-part>
|
||||
<p *ngIf="dso.hasMetadata('dc.description')" class="item-description card-text text-muted">
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="3">
|
||||
<span [innerHTML]="firstMetadataValue('dc.description')"></span>
|
||||
</ds-truncatable-part>
|
||||
</p>
|
||||
<div *ngIf="linkType != linkTypes.None" class="text-center">
|
||||
<a [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||
class="lead btn btn-primary viewButton">View</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<ds-item-type-badge [object]="dso"></ds-item-type-badge>
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="3" type="h4">
|
||||
<h4 class="card-title" [innerHTML]="firstMetadataValue('dc.title')"></h4>
|
||||
</ds-truncatable-part>
|
||||
<p *ngIf="dso.hasMetadata('dc.description')" class="item-description card-text text-muted">
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="3">
|
||||
<span [innerHTML]="firstMetadataValue('dc.description')"></span>
|
||||
</ds-truncatable-part>
|
||||
</p>
|
||||
<div *ngIf="linkType != linkTypes.None" class="text-center">
|
||||
<a [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'"
|
||||
rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||
class="lead btn btn-primary viewButton">View</a>
|
||||
</div>
|
||||
</div>
|
||||
</ds-truncatable>
|
||||
</ds-truncatable>
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
|
19
src/app/shared/mocks/mock-trucatable.service.ts
Normal file
19
src/app/shared/mocks/mock-trucatable.service.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { of as observableOf } from 'rxjs/internal/observable/of';
|
||||
|
||||
export const mockTruncatableService: any = {
|
||||
/* tslint:disable:no-empty */
|
||||
isCollapsed: (id: string) => {
|
||||
if (id === '1') {
|
||||
return observableOf(true)
|
||||
} else {
|
||||
return observableOf(false);
|
||||
}
|
||||
},
|
||||
expand: (id: string) => {
|
||||
},
|
||||
collapse: (id: string) => {
|
||||
},
|
||||
toggle: (id: string) => {
|
||||
}
|
||||
/* tslint:enable:no-empty */
|
||||
};
|
@@ -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<T extends ListableObject> {
|
||||
*/
|
||||
@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;
|
||||
}
|
||||
|
@@ -14,4 +14,5 @@
|
||||
<a [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer" [routerLink]="['/collections/', dso.id]" class="lead btn btn-primary viewButton">View</a>
|
||||
</div>
|
||||
</div>
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
|
@@ -6,6 +6,7 @@ import { Store } from '@ngrx/store';
|
||||
import { of as observableOf } from 'rxjs';
|
||||
import { RemoteDataBuildService } from '../../../../core/cache/builders/remote-data-build.service';
|
||||
import { ObjectCacheService } from '../../../../core/cache/object-cache.service';
|
||||
import { BitstreamDataService } from '../../../../core/data/bitstream-data.service';
|
||||
import { CommunityDataService } from '../../../../core/data/community-data.service';
|
||||
import { DefaultChangeAnalyzer } from '../../../../core/data/default-change-analyzer.service';
|
||||
import { DSOChangeAnalyzer } from '../../../../core/data/dso-change-analyzer.service';
|
||||
@@ -62,6 +63,7 @@ describe('CollectionSearchResultGridElementComponent', () => {
|
||||
{ provide: UUIDService, useValue: {} },
|
||||
{ provide: Store, useValue: {} },
|
||||
{ provide: RemoteDataBuildService, useValue: {} },
|
||||
{ provide: BitstreamDataService, useValue: {} },
|
||||
{ provide: CommunityDataService, useValue: {} },
|
||||
{ provide: HALEndpointService, useValue: {} },
|
||||
{ provide: NotificationsService, useValue: {} },
|
||||
|
@@ -1,17 +1,18 @@
|
||||
<div class="card">
|
||||
<a *ngIf="linkType != linkTypes.None" [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer" [routerLink]="['/communities/', dso.id]" class="card-img-top">
|
||||
<ds-grid-thumbnail [thumbnail]="dso.logo">
|
||||
</ds-grid-thumbnail>
|
||||
</a>
|
||||
<span *ngIf="linkType == linkTypes.None" class="card-img-top">
|
||||
<a *ngIf="linkType != linkTypes.None" [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer" [routerLink]="['/communities/', dso.id]" class="card-img-top">
|
||||
<ds-grid-thumbnail [thumbnail]="dso.logo">
|
||||
</ds-grid-thumbnail>
|
||||
</a>
|
||||
<span *ngIf="linkType == linkTypes.None" class="card-img-top">
|
||||
<ds-grid-thumbnail [thumbnail]="dso.logo">
|
||||
</ds-grid-thumbnail>
|
||||
</span>
|
||||
<div class="card-body">
|
||||
<h4 class="card-title">{{dso.name}}</h4>
|
||||
<p *ngIf="dso.shortDescription" class="card-text">{{dso.shortDescription}}</p>
|
||||
<div *ngIf="linkType != linkTypes.None" class="text-center">
|
||||
<a [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer" [routerLink]="['/communities/', dso.id]" class="lead btn btn-primary viewButton">View</a>
|
||||
<div class="card-body">
|
||||
<h4 class="card-title">{{dso.name}}</h4>
|
||||
<p *ngIf="dso.shortDescription" class="card-text">{{dso.shortDescription}}</p>
|
||||
<div *ngIf="linkType != linkTypes.None" class="text-center">
|
||||
<a [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer" [routerLink]="['/communities/', dso.id]" class="lead btn btn-primary viewButton">View</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
|
@@ -6,6 +6,7 @@ import { Store } from '@ngrx/store';
|
||||
import { of as observableOf } from 'rxjs';
|
||||
import { RemoteDataBuildService } from '../../../../core/cache/builders/remote-data-build.service';
|
||||
import { ObjectCacheService } from '../../../../core/cache/object-cache.service';
|
||||
import { BitstreamDataService } from '../../../../core/data/bitstream-data.service';
|
||||
import { CommunityDataService } from '../../../../core/data/community-data.service';
|
||||
import { DefaultChangeAnalyzer } from '../../../../core/data/default-change-analyzer.service';
|
||||
import { DSOChangeAnalyzer } from '../../../../core/data/dso-change-analyzer.service';
|
||||
@@ -62,6 +63,7 @@ describe('CommunitySearchResultGridElementComponent', () => {
|
||||
{ provide: UUIDService, useValue: {} },
|
||||
{ provide: Store, useValue: {} },
|
||||
{ provide: RemoteDataBuildService, useValue: {} },
|
||||
{ provide: BitstreamDataService, useValue: {} },
|
||||
{ provide: CommunityDataService, useValue: {} },
|
||||
{ provide: HALEndpointService, useValue: {} },
|
||||
{ provide: NotificationsService, useValue: {} },
|
||||
|
@@ -1,41 +1,44 @@
|
||||
<ds-truncatable [id]="dso.id">
|
||||
<div class="card" [@focusShadow]="(isCollapsed$ | async)?'blur':'focus'">
|
||||
<a *ngIf="linkType != linkTypes.None" [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||
class="card-img-top full-width">
|
||||
<div>
|
||||
<ds-grid-thumbnail [thumbnail]="getThumbnail() | async">
|
||||
</ds-grid-thumbnail>
|
||||
</div>
|
||||
</a>
|
||||
<span *ngIf="linkType == linkTypes.None" class="card-img-top full-width">
|
||||
<div>
|
||||
<ds-grid-thumbnail [thumbnail]="getThumbnail() | async">
|
||||
</ds-grid-thumbnail>
|
||||
</div>
|
||||
</span>
|
||||
<div class="card-body">
|
||||
<ds-item-type-badge [object]="dso"></ds-item-type-badge>
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="3" type="h4">
|
||||
<h4 class="card-title" [innerHTML]="firstMetadataValue('dc.title')"></h4>
|
||||
</ds-truncatable-part>
|
||||
<p *ngIf="dso.hasMetadata(['dc.contributor.author', 'dc.creator', 'dc.contributor.*'])"
|
||||
class="item-authors card-text text-muted">
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="1">
|
||||
<span *ngIf="dso.hasMetadata('dc.date.issued')" class="item-date">{{firstMetadataValue('dc.date.issued')}}</span>
|
||||
<span *ngFor="let author of allMetadataValues(['dc.contributor.author', 'dc.creator', 'dc.contributor.*']);">,
|
||||
<span [innerHTML]="author"></span>
|
||||
</span>
|
||||
</ds-truncatable-part>
|
||||
</p>
|
||||
<p *ngIf="dso.hasMetadata('dc.description.abstract')" class="item-abstract card-text">
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="3">
|
||||
<span [innerHTML]="firstMetadataValue('dc.description.abstract')"></span>
|
||||
</ds-truncatable-part>
|
||||
</p>
|
||||
<div *ngIf="linkType != linkTypes.None" class="text-center">
|
||||
<a [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||
class="lead btn btn-primary viewButton">View</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ds-truncatable>
|
||||
<div class="card" [@focusShadow]="(isCollapsed$ | async)?'blur':'focus'">
|
||||
<ds-truncatable [id]="dso.id">
|
||||
<ng-content></ng-content>
|
||||
<a *ngIf="linkType != linkTypes.None" [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||
class="card-img-top full-width">
|
||||
<div>
|
||||
<ds-grid-thumbnail [thumbnail]="getThumbnail() | async">
|
||||
</ds-grid-thumbnail>
|
||||
</div>
|
||||
</a>
|
||||
<span *ngIf="linkType == linkTypes.None" class="card-img-top full-width">
|
||||
<div>
|
||||
<ds-grid-thumbnail [thumbnail]="getThumbnail() | async">
|
||||
</ds-grid-thumbnail>
|
||||
</div>
|
||||
</span>
|
||||
<div class="card-body">
|
||||
<ds-item-type-badge [object]="dso"></ds-item-type-badge>
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="3" type="h4">
|
||||
<h4 class="card-title" [innerHTML]="firstMetadataValue('dc.title')"></h4>
|
||||
</ds-truncatable-part>
|
||||
<p *ngIf="dso.hasMetadata(['dc.contributor.author', 'dc.creator', 'dc.contributor.*'])"
|
||||
class="item-authors card-text text-muted">
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="1">
|
||||
<span *ngIf="dso.hasMetadata('dc.date.issued')" class="item-date">{{firstMetadataValue('dc.date.issued')}}</span>
|
||||
<span *ngFor="let author of allMetadataValues(['dc.contributor.author', 'dc.creator', 'dc.contributor.*']);">,
|
||||
<span [innerHTML]="author"></span>
|
||||
</span>
|
||||
</ds-truncatable-part>
|
||||
</p>
|
||||
<p *ngIf="dso.hasMetadata('dc.description.abstract')" class="item-abstract card-text">
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="3">
|
||||
<span [innerHTML]="firstMetadataValue('dc.description.abstract')"></span>
|
||||
</ds-truncatable-part>
|
||||
</p>
|
||||
<div *ngIf="linkType != linkTypes.None" class="text-center">
|
||||
<a [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||
class="lead btn btn-primary viewButton">View</a>
|
||||
</div>
|
||||
</div>
|
||||
</ds-truncatable>
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
|
||||
|
@@ -7,6 +7,7 @@ import { Item } from '../../../../../core/shared/item.model';
|
||||
import { ItemSearchResult } from '../../../../object-collection/shared/item-search-result.model';
|
||||
|
||||
@listableObjectComponent('PublicationSearchResult', ViewMode.GridElement)
|
||||
@listableObjectComponent(ItemSearchResult, ViewMode.GridElement)
|
||||
@Component({
|
||||
selector: 'ds-publication-search-result-grid-element',
|
||||
styleUrls: ['./publication-search-result-grid-element.component.scss'],
|
||||
|
@@ -27,9 +27,9 @@ describe('PaginatedSearchOptions', () => {
|
||||
'query=search query&' +
|
||||
'scope=0fde1ecb-82cc-425a-b600-ac3576d76b47&' +
|
||||
'dsoType=ITEM&' +
|
||||
'f.test=value,query&' +
|
||||
'f.example=another value,query&' +
|
||||
'f.example=second value,query'
|
||||
'f.test=value&' +
|
||||
'f.example=another value&' +
|
||||
'f.example=second value'
|
||||
);
|
||||
});
|
||||
|
||||
|
@@ -1,7 +1,6 @@
|
||||
/**
|
||||
* Represents a search filter
|
||||
*/
|
||||
import { hasValue } from '../empty.util';
|
||||
|
||||
export class SearchFilter {
|
||||
key: string;
|
||||
@@ -11,10 +10,6 @@ export class SearchFilter {
|
||||
constructor(key: string, values: string[], operator?: string) {
|
||||
this.key = key;
|
||||
this.values = values;
|
||||
if (hasValue(operator)) {
|
||||
this.operator = operator;
|
||||
} else {
|
||||
this.operator = 'query';
|
||||
}
|
||||
this.operator = operator;
|
||||
}
|
||||
}
|
||||
|
@@ -2,7 +2,9 @@
|
||||
[routerLink]="[searchLink]"
|
||||
[queryParams]="addQueryParams" queryParamsHandling="merge">
|
||||
<input type="checkbox" [checked]="false" class="my-1 align-self-stretch"/>
|
||||
<span class="filter-value px-1">{{filterValue.value}}</span>
|
||||
<span class="filter-value px-1">
|
||||
{{ 'search.filters.' + filterConfig.name + '.' + filterValue.value | translate: {default: filterValue.value} }}
|
||||
</span>
|
||||
<span class="float-right filter-value-count ml-auto">
|
||||
<span class="badge badge-secondary badge-pill">{{filterValue.count}}</span>
|
||||
</span>
|
||||
|
@@ -2,5 +2,7 @@
|
||||
[routerLink]="[searchLink]"
|
||||
[queryParams]="removeQueryParams" queryParamsHandling="merge">
|
||||
<input type="checkbox" [checked]="true" class="my-1 align-self-stretch"/>
|
||||
<span class="filter-value pl-1 text-capitalize">{{selectedValue.label}}</span>
|
||||
<span class="filter-value pl-1 text-capitalize">
|
||||
{{ 'search.filters.' + filterConfig.name + '.' + selectedValue.value | translate: {default: selectedValue.value} }}
|
||||
</span>
|
||||
</a>
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<a class="badge badge-primary mr-1 mb-1 text-capitalize"
|
||||
[routerLink]="searchLink"
|
||||
[queryParams]="(removeParameters | async)" queryParamsHandling="merge">
|
||||
{{('search.filters.applied.' + key) | translate}}: {{normalizeFilterValue(value)}}
|
||||
{{('search.filters.applied.' + key) | translate}}: {{'search.filters.' + filterName + '.' + value | translate: {default: normalizeFilterValue(value)} }}
|
||||
<span> ×</span>
|
||||
</a>
|
||||
</a>
|
||||
|
@@ -22,6 +22,11 @@ export class SearchLabelComponent implements OnInit {
|
||||
searchLink: string;
|
||||
removeParameters: Observable<Params>;
|
||||
|
||||
/**
|
||||
* The name of the filter without the f. prefix
|
||||
*/
|
||||
filterName: string;
|
||||
|
||||
/**
|
||||
* Initialize the instance variable
|
||||
*/
|
||||
@@ -33,6 +38,7 @@ export class SearchLabelComponent implements OnInit {
|
||||
ngOnInit(): void {
|
||||
this.searchLink = this.getSearchLink();
|
||||
this.removeParameters = this.getRemoveParams();
|
||||
this.filterName = this.getFilterName();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,4 +80,8 @@ export class SearchLabelComponent implements OnInit {
|
||||
const pattern = /,authority*$/g;
|
||||
return value.replace(pattern, '');
|
||||
}
|
||||
|
||||
private getFilterName(): string {
|
||||
return this.key.startsWith('f.') ? this.key.substring(2) : this.key;
|
||||
}
|
||||
}
|
||||
|
@@ -21,9 +21,9 @@ describe('SearchOptions', () => {
|
||||
'query=search query&' +
|
||||
'scope=0fde1ecb-82cc-425a-b600-ac3576d76b47&' +
|
||||
'dsoType=ITEM&' +
|
||||
'f.test=value,query&' +
|
||||
'f.example=another value,query&' +
|
||||
'f.example=second value,query'
|
||||
'f.test=value&' +
|
||||
'f.example=another value&' +
|
||||
'f.example=second value'
|
||||
);
|
||||
});
|
||||
|
||||
|
@@ -50,7 +50,7 @@ export class SearchOptions {
|
||||
if (isNotEmpty(this.filters)) {
|
||||
this.filters.forEach((filter: SearchFilter) => {
|
||||
filter.values.forEach((value) => {
|
||||
const filterValue = value.includes(',') ? `${value}` : `${value},${filter.operator}`;
|
||||
const filterValue = value.includes(',') ? `${value}` : value + (filter.operator ? ',' + filter.operator : '');
|
||||
args.push(`${filter.key}=${filterValue}`)
|
||||
});
|
||||
});
|
||||
|
@@ -6,7 +6,7 @@ import { NouisliderModule } from 'ng2-nouislider';
|
||||
|
||||
import { NgbDatepickerModule, NgbModule, NgbTimepickerModule, NgbTypeaheadModule } from '@ng-bootstrap/ng-bootstrap';
|
||||
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { MissingTranslationHandler, TranslateModule } from '@ngx-translate/core';
|
||||
|
||||
import { NgxPaginationModule } from 'ngx-pagination';
|
||||
import { PublicationListElementComponent } from './object-list/item-list-element/item-types/publication/publication-list-element.component';
|
||||
@@ -177,6 +177,7 @@ 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 { MissingTranslationHelper } from './translate/missing-translation.helper';
|
||||
|
||||
const MODULES = [
|
||||
// Do NOT include UniversalModule, HttpModule, or JsonpModule here
|
||||
@@ -194,7 +195,6 @@ const MODULES = [
|
||||
NgxPaginationModule,
|
||||
ReactiveFormsModule,
|
||||
RouterModule,
|
||||
TranslateModule,
|
||||
NouisliderModule,
|
||||
MomentModule,
|
||||
TextMaskModule,
|
||||
@@ -203,7 +203,11 @@ const MODULES = [
|
||||
];
|
||||
|
||||
const ROOT_MODULES = [
|
||||
TooltipModule.forRoot()
|
||||
TranslateModule.forChild({
|
||||
missingTranslationHandler: { provide: MissingTranslationHandler, useClass: MissingTranslationHelper },
|
||||
useDefaultLang: true
|
||||
}),
|
||||
TooltipModule.forRoot(),
|
||||
];
|
||||
|
||||
const PIPES = [
|
||||
@@ -339,7 +343,8 @@ const COMPONENTS = [
|
||||
SelectableListItemControlComponent,
|
||||
ExternalSourceEntryImportModalComponent,
|
||||
ImportableListItemControlComponent,
|
||||
ExistingMetadataListElementComponent
|
||||
ExistingMetadataListElementComponent,
|
||||
PublicationSearchResultListElementComponent,
|
||||
];
|
||||
|
||||
const ENTRY_COMPONENTS = [
|
||||
@@ -402,7 +407,7 @@ const ENTRY_COMPONENTS = [
|
||||
DsDynamicLookupRelationSearchTabComponent,
|
||||
DsDynamicLookupRelationSelectionTabComponent,
|
||||
DsDynamicLookupRelationExternalSourceTabComponent,
|
||||
ExternalSourceEntryImportModalComponent
|
||||
ExternalSourceEntryImportModalComponent,
|
||||
];
|
||||
|
||||
const SHARED_ITEM_PAGE_COMPONENTS = [
|
||||
@@ -435,8 +440,8 @@ const DIRECTIVES = [
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
...ROOT_MODULES,
|
||||
...MODULES,
|
||||
...ROOT_MODULES
|
||||
],
|
||||
declarations: [
|
||||
...PIPES,
|
||||
@@ -444,8 +449,7 @@ const DIRECTIVES = [
|
||||
...DIRECTIVES,
|
||||
...ENTRY_COMPONENTS,
|
||||
...SHARED_ITEM_PAGE_COMPONENTS,
|
||||
PublicationSearchResultListElementComponent,
|
||||
ExistingMetadataListElementComponent
|
||||
|
||||
],
|
||||
providers: [
|
||||
...PROVIDERS
|
||||
|
18
src/app/shared/translate/missing-translation.helper.ts
Normal file
18
src/app/shared/translate/missing-translation.helper.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { MissingTranslationHandler, MissingTranslationHandlerParams } from '@ngx-translate/core';
|
||||
|
||||
/**
|
||||
* Class to handle missing translations for the ngx-translate library
|
||||
*/
|
||||
export class MissingTranslationHelper implements MissingTranslationHandler {
|
||||
/**
|
||||
* Called when there is not translation for a specific key
|
||||
* Will return the 'default' parameter of the translate pipe, if there is one available
|
||||
* @param params
|
||||
*/
|
||||
handle(params: MissingTranslationHandlerParams) {
|
||||
if (params.interpolateParams) {
|
||||
return (params.interpolateParams as any).default || params.key;
|
||||
}
|
||||
return params.key;
|
||||
}
|
||||
}
|
@@ -1,5 +1,6 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { of as observableOf } from 'rxjs';
|
||||
import { mockTruncatableService } from '../mocks/mock-trucatable.service';
|
||||
import { TruncatableComponent } from './truncatable.component';
|
||||
import { TruncatableService } from './truncatable.service';
|
||||
import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
@@ -10,29 +11,12 @@ describe('TruncatableComponent', () => {
|
||||
let fixture: ComponentFixture<TruncatableComponent>;
|
||||
const identifier = '1234567890';
|
||||
let truncatableService;
|
||||
const truncatableServiceStub: any = {
|
||||
/* tslint:disable:no-empty */
|
||||
isCollapsed: (id: string) => {
|
||||
if (id === '1') {
|
||||
return observableOf(true)
|
||||
} else {
|
||||
return observableOf(false);
|
||||
}
|
||||
},
|
||||
expand: (id: string) => {
|
||||
},
|
||||
collapse: (id: string) => {
|
||||
},
|
||||
toggle: (id: string) => {
|
||||
}
|
||||
/* tslint:enable:no-empty */
|
||||
};
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [NoopAnimationsModule],
|
||||
declarations: [TruncatableComponent],
|
||||
providers: [
|
||||
{ provide: TruncatableService, useValue: truncatableServiceStub },
|
||||
{ provide: TruncatableService, useValue: mockTruncatableService },
|
||||
],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
}).overrideComponent(TruncatableComponent, {
|
||||
|
Reference in New Issue
Block a user