Skip to content

Commit

Permalink
Merge 6bf086b into 2789996
Browse files Browse the repository at this point in the history
  • Loading branch information
mspalti committed Sep 27, 2019
2 parents 2789996 + 6bf086b commit 711f2d8
Show file tree
Hide file tree
Showing 24 changed files with 495 additions and 79 deletions.
19 changes: 19 additions & 0 deletions src/app/+lookup-by-id/lookup-by-id-routing.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { LookupGuard } from './lookup-guard';
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { ObjectNotFoundComponent } from './objectnotfound/objectnotfound.component';

@NgModule({
imports: [
RouterModule.forChild([
{ path: ':idType/:id', canActivate: [LookupGuard], component: ObjectNotFoundComponent }
])
],
providers: [
LookupGuard
]
})

export class LookupRoutingModule {

}
23 changes: 23 additions & 0 deletions src/app/+lookup-by-id/lookup-by-id.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { SharedModule } from '../shared/shared.module';
import { LookupRoutingModule } from './lookup-by-id-routing.module';
import { ObjectNotFoundComponent } from './objectnotfound/objectnotfound.component';
import { DsoDataRedirectService } from '../core/data/dso-data-redirect.service';

@NgModule({
imports: [
LookupRoutingModule,
CommonModule,
SharedModule,
],
declarations: [
ObjectNotFoundComponent
],
providers: [
DsoDataRedirectService
]
})
export class LookupIdModule {

}
52 changes: 52 additions & 0 deletions src/app/+lookup-by-id/lookup-guard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router';
import { DsoDataRedirectService } from '../core/data/dso-data-redirect.service';
import { Injectable } from '@angular/core';
import { IdentifierType } from '../core/index/index.reducer';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { RemoteData } from '../core/data/remote-data';
import { FindByIDRequest } from '../core/data/request.models';

interface LookupParams {
type: IdentifierType;
id: string;
}

