diff --git a/docs/core/components/data-column.component.md b/docs/core/components/data-column.component.md index 2af1d94344..a7e4a2a93b 100644 --- a/docs/core/components/data-column.component.md +++ b/docs/core/components/data-column.component.md @@ -11,18 +11,18 @@ Defines column properties for DataTable, Tasklist, Document List and other compo ## Contents -- [Basic Usage](#basic-usage) -- [Class members](#class-members) - - [Properties](#properties) -- [Details](#details) - - [Conditional visibility](#conditional-visibility) - - [Automatic column header translation](#automatic-column-header-translation) - - [Custom tooltips](#custom-tooltips) - - [Column Template](#column-template) - - [Styling Techniques](#styling-techniques) - - [Using the copyContent option](#using-the-copycontent-option) - - [Example of column customData](#example-of-column-customdata) -- [See also](#see-also) +- [Basic Usage](#basic-usage) +- [Class members](#class-members) + - [Properties](#properties) +- [Details](#details) + - [Conditional visibility](#conditional-visibility) + - [Automatic column header translation](#automatic-column-header-translation) + - [Custom tooltips](#custom-tooltips) + - [Column Template](#column-template) + - [Styling Techniques](#styling-techniques) + - [Using the copyContent option](#using-the-copycontent-option) + - [Example of column customData](#example-of-column-customdata) +- [See also](#see-also) ## Basic Usage @@ -59,12 +59,22 @@ 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', 'json' and 'amount'. | +| type | `string` | "text" | Value type for the column. Possible settings are 'text', 'boolean', 'icon', 'image', 'date', 'fileSize', 'location', 'json', 'amount' and 'number'. | | 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. | +| decimalConfig | `DecimalConfig` | [Default decimal config](#default-decimal-config) | Decimal configuration to customize the formatting and display of decimal values within the component. | ## Properties configuration +### `type` Input + +The `type` input allows us to specify the type of hosted values for a given column. The complete array of possible values is outlined below: + +- `text` - The given values are represented as a strings (default option). +- `boolean` - The column expects true / false (boolean values) and in addition accepts two strings - 'false' and 'true'. Other values are not recognized by the column, and the cell remains empty. +- `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), +- `number` - This column is responsible for displaying numbers (integers and decimals). It expects numerals represented by a string or a number. This type comes with [`decimalConfig`](#default-decimal-config) + ### `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. @@ -89,21 +99,25 @@ These properties offer flexibility in customizing how currency values are presen 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 +### `decimalConfig` Input -### `type` Input +The `decimalConfig` input allows you to customize the formatting and display of decimal values within the component. It accepts an object of type `DecimalConfig` with optional properties for specifying the decimal precision and locale. -The `type` input allows us to specify the type of hosted values for a given column. The complete array of possible values is outlined below: +#### Properties -- `text` - The given values are represented as a strings (default option). -- `boolean` - The column expects true / false (boolean values) and in addition accepts two strings - 'false' and 'true'. Other values are not recognized by the column, and the cell remains empty. -- `icon` - TODO -- `image` - TODO -- `date` - TODO -- `fileSize` - TODO -- `location` - TODO -- `json` - TODO -- `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). +- `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 decimal config + +By default, the `decimalConfig` input is not required. If not provided, the component will use the following default values: + +- `digitsInfo`: undefined +- `locale`: undefined + +These properties offer flexibility in customizing how decimal 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/DecimalPipe). ## Details @@ -428,6 +442,6 @@ if (shouldPerformAction) { /* action */} ## See also -- [Document list component](../../content-services/components/document-list.component.md) -- [Datatable component](datatable.component.md) -- [Task list component](../../process-services/components/task-list.component.md) +- [Document list component](../../content-services/components/document-list.component.md) +- [Datatable component](datatable.component.md) +- [Task list component](../../process-services/components/task-list.component.md) diff --git a/lib/core/src/lib/datatable/components/datatable/datatable.component.html b/lib/core/src/lib/datatable/components/datatable/datatable.component.html index 9359754a13..d8faac9c53 100644 --- a/lib/core/src/lib/datatable/components/datatable/datatable.component.html +++ b/lib/core/src/lib/datatable/components/datatable/datatable.component.html @@ -290,7 +290,7 @@
+
+ + +
diff --git a/lib/core/src/lib/datatable/components/datatable/datatable.component.spec.ts b/lib/core/src/lib/datatable/components/datatable/datatable.component.spec.ts index 1f3c994468..cd4daaea4d 100644 --- a/lib/core/src/lib/datatable/components/datatable/datatable.component.spec.ts +++ b/lib/core/src/lib/datatable/components/datatable/datatable.component.spec.ts @@ -1218,6 +1218,17 @@ describe('DataTable', () => { expect(rows[1].getValue('car_price')).toBe(15000.12345); expect(rows[2].getValue('car_price')).toBe(10000); }); + + it('should be able to display column of type number', () => { + dataTable.data = new ObjectDataTableAdapter(mockCarsData, mockCarsSchemaDefinition); + + fixture.detectChanges(); + const rows = dataTable.data.getRows(); + + expect(rows[0].getValue('fuel_consumption')).toBe(5.25789); + expect(rows[1].getValue('fuel_consumption')).toBe(6); + expect(rows[2].getValue('fuel_consumption')).toBe(4.9); + }); }); describe('Accesibility', () => { diff --git a/lib/core/src/lib/datatable/components/mocks/datatable.mock.ts b/lib/core/src/lib/datatable/components/mocks/datatable.mock.ts index 629618ac21..eeaaad4fa2 100644 --- a/lib/core/src/lib/datatable/components/mocks/datatable.mock.ts +++ b/lib/core/src/lib/datatable/components/mocks/datatable.mock.ts @@ -22,6 +22,7 @@ export const mockCarsData: any = [ car_id: 1, car_name: 'Fiat 126p (Process)', car_price: 599.00, + fuel_consumption: 5.25789, is_available: 'false', production_start: '1972-04-23', description: 'The Fiat 126 (Type 126) is a four-passenger, rear-engine, city car manufactured and marketed by Fiat over a twenty-eight year production run from 1972 until 2000, over a single generation.', @@ -32,6 +33,7 @@ export const mockCarsData: any = [ car_id: 2, car_name: 'Citroen Xsara Picasso (Process)', car_price: 10000, + fuel_consumption: 4.9, is_available: 'true', production_start: '2004-02-10T12:25:43.511Z', description: 'The Citroën Xsara Picasso is a car produced by Citroën from 1999 to 2012. It has a five-seater five-door compact MPV design.', @@ -42,6 +44,7 @@ export const mockCarsData: any = [ car_id: 3, car_name: 'Audi A3 (Process)', car_price: 15000.12345, + fuel_consumption: 6, is_available: 'true', production_start: '1998-06-25T12:25:20', description: 'The Audi A3 is a subcompact executive/small family car (C-segment) manufactured and marketed by the German automaker Audi AG since September 1996, currently in its fourth generation.', @@ -85,6 +88,17 @@ export const mockCarsSchemaDefinition: DataColumn[] = [ locale: 'en-US' } }, + { + type: 'number', + key: 'fuel_consumption', + title: 'Fuel Consumption (l/100km)', + sortable: true, + draggable: true, + decimalConfig: { + digitsInfo: '1.0-3', + locale: 'en-US' + } + }, { type: 'boolean', key: 'is_available', diff --git a/lib/core/src/lib/datatable/components/number-cell/number-cell.component.html b/lib/core/src/lib/datatable/components/number-cell/number-cell.component.html new file mode 100644 index 0000000000..87eb4dbc3a --- /dev/null +++ b/lib/core/src/lib/datatable/components/number-cell/number-cell.component.html @@ -0,0 +1,8 @@ + + + {{ number | number: + (decimalConfig?.digitsInfo || defaultDecimalConfig.digitsInfo): + (decimalConfig?.locale || defaultDecimalConfig.locale) + }} + + diff --git a/lib/core/src/lib/datatable/components/number-cell/number-cell.component.spec.ts b/lib/core/src/lib/datatable/components/number-cell/number-cell.component.spec.ts new file mode 100644 index 0000000000..265c5ab0c5 --- /dev/null +++ b/lib/core/src/lib/datatable/components/number-cell/number-cell.component.spec.ts @@ -0,0 +1,86 @@ +/*! + * @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 { NumberCellComponent } from './number-cell.component'; +import { DecimalConfig } 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('NumberCellComponent', () => { + let component: NumberCellComponent; + let fixture: ComponentFixture; + + const renderAndCheckNumberValue = (decimalConfig: DecimalConfig, value: number, expectedResult: string) => { + component.value$ = new BehaviorSubject(value); + component.decimalConfig = decimalConfig; + + fixture.detectChanges(); + const displayedNumber = fixture.nativeElement.querySelector('span'); + + expect(displayedNumber).toBeTruthy(); + expect(displayedNumber.textContent.trim()).toBe(expectedResult); + }; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [NumberCellComponent] + }); + fixture = TestBed.createComponent(NumberCellComponent); + component = fixture.componentInstance; + }); + + it('should set default decimal config', () => { + expect(component.defaultDecimalConfig.digitsInfo).toBeUndefined(); + expect(component.defaultDecimalConfig.locale).toBeUndefined(); + }); + + it('should render number value', () => { + renderAndCheckNumberValue(component.decimalConfig, 123.45, '123.45'); + }); + + it('should render decimal value with custom digitsInfo', () => { + renderAndCheckNumberValue({ digitsInfo: '1.2-2' }, 123.456789, '123.46'); + }); +}); + +describe('NumberCellComponent locale', () => { + let component: NumberCellComponent; + let fixture: ComponentFixture; + + it('should render decimal value with custom locale', () => { + TestBed.configureTestingModule({ + imports: [NumberCellComponent], + providers: [{ provide: LOCALE_ID, useValue: 'pl-PL' }] + }); + + fixture = TestBed.createComponent(NumberCellComponent); + component = fixture.componentInstance; + registerLocaleData(localePL); + + component.value$ = new BehaviorSubject(123.45); + component.decimalConfig = { locale: 'pl-PL' }; + + fixture.detectChanges(); + const displayedNumber = fixture.nativeElement.querySelector('span'); + + expect(displayedNumber).toBeTruthy(); + expect(displayedNumber.textContent.trim()).toBe('123,45'); + }); +}); diff --git a/lib/core/src/lib/datatable/components/number-cell/number-cell.component.ts b/lib/core/src/lib/datatable/components/number-cell/number-cell.component.ts new file mode 100644 index 0000000000..ad1457f982 --- /dev/null +++ b/lib/core/src/lib/datatable/components/number-cell/number-cell.component.ts @@ -0,0 +1,59 @@ +/*! + * @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 +} from '@angular/core'; +import { DataTableCellComponent } from '../datatable-cell/datatable-cell.component'; +import { DataTableService } from '../../services/datatable.service'; +import { DecimalConfig } from '../../data/data-column.model'; +import { CommonModule } from '@angular/common'; + +@Component({ + standalone: true, + imports: [CommonModule], + selector: 'adf-number-cell', + templateUrl: './number-cell.component.html', + host: { class: 'adf-datatable-content-cell' }, + encapsulation: ViewEncapsulation.None, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class NumberCellComponent extends DataTableCellComponent implements OnInit { + + @Input() + decimalConfig: DecimalConfig; + + readonly defaultDecimalConfig: DecimalConfig = { + digitsInfo: undefined, + locale: undefined + }; + + constructor(@Optional() dataTableService: DataTableService) { + super(dataTableService); + } + + ngOnInit() { + if (this.column?.key && this.row && this.data) { + this.value$.next(this.data.getValue(this.row, this.column, this.resolverFn)); + } + } +} diff --git a/lib/core/src/lib/datatable/data/data-column.model.ts b/lib/core/src/lib/datatable/data/data-column.model.ts index 0d2ac7cfb8..4ff80f0bff 100644 --- a/lib/core/src/lib/datatable/data/data-column.model.ts +++ b/lib/core/src/lib/datatable/data/data-column.model.ts @@ -15,6 +15,8 @@ * limitations under the License. */ +/* eslint-disable id-blacklist */ + import { TemplateRef } from '@angular/core'; import { DataColumnType } from '@alfresco/adf-extensions'; @@ -40,11 +42,13 @@ export interface DataColumn { customData?: T; order?: number; currencyConfig?: CurrencyConfig; + decimalConfig?: DecimalConfig; } - -export interface CurrencyConfig { - code?: string; - display?: string; +export interface DecimalConfig { digitsInfo?: string; locale?: string; } +export interface CurrencyConfig extends DecimalConfig { + code?: string; + display?: string; +} diff --git a/lib/core/src/lib/datatable/data/object-datacolumn.model.ts b/lib/core/src/lib/datatable/data/object-datacolumn.model.ts index 3974675998..deeacc5363 100644 --- a/lib/core/src/lib/datatable/data/object-datacolumn.model.ts +++ b/lib/core/src/lib/datatable/data/object-datacolumn.model.ts @@ -17,7 +17,7 @@ import { TemplateRef } from '@angular/core'; import { DataColumnType } from '@alfresco/adf-extensions'; -import { CurrencyConfig, DataColumn } from './data-column.model'; +import { CurrencyConfig, DataColumn, DecimalConfig } from './data-column.model'; // Simple implementation of the DataColumn interface. export class ObjectDataColumn implements DataColumn { @@ -40,6 +40,7 @@ export class ObjectDataColumn implements DataColumn { width?: number; order?: number; currencyConfig?: CurrencyConfig; + decimalConfig?: DecimalConfig; constructor(input: any) { this.id = input.id ?? ''; @@ -61,5 +62,6 @@ export class ObjectDataColumn implements DataColumn { this.width = input.width; this.order = input.order; this.currencyConfig = input.currencyConfig; + this.decimalConfig = input.decimalConfig; } } diff --git a/lib/core/src/lib/datatable/datatable.module.ts b/lib/core/src/lib/datatable/datatable.module.ts index e4db022e17..83b83103d4 100644 --- a/lib/core/src/lib/datatable/datatable.module.ts +++ b/lib/core/src/lib/datatable/datatable.module.ts @@ -55,6 +55,7 @@ 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'; +import { NumberCellComponent } from './components/number-cell/number-cell.component'; @NgModule({ imports: [ @@ -73,7 +74,8 @@ import { AmountCellComponent } from './components/amount-cell/amount-cell.compon ResizableModule, DataColumnModule, BooleanCellComponent, - AmountCellComponent + AmountCellComponent, + NumberCellComponent ], declarations: [ DataTableComponent, diff --git a/lib/extensions/src/lib/config/document-list.extensions.ts b/lib/extensions/src/lib/config/document-list.extensions.ts index 87ec163587..88f9075b1f 100644 --- a/lib/extensions/src/lib/config/document-list.extensions.ts +++ b/lib/extensions/src/lib/config/document-list.extensions.ts @@ -15,6 +15,8 @@ * limitations under the License. */ +/* eslint-disable id-blacklist */ + import { ExtensionElement } from './extension-element'; export interface DataColumnTypes { @@ -25,9 +27,9 @@ export interface DataColumnTypes { icon: string; fileSize: string; location: string; - // eslint-disable-next-line id-blacklist boolean: string; amount: string; + number: string; } export type DataColumnType = keyof DataColumnTypes;