diff --git a/.commit b/.commit
index 1f3a8e7c6..d6edabbfe 100644
--- a/.commit
+++ b/.commit
@@ -1 +1 @@
-47d44c74207f3d773d1ffa718dc102fa887f1cab
+f1d5948d892d7b711ece214c0813f59849a9676b
diff --git a/.sync-history b/.sync-history
index a7f049007..e69de29bb 100644
--- a/.sync-history
+++ b/.sync-history
@@ -1 +0,0 @@
-41487b63c 2024-02-29 Merged PR 65170: #446439 - Develop new request url params
\ No newline at end of file
diff --git a/README.md b/README.md
index e3d4fbc0a..01e5c1e5d 100644
--- a/README.md
+++ b/README.md
@@ -3,6 +3,42 @@
# Identity Manager HTML5 applications
## Change log
+
+### May 6, 2024
+
+We are integrating [Compodoc](https://compodoc.app/) to provide Angular documentation for our components. Please see the [Documentation](#documentation) section for more information on how to generate documentation.
+
+The package versions have been updated to 9.2.1.
+
+The `v92` branch has been updated with fixes for the following issues.
+
+**Important**: Integrating these changes will require a server-side hotfix for the issue 454356 to be installed.
+
+- 454675: Fixed an issue where sometimes a blank screen was displayed instead of the login page
+- 446439: Fixed the preselection of a child service category on the new request page
+- 440745: Fixed the preset of the search term on the new request page
+- 454356: Data Explorer identities needs to load interactive entities.
+- 453350/447417/453346: Fixed issues where the filter wizard could enter an inconsistent state
+- 453132: Fixed an issue in the attestation policy editor where the "objects matching the condition" were not displayed hierarchically
+- 438231: Added documentation of some basic components
+- 450070: Fixed an issue where switching to another page while loading a page caused an error
+- 453932: Fixed an issue where approving multiple requests in bulk could cause an error
+- 439918: Fixed some issues in the product bundles component
+- 450675: Fixed an issue where some help text was shown in an incorrect language
+- 452886: Fixed an issue in the attestation policy editor
+- 449616: Fixed an issue where reports could not be saved in format other then PDF
+- 450404: Fixed an issue in the overview of attestation case approvers.
+- 442324: Duplicate (additional) "Target system" columns in the Data Explorer
+- 448531: Fixed a scrolling issue on the organizational chart view
+- 449891: Fixed the inherited group membership pagination
+- 448406: Fixed an issue where the list of entitlements assigned to a role was incomplete
+- 418493: Fixed an issue in the overview of request approvers
+- 447713: Fixed a styling issue with the login button
+- 449124: Fixed the declaration of the metadata service
+- 447723: Fixed an issue with additional columns in a grouped table view
+- 442324: Fixed the duplicate "Target system" columns in the Data Explorer
+- 447039: Fixed an issue where the FK picker could enter an inconsistent state
+
### March 11, 2024
The v92 branch has been updated with fixes for the following issues.
diff --git a/imxweb/.vscode/settings.json b/imxweb/.vscode/settings.json
index e309221cd..4aad9f8c8 100644
--- a/imxweb/.vscode/settings.json
+++ b/imxweb/.vscode/settings.json
@@ -1,5 +1,8 @@
{
"explorer.compactFolders": false,
"editor.tabSize": 2,
- "git.ignoreLimitWarning": true
+ "git.ignoreLimitWarning": true,
+ "cSpell.words": [
+ "requestable"
+ ]
}
\ No newline at end of file
diff --git a/imxweb/compodoc/assets/images/dashboard/1-dashboard.png b/imxweb/compodoc/assets/images/dashboard/1-dashboard.png
new file mode 100644
index 000000000..edf1cfc10
Binary files /dev/null and b/imxweb/compodoc/assets/images/dashboard/1-dashboard.png differ
diff --git a/imxweb/compodoc/assets/images/dashboard/2-block-identity-component.png b/imxweb/compodoc/assets/images/dashboard/2-block-identity-component.png
new file mode 100644
index 000000000..b13885428
Binary files /dev/null and b/imxweb/compodoc/assets/images/dashboard/2-block-identity-component.png differ
diff --git a/imxweb/compodoc/assets/images/dashboard/3-example-template-code.png b/imxweb/compodoc/assets/images/dashboard/3-example-template-code.png
new file mode 100644
index 000000000..8c3e2c37c
Binary files /dev/null and b/imxweb/compodoc/assets/images/dashboard/3-example-template-code.png differ
diff --git a/imxweb/compodoc/assets/images/dashboard/4-example-component-code.png b/imxweb/compodoc/assets/images/dashboard/4-example-component-code.png
new file mode 100644
index 000000000..a44f720ac
Binary files /dev/null and b/imxweb/compodoc/assets/images/dashboard/4-example-component-code.png differ
diff --git a/imxweb/compodoc/assets/images/dashboard/5-block-identity-button.png b/imxweb/compodoc/assets/images/dashboard/5-block-identity-button.png
new file mode 100644
index 000000000..8acfc5764
Binary files /dev/null and b/imxweb/compodoc/assets/images/dashboard/5-block-identity-button.png differ
diff --git a/imxweb/compodoc/assets/images/data_table/1-overall-structure.png b/imxweb/compodoc/assets/images/data_table/1-overall-structure.png
new file mode 100644
index 000000000..75393aaad
Binary files /dev/null and b/imxweb/compodoc/assets/images/data_table/1-overall-structure.png differ
diff --git a/imxweb/compodoc/assets/images/data_table/2-first-version.png b/imxweb/compodoc/assets/images/data_table/2-first-version.png
new file mode 100644
index 000000000..f8daef573
Binary files /dev/null and b/imxweb/compodoc/assets/images/data_table/2-first-version.png differ
diff --git a/imxweb/compodoc/assets/images/data_table/3-table-with-search-enabled.png b/imxweb/compodoc/assets/images/data_table/3-table-with-search-enabled.png
new file mode 100644
index 000000000..3759f2f26
Binary files /dev/null and b/imxweb/compodoc/assets/images/data_table/3-table-with-search-enabled.png differ
diff --git a/imxweb/compodoc/assets/images/data_table/4-table-with-search.png b/imxweb/compodoc/assets/images/data_table/4-table-with-search.png
new file mode 100644
index 000000000..6a09aad1f
Binary files /dev/null and b/imxweb/compodoc/assets/images/data_table/4-table-with-search.png differ
diff --git a/imxweb/compodoc/assets/images/menu/1-menu-bar.png b/imxweb/compodoc/assets/images/menu/1-menu-bar.png
new file mode 100644
index 000000000..51181e40a
Binary files /dev/null and b/imxweb/compodoc/assets/images/menu/1-menu-bar.png differ
diff --git a/imxweb/compodoc/assets/images/menu/2-example-folder.png b/imxweb/compodoc/assets/images/menu/2-example-folder.png
new file mode 100644
index 000000000..671e583f9
Binary files /dev/null and b/imxweb/compodoc/assets/images/menu/2-example-folder.png differ
diff --git a/imxweb/compodoc/assets/images/menu/3-sub-item-menu.png b/imxweb/compodoc/assets/images/menu/3-sub-item-menu.png
new file mode 100644
index 000000000..a857698c4
Binary files /dev/null and b/imxweb/compodoc/assets/images/menu/3-sub-item-menu.png differ
diff --git a/imxweb/compodoc/samples/data_table.md b/imxweb/compodoc/samples/data_table.md
new file mode 100644
index 000000000..f202a0893
--- /dev/null
+++ b/imxweb/compodoc/samples/data_table.md
@@ -0,0 +1,261 @@
+# Working with data tables
+
+A frequently recurring task is the representation of data in tables. The IMX QBM library offers components that facilitate the visualization of data and take the special IMX data structure into account.
+
+Data tables offer a lot of configuration possibilities. We will present the most important ones in this sample.
+
+The two most important modules in this context are "data-source-toolbar" (projects\qbm\src\lib\data-source-toolbar) and "data-table" (projects\qbm\src\lib\data-table).
+
+The basic structure consists of 3 elements, the data source toolbar, the actual table and a paginator.
+
+
+
+In addition to the ability to search, filter, etc, the Data Source Toolbar contains a Data Source component that is used by the Data Table and the Paginator to display data and move within the data set. Think of the DST (Data Source Toolbar) as a link between the Data Table and the Paginator.
+
+
+The "Hello World" version of the Data Table component looks like as follow.
+
+> Code
+``` html
+
{{ '#LDS#Identities' | translate }}
+
+
+
+
+
+
+
+```
+
+> Code
+``` ts
+
+@Component({
+ selector: 'imx-select-identity',
+ templateUrl: './select-identity.component.html',
+ styleUrls: ['./select-identity.component.scss'],
+})
+export class SelectIdentityComponent implements OnInit {
+ public dstSettings: DataSourceToolbarSettings;
+ public readonly schema: EntitySchema;
+ public readonly DisplayColumns = DisplayColumns;
+ public navigationState: CollectionLoadParameters = { PageSize: 20 };
+
+ private displayedColumns: IClientProperty[] = [];
+
+ constructor(private readonly qerApiClient: QerApiService) {
+ this.schema = this.qerApiClient.typedClient.PortalPersonAll.GetSchema();
+ this.displayedColumns = [
+ this.schema.Columns[DisplayColumns.DISPLAY_PROPERTYNAME],
+ this.schema.Columns.DefaultEmailAddress
+ ];
+ }
+
+ public async ngOnInit(): Promise {
+ await this.navigate();
+ }
+
+ public async onNavigationStateChanged(newState?: CollectionLoadParameters): Promise {
+ if (newState) {
+ this.navigationState = newState;
+ }
+ await this.navigate();
+ }
+
+ private async navigate(): Promise {
+ const data = await this.qerApiClient.typedClient.PortalPersonAll.Get(this.navigationState);
+
+ this.dstSettings = {
+ displayedColumns: this.displayedColumns,
+ dataSource: data,
+ entitySchema: this.schema,
+ navigationState: this.navigationState,
+ };
+ }
+}
+
+```
+
+The minimum set of properties that must be set are "EntitySchema", "DisplayColumns" and "CollectionLoadParameters".
+
+Three places in the .ts Datei are worth to be highlighted.
+
+> Code
+``` ts
+ this.displayedColumns = [
+ this.schema.Columns[DisplayColumns.DISPLAY_PROPERTYNAME],
+ this.schema.Columns.DefaultEmailAddress
+ ];
+```
+
+"displayedColumns" defines which columns the table should display.
+
+> Code
+``` ts
+ public async onNavigationStateChanged(newState?: CollectionLoadParameters): Promise {
+ if (newState) {
+ this.navigationState = newState;
+ }
+ await this.navigate();
+ }
+```
+
+This event handler is called every time the state of the data changes, e.g. when the user navigates to the next page.
+
+> Code
+``` ts
+ private async navigate(): Promise {
+ const data = await this.qerApiClient.typedClient.PortalPersonAll.Get(this.navigationState);
+
+ this.dstSettings = {
+ displayedColumns: this.displayedColumns,
+ dataSource: data,
+ entitySchema: this.schema,
+ navigationState: this.navigationState,
+ };
+ }
+```
+The "navigate()" method retrievs data from the API server. The actual request is made by calling the API client ("this.qerApiClient.typedClient.PortalPersonAll.Get(this.navigationState)"). The concept of API clients is described in a separate sample.
+
+The first version of the component looks like this.
+
+
+
+## Designing the table
+
+The table above shows two fields that are rendered automatically. It is also possible to design columns manually. Whether the table is rendered automatically or manually is controlled by the "mode" input field.
+
+> Code
+``` html
+
+
+```
+
+"mode" can take two values: "auto" and "manual".
+
+To display the previous table in manual mode, we need to add the two columns to the html template.
+
+> Code
+``` html
+
+
+
+
+
+
+
+```
+In the next step we will add a new column to the table containing a button and slightly modify the first column.
+
+The first column currently shows the default display of the object. We want to add a second row that indicates whether the person is a primary identity or not.
+
+> Code
+``` html
+
+
+
+
+
+
+
+```
+
+Next we will add a third column that will contain a button. To display data of an object the table uses the "" tag. To display other types of elements, such as buttons, we use the "" tag.
+Before we can display the button, we need to add the new synthetic column to the columns to be displayed. This is done in the *.ts file.
+
+> Code
+``` ts
+ this.displayedColumns = [
+ this.schema.Columns[DisplayColumns.DISPLAY_PROPERTYNAME],
+ this.schema.Columns.DefaultEmailAddress,
+ {
+ ColumnName: 'viewDetailsButton',
+ Type: ValType.String
+ }
+ ];
+```
+
+
+> Code
+``` html
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+The extended component now looks like this.
+
+
+
+## Adding search
+
+Enabling search is pretty straightforward.
+To do this, you must first enable the "search" option and secondly implement a method that processes the output of the "search" output parameter.
+
+The following code snippets shows these changes.
+
+> Code
+``` html
+
+```
+
+> Code
+``` ts
+ public async onSearch(keywords: string): Promise {
+ this.navigationState.StartIndex = 0;
+ this.navigationState.search = keywords;
+ await this.navigate();
+ }
+```
+
+
+
+
+
+
+
+
diff --git a/imxweb/compodoc/samples/menu.md b/imxweb/compodoc/samples/menu.md
new file mode 100644
index 000000000..bd441ac5c
--- /dev/null
+++ b/imxweb/compodoc/samples/menu.md
@@ -0,0 +1,121 @@
+# Adding a menu to the Portal
+
+In the previous example, we added a tile component to the dashboard to block a user's account.
+
+In this example, we want to add a new item to the portal main menu to achieve the same functionality.
+
+The main menu (projects\qbm\src\lib\menu) is a central component, just like the dashboard.
+
+
+
+New menus and menu items are dynamically added to the main menu via a plugin system.
+
+Before we implement the menu, we have to add a route that navigates to the (currently empty) component where you can select the identity you want to block.
+
+We will name the new component SelectIdentityComponent.
+
+
+
+First we add a new entry to the routing table.
+
+> Code
+
+``` ts
+const routes: Routes = [
+ :
+ {
+ path: 'selectidentity',
+ component: SelectIdentityComponent
+ }
+];
+```
+
+Now we can add the new menu with the associated route. Again, as in the previous example, this can be done in the init service (init-service.ts). In the code snippet below, only the part where the menu is added is shown, the rest is hidden.
+
+> Code
+
+``` ts
+:
+
+@Injectable({ providedIn: 'root' })
+export class InitService {
+ :
+
+ public onInit(routes: Route[]): void {
+ this.addRoutes(routes);
+ :
+ }
+
+ private addRoutes(routes: Route[]): void {
+ const config = this.router.config;
+ routes.forEach((route) => {
+ config.unshift(route);
+ });
+ this.router.resetConfig(config);
+ }
+
+ private setupMenu(): void {
+ this.menuService.addMenuFactories(
+ :
+ (preProps: string[], __: string[]) => {
+ return {
+ id: 'ROOT_SAMPLES',
+ title: '#LDS#Samples'
+ items: [
+ {
+ id: 'SAMPLE_SELECT_IDENTITY',
+ route: 'selectidentity',
+ title: '#LDS#Select Identity'
+ },
+ ],
+ };
+ );
+ }
+}
+```
+
+You can add menus and menu items via the menu service (projects\qbm\src\lib\menu). The structure of the menu and the menu items is defined by the menu-item.interface.ts file. The most important properties are "id" and "title". If you add a menu item, the "route" property specifies the route of the component to be displayed.
+
+Here is an extract of the file.
+
+> Code
+
+``` ts
+import { ProjectConfig } from 'imx-api-qbm';
+import { NavigationCommandsMenuItem } from './navigation-commands-menu-item.interface';
+
+/** Represents a single menu item. */
+export interface MenuItem {
+ /** Unique identifier for the menu item. */
+ readonly id?: string;
+
+ /** Display name. */
+ readonly title: string;
+
+ /** Returns a descriptive text, intended for tooltips. */
+ readonly description?: string;
+
+ /** Property for simple navigation. */
+ readonly route?: string;
+
+ /** Property for sorting the items. */
+ readonly sorting?: string;
+
+ /** Property for complex navigation, including outlets etc. */
+ navigationCommands?: NavigationCommandsMenuItem;
+
+ /** Called when the menu item is clicked. */
+ readonly trigger?: () => void;
+
+ /** Submenu items. */
+ items?: MenuItem[];
+
+}
+
+export type MenuFactory = (preProps: string[], groups: string[], projectConfig: ProjectConfig) => MenuItem;
+
+```
+
+The final result looks like this.
+
+
\ No newline at end of file
diff --git a/imxweb/compodoc/samples/samples.md b/imxweb/compodoc/samples/samples.md
new file mode 100644
index 000000000..4400068fc
--- /dev/null
+++ b/imxweb/compodoc/samples/samples.md
@@ -0,0 +1,6 @@
+# SDK Samples
+
+Currently, the following examples are available:
+- [Adding a tile component to the dashboard](sdk-samples/adding-a-tile-component-to-the-dashboard.html)
+- [Adding a menu to the Portal](sdk-samples/adding-a-menu-to-the-portal.html)
+- [Working with data tables](sdk-samples/working-with-data-tables.html)
diff --git a/imxweb/compodoc/samples/tiles.md b/imxweb/compodoc/samples/tiles.md
new file mode 100644
index 000000000..a63df6f71
--- /dev/null
+++ b/imxweb/compodoc/samples/tiles.md
@@ -0,0 +1,119 @@
+# Adding a tile component to the dashboard
+
+The IMX Portal landing page consists of the IMX Dashboard component, which can be found in the QER library (projects\qer\src\lib\wport\start).
+
+It is composed of 3 sections with different tiles.
+
+
+
+
+Tiles can be added dynamically to the dashboard. The following example gives an overview of the different types of tiles and demonstrates how to add a new element - the blue bordered tile - to the dashboard.
+
+
+## Dashboard tiles
+
+The Tiles modules (projects\qbm\src\lib\tile) and (projects\qer\src\lib\tiles) offer different base components :
+
+- TileComponent (QBM)
+- BadgeTileComponent (QER)
+- IconTileComponent (QER)
+- NotificationTileComponent (QER)
+
+
+These components are variations of the same concept. In the further course we will implement a new tile based on the IconTileComponent.
+
+
+## Implementing the "Block Identity" Tile
+
+What is the fictitious but realistic scenario we will implement?
+There is a security breach and an administrator wants to block the account of the affected identity. The implementation of this scenario will span several examples. Here we will first create the tile that can trigger that process.
+
+### Creating the "Block Identity" Component
+
+First we need to create the "Block Identity" component. We assume that the reader has a basic knowledge of the Angular framework and knows how to create components, services, etc.
+
+The component consists of 3 files, but we will not pay further attention to the stylesheet.
+
+
+
+### The anatomy of the "Block Identity" component
+
+Basically, the component consists of 2 parts, a Typescript file and the corresponding HTML template.
+
+
+The HTML template is based on the previously mentioned IconTileComponent component.
+
+> Code
+
+``` html
+
+
+
+
+
+```
+
+The IconTileComponent expects some input fields like "caption", "image" or "subtitle". Which tiles components expect which inputs can be found in the Tiles Module.
+
+> NOTE
+
+> IMX components and applications are based on the One Identity Elemental UI framework, which in turn extends Angular Material. The "eui-icon" tag is such an Elemental UI component (https://elemental.dev.oneidentity.com/)
+
+The corresponding *.ts component is not very exciting. On the other hand it sets the "Description" property/input used in the template and implements the (dummy) "block()" method.
+
+> Code
+``` ts
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'imx-block-identity',
+ templateUrl: './block-identity.component.html',
+ styleUrls: ['./block-identity.component.scss']
+})
+export class BlockIdentityComponent {
+ public description = 'Blocks an identity and marks the identity as security risk.';
+
+ constructor() { }
+
+ public block(): void {
+ alert('Block Tile Clicked');
+ }
+
+}
+```
+
+That's all we need at this time for the "Block Identity" component.
+
+## Wiring it up
+The next step is to include the component into the dashboard.
+To do this, we must make it available to the web application, in this case the portal.
+This is done in the init service of the corresponding library (don't worry, there will be more samples on the topic).
+
+Here is the relevant section of the service.
+
+> Code
+
+``` ts
+@Injectable({ providedIn: 'root' })
+export class InitService {
+ public onInit(routes: Route[]): void {
+ this.extService.register('Dashboard-MediumTiles', {
+ instance: BlockIdentityComponent,
+ });
+ }
+}
+```
+
+The final result looks like this.
+
+
+
+
+
+
+
+
diff --git a/imxweb/custom-theme/package.json b/imxweb/custom-theme/package.json
index f4bfb5e0c..e7f5dfe70 100644
--- a/imxweb/custom-theme/package.json
+++ b/imxweb/custom-theme/package.json
@@ -1,6 +1,6 @@
{
"name": "custom-theme",
- "version": "9.2.0",
+ "version": "9.2.1",
"private": true,
"scripts": {
"build": "sass custom-theme.scss:custom-theme.css --load-path=..\\node_modules"
diff --git a/imxweb/imx-modules/imx-api-aad.tgz b/imxweb/imx-modules/imx-api-aad.tgz
index a642a0ab1..b9da9f74a 100644
Binary files a/imxweb/imx-modules/imx-api-aad.tgz and b/imxweb/imx-modules/imx-api-aad.tgz differ
diff --git a/imxweb/imx-modules/imx-api-aob.tgz b/imxweb/imx-modules/imx-api-aob.tgz
index c56353b6c..c47c2f7cd 100644
Binary files a/imxweb/imx-modules/imx-api-aob.tgz and b/imxweb/imx-modules/imx-api-aob.tgz differ
diff --git a/imxweb/imx-modules/imx-api-apc.tgz b/imxweb/imx-modules/imx-api-apc.tgz
index 68124e7f8..353e32491 100644
Binary files a/imxweb/imx-modules/imx-api-apc.tgz and b/imxweb/imx-modules/imx-api-apc.tgz differ
diff --git a/imxweb/imx-modules/imx-api-att.tgz b/imxweb/imx-modules/imx-api-att.tgz
index 4f3caf4b4..05e83b24d 100644
Binary files a/imxweb/imx-modules/imx-api-att.tgz and b/imxweb/imx-modules/imx-api-att.tgz differ
diff --git a/imxweb/imx-modules/imx-api-cpl.tgz b/imxweb/imx-modules/imx-api-cpl.tgz
index 4a0677067..ccdd8c8bb 100644
Binary files a/imxweb/imx-modules/imx-api-cpl.tgz and b/imxweb/imx-modules/imx-api-cpl.tgz differ
diff --git a/imxweb/imx-modules/imx-api-dpr.tgz b/imxweb/imx-modules/imx-api-dpr.tgz
index bfd20e551..66fa0a585 100644
Binary files a/imxweb/imx-modules/imx-api-dpr.tgz and b/imxweb/imx-modules/imx-api-dpr.tgz differ
diff --git a/imxweb/imx-modules/imx-api-hds.tgz b/imxweb/imx-modules/imx-api-hds.tgz
index bba3ce95d..7fdbb7540 100644
Binary files a/imxweb/imx-modules/imx-api-hds.tgz and b/imxweb/imx-modules/imx-api-hds.tgz differ
diff --git a/imxweb/imx-modules/imx-api-o3e.tgz b/imxweb/imx-modules/imx-api-o3e.tgz
index 6e2a5935c..99a49756b 100644
Binary files a/imxweb/imx-modules/imx-api-o3e.tgz and b/imxweb/imx-modules/imx-api-o3e.tgz differ
diff --git a/imxweb/imx-modules/imx-api-o3t.tgz b/imxweb/imx-modules/imx-api-o3t.tgz
index 3a0ddb76c..3198ddd2c 100644
Binary files a/imxweb/imx-modules/imx-api-o3t.tgz and b/imxweb/imx-modules/imx-api-o3t.tgz differ
diff --git a/imxweb/imx-modules/imx-api-olg.tgz b/imxweb/imx-modules/imx-api-olg.tgz
index db36d77cd..9fbfea458 100644
Binary files a/imxweb/imx-modules/imx-api-olg.tgz and b/imxweb/imx-modules/imx-api-olg.tgz differ
diff --git a/imxweb/imx-modules/imx-api-pol.tgz b/imxweb/imx-modules/imx-api-pol.tgz
index 30a794265..bdd35084c 100644
Binary files a/imxweb/imx-modules/imx-api-pol.tgz and b/imxweb/imx-modules/imx-api-pol.tgz differ
diff --git a/imxweb/imx-modules/imx-api-qbm.tgz b/imxweb/imx-modules/imx-api-qbm.tgz
index d97914308..46b5dbf33 100644
Binary files a/imxweb/imx-modules/imx-api-qbm.tgz and b/imxweb/imx-modules/imx-api-qbm.tgz differ
diff --git a/imxweb/imx-modules/imx-api-qer.tgz b/imxweb/imx-modules/imx-api-qer.tgz
index 114a4d653..e49d40b66 100644
Binary files a/imxweb/imx-modules/imx-api-qer.tgz and b/imxweb/imx-modules/imx-api-qer.tgz differ
diff --git a/imxweb/imx-modules/imx-api-rmb.tgz b/imxweb/imx-modules/imx-api-rmb.tgz
index 2bdbb5a43..c7b37acab 100644
Binary files a/imxweb/imx-modules/imx-api-rmb.tgz and b/imxweb/imx-modules/imx-api-rmb.tgz differ
diff --git a/imxweb/imx-modules/imx-api-rms.tgz b/imxweb/imx-modules/imx-api-rms.tgz
index e214f843e..9a025df64 100644
Binary files a/imxweb/imx-modules/imx-api-rms.tgz and b/imxweb/imx-modules/imx-api-rms.tgz differ
diff --git a/imxweb/imx-modules/imx-api-rps.tgz b/imxweb/imx-modules/imx-api-rps.tgz
index e9b966344..1ca610ba9 100644
Binary files a/imxweb/imx-modules/imx-api-rps.tgz and b/imxweb/imx-modules/imx-api-rps.tgz differ
diff --git a/imxweb/imx-modules/imx-api-sac.tgz b/imxweb/imx-modules/imx-api-sac.tgz
index 6041a60e3..e6d9c8a8d 100644
Binary files a/imxweb/imx-modules/imx-api-sac.tgz and b/imxweb/imx-modules/imx-api-sac.tgz differ
diff --git a/imxweb/imx-modules/imx-api-tsb.tgz b/imxweb/imx-modules/imx-api-tsb.tgz
index 4cb4cfef1..36900ff1a 100644
Binary files a/imxweb/imx-modules/imx-api-tsb.tgz and b/imxweb/imx-modules/imx-api-tsb.tgz differ
diff --git a/imxweb/imx-modules/imx-api-uci.tgz b/imxweb/imx-modules/imx-api-uci.tgz
index a4bb73659..51648c9cb 100644
Binary files a/imxweb/imx-modules/imx-api-uci.tgz and b/imxweb/imx-modules/imx-api-uci.tgz differ
diff --git a/imxweb/imx-modules/imx-api.tgz b/imxweb/imx-modules/imx-api.tgz
index 78e874d66..b6a37ec44 100644
Binary files a/imxweb/imx-modules/imx-api.tgz and b/imxweb/imx-modules/imx-api.tgz differ
diff --git a/imxweb/imx-modules/imx-qbm-dbts.tgz b/imxweb/imx-modules/imx-qbm-dbts.tgz
index e55521c45..af7251247 100644
Binary files a/imxweb/imx-modules/imx-qbm-dbts.tgz and b/imxweb/imx-modules/imx-qbm-dbts.tgz differ
diff --git a/imxweb/package-lock.json b/imxweb/package-lock.json
index 411f3c3ab..850f8f221 100644
--- a/imxweb/package-lock.json
+++ b/imxweb/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "imxweb",
- "version": "9.2.0",
+ "version": "9.2.1",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
diff --git a/imxweb/package.json b/imxweb/package.json
index f5e916d4e..70d61de05 100644
--- a/imxweb/package.json
+++ b/imxweb/package.json
@@ -1,6 +1,6 @@
{
"name": "imxweb",
- "version": "9.2.0",
+ "version": "9.2.1",
"scripts": {
"ng": "ng",
"start": "ng serve --configuration development",
diff --git a/imxweb/projects/aad/.compodocrc.json b/imxweb/projects/aad/.compodocrc.json
index 887a5929c..c4e734351 100644
--- a/imxweb/projects/aad/.compodocrc.json
+++ b/imxweb/projects/aad/.compodocrc.json
@@ -1,11 +1,12 @@
{
"name": "IMX Web - AAD Library",
- "output": "../../documentation/aad",
+ "output": "../../documentation/v92/aad",
"theme": "material",
"assetsFolder": "../../compodoc/assets",
"customLogo": "../../compodoc/assets/images/oneidentity-logo.png",
"customFavicon": "../../compodoc/assets/images/favicon.ico",
- "serve": true,
- "watch": true,
- "coverageTest": 0
+ "serve": false,
+ "watch": false,
+ "coverageTest": 0,
+ "disableCoverage": true
}
diff --git a/imxweb/projects/aad/package.json b/imxweb/projects/aad/package.json
index d0291f568..df0bfba60 100644
--- a/imxweb/projects/aad/package.json
+++ b/imxweb/projects/aad/package.json
@@ -1,6 +1,6 @@
{
"name": "aad",
- "version": "9.2.0",
+ "version": "9.2.1",
"private": true,
"bundledDependencies": [
"imx-api-aad"
diff --git a/imxweb/projects/aob/.compodocrc.json b/imxweb/projects/aob/.compodocrc.json
index 6967afd81..6bac08861 100644
--- a/imxweb/projects/aob/.compodocrc.json
+++ b/imxweb/projects/aob/.compodocrc.json
@@ -1,11 +1,12 @@
{
"name": "IMX Web - AOB Library",
- "output": "../../documentation/aob",
+ "output": "../../documentation/v92/aob",
"theme": "material",
"assetsFolder": "../../compodoc/assets",
"customLogo": "../../compodoc/assets/images/oneidentity-logo.png",
"customFavicon": "../../compodoc/assets/images/favicon.ico",
- "serve": true,
- "watch": true,
- "coverageTest": 0
+ "serve": false,
+ "watch": false,
+ "coverageTest": 0,
+ "disableCoverage": true
}
diff --git a/imxweb/projects/aob/package.json b/imxweb/projects/aob/package.json
index e19f2b74b..5c8ce28bf 100644
--- a/imxweb/projects/aob/package.json
+++ b/imxweb/projects/aob/package.json
@@ -1,6 +1,6 @@
{
"name": "aob",
- "version": "9.2.0",
+ "version": "9.2.1",
"private": true,
"bundledDependencies": [
"imx-api-aob"
diff --git a/imxweb/projects/aob/src/lib/entitlements/entitlement-add/entitlements-add.component.ts b/imxweb/projects/aob/src/lib/entitlements/entitlement-add/entitlements-add.component.ts
index 3f8b567af..d683dde62 100644
--- a/imxweb/projects/aob/src/lib/entitlements/entitlement-add/entitlements-add.component.ts
+++ b/imxweb/projects/aob/src/lib/entitlements/entitlement-add/entitlements-add.component.ts
@@ -37,7 +37,7 @@ import {
StorageService,
MetadataService,
DataSourceToolbarFilter,
- CdrFactoryService
+ CdrFactoryService,
} from 'qbm';
import { CollectionLoadParameters, IClientProperty, EntitySchema, DisplayColumns, TypedEntity, FilterData } from 'imx-qbm-dbts';
import { EntitlementsService } from '../entitlements.service';
@@ -53,7 +53,7 @@ const helperAlertKey = `${HELPER_ALERT_KEY_PREFIX}_addNewEntitlements`;
@Component({
selector: 'imx-entitlements-add',
templateUrl: './entitlements-add.component.html',
- styleUrls: ['./entitlements-add.component.scss']
+ styleUrls: ['./entitlements-add.component.scss'],
})
export class EntitlementsAddComponent implements OnInit {
public readonly EntitlementsType = EntitlementsType; // Enables use of this Enum in Angular Templates.
@@ -70,7 +70,9 @@ export class EntitlementsAddComponent implements OnInit {
public selections: TypedEntity[];
public readonly browserCulture: string;
public entitlementSourceTypes: EntitlementSourceType[] = [];
- public get showHelperAlert(): boolean { return !this.storageService.isHelperAlertDismissed(helperAlertKey); }
+ public get showHelperAlert(): boolean {
+ return !this.storageService.isHelperAlertDismissed(helperAlertKey);
+ }
private filters: DataSourceToolbarFilter[];
@@ -83,7 +85,8 @@ export class EntitlementsAddComponent implements OnInit {
private readonly storageService: StorageService,
private readonly metaData: MetadataService,
private readonly sidesheet: EuiSidesheetService,
- private readonly translateService: TranslateService) {
+ private readonly translateService: TranslateService,
+ ) {
this.selectedSourceType = data.defaultType;
this.isSystemRolesEnabled = data.isSystemRolesEnabled;
@@ -91,8 +94,7 @@ export class EntitlementsAddComponent implements OnInit {
}
public async ngOnInit(): Promise {
-
- await this.metaData.update(['ESet', 'UNSGroup', 'QERResource', 'RPSReport', 'TSBAccountDef']);
+ await this.metaData.updateNonExisting(['ESet', 'UNSGroup', 'QERResource', 'RPSReport', 'TSBAccountDef']);
this.entitlementSourceTypes = [
{ entitlementsType: EntitlementsType.UnsGroup, display: this.metaData.tables.UNSGroup.Display },
@@ -112,7 +114,6 @@ export class EntitlementsAddComponent implements OnInit {
this.storageService.storeHelperAlertDismissal(helperAlertKey);
}
-
/**
* Call to toggle the view and show entitlements candidates or roles candidates.
*/
@@ -129,15 +130,17 @@ export class EntitlementsAddComponent implements OnInit {
}
public async onCreateRole(): Promise {
- const entitlementSystemRoleInput: EntitlementSystemRoleInput
- = await this.sidesheet.open(SystemRoleConfigComponent, {
+ const entitlementSystemRoleInput: EntitlementSystemRoleInput = await this.sidesheet
+ .open(SystemRoleConfigComponent, {
// TODO: make LDS Heading
title: await this.translateService.get('#LDS#Create new system role').toPromise(),
padding: '0px',
width: 'max(500px, 50%)',
testId: 'create-role-sidesheet',
- data: { uid: this.data.uidApplication, createOnly: true }
- }).afterClosed().toPromise();
+ data: { uid: this.data.uidApplication, createOnly: true },
+ })
+ .afterClosed()
+ .toPromise();
if (!entitlementSystemRoleInput) {
this.logger.debug(this, 'role dialog canceled');
@@ -151,21 +154,24 @@ export class EntitlementsAddComponent implements OnInit {
}
public async onAddToRole(): Promise {
- const entitlementSystemRoleInput: EntitlementSystemRoleInput
- = await this.sidesheet.open(SystemRoleConfigComponent, {
+ const entitlementSystemRoleInput: EntitlementSystemRoleInput = await this.sidesheet
+ .open(SystemRoleConfigComponent, {
title: await this.translateService.get('#LDS#Heading Merge Application Entitlements into System Role').toPromise(),
padding: '0px',
width: 'max(500px, 50%)',
testId: 'add-to-existing-role-sidesheet',
- data: { uid: this.data.uidApplication, createOnly: false }
- }).afterClosed().toPromise();
+ data: { uid: this.data.uidApplication, createOnly: false },
+ })
+ .afterClosed()
+ .toPromise();
if (!entitlementSystemRoleInput) {
this.logger.debug(this, 'role dialog canceled');
return;
}
- const keys = this.selections.map((elem: TypedEntity) => CdrFactoryService.tryGetColumn(elem.GetEntity(), 'XObjectKey')?.GetValue())
+ const keys = this.selections
+ .map((elem: TypedEntity) => CdrFactoryService.tryGetColumn(elem.GetEntity(), 'XObjectKey')?.GetValue())
.filter((elem: string) => elem != null);
if (keys.length < this.selections.length) {
@@ -207,7 +213,7 @@ export class EntitlementsAddComponent implements OnInit {
this.selectedSourceType = type;
this.entitySchema = this.entitlementsProvider.candidateSchema(type);
let overlayRef: OverlayRef;
- setTimeout(() => overlayRef = this.busyService.show());
+ setTimeout(() => (overlayRef = this.busyService.show()));
try {
this.filters = (await this.entitlementsProvider.getDataModel(type))?.Filters;
} finally {
@@ -223,7 +229,7 @@ export class EntitlementsAddComponent implements OnInit {
private async updateCandidates(): Promise {
let overlayRef: OverlayRef;
- setTimeout(() => overlayRef = this.busyService.show());
+ setTimeout(() => (overlayRef = this.busyService.show()));
try {
this.logger.debug(this, 'Get candidates from the server...');
const data = await this.entitlementsProvider.getCandidates(this.selectedSourceType, this.navigationState);
@@ -234,16 +240,17 @@ export class EntitlementsAddComponent implements OnInit {
entitySchema: this.entitySchema,
navigationState: this.navigationState,
filters: this.filters,
- filterTree: this.selectedSourceType === EntitlementsType.UnsGroup ?
- {
- filterMethode: async (parentkey) => {
- return this.entitlementsProvider.getEntitlementsFilterTree({
- parentkey,
- });
- },
- multiSelect: false,
- }
- : undefined
+ filterTree:
+ this.selectedSourceType === EntitlementsType.UnsGroup
+ ? {
+ filterMethode: async (parentkey) => {
+ return this.entitlementsProvider.getEntitlementsFilterTree({
+ parentkey,
+ });
+ },
+ multiSelect: false,
+ }
+ : undefined,
};
if (data == null) {
@@ -254,21 +261,22 @@ export class EntitlementsAddComponent implements OnInit {
}
}
- private getDisplayedColumnsForEntitlement(
- entitySchema: EntitySchema,
- type: EntitlementsType): IClientProperty[] {
- if (!entitySchema) { return []; }
+ private getDisplayedColumnsForEntitlement(entitySchema: EntitySchema, type: EntitlementsType): IClientProperty[] {
+ if (!entitySchema) {
+ return [];
+ }
switch (type) {
case EntitlementsType.UnsGroup:
return [
entitySchema.Columns[DisplayColumns.DISPLAY_PROPERTYNAME],
entitySchema.Columns.CanonicalName,
- entitySchema.Columns.UID_UNSRoot
+ entitySchema.Columns.UID_UNSRoot,
];
default:
return [entitySchema.Columns[DisplayColumns.DISPLAY_PROPERTYNAME]];
}
}
- public LdsInfoAlert = '#LDS#Here you can assign application entitlements to the application. Once assigned, you can publish these application entitlements so that they can be requested.';
+ public LdsInfoAlert =
+ '#LDS#Here you can assign application entitlements to the application. Once assigned, you can publish these application entitlements so that they can be requested.';
}
diff --git a/imxweb/projects/aob/src/lib/entitlements/entitlement-edit-auto-add/entitlement-edit-auto-add.component.html b/imxweb/projects/aob/src/lib/entitlements/entitlement-edit-auto-add/entitlement-edit-auto-add.component.html
index 317f5c16a..2d6a5d5a6 100644
--- a/imxweb/projects/aob/src/lib/entitlements/entitlement-edit-auto-add/entitlement-edit-auto-add.component.html
+++ b/imxweb/projects/aob/src/lib/entitlements/entitlement-edit-auto-add/entitlement-edit-auto-add.component.html
@@ -1,6 +1,6 @@
-
+
diff --git a/imxweb/projects/aob/src/lib/entitlements/entitlement-edit-auto-add/entitlement-edit-auto-add.component.ts b/imxweb/projects/aob/src/lib/entitlements/entitlement-edit-auto-add/entitlement-edit-auto-add.component.ts
index 9054ec639..b942b2618 100644
--- a/imxweb/projects/aob/src/lib/entitlements/entitlement-edit-auto-add/entitlement-edit-auto-add.component.ts
+++ b/imxweb/projects/aob/src/lib/entitlements/entitlement-edit-auto-add/entitlement-edit-auto-add.component.ts
@@ -49,8 +49,11 @@ export class EntitlementEditAutoAddComponent implements OnDestroy {
public sqlExpression: SqlWizardExpression;
- public checkChanges(): void {
- this.exprHasntChanged = _.isEqual(this.data.sqlExpression, this.sqlExpression);
+ public checkChanges(expression: SqlExpression): void {
+ this.exprHasntChanged = _.isEqual(expression, this.sqlExpression.Expression);
+ if (!this.exprHasntChanged) {
+ this.sqlExpression.Expression = expression;
+ }
}
public get controlsInvalid(): boolean {
@@ -99,7 +102,8 @@ export class EntitlementEditAutoAddComponent implements OnDestroy {
}
const entitlementToAdd = this.entitlementToAddWrapperService.buildTypedEntities(elements);
- const saveChanges: { save: boolean; map: boolean } = await this.sidesheet.open(MappedEntitlementsPreviewComponent, {
+ const saveChanges: { save: boolean; map: boolean } = await this.sidesheet
+ .open(MappedEntitlementsPreviewComponent, {
title: await this.translateService.get('#LDS#Heading View Matching Application Entitlements').toPromise(),
subTitle: this.data.application.GetEntity().GetDisplay(),
padding: '0px',
diff --git a/imxweb/projects/aob/src/lib/entitlements/entitlements.component.ts b/imxweb/projects/aob/src/lib/entitlements/entitlements.component.ts
index 3cedef830..3321f6199 100644
--- a/imxweb/projects/aob/src/lib/entitlements/entitlements.component.ts
+++ b/imxweb/projects/aob/src/lib/entitlements/entitlements.component.ts
@@ -135,7 +135,7 @@ export class EntitlementsComponent implements OnChanges {
private readonly settingsService: SettingsService,
private readonly systemInfo: SystemInfoService,
private readonly metadata: MetadataService,
- private readonly autoAddService: EntitlementEditAutoAddService
+ private readonly autoAddService: EntitlementEditAutoAddService,
) {
this.entitySchema = entitlementsProvider.entitlementSchema;
this.displayedColumns = [
@@ -309,7 +309,7 @@ export class EntitlementsComponent implements OnChanges {
try {
this.logger.debug(
this,
- `Publishing entitlement(s)/role(s) ${publishData.date && publishData.publishFuture ? `on ${publishData.date}` : 'now'}`
+ `Publishing entitlement(s)/role(s) ${publishData.date && publishData.publishFuture ? `on ${publishData.date}` : 'now'}`,
);
const publishCount = await this.entitlementsProvider.publish(selectedEntitlements, publishData);
@@ -477,7 +477,7 @@ export class EntitlementsComponent implements OnChanges {
return;
}
- this.unassignedDisabled = selection.some(elem => elem.IsDynamic.value === true);
+ this.unassignedDisabled = selection.some((elem) => elem.IsDynamic.value === true);
let foundPublished = false;
let foundUnpublished = false;
@@ -556,7 +556,7 @@ export class EntitlementsComponent implements OnChanges {
if (success) {
this.snackbar.open(
{ key: '#LDS#The application entitlements have been successfully merged into the system role and added to application.' },
- '#LDS#Close'
+ '#LDS#Close',
);
await this.getData();
}
@@ -598,7 +598,7 @@ export class EntitlementsComponent implements OnChanges {
}
this.updatedTableNames.push(...newTableNamesForUpdate);
this.logger.trace(this, 'following items are added to the list of table names', newTableNamesForUpdate);
- return this.metadata.update([...new Set(newTableNamesForUpdate)]);
+ return this.metadata.updateNonExisting([...new Set(newTableNamesForUpdate)]);
}
private async createEntitlementWrapper(entitlement: PortalEntitlement): Promise {
diff --git a/imxweb/projects/apc/.compodocrc.json b/imxweb/projects/apc/.compodocrc.json
index 73d69ccf8..442e29f03 100644
--- a/imxweb/projects/apc/.compodocrc.json
+++ b/imxweb/projects/apc/.compodocrc.json
@@ -1,11 +1,12 @@
{
"name": "IMX Web - APC Library",
- "output": "../../documentation/apc",
+ "output": "../../documentation/v92/apc",
"theme": "material",
"assetsFolder": "../../compodoc/assets",
"customLogo": "../../compodoc/assets/images/oneidentity-logo.png",
"customFavicon": "../../compodoc/assets/images/favicon.ico",
- "serve": true,
- "watch": true,
- "coverageTest": 0
+ "serve": false,
+ "watch": false,
+ "coverageTest": 0,
+ "disableCoverage": true
}
diff --git a/imxweb/projects/apc/package.json b/imxweb/projects/apc/package.json
index e9bae9c71..344a4c47d 100644
--- a/imxweb/projects/apc/package.json
+++ b/imxweb/projects/apc/package.json
@@ -1,6 +1,6 @@
{
"name": "apc",
- "version": "9.2.0",
+ "version": "9.2.1",
"private": true,
"bundledDependencies": [
"imx-api-apc"
diff --git a/imxweb/projects/apc/src/lib/software/software.component.ts b/imxweb/projects/apc/src/lib/software/software.component.ts
index 908501532..cb659972d 100644
--- a/imxweb/projects/apc/src/lib/software/software.component.ts
+++ b/imxweb/projects/apc/src/lib/software/software.component.ts
@@ -29,7 +29,14 @@ import { EuiSidesheetService } from '@elemental-ui/core';
import { TranslateService } from '@ngx-translate/core';
import { CollectionLoadParameters, DataModel, DisplayColumns, EntitySchema, IClientProperty, TypedEntity } from 'imx-qbm-dbts';
-import { BusyService, DataSourceToolbarSettings, HelpContextualValues, LdsReplacePipe, MetadataService, SideNavigationComponent } from 'qbm';
+import {
+ BusyService,
+ DataSourceToolbarSettings,
+ HelpContextualValues,
+ LdsReplacePipe,
+ MetadataService,
+ SideNavigationComponent,
+} from 'qbm';
import { SoftwareSidesheetComponent } from './software-sidesheet/software-sidesheet.component';
import { SoftwareService } from './software.service';
@@ -56,14 +63,14 @@ export class SoftwareComponent implements OnInit, SideNavigationComponent {
private readonly metadata: MetadataService,
private readonly sidesheet: EuiSidesheetService,
private readonly ldsReplace: LdsReplacePipe,
- private readonly translate: TranslateService
+ private readonly translate: TranslateService,
) {}
public async ngOnInit(): Promise {
const isBusy = this.busyService.beginBusy();
try {
this.entitySchema = this.resourceProvider.getSchema(false);
- await this.metadata.update(['Application']);
+ await this.metadata.updateNonExisting(['Application']);
this.dataModel = await this.resourceProvider.getDataModel(undefined);
} finally {
isBusy.endBusy();
diff --git a/imxweb/projects/att/.compodocrc.json b/imxweb/projects/att/.compodocrc.json
index 1996edd69..5a25aeb97 100644
--- a/imxweb/projects/att/.compodocrc.json
+++ b/imxweb/projects/att/.compodocrc.json
@@ -1,11 +1,12 @@
{
"name": "IMX Web - ATT Library",
- "output": "../../documentation/att",
+ "output": "../../documentation/v92att",
"theme": "material",
"assetsFolder": "../../compodoc/assets",
"customLogo": "../../compodoc/assets/images/oneidentity-logo.png",
"customFavicon": "../../compodoc/assets/images/favicon.ico",
- "serve": true,
- "watch": true,
- "coverageTest": 0
+ "serve": false,
+ "watch": false,
+ "coverageTest": 0,
+ "disableCoverage": true
}
diff --git a/imxweb/projects/att/package.json b/imxweb/projects/att/package.json
index 25c4431e5..b6ccecc96 100644
--- a/imxweb/projects/att/package.json
+++ b/imxweb/projects/att/package.json
@@ -1,6 +1,6 @@
{
"name": "att",
- "version": "9.2.0",
+ "version": "9.2.1",
"private": true,
"bundledDependencies": [
"imx-api-att"
diff --git a/imxweb/projects/att/src/lib/decision/attestation-case.component.ts b/imxweb/projects/att/src/lib/decision/attestation-case.component.ts
index 9aa42e029..6b10c4673 100644
--- a/imxweb/projects/att/src/lib/decision/attestation-case.component.ts
+++ b/imxweb/projects/att/src/lib/decision/attestation-case.component.ts
@@ -109,7 +109,7 @@ export class AttestationCaseComponent implements OnDestroy, OnInit {
private readonly systemInfoService: SystemInfoService,
private readonly logger: ClassloggerService,
private readonly metadataService: MetadataService,
- authentication: AuthenticationService
+ authentication: AuthenticationService,
) {
this.case = data.case;
this.approvers = data.approvers;
@@ -236,13 +236,13 @@ export class AttestationCaseComponent implements OnDestroy, OnInit {
this.data.case.data?.RelatedObjects.map(async (relatedObject) => {
const objectType = DbObjectKey.FromXml(relatedObject.ObjectKey);
if (!this.metadataService.tables[objectType.TableName]) {
- await this.metadataService.update([objectType.TableName]);
+ await this.metadataService.updateNonExisting([objectType.TableName]);
}
return {
ObjectKey: relatedObject.ObjectKey,
Display: `${relatedObject.Display} - ${this.metadataService.tables[objectType.TableName].DisplaySingular}`,
};
- })
+ }),
)) || [];
}
diff --git a/imxweb/projects/att/src/lib/policies/attestation-cases/attestation-cases-tree-database.service.ts b/imxweb/projects/att/src/lib/policies/attestation-cases/attestation-cases-tree-database.service.ts
new file mode 100644
index 000000000..47d64bbb7
--- /dev/null
+++ b/imxweb/projects/att/src/lib/policies/attestation-cases/attestation-cases-tree-database.service.ts
@@ -0,0 +1,122 @@
+/*
+ * ONE IDENTITY LLC. PROPRIETARY INFORMATION
+ *
+ * This software is confidential. One Identity, LLC. or one of its affiliates or
+ * subsidiaries, has supplied this software to you under terms of a
+ * license agreement, nondisclosure agreement or both.
+ *
+ * You may not copy, disclose, or use this software except in accordance with
+ * those terms.
+ *
+ *
+ * Copyright 2023 One Identity LLC.
+ * ALL RIGHTS RESERVED.
+ *
+ * ONE IDENTITY LLC. MAKES NO REPRESENTATIONS OR
+ * WARRANTIES ABOUT THE SUITABILITY OF THE SOFTWARE,
+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+ * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, OR
+ * NON-INFRINGEMENT. ONE IDENTITY LLC. SHALL NOT BE
+ * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
+ * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
+ * THIS SOFTWARE OR ITS DERIVATIVES.
+ *
+ */
+
+import { CollectionLoadParameters, EntityData, EntitySchema, HierarchyData, IEntity, TypedEntityBuilder, ValType } from 'imx-qbm-dbts';
+import { BusyService, SettingsService, TreeDatabase, TreeNodeResultParameter } from 'qbm';
+import { PolicyService } from '../policy.service';
+import { AttestationCasesComponentParameter } from './attestation-cases-component-parameter.interface';
+import { PortalAttestationFilterMatchingobjects } from 'imx-api-att';
+
+export class AttestationCasesTreeDatabaseService extends TreeDatabase {
+ private entitySchema: EntitySchema;
+ private builder: TypedEntityBuilder;
+
+ constructor(
+ private readonly policyService: PolicyService,
+ private readonly settingsService: SettingsService,
+ private readonly data: AttestationCasesComponentParameter,
+ public busyService: BusyService,
+ ) {
+ super();
+ this.canSearch = false;
+ this.builder = new TypedEntityBuilder(PortalAttestationFilterMatchingobjects);
+ }
+
+ public async getData(
+ showLoading: boolean,
+ parameter: CollectionLoadParameters = { ParentKey: '' /* first level */ }
+ ): Promise {
+ if (this.data == null) {
+ return { entities: [], canLoadMore: false, totalCount: 0 };
+ }
+
+ const isBusy = showLoading ? this.busyService.beginBusy() : undefined;
+
+ try {
+ const navigationState = {
+ ...parameter,
+ ...{
+ PageSize: this.settingsService.DefaultPageSize,
+ StartIndex: parameter.StartIndex ? parameter.StartIndex : 0,
+ },
+ };
+
+ const data = await this.policyService.getObjectsForFilterUntyped(
+ this.data.uidobject,
+ this.data.uidPickCategory,
+ { Elements: this.data.filter, ConcatenationType: this.data.concat },
+ navigationState
+ );
+
+ if (data) {
+ const nodeEntities = await Promise.all(
+ data.Entities.map(async (elem): Promise => {
+ return (await this.buildEntityWithHasChildren(elem, data.Hierarchy))?.GetEntity();
+ })
+ );
+ this.dataChanged.emit(nodeEntities.filter((elem) => elem != null));
+ return {
+ entities: nodeEntities.filter((elem) => elem != null),
+ canLoadMore: navigationState.StartIndex + navigationState.PageSize < data.TotalCount,
+ totalCount: data.TotalCount,
+ };
+ }
+ return { entities: [], canLoadMore: false, totalCount: 0 };
+ } finally {
+ isBusy?.endBusy();
+ }
+ }
+
+ public async prepare(entitySchema: EntitySchema, withReload: boolean): Promise {
+ this.entitySchema = entitySchema;
+ if (withReload) {
+ this.reloadData();
+ }
+ }
+
+ /** adds a hasChildren column to the entity */
+ private async buildEntityWithHasChildren(entityData: EntityData, data: HierarchyData): Promise {
+ if (!this.entitySchema) {
+ return undefined;
+ }
+ const entity = this.builder.buildReadWriteEntity({ entitySchema: this.entitySchema, entityData });
+ entity.GetEntity().AddColumns([
+ {
+ Type: ValType.Bool,
+ IsMultiValued: true,
+ ColumnName: 'HasChildren',
+ MinLen: 0,
+ Display: '',
+ },
+ ]);
+ await entity
+ .GetEntity()
+ .GetColumn('HasChildren')
+ .PutValue(data ? data.EntitiesWithHierarchy.some((elem) => entityData.Keys.some((key) => key === elem)) : false);
+
+ return entity;
+ }
+}
diff --git a/imxweb/projects/att/src/lib/policies/attestation-cases/attestation-cases.component.html b/imxweb/projects/att/src/lib/policies/attestation-cases/attestation-cases.component.html
index ce9a97de2..818858588 100644
--- a/imxweb/projects/att/src/lib/policies/attestation-cases/attestation-cases.component.html
+++ b/imxweb/projects/att/src/lib/policies/attestation-cases/attestation-cases.component.html
@@ -17,7 +17,8 @@
{{ '#LDS#A sample is assigned to this attestation policy. You can start the attestation only for all objects in the sample.' | translate }}
{{ '#LDS#Note: After you have started an attestation, it may take some time until the associated attestation cases are created.' | translate }}