Skip to content

Commit e9cf2e5

Browse files
committed
[CST-24913] Refactor collection page component to use CollectionDataService for fetching collection data
1 parent 7b7f152 commit e9cf2e5

9 files changed

Lines changed: 84 additions & 30 deletions

File tree

src/app/collection-page/collection-page.component.spec.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
import { TranslateModule } from '@ngx-translate/core';
1919
import { cold } from 'jasmine-marbles';
2020
import { of } from 'rxjs';
21+
import { CollectionDataService } from 'src/app/core/data/collection-data.service';
2122
import { environment } from 'src/environments/environment.test';
2223

2324
import { APP_CONFIG } from '../../config/app-config.interface';
@@ -53,6 +54,7 @@ describe('CollectionPageComponent', () => {
5354
let authServiceSpy: jasmine.SpyObj<AuthService>;
5455
let authorizationDataServiceSpy: jasmine.SpyObj<AuthorizationDataService>;
5556
let dsoNameServiceSpy: jasmine.SpyObj<DSONameService>;
57+
let collectionService: jasmine.SpyObj<CollectionDataService>;
5658
const aroute: ActivatedRouteStub = new ActivatedRouteStub();
5759
const router = new RouterStub();
5860

@@ -75,6 +77,7 @@ describe('CollectionPageComponent', () => {
7577
authServiceSpy = jasmine.createSpyObj('AuthService', ['isAuthenticated']);
7678
authorizationDataServiceSpy = jasmine.createSpyObj('AuthorizationDataService', ['isAuthorized']);
7779
dsoNameServiceSpy = jasmine.createSpyObj('DSONameService', ['getName']);
80+
collectionService = jasmine.createSpyObj('CollectionService', ['findById']);
7881

7982
await TestBed.configureTestingModule({
8083
imports: [FormsModule, TranslateModule.forRoot(), BrowserAnimationsModule, CollectionPageComponent, VarDirective],
@@ -85,6 +88,7 @@ describe('CollectionPageComponent', () => {
8588
{ provide: AuthService, useValue: authServiceSpy },
8689
{ provide: AuthorizationDataService, useValue: authorizationDataServiceSpy },
8790
{ provide: DSONameService, useValue: dsoNameServiceSpy },
91+
{ provide: CollectionDataService, useValue: collectionService },
8892
{ provide: APP_CONFIG, useValue: environment },
8993
{ provide: PLATFORM_ID, useValue: 'browser' },
9094
],
@@ -102,9 +106,10 @@ describe('CollectionPageComponent', () => {
102106

103107
describe('when collection has no logo', () => {
104108
beforeEach(() => {
105-
aroute.testData = {
106-
dso: collectionWithoutLogoRD,
109+
aroute.testParams = {
110+
id: 'id',
107111
};
112+
collectionService.findById.and.returnValue(of(collectionWithoutLogoRD));
108113
fixture.detectChanges();
109114
});
110115

@@ -113,7 +118,7 @@ describe('CollectionPageComponent', () => {
113118
});
114119

115120
it('should initialize the component', () => {
116-
expect(component.collectionRD$).toBeObservable(cold('(a|)', {
121+
expect(component.collectionRD$).toBeObservable(cold('(a)', {
117122
a: collectionWithoutLogoRD,
118123
}));
119124
expect(component.logoRD$).toBeObservable(cold('(a|)', {
@@ -133,9 +138,10 @@ describe('CollectionPageComponent', () => {
133138

134139
describe('when collection has logo', () => {
135140
beforeEach(() => {
136-
aroute.testData = {
137-
dso: collectionWithLogoRD,
141+
aroute.testParams = {
142+
id: 'id',
138143
};
144+
collectionService.findById.and.returnValue(of(collectionWithLogoRD));
139145
fixture.detectChanges();
140146
});
141147

@@ -144,7 +150,7 @@ describe('CollectionPageComponent', () => {
144150
});
145151

146152
it('should initialize the component', () => {
147-
expect(component.collectionRD$).toBeObservable(cold('(a|)', {
153+
expect(component.collectionRD$).toBeObservable(cold('(a)', {
148154
a: collectionWithLogoRD,
149155
}));
150156
expect(component.logoRD$).toBeObservable(cold('(a|)', {

src/app/collection-page/collection-page.component.ts

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,19 @@ import {
1616
RouterOutlet,
1717
} from '@angular/router';
1818
import { TranslateModule } from '@ngx-translate/core';
19-
import { Observable } from 'rxjs';
2019
import {
20+
BehaviorSubject,
21+
Observable,
22+
} from 'rxjs';
23+
import {
24+
distinctUntilChanged,
2125
filter,
2226
map,
2327
mergeMap,
28+
switchMap,
2429
take,
2530
} from 'rxjs/operators';
31+
import { CollectionDataService } from 'src/app/core/data/collection-data.service';
2632

2733
import {
2834
APP_CONFIG,
@@ -37,7 +43,10 @@ import { RemoteData } from '../core/data/remote-data';
3743
import { redirectOn4xx } from '../core/shared/authorized.operators';
3844
import { Bitstream } from '../core/shared/bitstream.model';
3945
import { Collection } from '../core/shared/collection.model';
40-
import { getAllSucceededRemoteDataPayload } from '../core/shared/operators';
46+
import {
47+
getAllSucceededRemoteDataPayload,
48+
getFirstCompletedRemoteData,
49+
} from '../core/shared/operators';
4150
import {
4251
fadeIn,
4352
fadeInOut,
@@ -48,14 +57,12 @@ import { ThemedComcolPageHandleComponent } from '../shared/comcol/comcol-page-ha
4857
import { ComcolPageHeaderComponent } from '../shared/comcol/comcol-page-header/comcol-page-header.component';
4958
import { ComcolPageLogoComponent } from '../shared/comcol/comcol-page-logo/comcol-page-logo.component';
5059
import { ContextMenuComponent } from '../shared/context-menu/context-menu.component';
51-
import { DsoEditMenuComponent } from '../shared/dso-page/dso-edit-menu/dso-edit-menu.component';
5260
import {
5361
hasValue,
5462
isNotEmpty,
5563
} from '../shared/empty.util';
5664
import { ErrorComponent } from '../shared/error/error.component';
5765
import { ThemedLoadingComponent } from '../shared/loading/themed-loading.component';
58-
import { ObjectCollectionComponent } from '../shared/object-collection/object-collection.component';
5966
import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model';
6067
import { VarDirective } from '../shared/utils/var.directive';
6168
import { getCollectionPageRoute } from './collection-page-routing-paths';
@@ -80,16 +87,14 @@ import { getCollectionPageRoute } from './collection-page-routing-paths';
8087
ComcolPageHeaderComponent,
8188
ComcolPageLogoComponent,
8289
ThemedComcolPageHandleComponent,
83-
DsoEditMenuComponent,
8490
ThemedComcolPageBrowseByComponent,
85-
ObjectCollectionComponent,
8691
RouterOutlet,
8792
ContextMenuComponent,
8893
],
8994
standalone: true,
9095
})
9196
export class CollectionPageComponent implements OnInit {
92-
collectionRD$: Observable<RemoteData<Collection>>;
97+
collectionRD$: BehaviorSubject<RemoteData<Collection>> = new BehaviorSubject(null);
9398
logoRD$: Observable<RemoteData<Bitstream>>;
9499
paginationConfig: PaginationComponentOptions;
95100
sortConfig: SortOptions;
@@ -111,6 +116,7 @@ export class CollectionPageComponent implements OnInit {
111116
protected router: Router,
112117
protected authService: AuthService,
113118
protected authorizationDataService: AuthorizationDataService,
119+
protected collectionService: CollectionDataService,
114120
public dsoNameService: DSONameService,
115121
) {
116122
}
@@ -120,12 +126,18 @@ export class CollectionPageComponent implements OnInit {
120126
return;
121127
}
122128

123-
this.collectionRD$ = this.route.data.pipe(
124-
map((data) => data.dso as RemoteData<Collection>),
125-
redirectOn4xx(this.router, this.authService),
126-
take(1),
127-
);
129+
this.route.params.pipe(
130+
map(params => params.id),
131+
distinctUntilChanged(),
132+
switchMap((id) => this.collectionService.findById(id).pipe(
133+
getFirstCompletedRemoteData(),
134+
redirectOn4xx(this.router, this.authService),
135+
take(1),
136+
)),
137+
).subscribe(this.collectionRD$);
138+
128139
this.logoRD$ = this.collectionRD$.pipe(
140+
getFirstCompletedRemoteData(),
129141
map((rd: RemoteData<Collection>) => rd.payload),
130142
filter((collection: Collection) => hasValue(collection)),
131143
mergeMap((collection: Collection) => collection.logo),

src/app/core/auth/auth.actions.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export const AuthActionTypes = {
3535
LOG_OUT_ERROR: type('dspace/auth/LOG_OUT_ERROR'),
3636
LOG_OUT_SUCCESS: type('dspace/auth/LOG_OUT_SUCCESS'),
3737
SET_REDIRECT_URL: type('dspace/auth/SET_REDIRECT_URL'),
38+
SET_REDIRECT_URL_AND_NAVIGATE: type('dspace/auth/SET_REDIRECT_URL_AND_NAVIGATE'),
3839
RETRIEVE_AUTHENTICATED_EPERSON: type('dspace/auth/RETRIEVE_AUTHENTICATED_EPERSON'),
3940
RETRIEVE_AUTHENTICATED_EPERSON_SUCCESS: type('dspace/auth/RETRIEVE_AUTHENTICATED_EPERSON_SUCCESS'),
4041
RETRIEVE_AUTHENTICATED_EPERSON_ERROR: type('dspace/auth/RETRIEVE_AUTHENTICATED_EPERSON_ERROR'),
@@ -360,6 +361,23 @@ export class SetRedirectUrlAction implements Action {
360361
}
361362
}
362363

364+
/**
365+
* Change the redirect url.
366+
* @class SetRedirectUrlAction
367+
* @implements {Action}
368+
*/
369+
export class SetRedirectUrlAdnNavigateAction implements Action {
370+
public type: string = AuthActionTypes.SET_REDIRECT_URL_AND_NAVIGATE;
371+
payload: {
372+
redirectUrl: string;
373+
navigateUrl: string;
374+
};
375+
376+
constructor(redirectUrl: string, navigateUrl: string) {
377+
this.payload = { redirectUrl, navigateUrl };
378+
}
379+
}
380+
363381
/**
364382
* Start loading for a hard redirect
365383
* @class StartHardRedirectLoadingAction

src/app/core/auth/auth.effects.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ import {
7979
RetrieveAuthMethodsErrorAction,
8080
RetrieveAuthMethodsSuccessAction,
8181
RetrieveTokenAction,
82+
SetRedirectUrlAdnNavigateAction,
8283
SetUserAsIdleAction,
8384
} from './auth.actions';
8485
// import services
@@ -347,6 +348,13 @@ export class AuthEffects {
347348
{ dispatch: false },
348349
);
349350

351+
public redirectAndNavigate$: Observable<Action> = createEffect(() => this.actions$
352+
.pipe(ofType(AuthActionTypes.SET_REDIRECT_URL_AND_NAVIGATE),
353+
tap((action: SetRedirectUrlAdnNavigateAction) => this.router.navigate([decodeURIComponent(action.payload.navigateUrl)])),
354+
),
355+
{ dispatch: false },
356+
);
357+
350358
/**
351359
* For any action that is not in {@link IDLE_TIMER_IGNORE_TYPES} that comes in => Start the idleness timer
352360
* If the idleness timer runs out (so no un-ignored action come through for that amount of time)

src/app/core/auth/auth.reducer.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
RetrieveAuthMethodsSuccessAction,
1818
SetAuthCookieStatus,
1919
SetRedirectUrlAction,
20+
SetRedirectUrlAdnNavigateAction,
2021
} from './auth.actions';
2122
import { AuthMethod } from './models/auth.method';
2223
import { AuthMethodType } from './models/auth.method-type';
@@ -267,6 +268,11 @@ export function authReducer(state: any = initialState, action: AuthActions): Aut
267268
redirectUrl: (action as SetRedirectUrlAction).payload,
268269
});
269270

271+
case AuthActionTypes.SET_REDIRECT_URL_AND_NAVIGATE:
272+
return Object.assign({}, state, {
273+
redirectUrl: (action as SetRedirectUrlAdnNavigateAction).payload.redirectUrl,
274+
});
275+
270276
case AuthActionTypes.REDIRECT_AFTER_LOGIN_SUCCESS:
271277
return Object.assign({}, state, {
272278
loading: true,

src/app/core/auth/auth.service.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ import {
6464
ResetAuthenticationMessagesAction,
6565
SetAuthCookieStatus,
6666
SetRedirectUrlAction,
67+
SetRedirectUrlAdnNavigateAction,
6768
SetUserAsIdleAction,
6869
UnsetUserAsIdleAction,
6970
} from './auth.actions';
@@ -556,15 +557,19 @@ export class AuthService {
556557
/**
557558
* Set redirect url
558559
*/
559-
setRedirectUrl(url: string) {
560+
setRedirectUrl(redirectUrl: string, navigateUrl?: string) {
560561
// Add 1 hour to the current date
561562
const expireDate = Date.now() + (1000 * 60 * 60);
562563

563564
// Set the cookie expire date
564565
const expires = new Date(expireDate);
565566
const options: CookieAttributes = { expires: expires };
566-
this.storage.set(REDIRECT_COOKIE, url, options);
567-
this.store.dispatch(new SetRedirectUrlAction(isNotUndefined(url) ? url : ''));
567+
this.storage.set(REDIRECT_COOKIE, redirectUrl, options);
568+
if (hasValue(navigateUrl)) {
569+
this.store.dispatch(new SetRedirectUrlAdnNavigateAction(isNotUndefined(redirectUrl) ? redirectUrl : '', navigateUrl));
570+
} else {
571+
this.store.dispatch(new SetRedirectUrlAction(isNotUndefined(redirectUrl) ? redirectUrl : ''));
572+
}
568573
}
569574

570575
/**

src/app/core/shared/authorized.operators.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,7 @@ export const redirectOn4xx = <T>(router: Router, authService: AuthService) =>
4747
router.navigateByUrl(getForbiddenRoute(), { skipLocationChange: true });
4848
return false;
4949
} else {
50-
authService.setRedirectUrl(router.url);
51-
router.navigateByUrl('login');
50+
authService.setRedirectUrl(router.url, 'login');
5251
return false;
5352
}
5453
}

src/app/core/shared/operators.spec.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,6 @@ describe('Core Module - RxJS Operators', () => {
277277
expectObservable(source.pipe(redirectOn4xx(router, authService))).toBe(expected, values);
278278
flush();
279279
expect(authService.setRedirectUrl).toHaveBeenCalled();
280-
expect(router.navigateByUrl).toHaveBeenCalledWith('login');
281280
});
282281
});
283282

@@ -291,7 +290,6 @@ describe('Core Module - RxJS Operators', () => {
291290
expectObservable(source.pipe(redirectOn4xx(router, authService))).toBe(expected, values);
292291
flush();
293292
expect(authService.setRedirectUrl).toHaveBeenCalled();
294-
expect(router.navigateByUrl).toHaveBeenCalledWith('login');
295293
});
296294
});
297295
});

src/app/statistics/statistics.service.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,13 @@ export class StatisticsService {
4444
dso: DSpaceObject,
4545
referrer: string,
4646
) {
47-
this.sendEvent('/statistics/viewevents', {
48-
targetId: dso.uuid,
49-
targetType: (dso as any).type,
50-
referrer,
51-
});
47+
if (dso) {
48+
this.sendEvent('/statistics/viewevents', {
49+
targetId: dso.uuid,
50+
targetType: (dso as any).type,
51+
referrer,
52+
});
53+
}
5254
}
5355

5456
/**

0 commit comments

Comments
 (0)