Skip to content

Commit f711033

Browse files
committed
feat: luigi lifecycle hooks config service implementation
1 parent f280e05 commit f711033

10 files changed

+196
-5
lines changed

package-lock.json

Lines changed: 26 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
"@angular-eslint/template-parser": "17.5.2",
4242
"@angular/cli": "^17.3.8",
4343
"@angular/compiler-cli": "^17.3.0",
44+
"@angular/localize": "17.3.11",
4445
"@briebug/jest-schematic": "^6.0.0",
4546
"@luigi-project/client": "2.14.1",
4647
"@luigi-project/client-support-angular": "2.14.1",

src/lib/injection-tokens.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
export const LUIGI_STATIC_SETTINGS_CONFIG_SERVICE_INJECTION_TOKEN =
22
'OPENMFP_LUIGI_STATIC_SETTINGS_CONFIG_SERVICE';
33
export const LUIGI_CUSTOM_MESSAGE_LISTENERS_INJECTION_TOKEN =
4-
'OPENMFP_LUIGI_CUSTOM_MESSAGE_LISTENERS_INJECTION_TOKEN';
4+
'OPENMFP_LUIGI_CUSTOM_MESSAGE_LISTENERS';
5+
export const LUIGI_USER_SETTINGS_CONFIG_SERVICE_INJECTION_TOKEN =
6+
'OPENMFP_LUIGI_USER_SETTINGS_CONFIG_SERVICE';
7+
export const LUIGI_GLOBAL_SEARCH_CONFIG_SERVICE_INJECTION_TOKEN =
8+
'OPENMFP_LUIGI_GLOBAL_SEARCH_CONFIG_SERVICE';
59
export const LOCAL_NODES_SERVICE_INJECTION_TOKEN =
610
'OPENMFP_LOCAL_NODES_SERVICE_INJECTION_TOKEN';

src/lib/portal.module.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ import { RouterOutlet } from '@angular/router';
55
import {
66
LOCAL_NODES_SERVICE_INJECTION_TOKEN,
77
LUIGI_CUSTOM_MESSAGE_LISTENERS_INJECTION_TOKEN,
8+
LUIGI_GLOBAL_SEARCH_CONFIG_SERVICE_INJECTION_TOKEN,
89
LUIGI_STATIC_SETTINGS_CONFIG_SERVICE_INJECTION_TOKEN,
10+
LUIGI_USER_SETTINGS_CONFIG_SERVICE_INJECTION_TOKEN,
911
} from './injection-tokens';
1012
import { LogoutComponent } from './logout/logout.component';
1113
import { LuigiComponent } from './luigi/luigi.component';
@@ -19,6 +21,14 @@ import {
1921
LocalNodesService,
2022
NoopLocalNodesService,
2123
} from './services';
24+
import {
25+
NoopUserSettingsConfigService,
26+
UserSettingsConfigService,
27+
} from './services/luigi-config/user-settings-config.service';
28+
import {
29+
GlobalSearchConfigService,
30+
NoopGlobalSearchConfigService,
31+
} from './services/luigi-config/global-search-config.service';
2232

