mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-13 13:03:04 +00:00
#150 Intermediate commit
This commit is contained in:
@@ -71,18 +71,27 @@ export class SearchPageComponent implements OnInit, OnDestroy {
|
|||||||
this.query = params.query || '';
|
this.query = params.query || '';
|
||||||
this.scope = params.scope;
|
this.scope = params.scope;
|
||||||
const page = +params.page || this.searchOptions.pagination.currentPage;
|
const page = +params.page || this.searchOptions.pagination.currentPage;
|
||||||
const pageSize = +params.pageSize || this.searchOptions.pagination.pageSize;
|
let pageSize = +params.pageSize || this.searchOptions.pagination.pageSize;
|
||||||
|
let pageSizeOptions: number[] = [5, 10, 20, 40, 60, 80, 100];
|
||||||
|
|
||||||
|
if (isNotEmpty(params.view) && params.view === ViewMode.Grid) {
|
||||||
|
pageSize = 12;
|
||||||
|
pageSizeOptions = [12, 24, 36, 48 , 50, 62, 74, 84];
|
||||||
|
// pageSize = 9;
|
||||||
|
// pageSizeOptions = [9, 18, 27, 36 , 45, 54, 63, 72];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const sortDirection = +params.sortDirection || this.searchOptions.sort.direction;
|
const sortDirection = +params.sortDirection || this.searchOptions.sort.direction;
|
||||||
const pagination = Object.assign({},
|
const pagination = Object.assign({},
|
||||||
this.searchOptions.pagination,
|
this.searchOptions.pagination,
|
||||||
{ currentPage: page, pageSize: pageSize }
|
{ currentPage: page, pageSize: pageSize, pageSizeOptions: pageSizeOptions}
|
||||||
);
|
);
|
||||||
const sort = Object.assign({},
|
const sort = Object.assign({},
|
||||||
this.searchOptions.sort,
|
this.searchOptions.sort,
|
||||||
{ direction: sortDirection, field: params.sortField }
|
{ direction: sortDirection, field: params.sortField }
|
||||||
);
|
);
|
||||||
|
|
||||||
this.updateSearchResults({
|
this.updateSearchResults({
|
||||||
pagination: pagination,
|
pagination: pagination,
|
||||||
sort: sort
|
sort: sort
|
||||||
@@ -98,6 +107,7 @@ export class SearchPageComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
private updateSearchResults(searchOptions) {
|
private updateSearchResults(searchOptions) {
|
||||||
this.resultsRDObs = this.service.search(this.query, this.scope, searchOptions);
|
this.resultsRDObs = this.service.search(this.query, this.scope, searchOptions);
|
||||||
|
this.searchOptions = searchOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
|
@@ -1,6 +1,9 @@
|
|||||||
|
@import '../../styles/custom_variables';
|
||||||
|
|
||||||
.card-title{
|
.card-title{
|
||||||
line-height: 1em;
|
line-height: $line-height-base;
|
||||||
height:3em;
|
height:$headings-line-height;
|
||||||
|
font-size:$headings-font-size;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
@@ -8,29 +11,35 @@
|
|||||||
.card-text {
|
.card-text {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
line-height: 1em;
|
line-height: $line-height-base;
|
||||||
margin-bottom:10px;
|
margin-bottom:$card-block-margin-base*2;
|
||||||
}
|
}
|
||||||
.card-text.item-authors {
|
.card-text.item-authors {
|
||||||
height: 1em;
|
height: $line-height-base;
|
||||||
}
|
}
|
||||||
.card-text.item-abstract {
|
.card-text.item-abstract {
|
||||||
height: 5em;
|
height: $content-line-height;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.viewButton{
|
.viewButton{
|
||||||
display:block;
|
display:table;
|
||||||
|
margin:auto;
|
||||||
|
width: $card-button-width;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card{
|
.card{
|
||||||
padding:10px;
|
margin-bottom: $card-block-margin-base *3;
|
||||||
margin-bottom: 15px;
|
height: 98%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-img-top ::ng-deep img
|
.card-img-top ::ng-deep img
|
||||||
{
|
{
|
||||||
height: 120px;
|
height: $card-thumbnail-height;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.card-block{
|
||||||
|
margin: $card-block-margin-base;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -0,0 +1,4 @@
|
|||||||
|
<div class="thumbnail">
|
||||||
|
<img *ngIf="thumbnail" [src]="thumbnail.content" (error)="errorHandler($event)"/>
|
||||||
|
<img *ngIf="!thumbnail" [src]="holderSource | dsSafeUrl"/>
|
||||||
|
</div>
|
@@ -0,0 +1 @@
|
|||||||
|
@import '../../../styles/variables.scss';
|
@@ -0,0 +1,42 @@
|
|||||||
|
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||||
|
import { By } from '@angular/platform-browser';
|
||||||
|
import { DebugElement } from '@angular/core';
|
||||||
|
|
||||||
|
import { ThumbnailComponent } from './thumbnail.component';
|
||||||
|
import { Bitstream } from '../../core/shared/bitstream.model';
|
||||||
|
import { SafeUrlPipe } from '../../shared/utils/safe-url-pipe';
|
||||||
|
|
||||||
|
describe('ThumbnailComponent', () => {
|
||||||
|
let comp: ThumbnailComponent;
|
||||||
|
let fixture: ComponentFixture<ThumbnailComponent>;
|
||||||
|
let de: DebugElement;
|
||||||
|
let el: HTMLElement;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ThumbnailComponent, SafeUrlPipe]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(ThumbnailComponent);
|
||||||
|
comp = fixture.componentInstance; // BannerComponent test instance
|
||||||
|
de = fixture.debugElement.query(By.css('div.thumbnail'));
|
||||||
|
el = de.nativeElement;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display image', () => {
|
||||||
|
comp.thumbnail = new Bitstream();
|
||||||
|
comp.thumbnail.content = 'test.url';
|
||||||
|
fixture.detectChanges();
|
||||||
|
const image: HTMLElement = de.query(By.css('img')).nativeElement;
|
||||||
|
expect(image.getAttribute('src')).toBe(comp.thumbnail.content);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display placeholder', () => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
const image: HTMLElement = de.query(By.css('img')).nativeElement;
|
||||||
|
expect(image.getAttribute('src')).toBe(comp.holderSource);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@@ -0,0 +1,30 @@
|
|||||||
|
import { Component, Input } from '@angular/core';
|
||||||
|
import { Bitstream } from '../../core/shared/bitstream.model';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This component renders a given Bitstream as a thumbnail.
|
||||||
|
* One input parameter of type Bitstream is expected.
|
||||||
|
* If no Bitstream is provided, a holderjs image will be rendered instead.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ds-grid-thumbnail',
|
||||||
|
styleUrls: ['./grid-thumbnail.component.scss'],
|
||||||
|
templateUrl: './grid-thumbnail.component.html'
|
||||||
|
})
|
||||||
|
export class GridThumbnailComponent {
|
||||||
|
|
||||||
|
@Input() thumbnail: Bitstream;
|
||||||
|
|
||||||
|
data: any = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default 'holder.js' image
|
||||||
|
*/
|
||||||
|
holderSource = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9InllcyI/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMjYwIiBoZWlnaHQ9IjE4MCIgdmlld0JveD0iMCAwIDI2MCAxODAiIHByZXNlcnZlQXNwZWN0UmF0aW89Im5vbmUiPjwhLS0KU291cmNlIFVSTDogaG9sZGVyLmpzLzEwMCV4MTgwL3RleHQ6Tm8gVGh1bWJuYWlsCkNyZWF0ZWQgd2l0aCBIb2xkZXIuanMgMi42LjAuCkxlYXJuIG1vcmUgYXQgaHR0cDovL2hvbGRlcmpzLmNvbQooYykgMjAxMi0yMDE1IEl2YW4gTWFsb3BpbnNreSAtIGh0dHA6Ly9pbXNreS5jbwotLT48ZGVmcz48c3R5bGUgdHlwZT0idGV4dC9jc3MiPjwhW0NEQVRBWyNob2xkZXJfMTVmNzJmMmFlMGIgdGV4dCB7IGZpbGw6I0FBQUFBQTtmb250LXdlaWdodDpib2xkO2ZvbnQtZmFtaWx5OkFyaWFsLCBIZWx2ZXRpY2EsIE9wZW4gU2Fucywgc2Fucy1zZXJpZiwgbW9ub3NwYWNlO2ZvbnQtc2l6ZToxM3B0IH0gXV0+PC9zdHlsZT48L2RlZnM+PGcgaWQ9ImhvbGRlcl8xNWY3MmYyYWUwYiI+PHJlY3Qgd2lkdGg9IjI2MCIgaGVpZ2h0PSIxODAiIGZpbGw9IiNFRUVFRUUiLz48Zz48dGV4dCB4PSI3Mi4yNDIxODc1IiB5PSI5NiI+Tm8gVGh1bWJuYWlsPC90ZXh0PjwvZz48L2c+PC9zdmc+';
|
||||||
|
|
||||||
|
errorHandler(event) {
|
||||||
|
event.currentTarget.src = this.holderSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -1,17 +1,18 @@
|
|||||||
<div class="card">
|
<div class="card">
|
||||||
|
|
||||||
<a [routerLink]="['/items/' + object.id]" class="card-img-top">
|
<a [routerLink]="['/items/' + object.id]" class="card-img-top">
|
||||||
<ds-thumbnail [thumbnail]="object.getThumbnail()">
|
<ds-grid-thumbnail [thumbnail]="object.getThumbnail()">
|
||||||
</ds-thumbnail>
|
</ds-grid-thumbnail>
|
||||||
</a>
|
</a>
|
||||||
<div class="card-block">
|
<div class="card-block">
|
||||||
<h4 class="card-title">{{object.findMetadata('dc.title')}}</h4>
|
<h4 class="card-title">{{object.findMetadata('dc.title')}}</h4>
|
||||||
<p *ngIf="object.filterMetadata(['dc.contributor.author', 'dc.creator', 'dc.contributor.*']);" class="item-authors card-text">
|
|
||||||
|
<p *ngIf="object.filterMetadata(['dc.contributor.author', 'dc.creator', 'dc.contributor.*']);" class="item-authors card-text text-muted">
|
||||||
<span *ngFor="let authorMd of object.filterMetadata(['dc.contributor.author', 'dc.creator', 'dc.contributor.*']); let last=last;">{{authorMd.value}}
|
<span *ngFor="let authorMd of object.filterMetadata(['dc.contributor.author', 'dc.creator', 'dc.contributor.*']); let last=last;">{{authorMd.value}}
|
||||||
<span *ngIf="!last">; </span>
|
<span *ngIf="!last">; </span>
|
||||||
</span>
|
</span>
|
||||||
|
<span *ngIf="object.findMetadata('dc.date.issued')">{{object.findMetadata("dc.date.issued")}}</span>
|
||||||
</p>
|
</p>
|
||||||
(<span *ngIf="object.findMetadata('dc.publisher')" class="item-list-publisher">{{object.findMetadata("dc.publisher")}}, </span><span *ngIf="object.findMetadata('dc.date.issued')" class="item-list-date">{{object.findMetadata("dc.date.issued")}}</span>)
|
|
||||||
|
|
||||||
<p *ngIf="object.findMetadata('dc.description.abstract')" class="item-abstract card-text">{{object.findMetadata("dc.description.abstract") | dsTruncate:[200] }}</p>
|
<p *ngIf="object.findMetadata('dc.description.abstract')" class="item-abstract card-text">{{object.findMetadata("dc.description.abstract") | dsTruncate:[200] }}</p>
|
||||||
|
|
||||||
|
@@ -10,14 +10,12 @@
|
|||||||
(sortDirectionChange)="onSortDirectionChange($event)"
|
(sortDirectionChange)="onSortDirectionChange($event)"
|
||||||
(sortFieldChange)="onSortDirectionChange($event)"
|
(sortFieldChange)="onSortDirectionChange($event)"
|
||||||
(paginationChange)="onPaginationChange($event)">
|
(paginationChange)="onPaginationChange($event)">
|
||||||
<ul *ngIf="objects.hasSucceeded | async" @fadeIn>
|
<div class="row" *ngIf="objects.hasSucceeded | async" @fadeIn>
|
||||||
<div class="row">
|
|
||||||
<div class="col-lg-4 col-sm-4 col-xs-12 "
|
<div class="col-lg-4 col-sm-4 col-xs-12 "
|
||||||
*ngFor="let object of (objects.payload | async) | paginate: { itemsPerPage: (pageInfo | async)?.elementsPerPage, currentPage: (pageInfo | async)?.currentPage, totalItems: (pageInfo | async)?.totalElements }">
|
*ngFor="let object of (objects.payload | async) | paginate: { itemsPerPage: (pageInfo | async)?.elementsPerPage, currentPage: (pageInfo | async)?.currentPage, totalItems: (pageInfo | async)?.totalElements }">
|
||||||
<ds-wrapper-grid-element [object]="object"></ds-wrapper-grid-element>
|
<ds-wrapper-grid-element [object]="object"></ds-wrapper-grid-element>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ul>
|
|
||||||
<ds-error *ngIf="objects.hasFailed | async" message="{{'error.objects' | translate}}"></ds-error>
|
<ds-error *ngIf="objects.hasFailed | async" message="{{'error.objects' | translate}}"></ds-error>
|
||||||
<ds-loading *ngIf="objects.isLoading | async" message="{{'loading.objects' | translate}}"></ds-loading>
|
<ds-loading *ngIf="objects.isLoading | async" message="{{'loading.objects' | translate}}"></ds-loading>
|
||||||
</ds-pagination>
|
</ds-pagination>
|
||||||
|
@@ -1,24 +1,29 @@
|
|||||||
<div class="card">
|
<div class="card">
|
||||||
<a [routerLink]="['/items/' + dso.id]" class="card-img-top">
|
<a [routerLink]="['/items/' + dso.id]" class="card-img-top">
|
||||||
<ds-thumbnail [thumbnail]="dso.getThumbnail()">
|
<ds-grid-thumbnail [thumbnail]="dso.getThumbnail()">
|
||||||
</ds-thumbnail>
|
</ds-grid-thumbnail>
|
||||||
</a>
|
</a>
|
||||||
<div class="card-block">
|
<div class="card-block">
|
||||||
<h4 class="card-title">{{dso.findMetadata('dc.title')}}</h4>
|
<p class="card-title" [innerHTML]="dso.findMetadata('dc.title')"></p>
|
||||||
|
|
||||||
<p *ngIf="dso.filterMetadata(['dc.contributor.author', 'dc.creator', 'dc.contributor.*']);"
|
<p *ngIf="dso.filterMetadata(['dc.contributor.author', 'dc.creator', 'dc.contributor.*'])"
|
||||||
class="item-authors card-text">
|
class="item-authors card-text text-muted">
|
||||||
<span
|
<span
|
||||||
*ngFor="let authorMd of dso.filterMetadata(['dc.contributor.author', 'dc.creator', 'dc.contributor.*']); let last=last;">{{authorMd.value}}
|
*ngFor="let authorMd of dso.filterMetadata(['dc.contributor.author', 'dc.creator', 'dc.contributor.*']); let first=first;">
|
||||||
<span *ngIf="!last">; </span>
|
<span *ngIf="first" [innerHTML]="authorMd.value">
|
||||||
|
<span
|
||||||
|
*ngIf="dso.filterMetadata(['dc.contributor.author', 'dc.creator', 'dc.contributor.*']).length>1">, ...</span>
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</p>
|
<span *ngIf="dso.findMetadata('dc.date.issued')"
|
||||||
(<span *ngIf="dso.findMetadata('dc.publisher')"
|
class="item-list-date">
|
||||||
class="item-list-publisher">{{dso.findMetadata("dc.publisher")}}, </span><span
|
<span *ngIf="dso.filterMetadata(['dc.contributor.author', 'dc.creator', 'dc.contributor.*']).length>1">,</span>
|
||||||
*ngIf="dso.findMetadata('dc.date.issued')" class="item-list-date">{{dso.findMetadata("dc.date.issued")}}</span>)
|
{{dso.findMetadata("dc.date.issued")}}</span>
|
||||||
|
|
||||||
<p *ngIf="dso.findMetadata('dc.description.abstract')" class="item-abstract card-text">
|
|
||||||
{{dso.findMetadata("dc.description.abstract") | dsTruncate:[200] }}</p>
|
</p>
|
||||||
|
<p class="item-abstract card-text" [innerHTML]="getFirstValue('dc.description.abstract') | dsTruncate:[200]">
|
||||||
|
</p>
|
||||||
|
|
||||||
<a [routerLink]="['/items/' + dso.id]" class="lead btn btn-primary viewButton">View</a>
|
<a [routerLink]="['/items/' + dso.id]" class="lead btn btn-primary viewButton">View</a>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -40,6 +40,7 @@ import { ThumbnailComponent } from '../thumbnail/thumbnail.component';
|
|||||||
import { SearchFormComponent } from './search-form/search-form.component';
|
import { SearchFormComponent } from './search-form/search-form.component';
|
||||||
import { SearchResultGridElementComponent } from '../object-grid/search-result-grid-element/search-result-grid-element.component';
|
import { SearchResultGridElementComponent } from '../object-grid/search-result-grid-element/search-result-grid-element.component';
|
||||||
import { ViewModeSwitchComponent } from './view-mode-switch/view-mode-switch.component';
|
import { ViewModeSwitchComponent } from './view-mode-switch/view-mode-switch.component';
|
||||||
|
import { GridThumbnailComponent } from '../object-grid/grid-thumbnail/grid-thumbnail.component';
|
||||||
import { VarDirective } from './utils/var.directive';
|
import { VarDirective } from './utils/var.directive';
|
||||||
|
|
||||||
const MODULES = [
|
const MODULES = [
|
||||||
@@ -78,6 +79,7 @@ const COMPONENTS = [
|
|||||||
PaginationComponent,
|
PaginationComponent,
|
||||||
SearchFormComponent,
|
SearchFormComponent,
|
||||||
ThumbnailComponent,
|
ThumbnailComponent,
|
||||||
|
GridThumbnailComponent,
|
||||||
WrapperListElementComponent,
|
WrapperListElementComponent,
|
||||||
ViewModeSwitchComponent
|
ViewModeSwitchComponent
|
||||||
];
|
];
|
||||||
|
Reference in New Issue
Block a user