mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 10:04:11 +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.errors.invalid-user": "Invalid email address or password.",
|
||||||
|
|
||||||
"auth.messages.expired": "Your session has expired. Please log in again.",
|
"auth.messages.expired": "Your session has expired. Please log in again.",
|
||||||
@@ -1117,6 +1145,10 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
"menu.section.admin_search": "Admin Search",
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"menu.section.browse_community": "This Community",
|
"menu.section.browse_community": "This Community",
|
||||||
|
|
||||||
"menu.section.browse_community_by_author": "By Author",
|
"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.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.control_panel": "Control Panel menu section",
|
||||||
|
|
||||||
"menu.section.icon.curation_task": "Curation Task 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.dateSubmitted": "Date submitted",
|
||||||
|
|
||||||
|
"search.filters.applied.f.discoverable": "Private",
|
||||||
|
|
||||||
"search.filters.applied.f.entityType": "Item Type",
|
"search.filters.applied.f.entityType": "Item Type",
|
||||||
|
|
||||||
"search.filters.applied.f.has_content_in_original_bundle": "Has files",
|
"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.subject": "Subject",
|
||||||
|
|
||||||
"search.filters.applied.f.submitter": "Submitter",
|
"search.filters.applied.f.submitter": "Submitter",
|
||||||
|
|
||||||
"search.filters.applied.f.jobTitle": "Job Title",
|
"search.filters.applied.f.jobTitle": "Job Title",
|
||||||
|
|
||||||
"search.filters.applied.f.birthDate.max": "End birth date",
|
"search.filters.applied.f.birthDate.max": "End birth date",
|
||||||
|
|
||||||
"search.filters.applied.f.birthDate.min": "Start birth date",
|
"search.filters.applied.f.birthDate.min": "Start birth date",
|
||||||
|
|
||||||
|
"search.filters.applied.f.withdrawn": "Withdrawn",
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"search.filters.filter.author.head": "Author",
|
"search.filters.filter.author.head": "Author",
|
||||||
@@ -1549,6 +1580,10 @@
|
|||||||
|
|
||||||
"search.filters.filter.dateSubmitted.placeholder": "Date submitted",
|
"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.head": "Item Type",
|
||||||
|
|
||||||
"search.filters.filter.entityType.placeholder": "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.head": "Filters",
|
||||||
|
|
||||||
"search.filters.reset": "Reset filters",
|
"search.filters.reset": "Reset filters",
|
||||||
@@ -1984,6 +2038,8 @@
|
|||||||
"title": "DSpace",
|
"title": "DSpace",
|
||||||
|
|
||||||
|
|
||||||
|
"administrativeView.search.results.head": "Administrative Search",
|
||||||
|
|
||||||
|
|
||||||
"uploader.browse": "browse",
|
"uploader.browse": "browse",
|
||||||
|
|
||||||
|
@@ -2,6 +2,8 @@ import { RouterModule } from '@angular/router';
|
|||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { URLCombiner } from '../core/url-combiner/url-combiner';
|
import { URLCombiner } from '../core/url-combiner/url-combiner';
|
||||||
import { getAdminModulePath } from '../app-routing.module';
|
import { getAdminModulePath } from '../app-routing.module';
|
||||||
|
import { AdminSearchPageComponent } from './admin-search-page/admin-search-page.component';
|
||||||
|
import { I18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.resolver';
|
||||||
|
|
||||||
const REGISTRIES_MODULE_PATH = 'registries';
|
const REGISTRIES_MODULE_PATH = 'registries';
|
||||||
|
|
||||||
@@ -15,7 +17,13 @@ export function getRegistriesModulePath() {
|
|||||||
{
|
{
|
||||||
path: REGISTRIES_MODULE_PATH,
|
path: REGISTRIES_MODULE_PATH,
|
||||||
loadChildren: './admin-registries/admin-registries.module#AdminRegistriesModule'
|
loadChildren: './admin-registries/admin-registries.module#AdminRegistriesModule'
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
path: 'search',
|
||||||
|
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: ''
|
link: ''
|
||||||
} as LinkMenuItemModel,
|
} as LinkMenuItemModel,
|
||||||
},
|
},
|
||||||
|
/* Admin Search */
|
||||||
/* Search */
|
|
||||||
{
|
{
|
||||||
id: 'find',
|
id: 'admin_search',
|
||||||
active: false,
|
active: false,
|
||||||
visible: true,
|
visible: true,
|
||||||
model: {
|
model: {
|
||||||
type: MenuItemType.TEXT,
|
type: MenuItemType.LINK,
|
||||||
text: 'menu.section.find'
|
text: 'menu.section.admin_search',
|
||||||
} as TextMenuItemModel,
|
link: '/admin/search'
|
||||||
|
} as LinkMenuItemModel,
|
||||||
icon: 'search',
|
icon: 'search',
|
||||||
index: 5
|
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 */
|
/* Registries */
|
||||||
{
|
{
|
||||||
id: 'registries',
|
id: 'registries',
|
||||||
|
@@ -2,13 +2,42 @@ import { NgModule } from '@angular/core';
|
|||||||
import { AdminRegistriesModule } from './admin-registries/admin-registries.module';
|
import { AdminRegistriesModule } from './admin-registries/admin-registries.module';
|
||||||
import { AdminRoutingModule } from './admin-routing.module';
|
import { AdminRoutingModule } from './admin-routing.module';
|
||||||
import { SharedModule } from '../shared/shared.module';
|
import { SharedModule } from '../shared/shared.module';
|
||||||
|
import { AdminSearchPageComponent } from './admin-search-page/admin-search-page.component';
|
||||||
|
import { SearchPageModule } from '../+search-page/search-page.module';
|
||||||
|
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({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
AdminRegistriesModule,
|
AdminRegistriesModule,
|
||||||
AdminRoutingModule,
|
AdminRoutingModule,
|
||||||
SharedModule,
|
SharedModule,
|
||||||
|
SearchPageModule
|
||||||
],
|
],
|
||||||
|
declarations: [
|
||||||
|
AdminSearchPageComponent,
|
||||||
|
ItemAdminSearchResultListElementComponent,
|
||||||
|
CommunityAdminSearchResultListElementComponent,
|
||||||
|
CollectionAdminSearchResultListElementComponent,
|
||||||
|
ItemAdminSearchResultGridElementComponent,
|
||||||
|
CommunityAdminSearchResultGridElementComponent,
|
||||||
|
CollectionAdminSearchResultGridElementComponent,
|
||||||
|
ItemAdminSearchResultActionsComponent
|
||||||
|
],
|
||||||
|
entryComponents: [
|
||||||
|
ItemAdminSearchResultListElementComponent,
|
||||||
|
CommunityAdminSearchResultListElementComponent,
|
||||||
|
CollectionAdminSearchResultListElementComponent,
|
||||||
|
ItemAdminSearchResultGridElementComponent,
|
||||||
|
CommunityAdminSearchResultGridElementComponent,
|
||||||
|
CollectionAdminSearchResultGridElementComponent,
|
||||||
|
ItemAdminSearchResultActionsComponent
|
||||||
|
]
|
||||||
})
|
})
|
||||||
export class AdminModule {
|
export class AdminModule {
|
||||||
|
|
||||||
|
@@ -40,6 +40,7 @@ const COLLECTION_EDIT_PATH = 'edit';
|
|||||||
dso: CollectionPageResolver,
|
dso: CollectionPageResolver,
|
||||||
breadcrumb: CollectionBreadcrumbResolver
|
breadcrumb: CollectionBreadcrumbResolver
|
||||||
},
|
},
|
||||||
|
runGuardsAndResolvers: 'always',
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: COLLECTION_EDIT_PATH,
|
path: COLLECTION_EDIT_PATH,
|
||||||
|
@@ -39,6 +39,7 @@ const COMMUNITY_EDIT_PATH = 'edit';
|
|||||||
dso: CommunityPageResolver,
|
dso: CommunityPageResolver,
|
||||||
breadcrumb: CommunityBreadcrumbResolver
|
breadcrumb: CommunityBreadcrumbResolver
|
||||||
},
|
},
|
||||||
|
runGuardsAndResolvers: 'always',
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: COMMUNITY_EDIT_PATH,
|
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 { ItemRelationshipsComponent } from './item-relationships/item-relationships.component';
|
||||||
import { I18nBreadcrumbResolver } from '../../core/breadcrumbs/i18n-breadcrumb.resolver';
|
import { I18nBreadcrumbResolver } from '../../core/breadcrumbs/i18n-breadcrumb.resolver';
|
||||||
|
|
||||||
const ITEM_EDIT_WITHDRAW_PATH = 'withdraw';
|
export const ITEM_EDIT_WITHDRAW_PATH = 'withdraw';
|
||||||
const ITEM_EDIT_REINSTATE_PATH = 'reinstate';
|
export const ITEM_EDIT_REINSTATE_PATH = 'reinstate';
|
||||||
const ITEM_EDIT_PRIVATE_PATH = 'private';
|
export const ITEM_EDIT_PRIVATE_PATH = 'private';
|
||||||
const ITEM_EDIT_PUBLIC_PATH = 'public';
|
export const ITEM_EDIT_PUBLIC_PATH = 'public';
|
||||||
const ITEM_EDIT_DELETE_PATH = 'delete';
|
export const ITEM_EDIT_DELETE_PATH = 'delete';
|
||||||
const ITEM_EDIT_MOVE_PATH = 'move';
|
export const ITEM_EDIT_MOVE_PATH = 'move';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Routing module that handles the routing for the Edit Item page administrator functionality
|
* Routing module that handles the routing for the Edit Item page administrator functionality
|
||||||
|
@@ -30,6 +30,7 @@ const ITEM_EDIT_PATH = 'edit';
|
|||||||
item: ItemPageResolver,
|
item: ItemPageResolver,
|
||||||
breadcrumb: ItemBreadcrumbResolver
|
breadcrumb: ItemBreadcrumbResolver
|
||||||
},
|
},
|
||||||
|
runGuardsAndResolvers: 'always',
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
import { switchMap } from 'rxjs/operators';
|
||||||
import { HostWindowService } from '../shared/host-window.service';
|
import { HostWindowService } from '../shared/host-window.service';
|
||||||
import { SidebarService } from '../shared/sidebar/sidebar.service';
|
import { SidebarService } from '../shared/sidebar/sidebar.service';
|
||||||
import { SearchComponent } from './search.component';
|
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 { SidebarFilterService } from '../shared/sidebar/filter/sidebar-filter.service';
|
||||||
import { SearchFilterService } from '../core/shared/search/search-filter.service';
|
import { SearchFilterService } from '../core/shared/search/search-filter.service';
|
||||||
import { SearchConfigurationService } from '../core/shared/search/search-configuration.service';
|
import { SearchConfigurationService } from '../core/shared/search/search-configuration.service';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
|
||||||
const components = [
|
const components = [
|
||||||
SearchPageComponent,
|
SearchPageComponent,
|
||||||
@@ -28,7 +29,7 @@ const components = [
|
|||||||
CommonModule,
|
CommonModule,
|
||||||
SharedModule,
|
SharedModule,
|
||||||
CoreModule.forRoot(),
|
CoreModule.forRoot(),
|
||||||
StatisticsModule.forRoot(),
|
StatisticsModule.forRoot()
|
||||||
],
|
],
|
||||||
declarations: components,
|
declarations: components,
|
||||||
providers: [
|
providers: [
|
||||||
|
@@ -22,7 +22,8 @@
|
|||||||
<ds-search-results [searchResults]="resultsRD$ | async"
|
<ds-search-results [searchResults]="resultsRD$ | async"
|
||||||
[searchConfig]="searchOptions$ | async"
|
[searchConfig]="searchOptions$ | async"
|
||||||
[configuration]="configuration$ | async"
|
[configuration]="configuration$ | async"
|
||||||
[disableHeader]="!searchEnabled"></ds-search-results>
|
[disableHeader]="!searchEnabled"
|
||||||
|
[context]="context"></ds-search-results>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ds-page-with-sidebar>
|
</ds-page-with-sidebar>
|
||||||
|
@@ -17,6 +17,7 @@ import { SearchConfigurationService } from '../core/shared/search/search-configu
|
|||||||
import { SearchService } from '../core/shared/search/search.service';
|
import { SearchService } from '../core/shared/search/search.service';
|
||||||
import { currentPath } from '../shared/utils/route.utils';
|
import { currentPath } from '../shared/utils/route.utils';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
|
import { Context } from '../core/shared/context.model';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-search',
|
selector: 'ds-search',
|
||||||
@@ -84,6 +85,12 @@ export class SearchComponent implements OnInit {
|
|||||||
@Input()
|
@Input()
|
||||||
configuration$: Observable<string>;
|
configuration$: Observable<string>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current context
|
||||||
|
*/
|
||||||
|
@Input()
|
||||||
|
context: Context;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Link to the search page
|
* Link to the search page
|
||||||
*/
|
*/
|
||||||
|
@@ -3,7 +3,6 @@ import { RouterModule } from '@angular/router';
|
|||||||
|
|
||||||
import { PageNotFoundComponent } from './pagenotfound/pagenotfound.component';
|
import { PageNotFoundComponent } from './pagenotfound/pagenotfound.component';
|
||||||
import { AuthenticatedGuard } from './core/auth/authenticated.guard';
|
import { AuthenticatedGuard } from './core/auth/authenticated.guard';
|
||||||
import { Breadcrumb } from './breadcrumbs/breadcrumb/breadcrumb.model';
|
|
||||||
import { DSpaceObject } from './core/shared/dspace-object.model';
|
import { DSpaceObject } from './core/shared/dspace-object.model';
|
||||||
import { Community } from './core/shared/community.model';
|
import { Community } from './core/shared/community.model';
|
||||||
import { getCommunityPageRoute } from './+community-page/community-page-routing.module';
|
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 { Item } from './core/shared/item.model';
|
||||||
import { getItemPageRoute } from './+item-page/item-page-routing.module';
|
import { getItemPageRoute } from './+item-page/item-page-routing.module';
|
||||||
import { getCollectionPageRoute } from './+collection-page/collection-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';
|
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: 'workspaceitems', loadChildren: './+workspaceitems-edit-page/workspaceitems-edit-page.module#WorkspaceitemsEditPageModule' },
|
||||||
{ path: 'workflowitems', loadChildren: './+workflowitems-edit-page/workflowitems-edit-page.module#WorkflowItemsEditPageModule' },
|
{ path: 'workflowitems', loadChildren: './+workflowitems-edit-page/workflowitems-edit-page.module#WorkflowItemsEditPageModule' },
|
||||||
{ path: '**', pathMatch: 'full', component: PageNotFoundComponent },
|
{ path: '**', pathMatch: 'full', component: PageNotFoundComponent },
|
||||||
])
|
],
|
||||||
|
{
|
||||||
|
onSameUrlNavigation: 'reload',
|
||||||
|
})
|
||||||
],
|
],
|
||||||
exports: [RouterModule],
|
exports: [RouterModule],
|
||||||
})
|
})
|
||||||
|
@@ -20,7 +20,7 @@ import { ITEM } from '../shared/item.resource-type';
|
|||||||
import {
|
import {
|
||||||
configureRequest,
|
configureRequest,
|
||||||
filterSuccessfulResponses,
|
filterSuccessfulResponses,
|
||||||
getRequestFromRequestHref,
|
getRequestFromRequestHref, getRequestFromRequestUUID,
|
||||||
getResponseFromEntry
|
getResponseFromEntry
|
||||||
} from '../shared/operators';
|
} from '../shared/operators';
|
||||||
import { URLCombiner } from '../url-combiner/url-combiner';
|
import { URLCombiner } from '../url-combiner/url-combiner';
|
||||||
@@ -180,14 +180,17 @@ export class ItemDataService extends DataService<Item> {
|
|||||||
const patchOperation = [{
|
const patchOperation = [{
|
||||||
op: 'replace', path: '/withdrawn', value: withdrawn
|
op: 'replace', path: '/withdrawn', value: withdrawn
|
||||||
}];
|
}];
|
||||||
|
this.requestService.removeByHrefSubstring('/discover');
|
||||||
|
|
||||||
return this.getItemWithdrawEndpoint(itemId).pipe(
|
return this.getItemWithdrawEndpoint(itemId).pipe(
|
||||||
distinctUntilChanged(),
|
distinctUntilChanged(),
|
||||||
map((endpointURL: string) =>
|
map((endpointURL: string) =>
|
||||||
new PatchRequest(this.requestService.generateRequestId(), endpointURL, patchOperation)
|
new PatchRequest(this.requestService.generateRequestId(), endpointURL, patchOperation)
|
||||||
),
|
),
|
||||||
configureRequest(this.requestService),
|
configureRequest(this.requestService),
|
||||||
map((request: RestRequest) => request.href),
|
map((request: RestRequest) => request.uuid),
|
||||||
getRequestFromRequestHref(this.requestService),
|
getRequestFromRequestUUID(this.requestService),
|
||||||
|
filter((requestEntry: RequestEntry) => requestEntry.completed),
|
||||||
map((requestEntry: RequestEntry) => requestEntry.response)
|
map((requestEntry: RequestEntry) => requestEntry.response)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -201,14 +204,17 @@ export class ItemDataService extends DataService<Item> {
|
|||||||
const patchOperation = [{
|
const patchOperation = [{
|
||||||
op: 'replace', path: '/discoverable', value: discoverable
|
op: 'replace', path: '/discoverable', value: discoverable
|
||||||
}];
|
}];
|
||||||
|
this.requestService.removeByHrefSubstring('/discover');
|
||||||
|
|
||||||
return this.getItemDiscoverableEndpoint(itemId).pipe(
|
return this.getItemDiscoverableEndpoint(itemId).pipe(
|
||||||
distinctUntilChanged(),
|
distinctUntilChanged(),
|
||||||
map((endpointURL: string) =>
|
map((endpointURL: string) =>
|
||||||
new PatchRequest(this.requestService.generateRequestId(), endpointURL, patchOperation)
|
new PatchRequest(this.requestService.generateRequestId(), endpointURL, patchOperation)
|
||||||
),
|
),
|
||||||
configureRequest(this.requestService),
|
configureRequest(this.requestService),
|
||||||
map((request: RestRequest) => request.href),
|
map((request: RestRequest) => request.uuid),
|
||||||
getRequestFromRequestHref(this.requestService),
|
getRequestFromRequestUUID(this.requestService),
|
||||||
|
filter((requestEntry: RequestEntry) => requestEntry.completed),
|
||||||
map((requestEntry: RequestEntry) => requestEntry.response)
|
map((requestEntry: RequestEntry) => requestEntry.response)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -9,6 +9,7 @@ import {
|
|||||||
SetQueryParameterAction,
|
SetQueryParameterAction,
|
||||||
SetQueryParametersAction
|
SetQueryParametersAction
|
||||||
} from './route.actions';
|
} from './route.actions';
|
||||||
|
import { isNotEmpty } from '../../shared/empty.util';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface to represent the parameter state of a current route in the store
|
* Interface to represent the parameter state of a current route in the store
|
||||||
@@ -81,7 +82,8 @@ function addParameter(state: RouteState, action: AddParameterAction | AddQueryPa
|
|||||||
* @param paramType The type of parameter to set: route or query parameter
|
* @param paramType The type of parameter to set: route or query parameter
|
||||||
*/
|
*/
|
||||||
function setParameters(state: RouteState, action: SetParametersAction | SetQueryParametersAction, paramType: string): RouteState {
|
function setParameters(state: RouteState, action: SetParametersAction | SetQueryParametersAction, paramType: string): RouteState {
|
||||||
return Object.assign({}, state, { [paramType]: { [action.payload.key]: action.payload.value } });
|
const param = isNotEmpty(action.payload) ? { [paramType]: { [action.payload.key]: action.payload.value } } : {};
|
||||||
|
return Object.assign({}, state, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -6,7 +6,7 @@ import { combineLatest, Observable } from 'rxjs';
|
|||||||
import { createSelector, MemoizedSelector, select, Store } from '@ngrx/store';
|
import { createSelector, MemoizedSelector, select, Store } from '@ngrx/store';
|
||||||
import { isEqual } from 'lodash';
|
import { isEqual } from 'lodash';
|
||||||
|
|
||||||
import { AddParameterAction, SetParameterAction, SetParametersAction, SetQueryParametersAction } from './route.actions';
|
import { AddParameterAction, SetParameterAction, SetParametersAction, SetQueryParameterAction, SetQueryParametersAction } from './route.actions';
|
||||||
import { CoreState } from '../core.reducers';
|
import { CoreState } from '../core.reducers';
|
||||||
import { coreSelector } from '../core.selectors';
|
import { coreSelector } from '../core.selectors';
|
||||||
import { hasValue } from '../../shared/empty.util';
|
import { hasValue } from '../../shared/empty.util';
|
||||||
@@ -194,6 +194,10 @@ export class RouteService {
|
|||||||
this.store.dispatch(new SetParameterAction(key, value));
|
this.store.dispatch(new SetParameterAction(key, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public setQueryParameter(key, value) {
|
||||||
|
this.store.dispatch(new SetQueryParameterAction(key, value));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the current route parameters and query parameters in the store
|
* Sets the current route parameters and query parameters in the store
|
||||||
*/
|
*/
|
||||||
|
@@ -10,4 +10,5 @@ export enum Context {
|
|||||||
Workspace = 'workspace',
|
Workspace = 'workspace',
|
||||||
AdminMenu = 'adminMenu',
|
AdminMenu = 'adminMenu',
|
||||||
SubmissionModal = 'submissionModal',
|
SubmissionModal = 'submissionModal',
|
||||||
|
AdminSearch = 'adminSearch',
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,10 @@
|
|||||||
<ds-truncatable [id]="dso.id">
|
|
||||||
<div class="card" [@focusShadow]="(isCollapsed$ | async)?'blur':'focus'">
|
<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">
|
<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>
|
<div>
|
||||||
<ds-grid-thumbnail [thumbnail]="getThumbnail() | async">
|
<ds-grid-thumbnail [thumbnail]="getThumbnail() | async">
|
||||||
</ds-grid-thumbnail>
|
</ds-grid-thumbnail>
|
||||||
@@ -17,7 +21,8 @@
|
|||||||
<ds-truncatable-part [id]="dso.id" [minLines]="3" type="h4">
|
<ds-truncatable-part [id]="dso.id" [minLines]="3" type="h4">
|
||||||
<h4 class="card-title" [innerHTML]="firstMetadataValue('dc.title')"></h4>
|
<h4 class="card-title" [innerHTML]="firstMetadataValue('dc.title')"></h4>
|
||||||
</ds-truncatable-part>
|
</ds-truncatable-part>
|
||||||
<p *ngIf="dso.hasMetadata('creativework.datePublished')" class="item-date card-text text-muted">
|
<p *ngIf="dso.hasMetadata('creativework.datePublished')"
|
||||||
|
class="item-date card-text text-muted">
|
||||||
<ds-truncatable-part [id]="dso.id" [minLines]="1">
|
<ds-truncatable-part [id]="dso.id" [minLines]="1">
|
||||||
<span [innerHTML]="firstMetadataValue('creativework.datePublished')"></span>
|
<span [innerHTML]="firstMetadataValue('creativework.datePublished')"></span>
|
||||||
</ds-truncatable-part>
|
</ds-truncatable-part>
|
||||||
@@ -28,9 +33,11 @@
|
|||||||
</ds-truncatable-part>
|
</ds-truncatable-part>
|
||||||
</p>
|
</p>
|
||||||
<div *ngIf="linkType != linkTypes.None" class="text-center">
|
<div *ngIf="linkType != linkTypes.None" class="text-center">
|
||||||
<a [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
<a [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'"
|
||||||
|
rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||||
class="lead btn btn-primary viewButton">View</a>
|
class="lead btn btn-primary viewButton">View</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</ds-truncatable>
|
</ds-truncatable>
|
||||||
|
<ng-content></ng-content>
|
||||||
|
</div>
|
||||||
|
@@ -1,6 +1,10 @@
|
|||||||
<ds-truncatable [id]="dso.id">
|
|
||||||
<div class="card" [@focusShadow]="(isCollapsed$ | async)?'blur':'focus'">
|
<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">
|
<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>
|
<div>
|
||||||
<ds-grid-thumbnail [thumbnail]="getThumbnail() | async">
|
<ds-grid-thumbnail [thumbnail]="getThumbnail() | async">
|
||||||
</ds-grid-thumbnail>
|
</ds-grid-thumbnail>
|
||||||
@@ -17,7 +21,8 @@
|
|||||||
<ds-truncatable-part [id]="dso.id" [minLines]="3" type="h4">
|
<ds-truncatable-part [id]="dso.id" [minLines]="3" type="h4">
|
||||||
<h4 class="card-title" [innerHTML]="dso.firstMetadataValue('dc.title')"></h4>
|
<h4 class="card-title" [innerHTML]="dso.firstMetadataValue('dc.title')"></h4>
|
||||||
</ds-truncatable-part>
|
</ds-truncatable-part>
|
||||||
<p *ngIf="dso.hasMetadata('creativework.datePublished')" class="item-date card-text text-muted">
|
<p *ngIf="dso.hasMetadata('creativework.datePublished')"
|
||||||
|
class="item-date card-text text-muted">
|
||||||
<ds-truncatable-part [id]="dso.id" [minLines]="1">
|
<ds-truncatable-part [id]="dso.id" [minLines]="1">
|
||||||
<span [innerHTML]="firstMetadataValue('creativework.datePublished')"></span>
|
<span [innerHTML]="firstMetadataValue('creativework.datePublished')"></span>
|
||||||
</ds-truncatable-part>
|
</ds-truncatable-part>
|
||||||
@@ -28,9 +33,11 @@
|
|||||||
</ds-truncatable-part>
|
</ds-truncatable-part>
|
||||||
</p>
|
</p>
|
||||||
<div *ngIf="linkType != linkTypes.None" class="text-center">
|
<div *ngIf="linkType != linkTypes.None" class="text-center">
|
||||||
<a [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
<a [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'"
|
||||||
|
rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||||
class="lead btn btn-primary viewButton">View</a>
|
class="lead btn btn-primary viewButton">View</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</ds-truncatable>
|
</ds-truncatable>
|
||||||
|
<ng-content></ng-content>
|
||||||
|
</div>
|
||||||
|
@@ -1,6 +1,10 @@
|
|||||||
<ds-truncatable [id]="dso.id">
|
|
||||||
<div class="card" [@focusShadow]="(isCollapsed$ | async)?'blur':'focus'">
|
<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">
|
<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>
|
<div>
|
||||||
<ds-grid-thumbnail [thumbnail]="getThumbnail() | async">
|
<ds-grid-thumbnail [thumbnail]="getThumbnail() | async">
|
||||||
</ds-grid-thumbnail>
|
</ds-grid-thumbnail>
|
||||||
@@ -33,9 +37,11 @@
|
|||||||
</ds-truncatable-part>
|
</ds-truncatable-part>
|
||||||
</p>
|
</p>
|
||||||
<div *ngIf="linkType != linkTypes.None" class="text-center">
|
<div *ngIf="linkType != linkTypes.None" class="text-center">
|
||||||
<a [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
<a [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'"
|
||||||
|
rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||||
class="lead btn btn-primary viewButton">View</a>
|
class="lead btn btn-primary viewButton">View</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</ds-truncatable>
|
</ds-truncatable>
|
||||||
|
<ng-content></ng-content>
|
||||||
|
</div>
|
||||||
|
@@ -1,6 +1,10 @@
|
|||||||
<ds-truncatable [id]="dso.id">
|
|
||||||
<div class="card" [@focusShadow]="(isCollapsed$ | async)?'blur':'focus'">
|
<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">
|
<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>
|
<div>
|
||||||
<ds-grid-thumbnail [thumbnail]="getThumbnail() | async">
|
<ds-grid-thumbnail [thumbnail]="getThumbnail() | async">
|
||||||
</ds-grid-thumbnail>
|
</ds-grid-thumbnail>
|
||||||
@@ -17,7 +21,8 @@
|
|||||||
<ds-truncatable-part [id]="dso.id" [minLines]="3" type="h4">
|
<ds-truncatable-part [id]="dso.id" [minLines]="3" type="h4">
|
||||||
<h4 class="card-title" [innerHTML]="firstMetadataValue('organization.legalName')"></h4>
|
<h4 class="card-title" [innerHTML]="firstMetadataValue('organization.legalName')"></h4>
|
||||||
</ds-truncatable-part>
|
</ds-truncatable-part>
|
||||||
<p *ngIf="dso.hasMetadata('organization.foundingDate')" class="item-date card-text text-muted">
|
<p *ngIf="dso.hasMetadata('organization.foundingDate')"
|
||||||
|
class="item-date card-text text-muted">
|
||||||
<ds-truncatable-part [id]="dso.id" [minLines]="1">
|
<ds-truncatable-part [id]="dso.id" [minLines]="1">
|
||||||
<span [innerHTML]="firstMetadataValue('organization.foundingDate')"></span>
|
<span [innerHTML]="firstMetadataValue('organization.foundingDate')"></span>
|
||||||
</ds-truncatable-part>
|
</ds-truncatable-part>
|
||||||
@@ -25,7 +30,8 @@
|
|||||||
<p *ngIf="dso.hasMetadata('organization.address.addressCountry')"
|
<p *ngIf="dso.hasMetadata('organization.address.addressCountry')"
|
||||||
class="item-location card-text">
|
class="item-location card-text">
|
||||||
<ds-truncatable-part [id]="dso.id" [minLines]="3">
|
<ds-truncatable-part [id]="dso.id" [minLines]="3">
|
||||||
<span class="item-country">{{firstMetadataValue('organization.address.addressCountry')}}</span>
|
<span
|
||||||
|
class="item-country">{{firstMetadataValue('organization.address.addressCountry')}}</span>
|
||||||
<span *ngIf="dso.hasMetadata('organization.address.addressLocality')" class="item-city">
|
<span *ngIf="dso.hasMetadata('organization.address.addressLocality')" class="item-city">
|
||||||
<span>, </span>
|
<span>, </span>
|
||||||
{{firstMetadataValue('organization.address.addressLocality')}}
|
{{firstMetadataValue('organization.address.addressLocality')}}
|
||||||
@@ -33,9 +39,11 @@
|
|||||||
</ds-truncatable-part>
|
</ds-truncatable-part>
|
||||||
</p>
|
</p>
|
||||||
<div *ngIf="linkType != linkTypes.None" class="text-center">
|
<div *ngIf="linkType != linkTypes.None" class="text-center">
|
||||||
<a [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
<a [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'"
|
||||||
|
rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||||
class="lead btn btn-primary viewButton">View</a>
|
class="lead btn btn-primary viewButton">View</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</ds-truncatable>
|
</ds-truncatable>
|
||||||
|
<ng-content></ng-content>
|
||||||
|
</div>
|
||||||
|
@@ -1,6 +1,9 @@
|
|||||||
<ds-truncatable [id]="dso.id">
|
|
||||||
<div class="card" [@focusShadow]="(isCollapsed$ | async)?'blur':'focus'">
|
<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]"
|
<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">
|
class="card-img-top full-width">
|
||||||
<div>
|
<div>
|
||||||
<ds-grid-thumbnail [thumbnail]="getThumbnail() | async">
|
<ds-grid-thumbnail [thumbnail]="getThumbnail() | async">
|
||||||
@@ -16,7 +19,8 @@
|
|||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<ds-item-type-badge [object]="dso"></ds-item-type-badge>
|
<ds-item-type-badge [object]="dso"></ds-item-type-badge>
|
||||||
<ds-truncatable-part [id]="dso.id" [minLines]="3" type="h4">
|
<ds-truncatable-part [id]="dso.id" [minLines]="3" type="h4">
|
||||||
<h4 class="card-title" [innerHTML]="firstMetadataValue('person.familyName') + ', ' + firstMetadataValue('person.givenName')"></h4>
|
<h4 class="card-title"
|
||||||
|
[innerHTML]="firstMetadataValue('person.familyName') + ', ' + firstMetadataValue('person.givenName')"></h4>
|
||||||
</ds-truncatable-part>
|
</ds-truncatable-part>
|
||||||
<p *ngIf="dso.hasMetadata('person.email')" class="item-email card-text text-muted">
|
<p *ngIf="dso.hasMetadata('person.email')" class="item-email card-text text-muted">
|
||||||
<ds-truncatable-part [id]="dso.id" [minLines]="1">
|
<ds-truncatable-part [id]="dso.id" [minLines]="1">
|
||||||
@@ -29,9 +33,11 @@
|
|||||||
</ds-truncatable-part>
|
</ds-truncatable-part>
|
||||||
</p>
|
</p>
|
||||||
<div *ngIf="linkType != linkTypes.None" class="text-center">
|
<div *ngIf="linkType != linkTypes.None" class="text-center">
|
||||||
<a [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
<a [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'"
|
||||||
|
rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||||
class="lead btn btn-primary viewButton">View</a>
|
class="lead btn btn-primary viewButton">View</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</ds-truncatable>
|
</ds-truncatable>
|
||||||
|
<ng-content></ng-content>
|
||||||
|
</div>
|
||||||
|
@@ -1,6 +1,10 @@
|
|||||||
<ds-truncatable [id]="dso.id">
|
|
||||||
<div class="card" [@focusShadow]="(isCollapsed$ | async)?'blur':'focus'">
|
<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">
|
<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>
|
<div>
|
||||||
<ds-grid-thumbnail [thumbnail]="getThumbnail() | async">
|
<ds-grid-thumbnail [thumbnail]="getThumbnail() | async">
|
||||||
</ds-grid-thumbnail>
|
</ds-grid-thumbnail>
|
||||||
@@ -23,9 +27,11 @@
|
|||||||
</ds-truncatable-part>
|
</ds-truncatable-part>
|
||||||
</p>
|
</p>
|
||||||
<div *ngIf="linkType != linkTypes.None" class="text-center">
|
<div *ngIf="linkType != linkTypes.None" class="text-center">
|
||||||
<a [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
<a [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'"
|
||||||
|
rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||||
class="lead btn btn-primary viewButton">View</a>
|
class="lead btn btn-primary viewButton">View</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</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 { Component, Input } from '@angular/core';
|
||||||
import { ListableObject } from '../listable-object.model';
|
import { ListableObject } from '../listable-object.model';
|
||||||
import { CollectionElementLinkType } from '../../collection-element-link.type';
|
import { CollectionElementLinkType } from '../../collection-element-link.type';
|
||||||
|
import { Context } from '../../../../core/shared/context.model';
|
||||||
|
import { ViewMode } from '../../../../core/shared/view-mode.model';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-abstract-object-element',
|
selector: 'ds-abstract-object-element',
|
||||||
@@ -22,8 +24,23 @@ export class AbstractListableElementComponent<T extends ListableObject> {
|
|||||||
*/
|
*/
|
||||||
@Input() listID: string;
|
@Input() listID: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The index of this element
|
||||||
|
*/
|
||||||
|
@Input() index: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The available link types
|
* The available link types
|
||||||
*/
|
*/
|
||||||
linkTypes = CollectionElementLinkType;
|
linkTypes = CollectionElementLinkType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The available view modes
|
||||||
|
*/
|
||||||
|
viewModes = ViewMode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The available contexts
|
||||||
|
*/
|
||||||
|
contexts = Context;
|
||||||
}
|
}
|
||||||
|
@@ -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>
|
<a [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer" [routerLink]="['/collections/', dso.id]" class="lead btn btn-primary viewButton">View</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<ng-content></ng-content>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -6,6 +6,7 @@ import { Store } from '@ngrx/store';
|
|||||||
import { of as observableOf } from 'rxjs';
|
import { of as observableOf } from 'rxjs';
|
||||||
import { RemoteDataBuildService } from '../../../../core/cache/builders/remote-data-build.service';
|
import { RemoteDataBuildService } from '../../../../core/cache/builders/remote-data-build.service';
|
||||||
import { ObjectCacheService } from '../../../../core/cache/object-cache.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 { CommunityDataService } from '../../../../core/data/community-data.service';
|
||||||
import { DefaultChangeAnalyzer } from '../../../../core/data/default-change-analyzer.service';
|
import { DefaultChangeAnalyzer } from '../../../../core/data/default-change-analyzer.service';
|
||||||
import { DSOChangeAnalyzer } from '../../../../core/data/dso-change-analyzer.service';
|
import { DSOChangeAnalyzer } from '../../../../core/data/dso-change-analyzer.service';
|
||||||
@@ -62,6 +63,7 @@ describe('CollectionSearchResultGridElementComponent', () => {
|
|||||||
{ provide: UUIDService, useValue: {} },
|
{ provide: UUIDService, useValue: {} },
|
||||||
{ provide: Store, useValue: {} },
|
{ provide: Store, useValue: {} },
|
||||||
{ provide: RemoteDataBuildService, useValue: {} },
|
{ provide: RemoteDataBuildService, useValue: {} },
|
||||||
|
{ provide: BitstreamDataService, useValue: {} },
|
||||||
{ provide: CommunityDataService, useValue: {} },
|
{ provide: CommunityDataService, useValue: {} },
|
||||||
{ provide: HALEndpointService, useValue: {} },
|
{ provide: HALEndpointService, useValue: {} },
|
||||||
{ provide: NotificationsService, useValue: {} },
|
{ provide: NotificationsService, useValue: {} },
|
||||||
|
@@ -14,4 +14,5 @@
|
|||||||
<a [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer" [routerLink]="['/communities/', dso.id]" class="lead btn btn-primary viewButton">View</a>
|
<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>
|
</div>
|
||||||
|
<ng-content></ng-content>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -6,6 +6,7 @@ import { Store } from '@ngrx/store';
|
|||||||
import { of as observableOf } from 'rxjs';
|
import { of as observableOf } from 'rxjs';
|
||||||
import { RemoteDataBuildService } from '../../../../core/cache/builders/remote-data-build.service';
|
import { RemoteDataBuildService } from '../../../../core/cache/builders/remote-data-build.service';
|
||||||
import { ObjectCacheService } from '../../../../core/cache/object-cache.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 { CommunityDataService } from '../../../../core/data/community-data.service';
|
||||||
import { DefaultChangeAnalyzer } from '../../../../core/data/default-change-analyzer.service';
|
import { DefaultChangeAnalyzer } from '../../../../core/data/default-change-analyzer.service';
|
||||||
import { DSOChangeAnalyzer } from '../../../../core/data/dso-change-analyzer.service';
|
import { DSOChangeAnalyzer } from '../../../../core/data/dso-change-analyzer.service';
|
||||||
@@ -62,6 +63,7 @@ describe('CommunitySearchResultGridElementComponent', () => {
|
|||||||
{ provide: UUIDService, useValue: {} },
|
{ provide: UUIDService, useValue: {} },
|
||||||
{ provide: Store, useValue: {} },
|
{ provide: Store, useValue: {} },
|
||||||
{ provide: RemoteDataBuildService, useValue: {} },
|
{ provide: RemoteDataBuildService, useValue: {} },
|
||||||
|
{ provide: BitstreamDataService, useValue: {} },
|
||||||
{ provide: CommunityDataService, useValue: {} },
|
{ provide: CommunityDataService, useValue: {} },
|
||||||
{ provide: HALEndpointService, useValue: {} },
|
{ provide: HALEndpointService, useValue: {} },
|
||||||
{ provide: NotificationsService, useValue: {} },
|
{ provide: NotificationsService, useValue: {} },
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
<ds-truncatable [id]="dso.id">
|
|
||||||
<div class="card" [@focusShadow]="(isCollapsed$ | async)?'blur':'focus'">
|
<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]"
|
<a *ngIf="linkType != linkTypes.None" [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||||
class="card-img-top full-width">
|
class="card-img-top full-width">
|
||||||
<div>
|
<div>
|
||||||
@@ -37,5 +38,7 @@
|
|||||||
class="lead btn btn-primary viewButton">View</a>
|
class="lead btn btn-primary viewButton">View</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</ds-truncatable>
|
</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';
|
import { ItemSearchResult } from '../../../../object-collection/shared/item-search-result.model';
|
||||||
|
|
||||||
@listableObjectComponent('PublicationSearchResult', ViewMode.GridElement)
|
@listableObjectComponent('PublicationSearchResult', ViewMode.GridElement)
|
||||||
|
@listableObjectComponent(ItemSearchResult, ViewMode.GridElement)
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-publication-search-result-grid-element',
|
selector: 'ds-publication-search-result-grid-element',
|
||||||
styleUrls: ['./publication-search-result-grid-element.component.scss'],
|
styleUrls: ['./publication-search-result-grid-element.component.scss'],
|
||||||
|
@@ -27,9 +27,9 @@ describe('PaginatedSearchOptions', () => {
|
|||||||
'query=search query&' +
|
'query=search query&' +
|
||||||
'scope=0fde1ecb-82cc-425a-b600-ac3576d76b47&' +
|
'scope=0fde1ecb-82cc-425a-b600-ac3576d76b47&' +
|
||||||
'dsoType=ITEM&' +
|
'dsoType=ITEM&' +
|
||||||
'f.test=value,query&' +
|
'f.test=value&' +
|
||||||
'f.example=another value,query&' +
|
'f.example=another value&' +
|
||||||
'f.example=second value,query'
|
'f.example=second value'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Represents a search filter
|
* Represents a search filter
|
||||||
*/
|
*/
|
||||||
import { hasValue } from '../empty.util';
|
|
||||||
|
|
||||||
export class SearchFilter {
|
export class SearchFilter {
|
||||||
key: string;
|
key: string;
|
||||||
@@ -11,10 +10,6 @@ export class SearchFilter {
|
|||||||
constructor(key: string, values: string[], operator?: string) {
|
constructor(key: string, values: string[], operator?: string) {
|
||||||
this.key = key;
|
this.key = key;
|
||||||
this.values = values;
|
this.values = values;
|
||||||
if (hasValue(operator)) {
|
|
||||||
this.operator = operator;
|
this.operator = operator;
|
||||||
} else {
|
|
||||||
this.operator = 'query';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,9 @@
|
|||||||
[routerLink]="[searchLink]"
|
[routerLink]="[searchLink]"
|
||||||
[queryParams]="addQueryParams" queryParamsHandling="merge">
|
[queryParams]="addQueryParams" queryParamsHandling="merge">
|
||||||
<input type="checkbox" [checked]="false" class="my-1 align-self-stretch"/>
|
<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="float-right filter-value-count ml-auto">
|
||||||
<span class="badge badge-secondary badge-pill">{{filterValue.count}}</span>
|
<span class="badge badge-secondary badge-pill">{{filterValue.count}}</span>
|
||||||
</span>
|
</span>
|
||||||
|
@@ -2,5 +2,7 @@
|
|||||||
[routerLink]="[searchLink]"
|
[routerLink]="[searchLink]"
|
||||||
[queryParams]="removeQueryParams" queryParamsHandling="merge">
|
[queryParams]="removeQueryParams" queryParamsHandling="merge">
|
||||||
<input type="checkbox" [checked]="true" class="my-1 align-self-stretch"/>
|
<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>
|
</a>
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
<a class="badge badge-primary mr-1 mb-1 text-capitalize"
|
<a class="badge badge-primary mr-1 mb-1 text-capitalize"
|
||||||
[routerLink]="searchLink"
|
[routerLink]="searchLink"
|
||||||
[queryParams]="(removeParameters | async)" queryParamsHandling="merge">
|
[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>
|
<span> ×</span>
|
||||||
</a>
|
</a>
|
@@ -22,6 +22,11 @@ export class SearchLabelComponent implements OnInit {
|
|||||||
searchLink: string;
|
searchLink: string;
|
||||||
removeParameters: Observable<Params>;
|
removeParameters: Observable<Params>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the filter without the f. prefix
|
||||||
|
*/
|
||||||
|
filterName: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the instance variable
|
* Initialize the instance variable
|
||||||
*/
|
*/
|
||||||
@@ -33,6 +38,7 @@ export class SearchLabelComponent implements OnInit {
|
|||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.searchLink = this.getSearchLink();
|
this.searchLink = this.getSearchLink();
|
||||||
this.removeParameters = this.getRemoveParams();
|
this.removeParameters = this.getRemoveParams();
|
||||||
|
this.filterName = this.getFilterName();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -74,4 +80,8 @@ export class SearchLabelComponent implements OnInit {
|
|||||||
const pattern = /,authority*$/g;
|
const pattern = /,authority*$/g;
|
||||||
return value.replace(pattern, '');
|
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&' +
|
'query=search query&' +
|
||||||
'scope=0fde1ecb-82cc-425a-b600-ac3576d76b47&' +
|
'scope=0fde1ecb-82cc-425a-b600-ac3576d76b47&' +
|
||||||
'dsoType=ITEM&' +
|
'dsoType=ITEM&' +
|
||||||
'f.test=value,query&' +
|
'f.test=value&' +
|
||||||
'f.example=another value,query&' +
|
'f.example=another value&' +
|
||||||
'f.example=second value,query'
|
'f.example=second value'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -50,7 +50,7 @@ export class SearchOptions {
|
|||||||
if (isNotEmpty(this.filters)) {
|
if (isNotEmpty(this.filters)) {
|
||||||
this.filters.forEach((filter: SearchFilter) => {
|
this.filters.forEach((filter: SearchFilter) => {
|
||||||
filter.values.forEach((value) => {
|
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}`)
|
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 { 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 { NgxPaginationModule } from 'ngx-pagination';
|
||||||
import { PublicationListElementComponent } from './object-list/item-list-element/item-types/publication/publication-list-element.component';
|
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 { DragDropModule } from '@angular/cdk/drag-drop';
|
||||||
import { ExistingMetadataListElementComponent } from './form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component';
|
import { ExistingMetadataListElementComponent } from './form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component';
|
||||||
import { SortablejsModule } from 'ngx-sortablejs';
|
import { SortablejsModule } from 'ngx-sortablejs';
|
||||||
|
import { MissingTranslationHelper } from './translate/missing-translation.helper';
|
||||||
|
|
||||||
const MODULES = [
|
const MODULES = [
|
||||||
// Do NOT include UniversalModule, HttpModule, or JsonpModule here
|
// Do NOT include UniversalModule, HttpModule, or JsonpModule here
|
||||||
@@ -194,7 +195,6 @@ const MODULES = [
|
|||||||
NgxPaginationModule,
|
NgxPaginationModule,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
RouterModule,
|
RouterModule,
|
||||||
TranslateModule,
|
|
||||||
NouisliderModule,
|
NouisliderModule,
|
||||||
MomentModule,
|
MomentModule,
|
||||||
TextMaskModule,
|
TextMaskModule,
|
||||||
@@ -203,7 +203,11 @@ const MODULES = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
const ROOT_MODULES = [
|
const ROOT_MODULES = [
|
||||||
TooltipModule.forRoot()
|
TranslateModule.forChild({
|
||||||
|
missingTranslationHandler: { provide: MissingTranslationHandler, useClass: MissingTranslationHelper },
|
||||||
|
useDefaultLang: true
|
||||||
|
}),
|
||||||
|
TooltipModule.forRoot(),
|
||||||
];
|
];
|
||||||
|
|
||||||
const PIPES = [
|
const PIPES = [
|
||||||
@@ -339,7 +343,8 @@ const COMPONENTS = [
|
|||||||
SelectableListItemControlComponent,
|
SelectableListItemControlComponent,
|
||||||
ExternalSourceEntryImportModalComponent,
|
ExternalSourceEntryImportModalComponent,
|
||||||
ImportableListItemControlComponent,
|
ImportableListItemControlComponent,
|
||||||
ExistingMetadataListElementComponent
|
ExistingMetadataListElementComponent,
|
||||||
|
PublicationSearchResultListElementComponent,
|
||||||
];
|
];
|
||||||
|
|
||||||
const ENTRY_COMPONENTS = [
|
const ENTRY_COMPONENTS = [
|
||||||
@@ -402,7 +407,7 @@ const ENTRY_COMPONENTS = [
|
|||||||
DsDynamicLookupRelationSearchTabComponent,
|
DsDynamicLookupRelationSearchTabComponent,
|
||||||
DsDynamicLookupRelationSelectionTabComponent,
|
DsDynamicLookupRelationSelectionTabComponent,
|
||||||
DsDynamicLookupRelationExternalSourceTabComponent,
|
DsDynamicLookupRelationExternalSourceTabComponent,
|
||||||
ExternalSourceEntryImportModalComponent
|
ExternalSourceEntryImportModalComponent,
|
||||||
];
|
];
|
||||||
|
|
||||||
const SHARED_ITEM_PAGE_COMPONENTS = [
|
const SHARED_ITEM_PAGE_COMPONENTS = [
|
||||||
@@ -435,8 +440,8 @@ const DIRECTIVES = [
|
|||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
|
...ROOT_MODULES,
|
||||||
...MODULES,
|
...MODULES,
|
||||||
...ROOT_MODULES
|
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
...PIPES,
|
...PIPES,
|
||||||
@@ -444,8 +449,7 @@ const DIRECTIVES = [
|
|||||||
...DIRECTIVES,
|
...DIRECTIVES,
|
||||||
...ENTRY_COMPONENTS,
|
...ENTRY_COMPONENTS,
|
||||||
...SHARED_ITEM_PAGE_COMPONENTS,
|
...SHARED_ITEM_PAGE_COMPONENTS,
|
||||||
PublicationSearchResultListElementComponent,
|
|
||||||
ExistingMetadataListElementComponent
|
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
...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 { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
import { of as observableOf } from 'rxjs';
|
import { of as observableOf } from 'rxjs';
|
||||||
|
import { mockTruncatableService } from '../mocks/mock-trucatable.service';
|
||||||
import { TruncatableComponent } from './truncatable.component';
|
import { TruncatableComponent } from './truncatable.component';
|
||||||
import { TruncatableService } from './truncatable.service';
|
import { TruncatableService } from './truncatable.service';
|
||||||
import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core';
|
import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
@@ -10,29 +11,12 @@ describe('TruncatableComponent', () => {
|
|||||||
let fixture: ComponentFixture<TruncatableComponent>;
|
let fixture: ComponentFixture<TruncatableComponent>;
|
||||||
const identifier = '1234567890';
|
const identifier = '1234567890';
|
||||||
let truncatableService;
|
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(() => {
|
beforeEach(async(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [NoopAnimationsModule],
|
imports: [NoopAnimationsModule],
|
||||||
declarations: [TruncatableComponent],
|
declarations: [TruncatableComponent],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: TruncatableService, useValue: truncatableServiceStub },
|
{ provide: TruncatableService, useValue: mockTruncatableService },
|
||||||
],
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
}).overrideComponent(TruncatableComponent, {
|
}).overrideComponent(TruncatableComponent, {
|
||||||
|
Reference in New Issue
Block a user