first draft breadcrumbs

This commit is contained in:
lotte
2020-02-24 16:06:12 +01:00
committed by Art Lowel
parent 725f20a9d0
commit f67387ed65
17 changed files with 197 additions and 191 deletions

View File

@@ -102,7 +102,7 @@ export class CollectionItemMapperComponent implements OnInit {
}
ngOnInit(): void {
this.collectionRD$ = this.route.data.pipe(map((data) => data.collection)).pipe(getSucceededRemoteData()) as Observable<RemoteData<Collection>>;
this.collectionRD$ = this.route.data.pipe(map((data) => data.dso)).pipe(getSucceededRemoteData()) as Observable<RemoteData<Collection>>;
this.searchOptions$ = this.searchConfigService.paginatedSearchOptions;
this.loadItemLists();
}

View File

@@ -10,6 +10,9 @@ import { DeleteCollectionPageComponent } from './delete-collection-page/delete-c
import { URLCombiner } from '../core/url-combiner/url-combiner';
import { getCollectionModulePath } from '../app-routing.module';
import { CollectionItemMapperComponent } from './collection-item-mapper/collection-item-mapper.component';
import { CollectionBreadcrumbResolver } from '../core/breadcrumbs/collection-breadcrumb.resolver';
import { DSOBreadcrumbsService } from '../core/breadcrumbs/dso-breadcrumbs.service';
import { LinkService } from '../core/cache/builders/link.service';
export const COLLECTION_PARENT_PARAMETER = 'parent';
@@ -26,51 +29,54 @@ export function getCollectionCreatePath() {
}
const COLLECTION_CREATE_PATH = 'create';
const COLLECTION_EDIT_PATH = ':id/edit';
const COLLECTION_EDIT_PATH = 'edit';
@NgModule({
imports: [
RouterModule.forChild([
{
path: COLLECTION_CREATE_PATH,
component: CreateCollectionPageComponent,
canActivate: [AuthenticatedGuard, CreateCollectionPageGuard]
path: ':id',
resolve: {
dso: CollectionPageResolver,
breadcrumb: CollectionBreadcrumbResolver
},
children: [
{
path: COLLECTION_EDIT_PATH,
loadChildren: './edit-collection-page/edit-collection-page.module#EditCollectionPageModule',
canActivate: [AuthenticatedGuard]
},
{
path: ':id/delete',
path: 'delete',
pathMatch: 'full',
component: DeleteCollectionPageComponent,
canActivate: [AuthenticatedGuard],
resolve: {
dso: CollectionPageResolver
}
},
{
path: ':id',
path: '',
component: CollectionPageComponent,
pathMatch: 'full',
resolve: {
collection: CollectionPageResolver
}
},
{
path: ':id/edit/mapper',
path: '/edit/mapper',
component: CollectionItemMapperComponent,
pathMatch: 'full',
resolve: {
collection: CollectionPageResolver
},
canActivate: [AuthenticatedGuard]
}
]
},
{
path: COLLECTION_CREATE_PATH,
component: CreateCollectionPageComponent,
canActivate: [AuthenticatedGuard, CreateCollectionPageGuard]
},
])
],
providers: [
CollectionPageResolver,
CollectionBreadcrumbResolver,
DSOBreadcrumbsService,
LinkService,
CreateCollectionPageGuard
]
})

View File