@Injectable()
export class LookupGuard implements CanActivate {
constructor(private dsoService: DsoDataRedirectService, private router: Router) {
}

canActivate(route: ActivatedRouteSnapshot, state:RouterStateSnapshot): Observable<boolean> {
const params = this.getLookupParams(route);
return this.dsoService.findById(params.id, params.type).pipe(
map((response: RemoteData<FindByIDRequest>) => response.hasFailed)
);
}

private getLookupParams(route: ActivatedRouteSnapshot): LookupParams {
let type;
let id;
const idType = route.params.idType;

// If the idType is not recognized, assume a legacy handle request (handle/prefix/id)
if (idType !== IdentifierType.HANDLE && idType !== IdentifierType.UUID) {
type = IdentifierType.HANDLE;
const prefix = route.params.idType;
const handleId = route.params.id;
id = `${prefix}%2F${handleId}`;

} else if (route.params.idType === IdentifierType.HANDLE) {
type = IdentifierType.HANDLE;
id = route.params.id;

} else {
type = IdentifierType.UUID;
id = route.params.id;
}
return {
type: type,
id: id
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<div class="object-not-found container">
<h1>{{"error.item" | translate}}</h1>
<h2><small><em>{{missingItem}}</em></small></h2>
<br />
<p class="text-center">
<a routerLink="/home" class="btn btn-primary">{{"404.link.home-page" | translate}}</a>
</p>
</div>
Empty file.
45 changes: 45 additions & 0 deletions src/app/+lookup-by-id/objectnotfound/objectnotfound.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@

import { Component, ChangeDetectionStrategy, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

/**
* This component representing the `PageNotFound` DSpace page.
*/
@Component({
selector: 'ds-objnotfound',
styleUrls: ['./objectnotfound.component.scss'],
templateUrl: './objectnotfound.component.html',
changeDetection: ChangeDetectionStrategy.Default
})
export class ObjectNotFoundComponent implements OnInit {

idType: string;

id: string;

missingItem: string;

/**
* Initialize instance variables
*
* @param {AuthService} authservice
* @param {ServerResponseService} responseService
*/
constructor(private route: ActivatedRoute) {
route.params.subscribe((params) => {
this.idType = params.idType;
this.id = params.id;
})
}

ngOnInit(): void {
if (this.idType.startsWith('handle')) {
this.missingItem = 'handle: ' + this.id;
} else if (this.idType.startsWith('uuid')) {
this.missingItem = 'uuid: ' + this.id;
} else {
this.missingItem = 'handle: ' + this.idType + '/' + this.id;
}
}

}
2 changes: 2 additions & 0 deletions src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ export function getAdminModulePath() {
RouterModule.forRoot([
{ path: '', redirectTo: '/home', pathMatch: 'full' },
{ path: 'home', loadChildren: './+home-page/home-page.module#HomePageModule' },
{ path: 'id', loadChildren: './+lookup-by-id/lookup-by-id.module#LookupIdModule' },
{ path: 'handle', loadChildren: './+lookup-by-id/lookup-by-id.module#LookupIdModule' },
{ path: COMMUNITY_MODULE_PATH, loadChildren: './+community-page/community-page.module#CommunityPageModule' },
{ path: COLLECTION_MODULE_PATH, loadChildren: './+collection-page/collection-page.module#CollectionPageModule' },
{ path: ITEM_MODULE_PATH, loadChildren: './+item-page/item-page.module#ItemPageModule' },
Expand Down
2 changes: 1 addition & 1 deletion src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ const EXPORTS = [
...PROVIDERS
],
declarations: [
...DECLARATIONS,
...DECLARATIONS
],
exports: [
...EXPORTS
Expand Down
1 change: 1 addition & 0 deletions src/app/core/cache/object-cache.reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export abstract class TypedObject {
*/
export class CacheableObject extends TypedObject {
uuid?: string;
handle?: string;
self: string;
// isNew: boolean;
// dirtyType: DirtyType;
Expand Down
16 changes: 9 additions & 7 deletions src/app/core/cache/object-cache.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { applyPatch, Operation } from 'fast-json-patch';
import { combineLatest as observableCombineLatest, Observable } from 'rxjs';

import { distinctUntilChanged, filter, map, mergeMap, take, } from 'rxjs/operators';
import { hasNoValue, hasValue, isNotEmpty } from '../../shared/empty.util';
import { hasNoValue, isNotEmpty } from '../../shared/empty.util';
import { CoreState } from '../core.reducers';
import { coreSelector } from '../core.selectors';
import { RestRequestMethod } from '../data/rest-request-method';
Expand All @@ -21,6 +21,7 @@ import {
import { CacheableObject, ObjectCacheEntry, ObjectCacheState } from './object-cache.reducer';
import { AddToSSBAction } from './server-sync-buffer.actions';
import { getMapsToType } from './builders/build-decorators';
import { IdentifierType } from '../index/index.reducer';

/**
* The base selector function to select the object cache in the store
Expand Down Expand Up @@ -75,14 +76,15 @@ export class ObjectCacheService {
/**
* Get an observable of the object with the specified UUID
*
* @param uuid
* @param id
* The UUID of the object to get
* @return Observable<NormalizedObject<T>>
* An observable of the requested object in normalized form
*/
getObjectByUUID<T extends CacheableObject>(uuid: string): Observable<NormalizedObject<T>> {
getObjectByID<T extends CacheableObject>(id: string, identifierType: IdentifierType = IdentifierType.UUID):
Observable<NormalizedObject<T>> {
return this.store.pipe(
select(selfLinkFromUuidSelector(uuid)),
select(selfLinkFromUuidSelector(id, identifierType)),
mergeMap((selfLink: string) => this.getObjectBySelfLink(selfLink)
)
)
Expand Down Expand Up @@ -188,17 +190,17 @@ export class ObjectCacheService {
/**
* Check whether the object with the specified UUID is cached
*
* @param uuid
* @param id
* The UUID of the object to check
* @return boolean
* true if the object with the specified UUID is cached,
* false otherwise
*/
hasByUUID(uuid: string): boolean {
hasById(id: string, identifierType: IdentifierType = IdentifierType.UUID): boolean {
let result: boolean;

this.store.pipe(
select(selfLinkFromUuidSelector(uuid)),
select(selfLinkFromUuidSelector(id, identifierType)),
take(1)
).subscribe((selfLink: string) => result = this.hasBySelfLink(selfLink));

Expand Down
4 changes: 2 additions & 2 deletions src/app/core/core.effects.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ObjectCacheEffects } from './cache/object-cache.effects';
import { UUIDIndexEffects } from './index/index.effects';
import { IdentifierIndexEffects } from './index/index.effects';
import { RequestEffects } from './data/request.effects';
import { AuthEffects } from './auth/auth.effects';
import { JsonPatchOperationsEffects } from './json-patch/json-patch-operations.effects';
Expand All @@ -10,7 +10,7 @@ import { RouteEffects } from './services/route.effects';
export const coreEffects = [
RequestEffects,
ObjectCacheEffects,
UUIDIndexEffects,
IdentifierIndexEffects,
AuthEffects,
JsonPatchOperationsEffects,
ServerSyncBufferEffects,
Expand Down
4 changes: 2 additions & 2 deletions src/app/core/data/comcol-data.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ describe('ComColDataService', () => {

function initMockObjectCacheService(): ObjectCacheService {
return jasmine.createSpyObj('objectCache', {
getObjectByUUID: cold('d-', {
getObjectByID: cold('d-', {
d: {
_links: {
[LINK_NAME]: scopedEndpoint
Expand Down Expand Up @@ -160,7 +160,7 @@ describe('ComColDataService', () => {
it('should fetch the scope Community from the cache', () => {
scheduler.schedule(() => service.getBrowseEndpoint(options).subscribe());
scheduler.flush();
expect(objectCache.getObjectByUUID).toHaveBeenCalledWith(scopeID);
expect(objectCache.getObjectByID).toHaveBeenCalledWith(scopeID);
});

it('should return the endpoint to fetch resources within the given scope', () => {
Expand Down
2 changes: 1 addition & 1 deletion src/app/core/data/comcol-data.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export abstract class ComColDataService<T extends CacheableObject> extends DataS
);
const successResponses = responses.pipe(
filter((response) => response.isSuccessful),
mergeMap(() => this.objectCache.getObjectByUUID(options.scopeID)),
mergeMap(() => this.objectCache.getObjectByID(options.scopeID)),
map((nc: NormalizedCommunity) => nc._links[linkPath]),
filter((href) => isNotEmpty(href))
);
Expand Down
18 changes: 13 additions & 5 deletions src/app/core/data/data.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import { NormalizedObjectBuildService } from '../cache/builders/normalized-objec
import { ChangeAnalyzer } from './change-analyzer';
import { RestRequestMethod } from './rest-request-method';
import { getMapsToType } from '../cache/builders/build-decorators';
import { IdentifierType } from '../index/index.reducer';

export abstract class DataService<T extends CacheableObject> {
protected abstract requestService: RequestService;
Expand Down Expand Up @@ -146,14 +147,21 @@ export abstract class DataService<T extends CacheableObject> {
return `${endpoint}/${resourceID}`;
}

findById(id: string): Observable<RemoteData<T>> {
const hrefObs = this.halService.getEndpoint(this.linkPath).pipe(
map((endpoint: string) => this.getIDHref(endpoint, id)));

findById(id: string, identifierType: IdentifierType = IdentifierType.UUID): Observable<RemoteData<T>> {
let hrefObs;
if (identifierType === IdentifierType.UUID) {
hrefObs = this.halService.getEndpoint(this.linkPath).pipe(
map((endpoint: string) => this.getIDHref(endpoint, id)));
} else if (identifierType === IdentifierType.HANDLE) {
hrefObs = this.halService.getEndpoint(this.linkPath).pipe(
map((endpoint: string) => {
return this.getIDHref(endpoint, encodeURIComponent(id));
}));
}
hrefObs.pipe(
find((href: string) => hasValue(href)))
.subscribe((href: string) => {
const request = new FindByIDRequest(this.requestService.generateRequestId(), href, id);
const request = new FindByIDRequest(this.requestService.generateRequestId(), href, id, identifierType);
this.requestService.configure(request, this.forceBypassCache);
});

Expand Down
Loading

0 comments on commit 711f2d8

Please sign in to comment.