Skip to content
Snippets Groups Projects
Commit c4c29189 authored by Art Lowel's avatar Art Lowel
Browse files

Merge branch 'master' into improve-support-for-hal-links

parents bf172461 dd2b8b76
Branches
Tags
No related merge requests found
Showing
with 117 additions and 129 deletions
......@@ -15,8 +15,6 @@ node_js:
cache:
yarn: true
directories:
- node_modules
bundler_args: --retry 5
......
......@@ -69,5 +69,14 @@
"head": "Communities in DSpace",
"help": "Select a community to browse its collections."
}
},
"search": {
"form": {
"search": "Search",
"search_dspace": "Search DSpace"
},
"results": {
"title": "Search Results"
}
}
}
......@@ -23,4 +23,6 @@ html {
.main-content {
flex: 1 0 auto;
margin-top: $content-spacing;
margin-bottom: $content-spacing;
}
......@@ -20,6 +20,8 @@ import { ItemPageModule } from './item-page/item-page.module';
import { CollectionPageModule } from './collection-page/collection-page.module';
import { CommunityPageModule } from './community-page/community-page.module';
import { SearchPageModule } from './search-page/search-page.module';
import { AppComponent } from './app.component';
import { HeaderComponent } from './header/header.component';
import { PageNotFoundComponent } from './pagenotfound/pagenotfound.component';
......@@ -43,6 +45,7 @@ export function getConfig() {
ItemPageModule,
CollectionPageModule,
CommunityPageModule,
SearchPageModule,
AppRoutingModule,
StoreModule.forRoot(appReducers, { metaReducers: appMetaReducers }),
StoreDevtoolsModule.instrument({ maxAge: 50 }),
......
......@@ -32,13 +32,9 @@
</ds-comcol-page-content>
</div>
<br>
<div *ngIf="itemData.hasSucceeded | async">
<div *ngIf="(itemData.hasSucceeded | async)">
<h2>{{'collection.page.browse.recent.head' | translate}}</h2>
<ds-object-list [config]="config" [sortConfig]="sortConfig"
[objects]="itemData" [hideGear]="true"
(pageChange)="onPageChange($event)"
(pageSizeChange)="onPageSizeChange($event)"
(sortDirectionChange)="onSortDirectionChange($event)"
(sortFieldChange)="onSortDirectionChange($event)"></ds-object-list>
<ds-object-list [config]="paginationConfig" [sortConfig]="sortConfig"
[objects]="itemData" [hideGear]="false"></ds-object-list>
</div>
</div>
......@@ -14,90 +14,81 @@ import { ItemDataService } from '../core/data/item-data.service';
import { Item } from '../core/shared/item.model';
import { SortOptions, SortDirection } from '../core/cache/models/sort-options.model';
import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model';
import { hasValue, isUndefined } from '../shared/empty.util';
import { hasValue, isNotEmpty, isUndefined } from '../shared/empty.util';
import { PageInfo } from '../core/shared/page-info.model';
import { Observable } from 'rxjs/Observable';
@Component({
selector: 'ds-collection-page',
styleUrls: ['./collection-page.component.scss'],
templateUrl: './collection-page.component.html',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class CollectionPageComponent implements OnInit, OnDestroy {
collectionData: RemoteData<Collection>;
itemData: RemoteData<Item[]>;
logoData: RemoteData<Bitstream>;
config: PaginationComponentOptions;
paginationConfig: PaginationComponentOptions;
sortConfig: SortOptions;
private subs: Subscription[] = [];
private collectionId: string;
private pageInfoState: PageInfo;
constructor(
private collectionDataService: CollectionDataService,
private itemDataService: ItemDataService,
private ref: ChangeDetectorRef,
private route: ActivatedRoute
) {
constructor(private collectionDataService: CollectionDataService,
private itemDataService: ItemDataService,
private route: ActivatedRoute) {
this.paginationConfig = new PaginationComponentOptions();
this.paginationConfig.id = 'collection-page-pagination';
this.paginationConfig.pageSizeOptions = [4];
this.paginationConfig.pageSize = 4;
this.paginationConfig.currentPage = 1;
this.sortConfig = new SortOptions();
}
ngOnInit(): void {
this.subs.push(this.route.params.map((params: Params) => params.id)
.subscribe((id: string) => {
this.collectionId = id;
this.collectionData = this.collectionDataService.findById(this.collectionId);
this.subs.push(this.collectionData.payload.subscribe((collection) => this.logoData = collection.logo));
this.subs.push(
Observable.combineLatest(
this.route.params,
this.route.queryParams,
(params, queryParams,) => {
return Object.assign({}, params, queryParams);
})
.subscribe((params) => {
this.collectionId = params.id;
this.collectionData = this.collectionDataService.findById(this.collectionId);
this.subs.push(this.collectionData.payload.subscribe((collection) => this.logoData = collection.logo));
this.config = new PaginationComponentOptions();
this.config.id = 'collection-browse';
this.config.pageSizeOptions = [4];
this.config.pageSize = 4;
this.sortConfig = new SortOptions();
const page = +params.page || this.paginationConfig.currentPage;
const pageSize = +params.pageSize || this.paginationConfig.pageSize;
const sortDirection = +params.page || this.sortConfig.direction;
const pagination = Object.assign({},
this.paginationConfig,
{ currentPage: page, pageSize: pageSize }
);
const sort = Object.assign({},
this.sortConfig,
{ direction: sortDirection, field: params.sortField }
);
this.updatePage({
pagination: pagination,
sort: sort
});
}));
this.updateResults();
}));
}
updatePage(searchOptions) {
this.itemData = this.itemDataService.findAll({
scopeID: this.collectionId,
currentPage: searchOptions.pagination.currentPage,
elementsPerPage: searchOptions.pagination.pageSize,
sort: searchOptions.sort
});
}
ngOnDestroy(): void {
this.subs.filter((sub) => hasValue(sub)).forEach((sub) => sub.unsubscribe());
}
onPageChange(currentPage: number): void {
this.config.currentPage = currentPage;
this.updateResults();
}
onPageSizeChange(elementsPerPage: number): void {
this.config.pageSize = elementsPerPage;
this.updateResults();
}
onSortDirectionChange(sortDirection: SortDirection): void {
this.sortConfig = new SortOptions(this.sortConfig.field, sortDirection);
this.updateResults();
}
onSortFieldChange(field: string): void {
this.sortConfig = new SortOptions(field, this.sortConfig.direction);
this.updateResults();
}
updateResults() {
this.itemData = null;
this.ref.markForCheck();
this.itemData = this.itemDataService.findAll({
scopeID: this.collectionId,
currentPage: this.config.currentPage,
elementsPerPage: this.config.pageSize,
sort: this.sortConfig
});
this.subs.push(this.itemData.pageInfo.subscribe((pageInfo) => {
if (isUndefined(this.pageInfoState) || this.pageInfoState !== pageInfo) {
this.pageInfoState = pageInfo;
this.ref.detectChanges();
}
}));
isNotEmpty(object: any) {
return isNotEmpty(object);
}
}
......@@ -14,6 +14,7 @@ import { GenericConstructor } from '../../shared/generic-constructor';
import { getMapsTo, getRelationMetadata, getRelationships } from './build-decorators';
import { NormalizedObjectFactory } from '../models/normalized-object-factory';
import { RestRequest } from '../../data/request.models';
import { PageInfo } from "../../shared/page-info.model";
@Injectable()
export class RemoteDataBuildService {
......@@ -68,6 +69,13 @@ export class RemoteDataBuildService {
const pageInfo = responseCacheObs
.filter((entry: ResponseCacheEntry) => hasValue(entry.response) && hasValue(entry.response['pageInfo']))
.map((entry: ResponseCacheEntry) => (entry.response as DSOSuccessResponse).pageInfo)
.map((pInfo: PageInfo) => {
if (isNotEmpty(pageInfo) && pInfo.currentPage >= 0) {
return Object.assign({}, pInfo, {currentPage: pInfo.currentPage + 1});
} else {
return pInfo;
}
})
.distinctUntilChanged();
/* tslint:enable:no-string-literal */
......
@import '../../../styles/variables.scss';
@import '../../../../node_modules/bootstrap/scss/_variables.scss';
$footer-bg: $gray-lighter;
$footer-bg: $gray-100;
$footer-border: 1px solid darken($footer-bg, 10%);
$footer-padding: $spacer * 1.5;
......
......@@ -3,11 +3,12 @@ import { isEmpty, isNotEmpty } from '../../shared/empty.util';
import { CacheableObject } from '../cache/object-cache.reducer';
import { RemoteData } from '../data/remote-data';
import { ResourceType } from './resource-type';
import { ListableObject } from '../../object-list/listable-object/listable-object.model';
/**
* An abstract model class for a DSpaceObject.
*/
export abstract class DSpaceObject implements CacheableObject {
export abstract class DSpaceObject implements CacheableObject, ListableObject {
self: string;
......
<header>
<nav class="navbar navbar-toggleable-sm navbar-inverse bg-inverse">
<button class="navbar-toggler navbar-toggler-right" type="button" (click)="toggle()" aria-controls="collapsingNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon fa fa-bars fa-fw" aria-hidden="true"></span>
</button>
<nav class="navbar navbar-expand-md navbar-dark bg-dark">
<div [ngClass]="{'clearfix': !(isNavBarCollapsed | async)}">
<a class="navbar-brand" routerLink="/home">{{ 'title' | translate }}</a>
</div>
<button class="navbar-toggler" type="button" (click)="toggle()" aria-controls="collapsingNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon fa fa-bars fa-fw" aria-hidden="true"></span>
</button>
<div [ngbCollapse]="(isNavBarCollapsed | async)" class="collapse navbar-collapse" id="collapsingNav">
<ul class="navbar-nav mr-auto">
<li class="nav-item">
......
@import '../../../styles/mixins.scss';
@import '../../../styles/variables.scss';
:host {
display: block;
@include negate-gutters();
margin-right: ($grid-gutter-width / -2);
margin-left: ($grid-gutter-width / -2);
margin-top: -$content-spacing;
margin-bottom: -$content-spacing;
}
.dspace-logo-container {
......
<ds-home-news></ds-home-news>
<ds-search-form></ds-search-form>
<ds-top-level-community-list></ds-top-level-community-list>
......@@ -2,9 +2,5 @@
<h2>{{'home.top-level-communities.head' | translate}}</h2>
<p class="lead">{{'home.top-level-communities.help' | translate}}</p>
<ds-object-list [config]="config" [sortConfig]="sortConfig"
[objects]="topLevelCommunities" [hideGear]="true"
(pageChange)="onPageChange($event)"
(pageSizeChange)="onPageSizeChange($event)"
(sortDirectionChange)="onSortDirectionChange($event)"
(sortFieldChange)="onSortDirectionChange($event)"></ds-object-list>
[objects]="topLevelCommunities" [hideGear]="true" (paginationChange)="updatePage($event)"></ds-object-list>
</div>
......@@ -5,58 +5,40 @@ import { CommunityDataService } from '../../core/data/community-data.service';
import { Community } from '../../core/shared/community.model';
import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model';
import { SortOptions, SortDirection } from '../../core/cache/models/sort-options.model';
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'ds-top-level-community-list',
styleUrls: ['./top-level-community-list.component.scss'],
templateUrl: './top-level-community-list.component.html',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class TopLevelCommunityListComponent implements OnInit {
export class TopLevelCommunityListComponent {
topLevelCommunities: RemoteData<Community[]>;
config: PaginationComponentOptions;
sortConfig: SortOptions;
constructor(
private cds: CommunityDataService,
private ref: ChangeDetectorRef
) {
}
ngOnInit(): void {
constructor(private cds: CommunityDataService) {
this.config = new PaginationComponentOptions();
this.config.id = 'top-level-pagination';
this.config.pageSizeOptions = [4];
this.config.pageSize = 4;
this.config.currentPage = 1;
this.sortConfig = new SortOptions();
this.updateResults();
}
onPageChange(currentPage: number): void {
this.config.currentPage = currentPage;
this.updateResults();
}
onPageSizeChange(elementsPerPage: number): void {
this.config.pageSize = elementsPerPage;
this.updateResults();
}
onSortDirectionChange(sortDirection: SortDirection): void {
this.sortConfig = new SortOptions(this.sortConfig.field, sortDirection);
this.updateResults();
}
onSortFieldChange(field: string): void {
this.sortConfig = new SortOptions(field, this.sortConfig.direction);
this.updateResults();
this.updatePage({
page: this.config.currentPage,
pageSize: this.config.pageSize,
sortField: this.sortConfig.field,
direction: this.sortConfig.direction
});
}
updateResults() {
this.topLevelCommunities = undefined;
this.topLevelCommunities = this.cds.findAll({ currentPage: this.config.currentPage, elementsPerPage: this.config.pageSize, sort: this.sortConfig });
// this.ref.detectChanges();
updatePage(data) {
this.topLevelCommunities = this.cds.findAll({
currentPage: data.page,
elementsPerPage: data.pageSize,
sort: { field: data.sortField, direction: data.sortDirection }
});
}
}
@import '../../../../../styles/variables.scss';
@import '../../../../../../node_modules/bootstrap/scss/_variables.scss';
@import '../../../../../styles/variables';
@import '../../../../../styles/mixins';
@media screen and (min-width: map-get($grid-breakpoints, md)) {
dt {
text-align: right;
......
......@@ -2,7 +2,7 @@
<ds-item-page-title-field [item]="item.payload | async"></ds-item-page-title-field>
<div class="simple-view-link">
<a class="btn btn-secondary col-4" [routerLink]="['/items/' + (item.payload | async)?.id]">
<a class="btn btn-outline-primary col-4" [routerLink]="['/items/' + (item.payload | async)?.id]">
{{"item.page.link.simple" | translate}}
</a>
</div>
......
<ds-metadata-field-wrapper [label]="label | translate">
<ds-metadata-field-wrapper *ngIf="(files | async)?.length > 0" [label]="label | translate">
<div class="file-section">
<a *ngFor="let file of (files | async); let last=last;" [href]="file?.content" [download]="file?.name">
<span>{{file?.name}}</span>
......
......@@ -16,7 +16,7 @@
<ds-item-page-uri-field [item]="item.payload | async"></ds-item-page-uri-field>
<ds-item-page-collections [item]="item.payload | async"></ds-item-page-collections>
<div>
<a class="btn btn-secondary" [routerLink]="['/items/' + (item.payload | async)?.id + '/full']">
<a class="btn btn-outline-primary" [routerLink]="['/items/' + (item.payload | async)?.id + '/full']">
{{"item.page.link.full" | translate}}
</a>
</div>
......
<a [routerLink]="['/collections/' + collection.id]" class="lead">
{{collection.name}}
<a [routerLink]="['/collections/' + object.id]" class="lead">
{{object.name}}
</a>
<div *ngIf="collection.shortDescription" class="text-muted">
{{collection.shortDescription}}
<div *ngIf="object.shortDescription" class="text-muted">
{{object.shortDescription}}
</div>
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment