From 411a1e7552108e80c2d55a12f546ec9b5dfb93b9 Mon Sep 17 00:00:00 2001 From: Kai Volland Date: Wed, 11 Sep 2024 16:33:17 +0200 Subject: [PATCH] feat: introduces dataType and valueMap to Displayfield MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: introduces dataType and valueMap to Displayfield * docs: update codedocs Co-authored-by: André Henn --- src/components/DisplayField/index.spec.tsx | 51 ++++++++++++ src/components/DisplayField/index.tsx | 92 ++++++++++++++++------ 2 files changed, 119 insertions(+), 24 deletions(-) diff --git a/src/components/DisplayField/index.spec.tsx b/src/components/DisplayField/index.spec.tsx index 3309d8179..eb09486ed 100644 --- a/src/components/DisplayField/index.spec.tsx +++ b/src/components/DisplayField/index.spec.tsx @@ -128,4 +128,55 @@ describe('', () => { } }); + it('can force a dataType', () => { + const { + container + } = render( + , + { + wrapper: createReduxWrapper() + }); + + expect(container).toBeVisible(); + const dateElem = screen.getByText('17.07.2024'); + expect(dateElem).toBeVisible(); + }); + + it('can render values from a valueMap', () => { + const valueMap = { + key1: 'value1' + }; + + render( + , + { + wrapper: createReduxWrapper() + }); + + const valueElem = screen.getByText('value1'); + expect(valueElem).toBeVisible(); + }); + + it('does render empty string for undefined', () => { + const { + container + } = render( + , + { + wrapper: createReduxWrapper() + }); + + expect(container).toBeVisible(); + const fieldElem = container.querySelector('.displayfield'); + expect(fieldElem).toHaveTextContent(''); + }); + }); diff --git a/src/components/DisplayField/index.tsx b/src/components/DisplayField/index.tsx index 061951f41..3752455f6 100644 --- a/src/components/DisplayField/index.tsx +++ b/src/components/DisplayField/index.tsx @@ -7,7 +7,7 @@ import { } from 'antd'; import isString from 'lodash/isString'; -import { +import moment, { isMoment } from 'moment'; @@ -26,6 +26,7 @@ import ImageUpload from '../ImageUpload'; import ReferenceTable from '../ReferenceTable'; export type ValueType = string | number | boolean | moment.Moment | Record; +export type DataType = 'auto' | 'number' | 'boolean' | 'string' | 'date' | 'url' | 'json'; export type ReferenceConfig = { tablePropertyName?: string; @@ -33,6 +34,17 @@ export type ReferenceConfig = { }; export type DisplayFieldProps = { + /** + * The data type of the value to display. If set to 'auto' (default), + * the component tries to guess the data type based on the value. Otherwise + * the component will try to enforce the given data type. + */ + dataType?: DataType; + /** + * A map of values to display instead of the actual value. The key is the + * original value and the value is the value to display instead. + */ + valueMap?: Record; format?: string; suffix?: string; value?: ValueType | ValueType[]; @@ -41,6 +53,8 @@ export type DisplayFieldProps = { }; export const DisplayField: React.FC = ({ + dataType = 'auto', + valueMap, format = 'DD.MM.YYYY', suffix, value, @@ -55,30 +69,52 @@ export const DisplayField: React.FC = ({ let displayValue: React.ReactNode = ''; - if (typeof value === 'string') { - displayValue = value; + if (value && typeof value === 'string' && valueMap?.hasOwnProperty(value)) { + value = valueMap[value]; } - if (typeof value === 'boolean' || value === 'false' || value === 'true') { + if ( + dataType === 'string' || + (dataType === 'auto' && typeof value === 'string') + ) { + if (value) { + displayValue = value?.toString(); + } + } + + if ( + dataType === 'boolean' || + (dataType === 'auto' && typeof value === 'boolean' || value === 'false' || value === 'true') + ) { return ( ); } - if (Number.isFinite(value)) { - displayValue = new Intl.NumberFormat(i18n.language, { - useGrouping: false - }).format(Number(value)); + if ( + dataType === 'number' || + (dataType === 'auto' && Number.isFinite(value)) + ) { + if (value) { + displayValue = new Intl.NumberFormat(i18n.language, { + useGrouping: false + }).format(Number(value)); + } } - if (isMoment(value)) { - displayValue = value.format(format); + if ( + dataType === 'date' || + (dataType === 'auto' && isMoment(value)) + ) { + if (value) { + displayValue = moment(value as string).format(format); + } } - if (Array.isArray(value)) { + if (dataType === 'auto' && Array.isArray(value)) { displayValue = value.join(', '); } @@ -88,16 +124,21 @@ export const DisplayField: React.FC = ({ return protocols.some(protocol => lowerCandidate.startsWith(protocol)); }; - if (isString(value) && isUrl(value)) { - displayValue = ( - - {value} - - ); + if ( + dataType === 'url' || + (dataType === 'auto' && isString(value) && isUrl(value)) + ) { + if (value) { + displayValue = ( + + {value?.toString()} + + ); + } } const getUpload = (val: ValueType | ValueType[]): UploadFile[] | null => { @@ -120,7 +161,7 @@ export const DisplayField: React.FC = ({ const uploadValue = value && getUpload(value); - if (uploadValue) { + if (dataType === 'auto' && uploadValue) { if (uploadValue[0].response?.fileType?.startsWith('image/')) { return ( = ({ return typeof v === 'object' && v !== null; }; - if (value && isJson(value)) { + if ( + dataType === 'json' || + dataType === 'auto' && value && isJson(value) + ) { return (