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 @@
8c6dad65a72631732d54c5a497f3d7529c0ec564
800253d0db65542d7805bc592b40cf4fd7b0b785
1 change: 0 additions & 1 deletion .sync-history
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@
9900fc181 2026-07-08 Merged PR 94405: #724499 - TSB: Fix parallel cart creation when requesting multiple group memberships
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
### October 6, 2026
- 725999 - Web Portal: Search approvals after loading.
- 736614 - Angular read-only view-property honors DateFormat metadata.
- 709042 - Web Portal: Do not resubmit unchanged Valid From on single approval.

### July 30, 2026
- 724499 - Fixing parallel cart creation when requesting multiple group memberships.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ export class AttestationCasesService {
const collection = await this.attClient.typedClient.PortalAttestationApprove.Get(attDecisionParameters, { signal });
if (!collection) return { totalCount: 0, Data: [] };
return {
...collection,
tableName: collection.tableName,
totalCount: collection.totalCount,
Data: collection.Data.map((item: PortalAttestationApprove, index: number) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
/*
* 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 2026 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 { DateFormat, ValType } from '@imx-modules/imx-qbm-dbts';
import { EntityColumnContainer } from '../entity-column-container';
import { ImxTranslationProviderService } from '../../translation/imx-translation-provider.service';
import { ViewPropertyComponent } from './view-property.component';

describe('ViewPropertyComponent', () => {
const translation = { CultureFormat: 'en-US' } as unknown as ImxTranslationProviderService;

function build(container: Partial<EntityColumnContainer>): ViewPropertyComponent {
const component = new ViewPropertyComponent(translation);
component.columnContainer = container as EntityColumnContainer;
component.defaultValue = '#LDS#Not set';
return component;
}

function dateContainer(opts: {
value: unknown;
displayValue?: string;
dateFormat?: DateFormat;
}): Partial<EntityColumnContainer> {
return {
type: ValType.Date,
value: opts.value as any,
displayValue: opts.displayValue,
metaData: {
GetDateFormat: () => opts.dateFormat,
} as any,
};
}

it('prefers the server-supplied DisplayValue for a Date-only column (CR-108653)', () => {
const c = build(
dateContainer({
value: '2000-02-20T00:00:00Z',
displayValue: '20-2-2000',
dateFormat: DateFormat.Date,
}),
);

expect(c.displayedValue).toBe('20-2-2000');
expect(c.displayedValue).not.toMatch(/[0-9]:[0-9]/);
});

it('prefers the server-supplied DisplayValue for a DateTime column', () => {
const c = build(
dateContainer({
value: '2000-02-20T00:00:00Z',
displayValue: '2/20/2000, 1:00:00 AM',
dateFormat: DateFormat.DateTime,
}),
);

expect(c.displayedValue).toBe('2/20/2000, 1:00:00 AM');
});

it('falls back to toLocaleDateString for a Date-only column when displayValue is absent', () => {
const c = build(
dateContainer({
value: '2000-02-20T00:00:00Z',
displayValue: undefined,
dateFormat: DateFormat.Date,
}),
);

expect(c.displayedValue).toBe(new Date('2000-02-20T00:00:00Z').toLocaleDateString('en-US'));
expect(c.displayedValue).not.toMatch(/[0-9]:[0-9]/);
});

it('falls back to toLocaleString for a DateTime column when displayValue is absent', () => {
const c = build(
dateContainer({
value: '2000-02-20T00:00:00Z',
displayValue: undefined,
dateFormat: DateFormat.DateTime,
}),
);

expect(c.displayedValue).toBe(new Date('2000-02-20T00:00:00Z').toLocaleString('en-US'));
});

it('falls back to toUTCString for a UtcDateTime column when displayValue is absent', () => {
const c = build(
dateContainer({
value: '2000-02-20T00:00:00Z',
displayValue: undefined,
dateFormat: DateFormat.UtcDateTime,
}),
);

expect(c.displayedValue).toBe(new Date('2000-02-20T00:00:00Z').toUTCString());
});

it('falls back to toLocaleString when DateFormat metadata is missing (unchanged legacy behavior)', () => {
const c = build(
dateContainer({
value: '2000-02-20T00:00:00Z',
displayValue: undefined,
dateFormat: undefined,
}),
);

expect(c.displayedValue).toBe(new Date('2000-02-20T00:00:00Z').toLocaleString('en-US'));
});

it('returns defaultValue for a Date column with a null value and no displayValue', () => {
const c = build(
dateContainer({
value: null,
displayValue: undefined,
dateFormat: DateFormat.Date,
}),
);

expect(c.displayedValue).toBe('#LDS#Not set');
});

it('returns defaultValue for a Date column whose value cannot be parsed', () => {
const c = build(
dateContainer({
value: 'not-a-date',
displayValue: undefined,
dateFormat: DateFormat.Date,
}),
);

expect(c.displayedValue).toBe('#LDS#Not set');
});

it('uses displayValue for non-Date types (unchanged behavior)', () => {
const c = build({
type: ValType.String,
value: 'raw-value' as any,
displayValue: 'Rendered',
});

expect(c.displayedValue).toBe('Rendered');
});

it('returns defaultValue when column container is undefined', () => {
const c = new ViewPropertyComponent(translation);
c.defaultValue = '#LDS#Not set';

expect(c.displayedValue).toBe('#LDS#Not set');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
import { Component, Input } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';

import { ValType } from '@imx-modules/imx-qbm-dbts';
import { DateFormat, ValType } from '@imx-modules/imx-qbm-dbts';
import { EntityColumnContainer } from '../entity-column-container';
import { ImxTranslationProviderService } from '../../translation/imx-translation-provider.service';

Expand All @@ -44,11 +44,26 @@ export class ViewPropertyComponent {

public get displayedValue(): string {
if (this.columnContainer?.type === ValType.Date) {
if (this.columnContainer?.value == null) {
// Prefer the server-supplied DisplayValue: it already honors DateFormat (DateOnly vs DateTime) via the shared DisplayBuilder.
if (this.columnContainer.displayValue) {
return this.columnContainer.displayValue;
}
if (this.columnContainer.value == null) {
return this.defaultValue;
}
const date: Date = new Date(this.columnContainer.value);
return date.getDate() ? date.toLocaleString(this.translationProviderService.CultureFormat) : this.defaultValue;
if (!date.getDate()) {
return this.defaultValue;
}
const cultureFormat = this.translationProviderService.CultureFormat;
switch (this.columnContainer.metaData?.GetDateFormat()) {
case DateFormat.Date:
return date.toLocaleDateString(cultureFormat);
case DateFormat.UtcDateTime:
return date.toUTCString();
default:
return date.toLocaleString(cultureFormat);
}
}
return this.columnContainer?.displayValue || this.columnContainer?.value || this.defaultValue;
}
Expand Down
Loading