Skip to content

Commit

Permalink
feat: reload app after configuration call
Browse files Browse the repository at this point in the history
if the locale cookie is different from current locale
  • Loading branch information
SGrueber committed Jun 16, 2023
1 parent 5ec1e6f commit 2a8400d
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 36 deletions.
16 changes: 6 additions & 10 deletions src/app/core/pipes/make-href.pipe.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@ describe('Make Href Pipe', () => {
providers: [{ provide: MultiSiteService, useFactory: () => instance(multiSiteService) }, MakeHrefPipe],
});
makeHrefPipe = TestBed.inject(MakeHrefPipe);
when(multiSiteService.getLangUpdatedUrl(anything(), anything(), anything())).thenCall(
(url: string, _: LocationStrategy) => of(url)
when(multiSiteService.getLangUpdatedUrl(anything(), anything())).thenCall((url: string, _: LocationStrategy) =>
of(url)
);
when(multiSiteService.appendUrlParams(anything(), anything(), anything())).thenCall(
(url: string, _, __: string) => url
);
});

Expand All @@ -30,13 +33,6 @@ describe('Make Href Pipe', () => {
it.each<any | jest.DoneCallback>([
[undefined, undefined, 'undefined'],
['/test', undefined, '/test'],
['/test', {}, '/test'],
['/test', { foo: 'bar' }, '/test;foo=bar'],
['/test', { foo: 'bar', marco: 'polo' }, '/test;foo=bar;marco=polo'],
['/test?query=q', undefined, '/test?query=q'],
['/test?query=q', {}, '/test?query=q'],
['/test?query=q', { foo: 'bar' }, '/test;foo=bar?query=q'],
['/test?query=q', { foo: 'bar', marco: 'polo' }, '/test;foo=bar;marco=polo?query=q'],
])(`should transform "%s" with %j to "%s"`, (url, params, expected, done: jest.DoneCallback) => {
makeHrefPipe.transform({ path: () => url, getBaseHref: () => '/' } as LocationStrategy, params).subscribe(res => {
expect(res).toEqual(expected);
Expand All @@ -48,7 +44,7 @@ describe('Make Href Pipe', () => {
makeHrefPipe
.transform({ path: () => '/de/test', getBaseHref: () => '/de' } as LocationStrategy, { lang: 'en_US' })
.subscribe(() => {
verify(multiSiteService.getLangUpdatedUrl(anything(), anything(), anything())).once();
verify(multiSiteService.getLangUpdatedUrl(anything(), anything())).once();
done();
});
});
Expand Down
18 changes: 4 additions & 14 deletions src/app/core/pipes/make-href.pipe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,29 +21,19 @@ export class MakeHrefPipe implements PipeTransform {

if (urlParams) {
if (urlParams.lang) {
return this.multiSiteService.getLangUpdatedUrl(urlParams.lang, newUrl, location.getBaseHref()).pipe(
return this.multiSiteService.getLangUpdatedUrl(urlParams.lang, newUrl).pipe(
map(modifiedUrl => {
const modifiedUrlParams = modifiedUrl === newUrl ? urlParams : omit(urlParams, 'lang');
return appendUrlParams(modifiedUrl, modifiedUrlParams, split?.[1]);
return this.multiSiteService.appendUrlParams(modifiedUrl, modifiedUrlParams, split?.[1]);
})
);
} else {
return of(newUrl).pipe(map(url => appendUrlParams(url, urlParams, split?.[1])));
return of(newUrl).pipe(map(url => this.multiSiteService.appendUrlParams(url, urlParams, split?.[1])));
}
} else {
return of(appendUrlParams(newUrl, undefined, split?.[1]));
return of(this.multiSiteService.appendUrlParams(newUrl, undefined, split?.[1]));
}
})
);
}
}

function appendUrlParams(url: string, urlParams: Record<string, string>, queryParams: string | undefined): string {
return `${url}${
urlParams
? Object.keys(urlParams)
.map(k => `;${k}=${urlParams[k]}`)
.join('')
: ''
}${queryParams ? `?${queryParams}` : ''}`;
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ import { FeatureToggleModule } from 'ish-core/feature-toggle.module';
import { ConfigurationService } from 'ish-core/services/configuration/configuration.service';
import { CoreStoreModule } from 'ish-core/store/core/core-store.module';
import { serverConfigError } from 'ish-core/store/core/error';
import { CookiesService } from 'ish-core/utils/cookies/cookies.service';
import { makeHttpError } from 'ish-core/utils/dev/api-service-utils';
import { StoreWithSnapshots, provideStoreSnapshots } from 'ish-core/utils/dev/ngrx-testing';
import { routerTestNavigationAction } from 'ish-core/utils/dev/routing';
import { MultiSiteService } from 'ish-core/utils/multi-site/multi-site.service';

import { loadServerConfig, loadServerConfigFail, loadServerConfigSuccess } from './server-config.actions';
import { ServerConfigEffects } from './server-config.effects';
Expand Down Expand Up @@ -67,6 +69,8 @@ describe('Server Config Effects', () => {
TestBed.configureTestingModule({
providers: [
{ provide: ConfigurationService, useFactory: () => instance(configurationServiceMock) },
{ provide: CookiesService, useFactory: () => instance(mock(CookiesService)) },
{ provide: MultiSiteService, useFactory: () => instance(mock(MultiSiteService)) },
provideMockActions(() => actions$),
provideMockStore(),
ServerConfigEffects,
Expand Down
39 changes: 36 additions & 3 deletions src/app/core/store/core/server-config/server-config.effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@ import { Actions, createEffect, ofType } from '@ngrx/effects';
import { routerNavigationAction } from '@ngrx/router-store';
import { Store, select } from '@ngrx/store';
import { EMPTY, identity } from 'rxjs';
import { concatMap, first, map, switchMap, takeWhile } from 'rxjs/operators';
import { concatMap, filter, first, map, switchMap, take, takeWhile, withLatestFrom } from 'rxjs/operators';

import { FeatureToggleService } from 'ish-core/feature-toggle.module';
import { ServerConfig } from 'ish-core/models/server-config/server-config.model';
import { ConfigurationService } from 'ish-core/services/configuration/configuration.service';
import { applyConfiguration } from 'ish-core/store/core/configuration';
import { applyConfiguration, getCurrentLocale } from 'ish-core/store/core/configuration';
import { ConfigurationState } from 'ish-core/store/core/configuration/configuration.reducer';
import { serverConfigError } from 'ish-core/store/core/error';
import { personalizationStatusDetermined } from 'ish-core/store/customer/user';
import { CookiesService } from 'ish-core/utils/cookies/cookies.service';
import { MultiSiteService } from 'ish-core/utils/multi-site/multi-site.service';
import { delayUntil, mapErrorToAction, mapToPayloadProperty, whenFalsy, whenTruthy } from 'ish-core/utils/operators';

import {
Expand All @@ -29,7 +31,9 @@ export class ServerConfigEffects {
private actions$: Actions,
private store: Store,
private configService: ConfigurationService,
private featureToggleService: FeatureToggleService
private featureToggleService: FeatureToggleService,
private cookiesService: CookiesService,
private multiSiteService: MultiSiteService
) {}

/**
Expand Down Expand Up @@ -57,6 +61,35 @@ export class ServerConfigEffects {
)
);

switchToPreferredLanguage$ = createEffect(
() =>
this.actions$.pipe(
ofType(loadServerConfigSuccess),
withLatestFrom(this.store.pipe(select(getCurrentLocale))),
map(([, currentLocale]) => ['locale', currentLocale]),
map(([, currentLocale]) => [this.cookiesService.get('locale'), currentLocale]),
filter(([preferredLocale, locale]) => preferredLocale && preferredLocale !== locale),
concatMap(([preferredLocale]) => {
const splittedUrl = location.pathname?.split('?');
const newUrl = splittedUrl[0];

return this.multiSiteService.getLangUpdatedUrl(preferredLocale, newUrl).pipe(
whenTruthy(),
take(1),
map(modifiedUrl => {
const modifiedUrlParams = modifiedUrl === newUrl ? { lang: preferredLocale } : {};
return this.multiSiteService.appendUrlParams(modifiedUrl, modifiedUrlParams, splittedUrl?.[1]);
}),
concatMap(url => {
location.assign(url);
return EMPTY;
})
);
})
),
{ dispatch: false }
);

loadExtraServerConfig$ = createEffect(() =>
this.actions$.pipe(
ofType(loadServerConfig),
Expand Down
27 changes: 23 additions & 4 deletions src/app/core/utils/multi-site/multi-site.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { APP_BASE_HREF } from '@angular/common';
import { TestBed } from '@angular/core/testing';
import { provideMockStore } from '@ngrx/store/testing';

Expand All @@ -16,7 +17,10 @@ describe('Multi Site Service', () => {

beforeEach(() => {
TestBed.configureTestingModule({
providers: [provideMockStore({ selectors: [{ selector: getMultiSiteLocaleMap, value: multiSiteLocaleMap }] })],
providers: [
{ provide: APP_BASE_HREF, useValue: '/de' },
provideMockStore({ selectors: [{ selector: getMultiSiteLocaleMap, value: multiSiteLocaleMap }] }),
],
});
multiSiteService = TestBed.inject(MultiSiteService);
});
Expand All @@ -25,21 +29,36 @@ describe('Multi Site Service', () => {
expect(multiSiteService).toBeTruthy();
});
it('should return url unchanged if no language baseHref exists', done => {
multiSiteService.getLangUpdatedUrl('de_DE', '/testpath', '/').subscribe(url => {
multiSiteService.getLangUpdatedUrl('de_DE', '/testpath').subscribe(url => {
expect(url).toMatchInlineSnapshot(`"/testpath"`);
done();
});
});
it('should return with new url if language baseHref exists and language is valid', done => {
multiSiteService.getLangUpdatedUrl('en_US', '/de/testpath', '/de').subscribe(url => {
multiSiteService.getLangUpdatedUrl('en_US', '/de/testpath').subscribe(url => {
expect(url).toMatchInlineSnapshot(`"/en/testpath"`);
done();
});
});
it('should return url unchanged if language baseHref exists but language is invalid', done => {
multiSiteService.getLangUpdatedUrl('xy_XY', '/de/testpath', '/de').subscribe(url => {
multiSiteService.getLangUpdatedUrl('xy_XY', '/de/testpath').subscribe(url => {
expect(url).toMatchInlineSnapshot(`"/de/testpath"`);
done();
});
});

it.each([
[undefined, undefined, 'undefined'],
['/test', undefined, '/test'],
['/test', {}, '/test'],
['/test', { foo: 'bar' }, '/test;foo=bar'],
['/test', { foo: 'bar', marco: 'polo' }, '/test;foo=bar;marco=polo'],
['/test?query=q', undefined, '/test?query=q'],
['/test?query=q', {}, '/test?query=q'],
['/test?query=q', { foo: 'bar' }, '/test;foo=bar?query=q'],
['/test?query=q', { foo: 'bar', marco: 'polo' }, '/test;foo=bar;marco=polo?query=q'],
])(`should transform "%s" with %j to "%s"`, (url, params, expected) => {
const splittedUrl = url?.split('?');
expect(multiSiteService.appendUrlParams(splittedUrl?.[0], params, splittedUrl?.[1])).toBe(expected);
});
});
21 changes: 16 additions & 5 deletions src/app/core/utils/multi-site/multi-site.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Injectable } from '@angular/core';
import { APP_BASE_HREF } from '@angular/common';
import { Inject, Injectable } from '@angular/core';
import { Store, select } from '@ngrx/store';
import { Observable } from 'rxjs';
import { map, take } from 'rxjs/operators';
Expand All @@ -9,7 +10,7 @@ export type MultiSiteLocaleMap = Record<string, unknown> | undefined;

@Injectable({ providedIn: 'root' })
export class MultiSiteService {
constructor(private store: Store) {}
constructor(private store: Store, @Inject(APP_BASE_HREF) private baseHref: string) {}

/**
* returns the current url, modified to fit the locale parameter if the environment parameter "multiSiteLocaleMap" is set
Expand All @@ -19,7 +20,7 @@ export class MultiSiteService {
* @param baseHref the current baseHref which needs to be replaced
* @returns the modified url
*/
getLangUpdatedUrl(locale: string, url: string, baseHref: string): Observable<string> {
getLangUpdatedUrl(locale: string, url: string): Observable<string> {
return this.store.pipe(
select(getMultiSiteLocaleMap),
take(1),
Expand All @@ -33,15 +34,25 @@ export class MultiSiteService {
*/
if (
multiSiteLocaleMap &&
Object.values(multiSiteLocaleMap).includes(baseHref) &&
Object.values(multiSiteLocaleMap).includes(this.baseHref) &&
localeMapHasLangString(locale, multiSiteLocaleMap)
) {
newUrl = newUrl.replace(baseHref, multiSiteLocaleMap[locale]);
newUrl = newUrl.replace(this.baseHref, multiSiteLocaleMap[locale]);
}
return newUrl;
})
);
}

appendUrlParams(url: string, urlParams: Record<string, string>, queryParams: string | undefined): string {
return `${url}${
urlParams
? Object.keys(urlParams)
.map(k => `;${k}=${urlParams[k]}`)
.join('')
: ''
}${queryParams ? `?${queryParams}` : ''}`;
}
}

function localeMapHasLangString(
Expand Down

0 comments on commit 2a8400d

Please sign in to comment.