mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-15 05:53:03 +00:00
solving SSR issue
This commit is contained in:
@@ -31,7 +31,8 @@ import { Angulartics2DSpace } from './statistics/angulartics/dspace-provider';
|
|||||||
import { environment } from '../environments/environment';
|
import { environment } from '../environments/environment';
|
||||||
import { models } from './core/core.module';
|
import { models } from './core/core.module';
|
||||||
import { LocaleService } from './core/locale/locale.service';
|
import { LocaleService } from './core/locale/locale.service';
|
||||||
import { CookiesService } from './shared/cookies/cookies.service';
|
import { KlaroService } from './shared/cookies/klaro.service';
|
||||||
|
import { hasValue } from './shared/empty.util';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-app',
|
selector: 'ds-app',
|
||||||
@@ -69,7 +70,7 @@ export class AppComponent implements OnInit, AfterViewInit {
|
|||||||
private menuService: MenuService,
|
private menuService: MenuService,
|
||||||
private windowService: HostWindowService,
|
private windowService: HostWindowService,
|
||||||
private localeService: LocaleService,
|
private localeService: LocaleService,
|
||||||
@Optional() private cookiesService: CookiesService
|
@Optional() private cookiesService: KlaroService
|
||||||
) {
|
) {
|
||||||
|
|
||||||
/* Use models object so all decorators are actually called */
|
/* Use models object so all decorators are actually called */
|
||||||
@@ -83,7 +84,7 @@ export class AppComponent implements OnInit, AfterViewInit {
|
|||||||
// set the current language code
|
// set the current language code
|
||||||
this.localeService.setCurrentLanguageCode();
|
this.localeService.setCurrentLanguageCode();
|
||||||
|
|
||||||
this.cookiesService.initialize();
|
this.initializeKlaro();
|
||||||
|
|
||||||
angulartics2GoogleAnalytics.startTracking();
|
angulartics2GoogleAnalytics.startTracking();
|
||||||
angulartics2DSpace.startTracking();
|
angulartics2DSpace.startTracking();
|
||||||
@@ -163,4 +164,9 @@ export class AppComponent implements OnInit, AfterViewInit {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private initializeKlaro() {
|
||||||
|
if (hasValue(this.cookiesService)) {
|
||||||
|
this.cookiesService.initialize()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -10,7 +10,7 @@ import { Observable, of as observableOf, combineLatest } from 'rxjs';
|
|||||||
import { map, take, flatMap } from 'rxjs/operators';
|
import { map, take, flatMap } from 'rxjs/operators';
|
||||||
import { NativeWindowService, NativeWindowRef } from '../services/window.service';
|
import { NativeWindowService, NativeWindowRef } from '../services/window.service';
|
||||||
|
|
||||||
export const LANG_COOKIE = 'language_cookie';
|
export const LANG_COOKIE = 'dsLanguage';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This enum defines the possible origin of the languages
|
* This enum defines the possible origin of the languages
|
||||||
|
@@ -184,4 +184,25 @@ export class DSpaceObject extends ListableObject implements CacheableObject {
|
|||||||
getRenderTypes(): Array<string | GenericConstructor<ListableObject>> {
|
getRenderTypes(): Array<string | GenericConstructor<ListableObject>> {
|
||||||
return [this.constructor as GenericConstructor<ListableObject>];
|
return [this.constructor as GenericConstructor<ListableObject>];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setMetadata(key: string, language?: string, ...values: string[]) {
|
||||||
|
const mdValues: MetadataValue[] = values.map((value: string, index: number) => {
|
||||||
|
const md = new MetadataValue();
|
||||||
|
md.value = value;
|
||||||
|
md.authority = null;
|
||||||
|
md.confidence = -1;
|
||||||
|
md.language = language || null;
|
||||||
|
md.place = index;
|
||||||
|
return md;
|
||||||
|
});
|
||||||
|
if (hasNoValue(this.metadata)) {
|
||||||
|
this.metadata = Object.create({});
|
||||||
|
}
|
||||||
|
this.metadata[key] = mdValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
removeMetadata(key: string) {
|
||||||
|
delete this.metadata[key];
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component, Optional } from '@angular/core';
|
||||||
import { CookiesService } from '../shared/cookies/cookies.service';
|
import { KlaroService } from '../shared/cookies/klaro.service';
|
||||||
|
import { hasValue } from '../shared/empty.util';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-footer',
|
selector: 'ds-footer',
|
||||||
@@ -7,14 +8,15 @@ import { CookiesService } from '../shared/cookies/cookies.service';
|
|||||||
templateUrl: 'footer.component.html'
|
templateUrl: 'footer.component.html'
|
||||||
})
|
})
|
||||||
export class FooterComponent {
|
export class FooterComponent {
|
||||||
constructor(private cookies: CookiesService) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
dateObj: number = Date.now();
|
dateObj: number = Date.now();
|
||||||
|
|
||||||
|
constructor(@Optional() private cookies: KlaroService) {
|
||||||
|
}
|
||||||
|
|
||||||
showCookieSettings() {
|
showCookieSettings() {
|
||||||
this.cookies.showSettings();
|
if (hasValue(this.cookies)) {
|
||||||
|
this.cookies.showSettings();
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,12 +1,12 @@
|
|||||||
import { TestBed } from '@angular/core/testing';
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
import { CookiesService } from './cookies.service';
|
import { KlaroService } from './klaro.service';
|
||||||
|
|
||||||
describe('CookiesService', () => {
|
describe('KlaroService', () => {
|
||||||
beforeEach(() => TestBed.configureTestingModule({}));
|
beforeEach(() => TestBed.configureTestingModule({}));
|
||||||
|
|
||||||
it('should be created', () => {
|
it('should be created', () => {
|
||||||
const service: CookiesService = TestBed.get(CookiesService);
|
const service: KlaroService = TestBed.get(KlaroService);
|
||||||
expect(service).toBeTruthy();
|
expect(service).toBeTruthy();
|
||||||
});
|
});
|
||||||
});
|
});
|
@@ -1,26 +1,23 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import * as Klaro from 'klaro'
|
import * as Klaro from 'klaro'
|
||||||
import { BehaviorSubject } from 'rxjs';
|
import { BehaviorSubject, Observable } from 'rxjs';
|
||||||
import { TOKENITEM } from '../../core/auth/models/auth-token-info.model';
|
import { TOKENITEM } from '../../core/auth/models/auth-token-info.model';
|
||||||
import { AuthService, IMPERSONATING_COOKIE, REDIRECT_COOKIE } from '../../core/auth/auth.service';
|
import { AuthService, IMPERSONATING_COOKIE, REDIRECT_COOKIE } from '../../core/auth/auth.service';
|
||||||
import { LANG_COOKIE } from '../../core/locale/locale.service';
|
import { LANG_COOKIE } from '../../core/locale/locale.service';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { environment } from '../../../environments/environment';
|
import { environment } from '../../../environments/environment';
|
||||||
import { take } from 'rxjs/operators';
|
import { map, switchMap, take } from 'rxjs/operators';
|
||||||
import { EPerson } from '../../core/eperson/models/eperson.model';
|
import { EPerson } from '../../core/eperson/models/eperson.model';
|
||||||
|
import { of as observableOf, combineLatest as observableCombineLatest } from 'rxjs';
|
||||||
|
|
||||||
export const HAS_AGREED_END_USER = 'hasAgreedEndUser';
|
export const HAS_AGREED_END_USER = 'dsHasAgreedEndUser';
|
||||||
export const KLARO = 'klaro';
|
export const COOKIE_MDFIELD = 'dspace.agreements.cookies';
|
||||||
|
|
||||||
const cookieNameMessagePrefix = 'cookies.consent.app.title.';
|
const cookieNameMessagePrefix = 'cookies.consent.app.title.';
|
||||||
const cookieDescriptionMessagePrefix = 'cookies.consent.app.description.';
|
const cookieDescriptionMessagePrefix = 'cookies.consent.app.description.';
|
||||||
const cookiePurposeMessagePrefix = 'cookies.consent.purpose.';
|
const cookiePurposeMessagePrefix = 'cookies.consent.purpose.';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable()
|
||||||
providedIn: 'root'
|
export class KlaroService {
|
||||||
})
|
|
||||||
|
|
||||||
export class CookiesService {
|
|
||||||
|
|
||||||
message$: BehaviorSubject<string> = new BehaviorSubject<string>('');
|
message$: BehaviorSubject<string> = new BehaviorSubject<string>('');
|
||||||
|
|
||||||
@@ -129,7 +126,7 @@ export class CookiesService {
|
|||||||
purposes: ['acknowledgement'],
|
purposes: ['acknowledgement'],
|
||||||
required: true,
|
required: true,
|
||||||
cookies: [
|
cookies: [
|
||||||
KLARO
|
[/^klaro-.+$/],
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -183,6 +180,7 @@ export class CookiesService {
|
|||||||
passed as the second parameter.
|
passed as the second parameter.
|
||||||
*/
|
*/
|
||||||
callback: (consent, app) => {
|
callback: (consent, app) => {
|
||||||
|
console.log(consent, app);
|
||||||
this.message$.next('User consent for app ' + app.name + ': consent=' + consent);
|
this.message$.next('User consent for app ' + app.name + ': consent=' + consent);
|
||||||
},
|
},
|
||||||
/*
|
/*
|
||||||
@@ -193,41 +191,72 @@ export class CookiesService {
|
|||||||
*/
|
*/
|
||||||
onlyOnce: true,
|
onlyOnce: true,
|
||||||
},
|
},
|
||||||
]
|
],
|
||||||
|
/*
|
||||||
|
You can define an optional callback function that will be called each time the
|
||||||
|
consent state for any given app changes. The consent value will be passed as the
|
||||||
|
first parameter to the function (true=consented). The `app` config will be
|
||||||
|
passed as the second parameter.
|
||||||
|
*/
|
||||||
|
callback: (consent, app) => {
|
||||||
|
|
||||||
|
/*
|
||||||
|
You can define an optional callback function that will be called each time the
|
||||||
|
consent state for any given app changes. The consent value will be passed as the
|
||||||
|
first parameter to the function (true=consented). The `app` config will be
|
||||||
|
passed as the second parameter.
|
||||||
|
*/
|
||||||
|
console.log(
|
||||||
|
'User consent for app ' + app.name + ': consent=' + consent
|
||||||
|
);
|
||||||
|
// this.updateUserCookieConsent();
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private translateService: TranslateService,
|
private translateService: TranslateService,
|
||||||
private authService: AuthService,
|
private authService: AuthService) {
|
||||||
) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
initialize() {
|
initialize() {
|
||||||
this.authService.getAuthenticatedUserFromStore()
|
|
||||||
.subscribe((user: EPerson) => {
|
|
||||||
this.klaroConfig.storageName = 'klaro-' + (user.uuid);
|
|
||||||
|
|
||||||
});
|
|
||||||
/**
|
|
||||||
* Add all message keys for apps and purposes
|
|
||||||
*/
|
|
||||||
this.addAppMessages();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make sure the fallback language is english
|
* Make sure the fallback language is english
|
||||||
*/
|
*/
|
||||||
this.translateService.setDefaultLang(environment.defaultLanguage);
|
this.translateService.setDefaultLang(environment.defaultLanguage);
|
||||||
|
|
||||||
/**
|
const storageName$: Observable<string> = this.authService.isAuthenticated()
|
||||||
* Subscribe on a message to make sure the translation service is ready
|
.pipe(
|
||||||
* Translate all keys in the translation section of the configuration
|
take(1),
|
||||||
* Show the configuration if the configuration has not been confirmed
|
switchMap((loggedIn: boolean) => {
|
||||||
*/
|
if (loggedIn) {
|
||||||
this.translateService.get('loading.default').pipe(take(1)).subscribe(() => {
|
return this.authService.getAuthenticatedUserFromStore().pipe(map((user: EPerson) => 'klaro-' + user.uuid), take(1))
|
||||||
this.translateConfiguration();
|
} else {
|
||||||
Klaro.renderKlaro(this.klaroConfig, false);
|
return observableOf('klaro-anonymous')
|
||||||
Klaro.initialize();
|
}
|
||||||
})
|
})
|
||||||
|
);
|
||||||
|
const translationServiceReady$ = this.translateService.get('loading.default').pipe(take(1));
|
||||||
|
|
||||||
|
observableCombineLatest(storageName$, translationServiceReady$)
|
||||||
|
.subscribe(([name, translation]: string[]) => {
|
||||||
|
this.klaroConfig.storageName = name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add all message keys for apps and purposes
|
||||||
|
*/
|
||||||
|
this.addAppMessages();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscribe on a message to make sure the translation service is ready
|
||||||
|
* Translate all keys in the translation section of the configuration
|
||||||
|
* Show the configuration if the configuration has not been confirmed
|
||||||
|
*/
|
||||||
|
this.translateConfiguration();
|
||||||
|
Klaro.renderKlaro(this.klaroConfig, false);
|
||||||
|
Klaro.initialize();
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private getTitleTranslation(title: string) {
|
private getTitleTranslation(title: string) {
|
||||||
@@ -277,4 +306,12 @@ export class CookiesService {
|
|||||||
});
|
});
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getSettingsForUser(user: EPerson) {
|
||||||
|
return JSON.parse(user.firstMetadataValue(COOKIE_MDFIELD));
|
||||||
|
}
|
||||||
|
|
||||||
|
setSettingsForUser(user: EPerson, config: object) {
|
||||||
|
return user.setMetadata(COOKIE_MDFIELD, undefined, JSON.stringify(config));
|
||||||
|
}
|
||||||
}
|
}
|
@@ -21,9 +21,9 @@ import { AuthService } from '../../app/core/auth/auth.service';
|
|||||||
import { Angulartics2RouterlessModule } from 'angulartics2/routerlessmodule';
|
import { Angulartics2RouterlessModule } from 'angulartics2/routerlessmodule';
|
||||||
import { SubmissionService } from '../../app/submission/submission.service';
|
import { SubmissionService } from '../../app/submission/submission.service';
|
||||||
import { StatisticsModule } from '../../app/statistics/statistics.module';
|
import { StatisticsModule } from '../../app/statistics/statistics.module';
|
||||||
|
import { KlaroService } from '../../app/shared/cookies/klaro.service';
|
||||||
import { HardRedirectService } from '../../app/core/services/hard-redirect.service';
|
import { HardRedirectService } from '../../app/core/services/hard-redirect.service';
|
||||||
import { BrowserHardRedirectService } from '../../app/core/services/browser-hard-redirect.service';
|
import { BrowserHardRedirectService } from '../../app/core/services/browser-hard-redirect.service';
|
||||||
import { CookiesService } from '../../app/shared/cookies/cookies.service';
|
|
||||||
|
|
||||||
export const REQ_KEY = makeStateKey<string>('req');
|
export const REQ_KEY = makeStateKey<string>('req');
|
||||||
|
|
||||||
@@ -85,8 +85,8 @@ export function locationProvider(): Location {
|
|||||||
useClass: ClientCookieService
|
useClass: ClientCookieService
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
provide: CookiesService,
|
provide: KlaroService,
|
||||||
useClass: CookiesService
|
useClass: KlaroService
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
provide: SubmissionService,
|
provide: SubmissionService,
|
||||||
|
@@ -6,5 +6,15 @@
|
|||||||
},
|
},
|
||||||
"angularCompilerOptions": {
|
"angularCompilerOptions": {
|
||||||
"entryModule": "./src/modules/app/server-app.module#ServerAppModule"
|
"entryModule": "./src/modules/app/server-app.module#ServerAppModule"
|
||||||
}
|
},
|
||||||
|
"exclude": [
|
||||||
|
"src/test.ts",
|
||||||
|
"src/**/*.spec.ts",
|
||||||
|
"src/**/*.mock.ts",
|
||||||
|
"src/**/*.test.ts",
|
||||||
|
"src/**/*.stub.ts",
|
||||||
|
"src/**/testing/*",
|
||||||
|
"src/**/mocks/*",
|
||||||
|
"node_modules/klaro"
|
||||||
|
],
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user