2333
export interface PortalModuleOptions {
2434
/** Service containing and providing the luigi settings configuration **/
@@ -29,6 +39,12 @@ export interface PortalModuleOptions {
2939

3040
/** Service providing local nodes merging services **/
3141
localNodesService?: Type<LocalNodesService>;
42+
43+
/** Service providing user setting specific configuration **/
44+
userSettingsConfigService: Type<UserSettingsConfigService>;
45+
46+
/** Service providing global search configuration **/
47+
globalSearchConfigService: Type<GlobalSearchConfigService>;
3248
}
3349

3450
@NgModule({
@@ -43,6 +59,14 @@ export interface PortalModuleOptions {
4359
provide: LUIGI_STATIC_SETTINGS_CONFIG_SERVICE_INJECTION_TOKEN,
4460
useClass: StaticSettingsConfigServiceImpl,
4561
},
62+
{
63+
provide: LUIGI_USER_SETTINGS_CONFIG_SERVICE_INJECTION_TOKEN,
64+
useClass: NoopUserSettingsConfigService,
65+
},
66+
{
67+
provide: LUIGI_GLOBAL_SEARCH_CONFIG_SERVICE_INJECTION_TOKEN,
68+
useClass: NoopGlobalSearchConfigService,
69+
},
4670
{
4771
provide: LOCAL_NODES_SERVICE_INJECTION_TOKEN,
4872
useClass: NoopLocalNodesService,
@@ -81,6 +105,16 @@ export class PortalModule {
81105
provide: LOCAL_NODES_SERVICE_INJECTION_TOKEN,
82106
useClass: options.localNodesService || NoopLocalNodesService,
83107
},
108+
{
109+
provide: LUIGI_USER_SETTINGS_CONFIG_SERVICE_INJECTION_TOKEN,
110+
useClass:
111+
options.userSettingsConfigService || NoopUserSettingsConfigService,
112+
},
113+
{
114+
provide: LUIGI_GLOBAL_SEARCH_CONFIG_SERVICE_INJECTION_TOKEN,
115+
useClass:
116+
options.globalSearchConfigService || NoopGlobalSearchConfigService,
117+
},
84118
],
85119
imports: [
86120
PortalRoutingModule,
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
export interface GlobalSearchConfigService {
2+
getGlobalSearchConfig(): any;
3+
}
4+
5+
export class NoopGlobalSearchConfigService
6+
implements GlobalSearchConfigService
7+
{
8+
getGlobalSearchConfig() {
9+
return undefined;
10+
}
11+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import { Inject, Injectable } from '@angular/core';
2+
import { $localize } from '@angular/localize/init';
3+
import { I18nService } from '../i18n.service';
4+
import { LuigiCoreService } from '../luigi-core.service';
5+
import { LuigiNodesService } from '../luigi-nodes/luigi-nodes.service';
6+
import { GlobalSearchConfigService } from './global-search-config.service';
7+
import { RoutingConfigService } from './routing-config.service';
8+
import { StaticSettingsConfigService } from './static-settings-config.service';
9+
import { UserSettingsConfigService } from './user-settings-config.service';
10+
import {
11+
LUIGI_GLOBAL_SEARCH_CONFIG_SERVICE_INJECTION_TOKEN,
12+
LUIGI_STATIC_SETTINGS_CONFIG_SERVICE_INJECTION_TOKEN,
13+
LUIGI_USER_SETTINGS_CONFIG_SERVICE_INJECTION_TOKEN,
14+
} from '../../injection-tokens';
15+
import { LuigiNode } from '../../models/luigi';
16+
import { ClientEnvironment } from '../../models/env';
17+
18+
@Injectable({ providedIn: 'root' })
19+
export class LifecycleHooksConfigService {
20+
constructor(
21+
private i18nService: I18nService,
22+
private luigiNodesService: LuigiNodesService,
23+
private luigiCoreService: LuigiCoreService,
24+
private routingConfigService: RoutingConfigService,
25+
@Inject(LUIGI_STATIC_SETTINGS_CONFIG_SERVICE_INJECTION_TOKEN)
26+
private staticSettingsConfigService: StaticSettingsConfigService,
27+
@Inject(LUIGI_USER_SETTINGS_CONFIG_SERVICE_INJECTION_TOKEN)
28+
private userSettingsConfigService: UserSettingsConfigService,
29+
@Inject(LUIGI_GLOBAL_SEARCH_CONFIG_SERVICE_INJECTION_TOKEN)
30+
private globalSearchConfigService: GlobalSearchConfigService
31+
) {}
32+
33+
getLifecycleHooksConfig(envConfig: ClientEnvironment) {
34+
return {
35+
luigiAfterInit: async () => {
36+
this.i18nService.afterInit();
37+
38+
let childrenByEntity: Record<string, LuigiNode[]>;
39+
40+
try {
41+
childrenByEntity =
42+
await this.luigiNodesService.retrieveChildrenByEntity();
43+
} catch (e) {
44+
console.error(`Error retrieving Luigi navigation nodes ${e}`);
45+
this.openErrorDialog();
46+
}
47+
48+
const config = {
49+
...this.luigiCoreService.getConfig(),
50+
lifecycleHooks: {},
51+
settings:
52+
await this.staticSettingsConfigService.getStaticSettingsConfig(),
53+
routing: this.routingConfigService.getRoutingConfig(),
54+
userSettings:
55+
await this.userSettingsConfigService.getUserSettings(
56+
childrenByEntity
57+
),
58+
globalSearch: this.globalSearchConfigService.getGlobalSearchConfig(),
59+
};
60+
61+
this.luigiCoreService.ux().hideAppLoadingIndicator();
62+
this.luigiCoreService.setConfig(config);
63+
if (this.luigiCoreService.isFeatureToggleActive('btpLayout')) {
64+
this.luigiCoreService.resetLuigi();
65+
}
66+
},
67+
};
68+
}
69+
70+
private openErrorDialog() {
71+
const appTitle =
72+
this.staticSettingsConfigService.getInitialStaticSettingsConfig()[
73+
'header'
74+
].title;
75+
this.luigiCoreService
76+
.showAlert({
77+
text: $localize`There was an error loading the ${appTitle}`,
78+
type: 'error',
79+
})
80+
.then(() => {
81+
location.reload();
82+
});
83+
}
84+
}

src/lib/services/luigi-config/luigi-config.service.spec.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { ClientEnvironment } from '../../models/env';
55
import { RoutingConfigService } from './routing-config.service';
66
import { StaticSettingsConfigService } from './static-settings-config.service';
77
import { CustomMessageListenersService } from './custom-message-listeners.service';
8+
import { LifecycleHooksConfigService } from './lifecycle-hooks-config.service';
89

910
describe('LuigiConfigService', () => {
1011
let service: LuigiConfigService;
@@ -13,6 +14,7 @@ describe('LuigiConfigService', () => {
1314
let staticSettingsConfigServiceMock: jest.Mocked<StaticSettingsConfigService>;
1415
let customMessageListenersMock: jest.Mocked<CustomMessageListenersService>;
1516
let routingConfigServiceMock: jest.Mocked<RoutingConfigService>;
17+
let lifecycleHooksConfigServiceMock: jest.Mocked<LifecycleHooksConfigService>;
1618

1719
beforeEach(() => {
1820
envConfigServiceMock = {
@@ -36,11 +38,16 @@ describe('LuigiConfigService', () => {
3638
getRoutingConfig: jest.fn(),
3739
} as any;
3840

41+
lifecycleHooksConfigServiceMock = {
42+
getLifecycleHooksConfig: jest.fn(),
43+
} as any;
44+
3945
service = new LuigiConfigService(
4046
envConfigServiceMock,
4147
authConfigServiceMock,
4248
customMessageListenersMock,
4349
routingConfigServiceMock,
50+
lifecycleHooksConfigServiceMock,
4451
staticSettingsConfigServiceMock
4552
);
4653
});
@@ -69,6 +76,10 @@ describe('LuigiConfigService', () => {
6976
customMessagesListeners: { 'id-43545': () => {} },
7077
};
7178

79+
const mockLifecycleHooks = {
80+
luigiAfterInit: null,
81+
};
82+
7283
const mockRoutingConfig = {
7384
useHashRouting: false,
7485
showModalPathInUrl: false,
@@ -78,12 +89,15 @@ describe('LuigiConfigService', () => {
7889

7990
envConfigServiceMock.getEnvConfig.mockResolvedValue(mockEnvConfig);
8091
authConfigServiceMock.getAuthConfig.mockReturnValue(mockAuthConfig);
92+
lifecycleHooksConfigServiceMock.getLifecycleHooksConfig.mockReturnValue(
93+
mockLifecycleHooks
94+
);
8195
staticSettingsConfigServiceMock.getInitialStaticSettingsConfig.mockReturnValue(
8296
mockStaticSettings
8397
);
84-
jest
85-
.spyOn(customMessageListenersMock, 'getMessageListeners')
86-
.mockReturnValue(mockCommunicationConfig);
98+
customMessageListenersMock.getMessageListeners.mockReturnValue(
99+
mockCommunicationConfig
100+
);
87101
routingConfigServiceMock.getInitialRoutingConfig.mockReturnValue(
88102
mockRoutingConfig
89103
);
@@ -106,6 +120,7 @@ describe('LuigiConfigService', () => {
106120
routing: mockRoutingConfig,
107121
settings: mockStaticSettings,
108122
communication: mockCommunicationConfig,
123+
lifecycleHooks: mockLifecycleHooks,
109124
});
110125
});
111126
});

src/lib/services/luigi-config/luigi-config.service.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { EnvConfigService } from '../portal/env-config.service';
66
import { RoutingConfigService } from './routing-config.service';
77
import { StaticSettingsConfigService } from './static-settings-config.service';
88
import { CustomMessageListenersService } from './custom-message-listeners.service';
9+
import { LifecycleHooksConfigService } from './lifecycle-hooks-config.service';
910

1011
@Injectable({
1112
providedIn: 'root',
@@ -16,6 +17,7 @@ export class LuigiConfigService {
1617
private authConfigService: AuthConfigService,
1718
private customMessageListenersService: CustomMessageListenersService,
1819
private routingConfigService: RoutingConfigService,
20+
private lifecycleHooksConfigService: LifecycleHooksConfigService,
1921
@Inject(LUIGI_STATIC_SETTINGS_CONFIG_SERVICE_INJECTION_TOKEN)
2022
private staticSettingsConfigService: StaticSettingsConfigService
2123
) {}
@@ -32,6 +34,8 @@ export class LuigiConfigService {
3234
communication: this.customMessageListenersService.getMessageListeners(),
3335
settings:
3436
this.staticSettingsConfigService.getInitialStaticSettingsConfig(),
37+
lifecycleHooks:
38+
this.lifecycleHooksConfigService.getLifecycleHooksConfig(envConfig),
3539
};
3640
}
3741
}

src/lib/services/luigi-config/static-settings-config.service.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { Injectable } from '@angular/core';
2-
import { LuigiCoreService } from '../luigi-core.service';
32

43
export interface StaticSettingsConfigService {
54
getInitialStaticSettingsConfig(): Record<string, any>;
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { LuigiNode } from '../../models/luigi';
2+
3+
export interface UserSettingsConfigService {
4+
getUserSettings(luigiNodes: Record<string, LuigiNode[]>): Promise<any>;
5+
}
6+
7+
export class NoopUserSettingsConfigService
8+
implements UserSettingsConfigService
9+
{
10+
async getUserSettings(luigiNodes: Record<string, LuigiNode[]>): Promise<any> {
11+
return undefined;
12+
}
13+
}

0 commit comments

Comments
 (0)