Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .commit
Original file line number Diff line number Diff line change
@@ -1 +1 @@
d34e16125bbef14cf07b1e061eab4d0bb9cf8f89
ebc8751bde170ebbe37e86849f6bcfb48150dec7
3 changes: 1 addition & 2 deletions .sync-history
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
83aec620e 2026-06-17 Merged PR 93487: #713974 - Web Portal: Fix SearchMode and RoleAssignmentsFilter reset in IT Shop and Attestation approval APIs
23ef9ee39 2026-06-08 Merged PR 93299: PBI:#710272 - CPL: Fix column name casing for IsWorkingCopy filter
ebc8751bd 2026-06-29 Merged PR 93370: #713400 - Parallelize Web Portal initial page load (App + Start) and make Proj...
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
### June 29, 2026
- 713400: Fixing an issue with Web Portal init page load time.

### June 18, 2026
- 710272: Fixing an issue with Rule violations filter column mismatch.
- 722179: Fixing an issue with new request approval workflow valid dates.
Expand Down
Binary file modified imxweb/imx-modules/imx-api-aad.tgz
Binary file not shown.
Binary file modified imxweb/imx-modules/imx-api-aob.tgz
Binary file not shown.
Binary file modified imxweb/imx-modules/imx-api-apc.tgz
Binary file not shown.
Binary file modified imxweb/imx-modules/imx-api-att.tgz
Binary file not shown.
Binary file modified imxweb/imx-modules/imx-api-cpl.tgz
Binary file not shown.
Binary file modified imxweb/imx-modules/imx-api-dpr.tgz
Binary file not shown.
Binary file modified imxweb/imx-modules/imx-api-hds.tgz
Binary file not shown.
Binary file modified imxweb/imx-modules/imx-api-o3e.tgz
Binary file not shown.
Binary file modified imxweb/imx-modules/imx-api-o3t.tgz
Binary file not shown.
Binary file modified imxweb/imx-modules/imx-api-olg.tgz
Binary file not shown.
Binary file modified imxweb/imx-modules/imx-api-pol.tgz
Binary file not shown.
Binary file modified imxweb/imx-modules/imx-api-qbm.tgz
Binary file not shown.
Binary file modified imxweb/imx-modules/imx-api-qer.tgz
Binary file not shown.
Binary file modified imxweb/imx-modules/imx-api-rmb.tgz
Binary file not shown.
Binary file modified imxweb/imx-modules/imx-api-rms.tgz
Binary file not shown.
Binary file modified imxweb/imx-modules/imx-api-rps.tgz
Binary file not shown.
Binary file modified imxweb/imx-modules/imx-api-sac.tgz
Binary file not shown.
Binary file modified imxweb/imx-modules/imx-api-tsb.tgz
Binary file not shown.
Binary file modified imxweb/imx-modules/imx-api-uci.tgz
Binary file not shown.
Binary file modified imxweb/imx-modules/imx-api.tgz
Binary file not shown.
Binary file modified imxweb/imx-modules/imx-qbm-dbts.tgz
Binary file not shown.
19 changes: 14 additions & 5 deletions imxweb/projects/qer-app-portal/src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,20 @@ export class AppComponent implements OnInit, OnDestroy {
// Needs to close here when running in containers (auth skipped)
splash.close();

const config: QerProjectConfig & ProjectConfig = await projectConfig.getConfig();
const features = (await userModelService.getFeatures()).Features;
const systemInfo = await systemInfoService.get();
const groups = (await userModelService.getGroups()).map((group) => group.Name || '');
this.profileSettings = await this.qerClient.v2Client.portal_profile_get();
// The following calls are independent of each other and can be issued in parallel.
// This is important on installations where individual REST calls may be slow
// (e.g. read-only secondary SQL databases): the post-login wall-clock time
// is bounded by the slowest single call instead of the sum.
const [config, featuresResp, systemInfo, groupsResp, profileSettings] = await Promise.all([
projectConfig.getConfig() as Promise<QerProjectConfig & ProjectConfig>,
userModelService.getFeatures(),
systemInfoService.get(),
userModelService.getGroups(),
this.qerClient.v2Client.portal_profile_get(),
]);
const features = featuresResp.Features;
const groups = groupsResp.map((group) => group.Name || '');
this.profileSettings = profileSettings;
const isUseProfileLangChecked = this.profileSettings.UseProfileLanguage ?? config.PersonConfig?.UseProfileCulture ?? false;
// Set session culture if isUseProfileLangChecked is true, set browser culture otherwise
if (isUseProfileLangChecked) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@

import { Injectable } from '@angular/core';

import { ClassloggerService, SettingsService } from 'qbm';
import { ProjectConfig, QerProjectConfig } from 'imx-api-qer';
import { CachedPromise } from 'imx-qbm-dbts';
import { CacheService, ClassloggerService, SettingsService } from 'qbm';
import { QerApiService } from '../qer-api-client.service';

/**
Expand All @@ -38,27 +39,31 @@ import { QerApiService } from '../qer-api-client.service';
providedIn: 'root'
})
export class ProjectConfigurationService {
private projectConfig: QerProjectConfig & ProjectConfig;
private readonly projectConfigCache: CachedPromise<QerProjectConfig & ProjectConfig>;

constructor(private qerClient: QerApiService,
private readonly settings: SettingsService,
private readonly logger: ClassloggerService) { }
private readonly logger: ClassloggerService,
cacheService: CacheService) {
this.projectConfigCache = cacheService.buildCache(() => this.fetchConfig());
}

public async getConfig(): Promise<QerProjectConfig & ProjectConfig> {
if (this.projectConfig == null) {
this.logger.info(this, 'Project configuration is undefined. Retrieving...');
this.projectConfig = {
...await this.qerClient.client.portal_qer_projectconfig_get(),
...await this.qerClient.client.portal_config_get()
};

this.logger.info(this, 'Received project configuration.');
this.logger.trace(this, '', this.projectConfig);
}

this.settings.DefaultPageSize = this.projectConfig.DefaultPageSize;
const projectConfig = await this.projectConfigCache.get();
this.settings.DefaultPageSize = projectConfig.DefaultPageSize;
return projectConfig;
}

return this.projectConfig;
private async fetchConfig(): Promise<QerProjectConfig & ProjectConfig> {
this.logger.info(this, 'Fetching project configuration...');
const [qerProjectConfig, projectConfig] = await Promise.all([
this.qerClient.client.portal_qer_projectconfig_get(),
this.qerClient.client.portal_config_get()
]);
const merged = { ...qerProjectConfig, ...projectConfig };
this.logger.info(this, 'Received project configuration.');
this.logger.trace(this, '', merged);
return merged;
}

}
23 changes: 17 additions & 6 deletions imxweb/projects/qer/src/lib/wport/start/start.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export class StartComponent implements OnInit {
private readonly detectRef: ChangeDetectorRef,
private readonly projectConfigurationService: ProjectConfigurationService,
private readonly splash: SplashService,
) {}
) { }

public async ngOnInit(): Promise<void> {
this.dashboardService.busyStateChanged.subscribe((busy) => {
Expand All @@ -66,11 +66,22 @@ export class StartComponent implements OnInit {
});
const busy = this.dashboardService.beginBusy();
try {
this.userConfig = await this.userModelSvc.getUserConfig();
this.pendingItems = await this.userModelSvc.getPendingItems();
this.projectConfig = await this.projectConfigurationService.getConfig();
this.systemInfo = await this.systemInfoService.get();
this.userUid = (await this.sessionService.getSessionState()).UserUid;
// The following calls are independent of each other and can be issued in parallel.
// This is important on installations where individual REST calls may be slow
// (e.g. read-only secondary SQL databases): with Promise.all, the splash-screen
// wall-clock time is bounded by the slowest single call instead of the sum.
const [userConfig, pendingItems, projectConfig, systemInfo, sessionState] = await Promise.all([
this.userModelSvc.getUserConfig(),
this.userModelSvc.getPendingItems(),
this.projectConfigurationService.getConfig(),
this.systemInfoService.get(),
this.sessionService.getSessionState(),
]);
this.userConfig = userConfig;
this.pendingItems = pendingItems;
this.projectConfig = projectConfig;
this.systemInfo = systemInfo;
this.userUid = sessionState.UserUid;
} finally {
this.splash.close();
busy.endBusy();
Expand Down
Loading