@@ -62,7 +62,7 @@ export class CollectionPageComponent implements OnInit {
ngOnInit(): void {
this.collectionRD$ = this.route.data.pipe(
map((data) => data.collection as RemoteData<Collection>),
map((data) => data.dso as RemoteData<Collection>),
redirectToPageNotFoundOn404(this.router),
take(1)
);

View File

@@ -1,7 +1,6 @@
import { RouterModule } from '@angular/router';
import { NgModule } from '@angular/core';
import { EditCollectionPageComponent } from './edit-collection-page.component';
import { CollectionPageResolver } from '../collection-page.resolver';
import { CollectionMetadataComponent } from './collection-metadata/collection-metadata.component';
import { CollectionRolesComponent } from './collection-roles/collection-roles.component';
import { CollectionSourceComponent } from './collection-source/collection-source.component';
@@ -16,9 +15,6 @@ import { CollectionCurateComponent } from './collection-curate/collection-curate
{
path: '',
component: EditCollectionPageComponent,
resolve: {
dso: CollectionPageResolver
},
children: [
{
path: '',
@@ -51,9 +47,6 @@ import { CollectionCurateComponent } from './collection-curate/collection-curate
]
}
])
],
providers: [
CollectionPageResolver,
]
})
export class EditCollectionPageRoutingModule {

View File

@@ -9,6 +9,9 @@ import { CreateCommunityPageGuard } from './create-community-page/create-communi
import { DeleteCommunityPageComponent } from './delete-community-page/delete-community-page.component';
import { URLCombiner } from '../core/url-combiner/url-combiner';
import { getCommunityModulePath } from '../app-routing.module';
import { CommunityBreadcrumbResolver } from '../core/breadcrumbs/community-breadcrumb.resolver';
import { DSOBreadcrumbsService } from '../core/breadcrumbs/dso-breadcrumbs.service';
import { LinkService } from '../core/cache/builders/link.service';
export const COMMUNITY_PARENT_PARAMETER = 'parent';
@@ -25,42 +28,48 @@ export function getCommunityCreatePath() {
}
const COMMUNITY_CREATE_PATH = 'create';
const COMMUNITY_EDIT_PATH = ':id/edit';
const COMMUNITY_EDIT_PATH = 'edit';
@NgModule({
imports: [
RouterModule.forChild([
{
path: COMMUNITY_CREATE_PATH,
component: CreateCommunityPageComponent,
canActivate: [AuthenticatedGuard, CreateCommunityPageGuard]
path: ':id',
resolve: {
dso: CommunityPageResolver,
breadcrumb: CommunityBreadcrumbResolver
},
children: [
{
path: COMMUNITY_EDIT_PATH,
loadChildren: './edit-community-page/edit-community-page.module#EditCommunityPageModule',
canActivate: [AuthenticatedGuard]
},
{
path: ':id/delete',
path: 'delete',
pathMatch: 'full',
component: DeleteCommunityPageComponent,
canActivate: [AuthenticatedGuard],
resolve: {
dso: CommunityPageResolver
}
},
{
path: ':id',
path: '',
component: CommunityPageComponent,
pathMatch: 'full',
resolve: {
community: CommunityPageResolver
}
}
]
},
{
path: COMMUNITY_CREATE_PATH,
component: CreateCommunityPageComponent,
canActivate: [AuthenticatedGuard, CreateCommunityPageGuard]
},
])
],
providers: [
CommunityPageResolver,
CommunityBreadcrumbResolver,
DSOBreadcrumbsService,
LinkService,
CreateCommunityPageGuard
]
})

View File

@@ -46,7 +46,7 @@ export class CommunityPageComponent implements OnInit {
ngOnInit(): void {
this.communityRD$ = this.route.data.pipe(
map((data) => data.community as RemoteData<Community>),
map((data) => data.dso as RemoteData<Community>),
redirectToPageNotFoundOn404(this.router)
);
this.logoRD$ = this.communityRD$.pipe(

View File

@@ -15,9 +15,6 @@ import { CommunityCurateComponent } from './community-curate/community-curate.co
{
path: '',
component: EditCommunityPageComponent,
resolve: {
dso: CommunityPageResolver
},
children: [
{
path: '',
@@ -46,9 +43,6 @@ import { CommunityCurateComponent } from './community-curate/community-curate.co
}
])
],
providers: [
CommunityPageResolver,
]
})
export class EditCommunityPageRoutingModule {

View File

@@ -13,6 +13,7 @@ import { ItemBitstreamsComponent } from './item-bitstreams/item-bitstreams.compo
import { ItemCollectionMapperComponent } from './item-collection-mapper/item-collection-mapper.component';
import { ItemMoveComponent } from './item-move/item-move.component';
import { ItemRelationshipsComponent } from './item-relationships/item-relationships.component';
import { I18nBreadcrumbResolver } from '../../core/breadcrumbs/i18n-breadcrumb.resolver';
const ITEM_EDIT_WITHDRAW_PATH = 'withdraw';
const ITEM_EDIT_REINSTATE_PATH = 'reinstate';
@@ -29,10 +30,14 @@ const ITEM_EDIT_MOVE_PATH = 'move';
RouterModule.forChild([
{
path: '',
component: EditItemPageComponent,
resolve: {
item: ItemPageResolver
breadcrumb: I18nBreadcrumbResolver
},
data: { breadcrumbKey: 'edit.item' },
children: [
{
path: '',
component: EditItemPageComponent,
children: [
{
path: '',
@@ -70,63 +75,43 @@ const ITEM_EDIT_MOVE_PATH = 'move';
/* TODO - change when curate page exists */
component: ItemBitstreamsComponent,
data: { title: 'item.edit.tabs.curate.title' }
},
}
]
},
{
path: 'mapper',
component: ItemCollectionMapperComponent,
resolve: {
item: ItemPageResolver
}
},
{
path: ITEM_EDIT_WITHDRAW_PATH,
component: ItemWithdrawComponent,
resolve: {
item: ItemPageResolver
}
},
{
path: ITEM_EDIT_REINSTATE_PATH,
component: ItemReinstateComponent,
resolve: {
item: ItemPageResolver
}
},
{
path: ITEM_EDIT_PRIVATE_PATH,
component: ItemPrivateComponent,
resolve: {
item: ItemPageResolver
}
},
{
path: ITEM_EDIT_PUBLIC_PATH,
component: ItemPublicComponent,
resolve: {
item: ItemPageResolver
}
},
{
path: ITEM_EDIT_DELETE_PATH,
component: ItemDeleteComponent,
resolve: {
item: ItemPageResolver
}
},
{
path: ITEM_EDIT_MOVE_PATH,
component: ItemMoveComponent,
data: { title: 'item.edit.move.title' },
resolve: {
item: ItemPageResolver
}
}])
],
providers: [
ItemPageResolver,
]
}
])
],
providers: []
})
export class EditItemPageRoutingModule {

View File

@@ -14,37 +14,39 @@ import { LinkService } from '../core/cache/builders/link.service';
export function getItemPageRoute(itemId: string) {
return new URLCombiner(getItemModulePath(), itemId).toString();
}
export function getItemEditPath(id: string) {
return new URLCombiner(getItemModulePath(),ITEM_EDIT_PATH.replace(/:id/, id)).toString()
return new URLCombiner(getItemModulePath(), ITEM_EDIT_PATH.replace(/:id/, id)).toString()
}
const ITEM_EDIT_PATH = ':id/edit';
const ITEM_EDIT_PATH = 'edit';
@NgModule({
imports: [
RouterModule.forChild([
{
path: ':id',
resolve: {
item: ItemPageResolver,
breadcrumb: ItemBreadcrumbResolver
},
children: [
{
path: '',
component: ItemPageComponent,
pathMatch: 'full',
resolve: {
item: ItemPageResolver,
breadcrumb: ItemBreadcrumbResolver
}
},
{
path: ':id/full',
path: 'full',
component: FullItemPageComponent,
resolve: {
item: ItemPageResolver,
breadcrumb: ItemBreadcrumbResolver
}
},
{
path: ITEM_EDIT_PATH,
loadChildren: './edit-item-page/edit-item-page.module#EditItemPageModule',
canActivate: [AuthenticatedGuard]
},
}
],
}
])
],
providers: [
@@ -53,6 +55,7 @@ const ITEM_EDIT_PATH = ':id/edit';
DSOBreadcrumbsService,
LinkService
]
})
export class ItemPageRoutingModule {

View File

@@ -2,12 +2,14 @@ import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { LoginPageComponent } from './login-page.component';
import { I18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.resolver';
@NgModule({
imports: [
RouterModule.forChild([
{ path: '', pathMatch: 'full', component: LoginPageComponent, data: { title: 'login.title' } }
{ path: '', pathMatch: 'full', component: LoginPageComponent, resolve: { breadcrumb: I18nBreadcrumbResolver }, data: { breadcrumbKey: 'Search', title: 'login.title' } }
])
]
})
export class LoginPageRoutingModule { }
export class LoginPageRoutingModule {
}

View File

@@ -9,10 +9,15 @@ import { I18nBreadcrumbsService } from '../core/breadcrumbs/i18n-breadcrumbs.ser
@NgModule({
imports: [
RouterModule.forChild([
{ path: '', component: SearchPageComponent, resolve: { breadcrumb: I18nBreadcrumbResolver }, data: { title: 'search.title', breadcrumbKey: 'Search' } },
RouterModule.forChild([{
path: '',
resolve: { breadcrumb: I18nBreadcrumbResolver }, data: { title: 'search.title', breadcrumbKey: 'Search' },
children: [
{ path: '', component: SearchPageComponent },
{ path: ':configuration', component: ConfigurationSearchPageComponent, canActivate: [ConfigurationSearchPageGuard] }
])
]
}]
)
],
providers: [
I18nBreadcrumbResolver,

View File

@@ -1,16 +1,17 @@
<nav *ngIf="showBreadcrumbs" aria-label="breadcrumb">
<ol class="breadcrumb">
<ng-container *ngTemplateOutlet="breadcrumbs.length > 0 ? breadcrumb : activeBreadcrumb; context: {text: 'Home', url: '/'}"></ng-container>
<ng-container *ngFor="let bc of breadcrumbs; let last;">
<ng-container *ngFor="let bc of breadcrumbs; let last = last;">
<ng-container *ngTemplateOutlet="!last ? breadcrumb : activeBreadcrumb; context: bc"></ng-container>
</ng-container>
</ol>
</nav>
<ng-template #breadcrumb let-text="text" let-url="url">
<li class="breadcrumb-item"><a [routerLink]="url">{{text}}</a></li>
<li class="breadcrumb-item"><a [routerLink]="url">{{text | translate}}</a></li>
</ng-template>
<ng-template #activeBreadcrumb let-text="text" >
<li class="breadcrumb-item active" aria-current="page">{{text}}</li>
<li class="breadcrumb-item active" aria-current="page">{{text | translate}}</li>
</ng-template>

View File

@@ -32,13 +32,17 @@ export class BreadcrumbsComponent implements OnDestroy {
resolveBreadcrumb(route: ActivatedRoute): Observable<Breadcrumb[]> {
const data = route.snapshot.data;
const last: boolean = route.children.length === 0;
const routeConfig = route.snapshot.routeConfig;
const last: boolean = route.children.length === 0;
if (last && isNotUndefined(data.showBreadcrumbs)) {
this.showBreadcrumbs = data.showBreadcrumbs;
}
if (hasValue(data) && hasValue(data.breadcrumb)) {
if (
hasValue(data) && hasValue(data.breadcrumb) &&
hasValue(routeConfig) && hasValue(routeConfig.resolve) && hasValue(routeConfig.resolve.breadcrumb)
) {
const { provider, key, url } = data.breadcrumb;
if (!last) {
return combineLatest(provider.getBreadcrumbs(key, url), this.resolveBreadcrumb(route.firstChild))

View File

@@ -29,7 +29,7 @@ export class DSOBreadcrumbResolver<T extends ChildHALResource & DSpaceObject> im
getSucceededRemoteData(),
getRemoteDataPayload(),
map((object: T) => {
const fullPath = route.url.join('');
const fullPath = state.url;
const url = fullPath.substr(0, fullPath.indexOf(uuid)) + uuid;
return { provider: this.breadcrumbService, key: object, url: url };
})

View File

@@ -21,7 +21,7 @@ export class DSOBreadcrumbsService implements BreadcrumbsService<ChildHALResourc
const crumb = new Breadcrumb(key.name, url);
const propertyName = key.getParentLinkKey();
return this.linkService.resolveLink(key, followLink(propertyName))[propertyName].pipe(
filter((childRD: RemoteData<ChildHALResource & DSpaceObject>) => childRD.isSuccessful === true && childRD.requestPending === false && childRD.responsePending === false),
find((childRD: RemoteData<ChildHALResource & DSpaceObject>) => childRD.hasSucceeded || childRD.statusCode === 204),
switchMap((childRD: RemoteData<ChildHALResource & DSpaceObject>) => {
if (hasValue(childRD.payload)) {
const child = childRD.payload;

View File

@@ -96,13 +96,14 @@ export class RemoteDataBuildService {
const responsePending = hasValue(reqEntry) && hasValue(reqEntry.responsePending) ? reqEntry.responsePending : false;
let isSuccessful: boolean;
let error: RemoteDataError;
if (hasValue(reqEntry) && hasValue(reqEntry.response)) {
isSuccessful = reqEntry.response.isSuccessful;
const errorMessage = isSuccessful === false ? (reqEntry.response as ErrorResponse).errorMessage : undefined;
const response = reqEntry ? reqEntry.response : undefined;
if (hasValue(response)) {
isSuccessful = response.isSuccessful;
const errorMessage = isSuccessful === false ? (response as ErrorResponse).errorMessage : undefined;
if (hasValue(errorMessage)) {
error = new RemoteDataError(
(reqEntry.response as ErrorResponse).statusCode,
(reqEntry.response as ErrorResponse).statusText,
response.statusCode,
response.statusText,
errorMessage
);
}
@@ -112,7 +113,9 @@ export class RemoteDataBuildService {
responsePending,
isSuccessful,
error,
payload
payload,
hasValue(response) ? response.statusCode : undefined
);
})
);

View File

@@ -13,11 +13,12 @@ export enum RemoteDataState {
*/
export class RemoteData<T> {
constructor(
public requestPending?: boolean,
public responsePending?: boolean,
public isSuccessful?: boolean,
private requestPending?: boolean,
private responsePending?: boolean,
private isSuccessful?: boolean,
public error?: RemoteDataError,
public payload?: T
public payload?: T,
public statusCode?: number,
) {
}