mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-05-12 17:04:57 +00:00
[AAE-16964] Handle amount data table cloumn type (#8984)
* [AAE-16964] Handle amount data table cloumn type * remove not needed reset testing module * improve spacing * update documentation * remove code duplications in unit tests * add type for default currency config * update doc
This commit is contained in:
parent
962a2be698
commit
6644f539fa
@ -59,8 +59,35 @@ Defines column properties for DataTable, Tasklist, Document List and other compo
|
||||
| sortingKey | `string` | | When using server side sorting the column used by the api call where the sorting will be performed |
|
||||
| srTitle | `string` | | Title to be used for screen readers. |
|
||||
| title | `string` | "" | Display title of the column, typically used for column headers. You can use the i18n resource key to get it translated automatically. |
|
||||
| type | `string` | "text" | Value type for the column. Possible settings are 'text', 'boolean', 'icon', 'image', 'date', 'fileSize', 'location', and 'json'. |
|
||||
| type | `string` | "text" | Value type for the column. Possible settings are 'text', 'boolean', 'icon', 'image', 'date', 'fileSize', 'location', 'json' and 'amount'. |
|
||||
| order | `number` | | Sets position of column. |
|
||||
| currencyConfig | `CurrencyConfig` | [Default currency config](#default-currency-config) | Currency configuration to customize the formatting and display of currency values within the component. |
|
||||
|
||||
## Properties configuration
|
||||
|
||||
### `currencyConfig` Input
|
||||
|
||||
The `currencyConfig` input allows you to customize the formatting and display of currency values within the component. It accepts an object of type `CurrencyConfig` with optional properties for specifying the currency code, display format, decimal precision, and locale.
|
||||
|
||||
#### Properties
|
||||
|
||||
- `code` (optional): A string representing the currency code (e.g., "USD" for US Dollars).
|
||||
- `display` (optional): A string specifying how the currency value should be displayed.
|
||||
- `digitsInfo` (optional): A string determining the number of decimal places and other formatting details.
|
||||
- `locale` (optional): A string indicating the locale or region-specific formatting to use for the currency.
|
||||
|
||||
#### Default currency config
|
||||
|
||||
By default, the `currencyConfig` input is not required. If not provided, the component will use the following default values:
|
||||
|
||||
- `code`: "USD"
|
||||
- `display`: "symbol"
|
||||
- `digitsInfo`: undefined
|
||||
- `locale`: undefined
|
||||
|
||||
These properties offer flexibility in customizing how currency values are presented within the component.
|
||||
|
||||
For more details on the possible use cases of the above properties, see the [official Angular documents](https://angular.io/api/common/CurrencyPipe).
|
||||
|
||||
## Properties configuration
|
||||
|
||||
@ -76,7 +103,7 @@ The `type` input allows us to specify the type of hosted values for a given colu
|
||||
- `fileSize` - TODO
|
||||
- `location` - TODO
|
||||
- `json` - TODO
|
||||
- `currency` - This column is responsible for displaying currencies. It expects numerals represented by a string or a number. This type comes with `currencyConfig` (TODO: Add ref). The default setup use **USD** `code` with a **symbol** as a `display` option. Example output: $10.26 (for number 10.26)
|
||||
- `amount` - This column is responsible for displaying currencies. It expects numerals represented by a string or a number. This type comes with [`currencyConfig`](#default-currency-config).
|
||||
|
||||
## Details
|
||||
|
||||
|
@ -0,0 +1,10 @@
|
||||
<ng-container *ngIf="value$ | async as amount">
|
||||
<span [title]="amount">
|
||||
{{ amount | currency:
|
||||
(currencyConfig?.code || defaultCurrencyConfig.code):
|
||||
(currencyConfig?.display || defaultCurrencyConfig.display):
|
||||
(currencyConfig?.digitsInfo || defaultCurrencyConfig.digitsInfo):
|
||||
(currencyConfig?.locale || defaultCurrencyConfig.locale)
|
||||
}}
|
||||
</span>
|
||||
</ng-container>
|
@ -0,0 +1,96 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2023 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { AmountCellComponent } from './amount-cell.component';
|
||||
import { CurrencyConfig } from '../../data/data-column.model';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { LOCALE_ID } from '@angular/core';
|
||||
import { registerLocaleData } from '@angular/common';
|
||||
import localePL from '@angular/common/locales/pl';
|
||||
|
||||
describe('AmountCellComponent', () => {
|
||||
let component: AmountCellComponent;
|
||||
let fixture: ComponentFixture<AmountCellComponent>;
|
||||
|
||||
const renderAndCheckCurrencyValue = (currencyConfig: CurrencyConfig, value: number, expectedResult: string) => {
|
||||
component.value$ = new BehaviorSubject<number>(value);
|
||||
component.currencyConfig = currencyConfig;
|
||||
|
||||
fixture.detectChanges();
|
||||
const displayedAmount = fixture.nativeElement.querySelector('span');
|
||||
|
||||
expect(displayedAmount).toBeTruthy();
|
||||
expect(displayedAmount.textContent.trim()).toBe(expectedResult);
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [AmountCellComponent]
|
||||
});
|
||||
fixture = TestBed.createComponent(AmountCellComponent);
|
||||
component = fixture.componentInstance;
|
||||
});
|
||||
|
||||
it('should set default currency config', () => {
|
||||
expect(component.defaultCurrencyConfig.code).toBe('USD');
|
||||
expect(component.defaultCurrencyConfig.display).toBe('symbol');
|
||||
expect(component.defaultCurrencyConfig.digitsInfo).toBeUndefined();
|
||||
expect(component.defaultCurrencyConfig.locale).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should render currency value', () => {
|
||||
renderAndCheckCurrencyValue(component.currencyConfig, 123.45, '$123.45');
|
||||
});
|
||||
|
||||
it('should render currency value with custom currency code', () => {
|
||||
renderAndCheckCurrencyValue({ code: 'MY CUSTOM CURRENCY', display: 'symbol' }, 123.45, 'MY CUSTOM CURRENCY123.45');
|
||||
});
|
||||
|
||||
it('should render currency value with custom display code', () => {
|
||||
renderAndCheckCurrencyValue({ code: 'EUR', display: 'symbol' }, 123.45, '€123.45');
|
||||
});
|
||||
|
||||
it('should render currency value with custom digitsInfo', () => {
|
||||
renderAndCheckCurrencyValue({ code: 'USD', display: 'symbol', digitsInfo: '1.2-2' }, 123.456789, '$123.46');
|
||||
});
|
||||
});
|
||||
|
||||
describe('AmountCellComponent locale', () => {
|
||||
let component: AmountCellComponent;
|
||||
let fixture: ComponentFixture<AmountCellComponent>;
|
||||
|
||||
it('should render currency value with custom locale', () => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [AmountCellComponent],
|
||||
providers: [{ provide: LOCALE_ID, useValue: 'pl-PL' }]
|
||||
});
|
||||
|
||||
fixture = TestBed.createComponent(AmountCellComponent);
|
||||
component = fixture.componentInstance;
|
||||
registerLocaleData(localePL);
|
||||
|
||||
component.value$ = new BehaviorSubject<number>(123.45);
|
||||
component.currencyConfig = { code: 'PLN', display: 'symbol', locale: 'pl-PL' };
|
||||
|
||||
fixture.detectChanges();
|
||||
const displayedAmount = fixture.nativeElement.querySelector('span');
|
||||
|
||||
expect(displayedAmount).toBeTruthy();
|
||||
expect(displayedAmount.textContent.trim()).toMatch(/123,45\s?zł/);
|
||||
});
|
||||
});
|
@ -0,0 +1,66 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2023 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
ViewEncapsulation,
|
||||
Input,
|
||||
Optional,
|
||||
OnInit,
|
||||
DEFAULT_CURRENCY_CODE,
|
||||
Inject
|
||||
} from '@angular/core';
|
||||
import { DataTableCellComponent } from '../datatable-cell/datatable-cell.component';
|
||||
import { DataTableService } from '../../services/datatable.service';
|
||||
import { CurrencyConfig } from '../../data/data-column.model';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
imports: [CommonModule],
|
||||
selector: 'adf-amount-cell',
|
||||
templateUrl: './amount-cell.component.html',
|
||||
host: { class: 'adf-datatable-content-cell' },
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class AmountCellComponent extends DataTableCellComponent implements OnInit {
|
||||
|
||||
@Input()
|
||||
currencyConfig: CurrencyConfig;
|
||||
|
||||
readonly defaultCurrencyConfig: CurrencyConfig = {
|
||||
code: this.defaultCurrencyCode,
|
||||
display: 'symbol',
|
||||
digitsInfo: undefined,
|
||||
locale: undefined
|
||||
};
|
||||
|
||||
constructor(
|
||||
@Optional() dataTableService: DataTableService,
|
||||
@Inject(DEFAULT_CURRENCY_CODE) private readonly defaultCurrencyCode: string
|
||||
) {
|
||||
super(dataTableService);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
if (this.column?.key && this.row && this.data) {
|
||||
this.value$.next(this.data.getValue(this.row, this.column, this.resolverFn));
|
||||
}
|
||||
}
|
||||
}
|
@ -306,6 +306,18 @@
|
||||
[row]="row">
|
||||
</adf-json-cell>
|
||||
</div>
|
||||
<div *ngSwitchCase="'amount'"
|
||||
class="adf-cell-value"
|
||||
[attr.tabindex]="data.getValue(row, col, resolverFn)? 0 : -1"
|
||||
[attr.data-automation-id]="'amount_' + data.getValue(row, col, resolverFn)">
|
||||
<adf-amount-cell
|
||||
[data]="data"
|
||||
[column]="col"
|
||||
[resolverFn]="resolverFn"
|
||||
[row]="row"
|
||||
[currencyConfig]="col.currencyConfig">
|
||||
</adf-amount-cell>
|
||||
</div>
|
||||
<span *ngSwitchDefault class="adf-cell-value">
|
||||
<!-- empty cell for unknown column type -->
|
||||
</span>
|
||||
|
@ -1207,6 +1207,17 @@ describe('DataTable', () => {
|
||||
expect(rows[1].getValue('is_available')).toBe('true');
|
||||
expect(rows[2].getValue('is_available')).toBe('true');
|
||||
});
|
||||
|
||||
it('should be able to display column of type amount', () => {
|
||||
dataTable.data = new ObjectDataTableAdapter(mockCarsData, mockCarsSchemaDefinition);
|
||||
|
||||
fixture.detectChanges();
|
||||
const rows = dataTable.data.getRows();
|
||||
|
||||
expect(rows[0].getValue('car_price')).toBe(599);
|
||||
expect(rows[1].getValue('car_price')).toBe(15000.12345);
|
||||
expect(rows[2].getValue('car_price')).toBe(10000);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Accesibility', () => {
|
||||
|
@ -15,6 +15,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { DataColumn } from '../../data/data-column.model';
|
||||
|
||||
export const mockCarsData: any = [
|
||||
{
|
||||
car_id: 1,
|
||||
@ -48,7 +50,7 @@ export const mockCarsData: any = [
|
||||
}
|
||||
];
|
||||
|
||||
export const mockCarsSchemaDefinition: any[] = [
|
||||
export const mockCarsSchemaDefinition: DataColumn[] = [
|
||||
{
|
||||
type: 'icon',
|
||||
key: 'icon',
|
||||
|
@ -27,6 +27,7 @@ export interface DataColumnTypes {
|
||||
location: string;
|
||||
// eslint-disable-next-line id-blacklist
|
||||
boolean: string;
|
||||
amount: string;
|
||||
}
|
||||
|
||||
export type DataColumnType = keyof DataColumnTypes;
|
||||
@ -52,4 +53,12 @@ export interface DataColumn<T = unknown> {
|
||||
width?: number;
|
||||
customData?: T;
|
||||
order?: number;
|
||||
currencyConfig?: CurrencyConfig;
|
||||
}
|
||||
|
||||
export interface CurrencyConfig {
|
||||
code?: string;
|
||||
display?: string;
|
||||
digitsInfo?: string;
|
||||
locale?: string;
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
import { TemplateRef } from '@angular/core';
|
||||
import { DataColumn, DataColumnType } from './data-column.model';
|
||||
import { CurrencyConfig, DataColumn, DataColumnType } from './data-column.model';
|
||||
|
||||
// Simple implementation of the DataColumn interface.
|
||||
export class ObjectDataColumn<T = unknown> implements DataColumn<T> {
|
||||
@ -38,6 +38,7 @@ export class ObjectDataColumn<T = unknown> implements DataColumn<T> {
|
||||
customData?: T;
|
||||
width?: number;
|
||||
order?: number;
|
||||
currencyConfig?: CurrencyConfig;
|
||||
|
||||
constructor(input: any) {
|
||||
this.id = input.id ?? '';
|
||||
@ -58,5 +59,6 @@ export class ObjectDataColumn<T = unknown> implements DataColumn<T> {
|
||||
this.customData = input.customData;
|
||||
this.width = input.width;
|
||||
this.order = input.order;
|
||||
this.currencyConfig = input.currencyConfig;
|
||||
}
|
||||
}
|
||||
|
@ -54,6 +54,7 @@ import { DataColumnComponent, DataColumnListComponent, DateColumnHeaderComponent
|
||||
import { ResizableModule } from './directives/resizable/resizable.module';
|
||||
import { DataColumnModule } from './data-column/data-column.module';
|
||||
import { BooleanCellComponent } from './components/boolean-cell/boolean-cell.component';
|
||||
import { AmountCellComponent } from './components/amount-cell/amount-cell.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@ -71,7 +72,8 @@ import { BooleanCellComponent } from './components/boolean-cell/boolean-cell.com
|
||||
ReactiveFormsModule,
|
||||
ResizableModule,
|
||||
DataColumnModule,
|
||||
BooleanCellComponent
|
||||
BooleanCellComponent,
|
||||
AmountCellComponent
|
||||
],
|
||||
declarations: [
|
||||
DataTableComponent,
|
||||
|
Loading…
x
Reference in New Issue
Block a user