mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2026-09-09 18:03:21 +00:00
ACS-10745 File size columns not translating the tooltips (#11368)
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
<ng-container *ngIf="value$ | async as amount">
|
@let amount = amountValue();
|
||||||
|
@if (amount) {
|
||||||
<span [title]="amount">
|
<span [title]="amount">
|
||||||
{{ amount | currency:
|
{{ amount | currency:
|
||||||
(currencyConfig?.code || defaultCurrencyConfig.code):
|
(currencyConfig?.code || defaultCurrencyConfig.code):
|
||||||
@@ -7,4 +8,4 @@
|
|||||||
(currencyConfig?.locale || defaultCurrencyConfig.locale)
|
(currencyConfig?.locale || defaultCurrencyConfig.locale)
|
||||||
}}
|
}}
|
||||||
</span>
|
</span>
|
||||||
</ng-container>
|
}
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
import { AmountCellComponent } from './amount-cell.component';
|
import { AmountCellComponent } from './amount-cell.component';
|
||||||
import { CurrencyConfig } from '../../data/data-column.model';
|
import { CurrencyConfig } from '../../data/data-column.model';
|
||||||
import { BehaviorSubject } from 'rxjs';
|
|
||||||
import { LOCALE_ID } from '@angular/core';
|
import { LOCALE_ID } from '@angular/core';
|
||||||
import { registerLocaleData } from '@angular/common';
|
import { registerLocaleData } from '@angular/common';
|
||||||
import localePL from '@angular/common/locales/pl';
|
import localePL from '@angular/common/locales/pl';
|
||||||
@@ -30,8 +29,8 @@ describe('AmountCellComponent', () => {
|
|||||||
let testingUtils: UnitTestingUtils;
|
let testingUtils: UnitTestingUtils;
|
||||||
|
|
||||||
const renderAndCheckCurrencyValue = (currencyConfig: CurrencyConfig, value: number, expectedResult: string) => {
|
const renderAndCheckCurrencyValue = (currencyConfig: CurrencyConfig, value: number, expectedResult: string) => {
|
||||||
component.value$ = new BehaviorSubject<number>(value);
|
|
||||||
component.currencyConfig = currencyConfig;
|
component.currencyConfig = currencyConfig;
|
||||||
|
component.value$.next(value);
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
const displayedAmount = testingUtils.getByCSS('span');
|
const displayedAmount = testingUtils.getByCSS('span');
|
||||||
@@ -89,8 +88,8 @@ describe('AmountCellComponent locale', () => {
|
|||||||
testingUtils = new UnitTestingUtils(fixture.debugElement);
|
testingUtils = new UnitTestingUtils(fixture.debugElement);
|
||||||
registerLocaleData(localePL);
|
registerLocaleData(localePL);
|
||||||
|
|
||||||
component.value$ = new BehaviorSubject<number>(123.45);
|
|
||||||
component.currencyConfig = { code: 'PLN', display: 'symbol', locale: 'pl-PL' };
|
component.currencyConfig = { code: 'PLN', display: 'symbol', locale: 'pl-PL' };
|
||||||
|
component.value$.next(123.45);
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
const displayedAmount = testingUtils.getByCSS('span');
|
const displayedAmount = testingUtils.getByCSS('span');
|
||||||
|
|||||||
@@ -15,20 +15,21 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ChangeDetectionStrategy, Component, ViewEncapsulation, Input, OnInit, DEFAULT_CURRENCY_CODE, inject } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, ViewEncapsulation, Input, DEFAULT_CURRENCY_CODE, inject } from '@angular/core';
|
||||||
import { DataTableCellComponent } from '../datatable-cell/datatable-cell.component';
|
import { DataTableCellComponent } from '../datatable-cell/datatable-cell.component';
|
||||||
import { CurrencyConfig } from '../../data/data-column.model';
|
import { CurrencyConfig } from '../../data/data-column.model';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CurrencyPipe } from '@angular/common';
|
||||||
|
import { toSignal } from '@angular/core/rxjs-interop';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
imports: [CommonModule],
|
imports: [CurrencyPipe],
|
||||||
selector: 'adf-amount-cell',
|
selector: 'adf-amount-cell',
|
||||||
templateUrl: './amount-cell.component.html',
|
templateUrl: './amount-cell.component.html',
|
||||||
host: { class: 'adf-datatable-content-cell' },
|
host: { class: 'adf-datatable-content-cell' },
|
||||||
encapsulation: ViewEncapsulation.None,
|
encapsulation: ViewEncapsulation.None,
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
})
|
})
|
||||||
export class AmountCellComponent extends DataTableCellComponent implements OnInit {
|
export class AmountCellComponent extends DataTableCellComponent {
|
||||||
@Input()
|
@Input()
|
||||||
currencyConfig: CurrencyConfig;
|
currencyConfig: CurrencyConfig;
|
||||||
|
|
||||||
@@ -40,7 +41,5 @@ export class AmountCellComponent extends DataTableCellComponent implements OnIni
|
|||||||
locale: undefined
|
locale: undefined
|
||||||
};
|
};
|
||||||
|
|
||||||
ngOnInit() {
|
readonly amountValue = toSignal(this.value$);
|
||||||
super.ngOnInit();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,35 +15,26 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ChangeDetectionStrategy, Component, OnInit, ViewEncapsulation } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, ViewEncapsulation, computed } from '@angular/core';
|
||||||
import { DataTableCellComponent } from '../datatable-cell/datatable-cell.component';
|
import { DataTableCellComponent } from '../datatable-cell/datatable-cell.component';
|
||||||
import { CommonModule } from '@angular/common';
|
import { toSignal } from '@angular/core/rxjs-interop';
|
||||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
imports: [CommonModule],
|
|
||||||
selector: 'adf-boolean-cell',
|
selector: 'adf-boolean-cell',
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
template: `
|
template: ` <span [title]="title()">{{ boolValue() }}</span> `,
|
||||||
<span [title]="tooltip">
|
|
||||||
{{ boolValue }}
|
|
||||||
</span>
|
|
||||||
`,
|
|
||||||
encapsulation: ViewEncapsulation.None,
|
encapsulation: ViewEncapsulation.None,
|
||||||
host: { class: 'adf-datatable-content-cell' }
|
host: { class: 'adf-datatable-content-cell' }
|
||||||
})
|
})
|
||||||
export class BooleanCellComponent extends DataTableCellComponent implements OnInit {
|
export class BooleanCellComponent extends DataTableCellComponent {
|
||||||
boolValue = '';
|
private readonly booleanValue = toSignal(this.value$);
|
||||||
|
|
||||||
ngOnInit() {
|
readonly boolValue = computed(() => {
|
||||||
super.ngOnInit();
|
const value = this.booleanValue();
|
||||||
|
return this.transformBoolean(value);
|
||||||
this.value$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((value) => {
|
|
||||||
this.boolValue = this.transformBoolean(value);
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
private transformBoolean(value: any): string {
|
private transformBoolean(value: unknown): string {
|
||||||
if (value === true || value === 'true') {
|
if (value === true || value === 'true') {
|
||||||
return 'true';
|
return 'true';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ChangeDetectionStrategy, Component, DestroyRef, inject, Input, OnInit, ViewEncapsulation, signal, computed } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, DestroyRef, inject, Input, OnInit, ViewEncapsulation, signal, computed, effect } from '@angular/core';
|
||||||
import { DataColumn } from '../../data/data-column.model';
|
import { DataColumn } from '../../data/data-column.model';
|
||||||
import { DataRow } from '../../data/data-row.model';
|
import { DataRow } from '../../data/data-row.model';
|
||||||
import { DataTableAdapter } from '../../data/datatable-adapter';
|
import { DataTableAdapter } from '../../data/datatable-adapter';
|
||||||
@@ -25,6 +25,7 @@ import { CommonModule } from '@angular/common';
|
|||||||
import { ClipboardDirective } from '../../../clipboard/clipboard.directive';
|
import { ClipboardDirective } from '../../../clipboard/clipboard.directive';
|
||||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||||
import { TruncatePipe } from '../../../pipes/truncate.pipe';
|
import { TruncatePipe } from '../../../pipes/truncate.pipe';
|
||||||
|
import { UserPreferencesService } from '../../../common/services/user-preferences.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'adf-datatable-cell',
|
selector: 'adf-datatable-cell',
|
||||||
@@ -77,6 +78,7 @@ export class DataTableCellComponent implements OnInit {
|
|||||||
|
|
||||||
protected destroyRef = inject(DestroyRef);
|
protected destroyRef = inject(DestroyRef);
|
||||||
protected dataTableService = inject(DataTableService, { optional: true });
|
protected dataTableService = inject(DataTableService, { optional: true });
|
||||||
|
protected readonly userPreferencesService = inject(UserPreferencesService);
|
||||||
value$ = new BehaviorSubject<any>('');
|
value$ = new BehaviorSubject<any>('');
|
||||||
|
|
||||||
// Signal to track the raw computed title (without tooltip override)
|
// Signal to track the raw computed title (without tooltip override)
|
||||||
@@ -85,6 +87,18 @@ export class DataTableCellComponent implements OnInit {
|
|||||||
// Computed signal that automatically combines tooltip input with computed title
|
// Computed signal that automatically combines tooltip input with computed title
|
||||||
title = computed(() => this.tooltip || this.rawComputedTitle());
|
title = computed(() => this.tooltip || this.rawComputedTitle());
|
||||||
|
|
||||||
|
// Store the latest value for locale change re-computation
|
||||||
|
private latestValue: any = null;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
// Listen to locale changes and re-compute the title with the latest value
|
||||||
|
effect(() => {
|
||||||
|
this.userPreferencesService.localeSignal();
|
||||||
|
// When locale changes, re-compute title using the stored latest value
|
||||||
|
this.recomputeTitle();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.updateValue();
|
this.updateValue();
|
||||||
this.subscribeToRowUpdates();
|
this.subscribeToRowUpdates();
|
||||||
@@ -94,10 +108,20 @@ export class DataTableCellComponent implements OnInit {
|
|||||||
if (this.column?.key && this.row && this.data) {
|
if (this.column?.key && this.row && this.data) {
|
||||||
const value = this.data.getValue(this.row, this.column, this.resolverFn);
|
const value = this.data.getValue(this.row, this.column, this.resolverFn);
|
||||||
this.value$.next(value);
|
this.value$.next(value);
|
||||||
this.rawComputedTitle.set(this.computeTitle(value));
|
// Store the value for locale change re-computation and update the title
|
||||||
|
this.latestValue = value;
|
||||||
|
this.recomputeTitle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Re-computes the title based on the current latestValue.
|
||||||
|
* This is called both when the value changes (via updateValue) and when the locale changes (via effect).
|
||||||
|
*/
|
||||||
|
private recomputeTitle(): void {
|
||||||
|
this.rawComputedTitle.set(this.computeTitle(this.latestValue));
|
||||||
|
}
|
||||||
|
|
||||||
private subscribeToRowUpdates() {
|
private subscribeToRowUpdates() {
|
||||||
if (!this.dataTableService || !this.row.obj) {
|
if (!this.dataTableService || !this.row.obj) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
@let date = value$ | async;
|
|
||||||
|
|
||||||
@if (date) {
|
|
||||||
<span [title]="title()" class="adf-datatable-cell-value">
|
|
||||||
@if (config.format === 'timeAgo') {
|
|
||||||
@if (config.locale) {
|
|
||||||
{{ date | adfTimeAgo: config.locale }}
|
|
||||||
} @else {
|
|
||||||
{{ date | adfTimeAgo }}
|
|
||||||
}
|
|
||||||
} @else {
|
|
||||||
@if (config.locale) {
|
|
||||||
{{ date | adfLocalizedDate: config.format: config.locale }}
|
|
||||||
} @else {
|
|
||||||
{{ date | adfLocalizedDate: config.format }}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</span>
|
|
||||||
}
|
|
||||||
@@ -18,7 +18,6 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
import { DateCellComponent } from './date-cell.component';
|
import { DateCellComponent } from './date-cell.component';
|
||||||
import { DataColumn, DateConfig } from '../../data/data-column.model';
|
import { DataColumn, DateConfig } from '../../data/data-column.model';
|
||||||
import { BehaviorSubject } from 'rxjs';
|
|
||||||
import { AppConfigService } from '../../../app-config';
|
import { AppConfigService } from '../../../app-config';
|
||||||
import { LOCALE_ID } from '@angular/core';
|
import { LOCALE_ID } from '@angular/core';
|
||||||
import { registerLocaleData } from '@angular/common';
|
import { registerLocaleData } from '@angular/common';
|
||||||
@@ -39,25 +38,31 @@ const mockColumn: DataColumn = {
|
|||||||
|
|
||||||
const renderDateCell = (dateConfig: DateConfig, value: number | string | Date, tooltip?: string) => {
|
const renderDateCell = (dateConfig: DateConfig, value: number | string | Date, tooltip?: string) => {
|
||||||
// Set up mock data if not already set
|
// Set up mock data if not already set
|
||||||
if (!component.data) {
|
|
||||||
component.data = {
|
component.data = {
|
||||||
getValue: () => value
|
getValue: () => value
|
||||||
} as any;
|
} as any;
|
||||||
}
|
|
||||||
if (!component.row) {
|
|
||||||
component.row = { id: '1', getValue: () => value } as any;
|
component.row = { id: '1', getValue: () => value } as any;
|
||||||
}
|
|
||||||
|
// Only set column if not already set (preserve any test-specific column config)
|
||||||
if (!component.column) {
|
if (!component.column) {
|
||||||
component.column = { key: 'date' } as any;
|
component.column = { key: 'date' } as any;
|
||||||
}
|
}
|
||||||
|
|
||||||
component.value$ = new BehaviorSubject<number | string | Date>(value);
|
|
||||||
component.dateConfig = dateConfig;
|
component.dateConfig = dateConfig;
|
||||||
|
|
||||||
if (tooltip) {
|
if (tooltip) {
|
||||||
component.tooltip = tooltip;
|
component.tooltip = tooltip;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialize the component first, then emit the value
|
||||||
component.ngOnInit();
|
component.ngOnInit();
|
||||||
|
|
||||||
|
// Trigger config recalculation by simulating a locale change
|
||||||
|
// This is needed when column.format is set after component construction
|
||||||
|
(component as any).setConfig();
|
||||||
|
|
||||||
|
// Emit the value to the observable which will trigger the signal update
|
||||||
|
component.value$.next(value);
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -131,9 +136,9 @@ describe('DateCellComponent', () => {
|
|||||||
checkDisplayedDate(expectedDate);
|
checkDisplayedDate(expectedDate);
|
||||||
checkDisplayedTooltip(expectedTooltip);
|
checkDisplayedTooltip(expectedTooltip);
|
||||||
|
|
||||||
expect(component.config.format).toEqual('mediumDate');
|
expect(component.config().format).toEqual('mediumDate');
|
||||||
expect(component.config.tooltipFormat).toEqual('long');
|
expect(component.config().tooltipFormat).toEqual('long');
|
||||||
expect(component.config.locale).toEqual('en-US');
|
expect(component.config().locale).toEqual('en-US');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display date and tooltip with defaules values if NO dateConfig or appConfig is provided', () => {
|
it('should display date and tooltip with defaules values if NO dateConfig or appConfig is provided', () => {
|
||||||
@@ -165,13 +170,15 @@ describe('DateCellComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should display date with timeAgo format if NO dateConfig and column format provided', () => {
|
it('should display date with timeAgo format if NO dateConfig and column format provided', () => {
|
||||||
component.column = { ...mockColumn, format: 'timeAgo' };
|
|
||||||
const mockDateConfig = undefined as any;
|
const mockDateConfig = undefined as any;
|
||||||
const today = new Date();
|
const today = new Date();
|
||||||
const yesterday = new Date(today);
|
const yesterday = new Date(today);
|
||||||
yesterday.setDate(today.getDate() - 1);
|
yesterday.setDate(today.getDate() - 1);
|
||||||
|
|
||||||
const expectedDate = '1 day ago';
|
const expectedDate = '1 day ago';
|
||||||
|
|
||||||
|
// Set column format before calling renderDateCell
|
||||||
|
component.column = { ...mockColumn, format: 'timeAgo' };
|
||||||
renderDateCell(mockDateConfig, yesterday);
|
renderDateCell(mockDateConfig, yesterday);
|
||||||
checkDisplayedDate(expectedDate);
|
checkDisplayedDate(expectedDate);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -15,33 +15,34 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ChangeDetectionStrategy, Component, Input, OnInit, ViewEncapsulation, inject, ChangeDetectorRef, effect } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, Input, OnInit, ViewEncapsulation, inject, effect, signal, computed } from '@angular/core';
|
||||||
import { DataTableCellComponent } from '../datatable-cell/datatable-cell.component';
|
import { DataTableCellComponent } from '../datatable-cell/datatable-cell.component';
|
||||||
import { AppConfigService } from '../../../app-config/app-config.service';
|
import { AppConfigService } from '../../../app-config/app-config.service';
|
||||||
import { DateConfig } from '../../data/data-column.model';
|
import { DateConfig } from '../../data/data-column.model';
|
||||||
import { LocalizedDatePipe, TimeAgoPipe } from '../../../pipes';
|
import { LocalizedDatePipe, TimeAgoPipe } from '../../../pipes';
|
||||||
import { AsyncPipe } from '@angular/common';
|
import { toSignal } from '@angular/core/rxjs-interop';
|
||||||
import { UserPreferencesService } from '../../../common/services/user-preferences.service';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
imports: [LocalizedDatePipe, TimeAgoPipe, AsyncPipe],
|
|
||||||
selector: 'adf-date-cell',
|
selector: 'adf-date-cell',
|
||||||
templateUrl: './date-cell.component.html',
|
template: `
|
||||||
|
@if (formattedDate()) {
|
||||||
|
<span [title]="title()" class="adf-datatable-cell-value">{{ formattedDate() }}</span>
|
||||||
|
}
|
||||||
|
`,
|
||||||
encapsulation: ViewEncapsulation.None,
|
encapsulation: ViewEncapsulation.None,
|
||||||
host: { class: 'adf-datatable-content-cell' },
|
host: { class: 'adf-datatable-content-cell' },
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
providers: [LocalizedDatePipe]
|
providers: [LocalizedDatePipe, TimeAgoPipe]
|
||||||
})
|
})
|
||||||
export class DateCellComponent extends DataTableCellComponent implements OnInit {
|
export class DateCellComponent extends DataTableCellComponent implements OnInit {
|
||||||
@Input()
|
@Input()
|
||||||
dateConfig: DateConfig;
|
dateConfig: DateConfig;
|
||||||
|
|
||||||
config: DateConfig = {};
|
config = signal<DateConfig>({});
|
||||||
|
|
||||||
private readonly appConfig: AppConfigService = inject(AppConfigService);
|
private readonly appConfig = inject(AppConfigService);
|
||||||
private readonly localizedDatePipe: LocalizedDatePipe = inject(LocalizedDatePipe);
|
private readonly localizedDatePipe = inject(LocalizedDatePipe);
|
||||||
private readonly userPreferencesService: UserPreferencesService = inject(UserPreferencesService);
|
private readonly timeAgoPipe = inject(TimeAgoPipe);
|
||||||
private readonly cdr: ChangeDetectorRef = inject(ChangeDetectorRef);
|
|
||||||
|
|
||||||
private userLocale: string = 'en';
|
private userLocale: string = 'en';
|
||||||
|
|
||||||
@@ -51,14 +52,31 @@ export class DateCellComponent extends DataTableCellComponent implements OnInit
|
|||||||
locale: undefined
|
locale: undefined
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Convert value$ observable to signal for reactive computation
|
||||||
|
private readonly dateValue = toSignal(this.value$);
|
||||||
|
|
||||||
|
// Computed signal that automatically formats the date based on value and config
|
||||||
|
protected readonly formattedDate = computed(() => {
|
||||||
|
const date = this.dateValue();
|
||||||
|
const currentConfig = this.config();
|
||||||
|
|
||||||
|
if (!date) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentConfig.format === 'timeAgo') {
|
||||||
|
return this.timeAgoPipe.transform(date, currentConfig.locale) || '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.localizedDatePipe.transform(date, currentConfig.format, currentConfig.locale) || '';
|
||||||
|
});
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
// Use effect to react to locale signal changes (must be in injection context)
|
// Use effect to react to locale signal changes (must be in injection context)
|
||||||
effect(() => {
|
effect(() => {
|
||||||
this.userLocale = this.userPreferencesService.localeSignal() || 'en';
|
this.userLocale = this.userPreferencesService.localeSignal() || 'en';
|
||||||
this.setConfig();
|
this.setConfig();
|
||||||
this.updateValue(); // Recalculate computedTitle with new locale
|
|
||||||
this.cdr.markForCheck();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,7 +86,8 @@ export class DateCellComponent extends DataTableCellComponent implements OnInit
|
|||||||
|
|
||||||
protected override computeTitle(value: any): string {
|
protected override computeTitle(value: any): string {
|
||||||
if (value) {
|
if (value) {
|
||||||
return this.localizedDatePipe.transform(value, this.config.tooltipFormat, this.config.locale) || '';
|
const currentConfig = this.config();
|
||||||
|
return this.localizedDatePipe.transform(value, currentConfig.tooltipFormat, currentConfig.locale) || '';
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
@@ -82,15 +101,19 @@ export class DateCellComponent extends DataTableCellComponent implements OnInit
|
|||||||
}
|
}
|
||||||
|
|
||||||
private setCustomConfig(): void {
|
private setCustomConfig(): void {
|
||||||
this.config.format = this.dateConfig?.format || this.getDefaultFormat();
|
this.config.set({
|
||||||
this.config.tooltipFormat = this.dateConfig?.tooltipFormat || this.getDefaultTooltipFormat();
|
format: this.dateConfig?.format || this.getDefaultFormat(),
|
||||||
this.config.locale = this.normalizeLocale(this.dateConfig?.locale || this.getDefaultLocale());
|
tooltipFormat: this.dateConfig?.tooltipFormat || this.getDefaultTooltipFormat(),
|
||||||
|
locale: this.normalizeLocale(this.dateConfig?.locale || this.userLocale)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private setDefaultConfig(): void {
|
private setDefaultConfig(): void {
|
||||||
this.config.format = this.getDefaultFormat();
|
this.config.set({
|
||||||
this.config.tooltipFormat = this.getDefaultTooltipFormat();
|
format: this.getDefaultFormat(),
|
||||||
this.config.locale = this.normalizeLocale(this.getDefaultLocale());
|
tooltipFormat: this.getDefaultTooltipFormat(),
|
||||||
|
locale: this.normalizeLocale(this.userLocale)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private normalizeLocale(locale: string): string {
|
private normalizeLocale(locale: string): string {
|
||||||
@@ -109,12 +132,6 @@ export class DateCellComponent extends DataTableCellComponent implements OnInit
|
|||||||
return this.column?.format || this.getAppConfigPropertyValue('dateValues.defaultDateFormat', this.defaultDateConfig.format);
|
return this.column?.format || this.getAppConfigPropertyValue('dateValues.defaultDateFormat', this.defaultDateConfig.format);
|
||||||
}
|
}
|
||||||
|
|
||||||
private getDefaultLocale(): string {
|
|
||||||
// Always use the user locale from UserPreferencesService
|
|
||||||
// This is kept in sync via subscription and reflects the user's current locale choice
|
|
||||||
return this.userLocale;
|
|
||||||
}
|
|
||||||
|
|
||||||
private getDefaultTooltipFormat(): string {
|
private getDefaultTooltipFormat(): string {
|
||||||
return this.getAppConfigPropertyValue('dateValues.defaultTooltipDateFormat', this.defaultDateConfig.tooltipFormat);
|
return this.getAppConfigPropertyValue('dateValues.defaultTooltipDateFormat', this.defaultDateConfig.tooltipFormat);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Component, OnInit, ViewEncapsulation, inject } from '@angular/core';
|
import { Component, ViewEncapsulation } from '@angular/core';
|
||||||
import { DataTableCellComponent } from '../datatable-cell/datatable-cell.component';
|
import { DataTableCellComponent } from '../datatable-cell/datatable-cell.component';
|
||||||
import { FileSizePipe } from '../../../pipes';
|
import { FileSizePipe } from '../../../pipes';
|
||||||
import { AsyncPipe } from '@angular/common';
|
import { AsyncPipe } from '@angular/common';
|
||||||
@@ -25,23 +25,10 @@ import { AsyncPipe } from '@angular/common';
|
|||||||
imports: [FileSizePipe, AsyncPipe],
|
imports: [FileSizePipe, AsyncPipe],
|
||||||
template: `
|
template: `
|
||||||
@let value = value$ | async;
|
@let value = value$ | async;
|
||||||
<span [title]="title()" class="adf-datatable-cell-value">{{ value | adfFileSize }}</span>
|
<span [title]="value | adfFileSize" class="adf-datatable-cell-value">{{ value | adfFileSize }}</span>
|
||||||
`,
|
`,
|
||||||
encapsulation: ViewEncapsulation.None,
|
encapsulation: ViewEncapsulation.None,
|
||||||
host: { class: 'adf-filesize-cell' },
|
host: { class: 'adf-filesize-cell' },
|
||||||
providers: [FileSizePipe]
|
providers: [FileSizePipe]
|
||||||
})
|
})
|
||||||
export class FileSizeCellComponent extends DataTableCellComponent implements OnInit {
|
export class FileSizeCellComponent extends DataTableCellComponent {}
|
||||||
private readonly fileSizePipe = inject(FileSizePipe);
|
|
||||||
|
|
||||||
ngOnInit(): void {
|
|
||||||
super.ngOnInit();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override computeTitle(value: any): string {
|
|
||||||
if (value != null) {
|
|
||||||
return this.fileSizePipe.transform(value);
|
|
||||||
}
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -15,43 +15,32 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { CommonModule } from '@angular/common';
|
import { ChangeDetectionStrategy, Component, ViewEncapsulation, computed } from '@angular/core';
|
||||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit, ViewEncapsulation } from '@angular/core';
|
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
import { DataTableCellComponent } from '../datatable-cell/datatable-cell.component';
|
import { DataTableCellComponent } from '../datatable-cell/datatable-cell.component';
|
||||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
import { toSignal } from '@angular/core/rxjs-interop';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
imports: [CommonModule, MatIconModule],
|
imports: [MatIconModule],
|
||||||
selector: 'adf-icon-cell',
|
selector: 'adf-icon-cell',
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
template: `
|
template: `
|
||||||
<ng-container *ngIf="icon">
|
@if (icon()) {
|
||||||
<mat-icon [title]="tooltip" aria-hidden="true">{{ icon }}</mat-icon>
|
<mat-icon [title]="title()" aria-hidden="true">{{ icon() }}</mat-icon>
|
||||||
</ng-container>
|
}
|
||||||
`,
|
`,
|
||||||
encapsulation: ViewEncapsulation.None,
|
encapsulation: ViewEncapsulation.None,
|
||||||
host: { class: 'adf-datatable-content-cell' }
|
host: { class: 'adf-datatable-content-cell' }
|
||||||
})
|
})
|
||||||
export class IconCellComponent extends DataTableCellComponent implements OnInit {
|
export class IconCellComponent extends DataTableCellComponent {
|
||||||
icon: string = '';
|
private readonly iconValue = toSignal(this.value$);
|
||||||
|
|
||||||
constructor(private changeDetectorRef: ChangeDetectorRef) {
|
readonly icon = computed(() => {
|
||||||
super();
|
const value = this.iconValue();
|
||||||
}
|
return this.validateIconValue(value) ? value : '';
|
||||||
|
|
||||||
ngOnInit(): void {
|
|
||||||
super.ngOnInit();
|
|
||||||
this.value$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((value) => {
|
|
||||||
const newIcon = this.validateIconValue(value) ? value : '';
|
|
||||||
if (this.icon !== newIcon) {
|
|
||||||
this.icon = newIcon;
|
|
||||||
this.changeDetectorRef.detectChanges();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
private validateIconValue(value: any): boolean {
|
private validateIconValue(value: unknown): boolean {
|
||||||
return typeof value === 'string';
|
return typeof value === 'string';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,46 +15,45 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ChangeDetectionStrategy, Component, OnInit, ViewEncapsulation, Input } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, ViewEncapsulation, Input, computed } from '@angular/core';
|
||||||
import { DataTableCellComponent } from '../datatable-cell/datatable-cell.component';
|
import { DataTableCellComponent } from '../datatable-cell/datatable-cell.component';
|
||||||
import { MatDialog, MatDialogModule } from '@angular/material/dialog';
|
import { MatDialog, MatDialogModule } from '@angular/material/dialog';
|
||||||
import { EditJsonDialogComponent, EditJsonDialogSettings } from '../../../dialogs/edit-json/edit-json.dialog';
|
import { EditJsonDialogComponent, EditJsonDialogSettings } from '../../../dialogs/edit-json/edit-json.dialog';
|
||||||
import { CommonModule } from '@angular/common';
|
|
||||||
import { MatButtonModule } from '@angular/material/button';
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
|
import { toSignal } from '@angular/core/rxjs-interop';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'adf-json-cell',
|
selector: 'adf-json-cell',
|
||||||
imports: [CommonModule, MatButtonModule, MatDialogModule],
|
imports: [MatButtonModule, MatDialogModule],
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
template: `
|
template: `
|
||||||
<ng-container *ngIf="value$ | async as value; else editEmpty">
|
@if (shouldShowButton()) {
|
||||||
<button mat-button color="primary" (click)="view()">json</button>
|
<button mat-button (click)="view()">json</button>
|
||||||
</ng-container>
|
}
|
||||||
|
|
||||||
<ng-template #editEmpty>
|
|
||||||
<button *ngIf="editable" mat-button color="primary" (click)="view()">json</button>
|
|
||||||
</ng-template>
|
|
||||||
`,
|
`,
|
||||||
styleUrls: ['./json-cell.component.scss'],
|
styleUrls: ['./json-cell.component.scss'],
|
||||||
encapsulation: ViewEncapsulation.None,
|
encapsulation: ViewEncapsulation.None,
|
||||||
host: { class: 'adf-datatable-content-cell' }
|
host: { class: 'adf-datatable-content-cell' }
|
||||||
})
|
})
|
||||||
export class JsonCellComponent extends DataTableCellComponent implements OnInit {
|
export class JsonCellComponent extends DataTableCellComponent {
|
||||||
/** Editable JSON. */
|
/** Editable JSON. */
|
||||||
@Input()
|
@Input()
|
||||||
editable: boolean = false;
|
editable: boolean = false;
|
||||||
|
|
||||||
|
private readonly jsonValue = toSignal(this.value$);
|
||||||
|
|
||||||
|
readonly shouldShowButton = computed(() => {
|
||||||
|
const value = this.jsonValue();
|
||||||
|
return !!value || this.editable;
|
||||||
|
});
|
||||||
|
|
||||||
constructor(private dialog: MatDialog) {
|
constructor(private dialog: MatDialog) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
|
||||||
super.ngOnInit();
|
|
||||||
}
|
|
||||||
|
|
||||||
view() {
|
view() {
|
||||||
const rawValue: string | any = this.data.getValue(this.row, this.column, this.resolverFn);
|
const rawValue = this.data.getValue(this.row, this.column, this.resolverFn);
|
||||||
const value = typeof rawValue === 'object' ? JSON.stringify(rawValue || {}, null, 2) : rawValue;
|
const value = typeof rawValue === 'object' ? JSON.stringify(rawValue || {}, null, 2) : String(rawValue ?? '');
|
||||||
|
|
||||||
const settings: EditJsonDialogSettings = {
|
const settings: EditJsonDialogSettings = {
|
||||||
title: this.column.title,
|
title: this.column.title,
|
||||||
@@ -69,12 +68,6 @@ export class JsonCellComponent extends DataTableCellComponent implements OnInit
|
|||||||
minHeight: '50%'
|
minHeight: '50%'
|
||||||
})
|
})
|
||||||
.afterClosed()
|
.afterClosed()
|
||||||
.subscribe((/*result: string*/) => {
|
.subscribe();
|
||||||
if (typeof rawValue === 'object') {
|
|
||||||
// todo: update cell value as object
|
|
||||||
} else {
|
|
||||||
// todo: update cell value as string
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,33 +15,29 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ChangeDetectionStrategy, Component, Input, OnInit, ViewEncapsulation } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, Input, ViewEncapsulation } from '@angular/core';
|
||||||
import { DataTableCellComponent } from '../datatable-cell/datatable-cell.component';
|
import { DataTableCellComponent } from '../datatable-cell/datatable-cell.component';
|
||||||
import { AsyncPipe } from '@angular/common';
|
|
||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
import { PathInfo } from '../../../models/path.model';
|
import { PathInfo } from '../../../models/path.model';
|
||||||
|
import { toSignal } from '@angular/core/rxjs-interop';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
imports: [AsyncPipe, RouterModule],
|
imports: [RouterModule],
|
||||||
selector: 'adf-location-cell',
|
selector: 'adf-location-cell',
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
template: `
|
template: `
|
||||||
<ng-container>
|
|
||||||
<a [title]="tooltip" [routerLink]="link">
|
<a [title]="tooltip" [routerLink]="link">
|
||||||
{{ value$ | async }}
|
{{ locationValue() }}
|
||||||
</a>
|
</a>
|
||||||
</ng-container>
|
|
||||||
`,
|
`,
|
||||||
encapsulation: ViewEncapsulation.None,
|
encapsulation: ViewEncapsulation.None,
|
||||||
host: { class: 'adf-location-cell adf-datatable-content-cell' }
|
host: { class: 'adf-location-cell adf-datatable-content-cell' }
|
||||||
})
|
})
|
||||||
export class LocationCellComponent extends DataTableCellComponent implements OnInit {
|
export class LocationCellComponent extends DataTableCellComponent {
|
||||||
@Input()
|
@Input()
|
||||||
link: any[];
|
link: (string | number)[];
|
||||||
|
|
||||||
ngOnInit() {
|
readonly locationValue = toSignal(this.value$);
|
||||||
super.ngOnInit();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected updateValue(): void {
|
protected updateValue(): void {
|
||||||
if (this.column?.key && this.column?.format && this.row && this.data) {
|
if (this.column?.key && this.column?.format && this.row && this.data) {
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
<ng-container *ngIf="value$ | async as number">
|
@let number = numberValue();
|
||||||
|
@if (number) {
|
||||||
<span [title]="number">
|
<span [title]="number">
|
||||||
{{ number | number:
|
{{ number | number:
|
||||||
(decimalConfig?.digitsInfo || defaultDecimalConfig.digitsInfo):
|
(decimalConfig?.digitsInfo || defaultDecimalConfig.digitsInfo):
|
||||||
(decimalConfig?.locale || defaultDecimalConfig.locale)
|
(decimalConfig?.locale || defaultDecimalConfig.locale)
|
||||||
}}
|
}}
|
||||||
</span>
|
</span>
|
||||||
</ng-container>
|
}
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
import { NumberCellComponent } from './number-cell.component';
|
import { NumberCellComponent } from './number-cell.component';
|
||||||
import { DecimalConfig } from '../../data/data-column.model';
|
import { DecimalConfig } from '../../data/data-column.model';
|
||||||
import { BehaviorSubject } from 'rxjs';
|
|
||||||
import { LOCALE_ID } from '@angular/core';
|
import { LOCALE_ID } from '@angular/core';
|
||||||
import { registerLocaleData } from '@angular/common';
|
import { registerLocaleData } from '@angular/common';
|
||||||
import localePL from '@angular/common/locales/pl';
|
import localePL from '@angular/common/locales/pl';
|
||||||
@@ -30,8 +29,8 @@ describe('NumberCellComponent', () => {
|
|||||||
let testingUtils: UnitTestingUtils;
|
let testingUtils: UnitTestingUtils;
|
||||||
|
|
||||||
const renderAndCheckNumberValue = (decimalConfig: DecimalConfig, value: number, expectedResult: string) => {
|
const renderAndCheckNumberValue = (decimalConfig: DecimalConfig, value: number, expectedResult: string) => {
|
||||||
component.value$ = new BehaviorSubject<number>(value);
|
|
||||||
component.decimalConfig = decimalConfig;
|
component.decimalConfig = decimalConfig;
|
||||||
|
component.value$.next(value);
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
const displayedNumber = testingUtils.getByCSS('span');
|
const displayedNumber = testingUtils.getByCSS('span');
|
||||||
@@ -79,8 +78,8 @@ describe('NumberCellComponent locale', () => {
|
|||||||
testingUtils = new UnitTestingUtils(fixture.debugElement);
|
testingUtils = new UnitTestingUtils(fixture.debugElement);
|
||||||
registerLocaleData(localePL);
|
registerLocaleData(localePL);
|
||||||
|
|
||||||
component.value$ = new BehaviorSubject<number>(123.45);
|
|
||||||
component.decimalConfig = { locale: 'pl-PL' };
|
component.decimalConfig = { locale: 'pl-PL' };
|
||||||
|
component.value$.next(123.45);
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
const displayedNumber = testingUtils.getByCSS('span');
|
const displayedNumber = testingUtils.getByCSS('span');
|
||||||
|
|||||||
@@ -15,10 +15,11 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ChangeDetectionStrategy, Component, ViewEncapsulation, Input, OnInit } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, ViewEncapsulation, Input } from '@angular/core';
|
||||||
import { DataTableCellComponent } from '../datatable-cell/datatable-cell.component';
|
import { DataTableCellComponent } from '../datatable-cell/datatable-cell.component';
|
||||||
import { DecimalConfig } from '../../data/data-column.model';
|
import { DecimalConfig } from '../../data/data-column.model';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { toSignal } from '@angular/core/rxjs-interop';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
imports: [CommonModule],
|
imports: [CommonModule],
|
||||||
@@ -28,7 +29,7 @@ import { CommonModule } from '@angular/common';
|
|||||||
encapsulation: ViewEncapsulation.None,
|
encapsulation: ViewEncapsulation.None,
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
})
|
})
|
||||||
export class NumberCellComponent extends DataTableCellComponent implements OnInit {
|
export class NumberCellComponent extends DataTableCellComponent {
|
||||||
@Input()
|
@Input()
|
||||||
decimalConfig: DecimalConfig;
|
decimalConfig: DecimalConfig;
|
||||||
|
|
||||||
@@ -37,7 +38,5 @@ export class NumberCellComponent extends DataTableCellComponent implements OnIni
|
|||||||
locale: undefined
|
locale: undefined
|
||||||
};
|
};
|
||||||
|
|
||||||
ngOnInit() {
|
readonly numberValue = toSignal(this.value$);
|
||||||
super.ngOnInit();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user