Skip to content

Commit

Permalink
feat: introduces dataType and valueMap to Displayfield
Browse files Browse the repository at this point in the history
* feat: introduces dataType and valueMap to Displayfield
* docs: update codedocs

Co-authored-by: André Henn <[email protected]>
  • Loading branch information
KaiVolland and ahennr authored Sep 11, 2024
1 parent c292538 commit 411a1e7
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 24 deletions.
51 changes: 51 additions & 0 deletions src/components/DisplayField/index.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -128,4 +128,55 @@ describe('<DisplayField />', () => {
}
});

it('can force a dataType', () => {
const {
container
} = render(
<DisplayField
dataType={'date'}
value={'2024-07-17T11:01:38.128Z'}
/>,
{
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(
<DisplayField
value={'key1'}
valueMap={valueMap}
/>,
{
wrapper: createReduxWrapper()
});

const valueElem = screen.getByText('value1');
expect(valueElem).toBeVisible();
});

it('does render empty string for undefined', () => {
const {
container
} = render(
<DisplayField
value={undefined}
/>,
{
wrapper: createReduxWrapper()
});

expect(container).toBeVisible();
const fieldElem = container.querySelector('.displayfield');
expect(fieldElem).toHaveTextContent('');
});

});
92 changes: 68 additions & 24 deletions src/components/DisplayField/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
} from 'antd';

import isString from 'lodash/isString';
import {
import moment, {
isMoment
} from 'moment';

Expand All @@ -26,13 +26,25 @@ import ImageUpload from '../ImageUpload';
import ReferenceTable from '../ReferenceTable';

export type ValueType = string | number | boolean | moment.Moment | Record<string, any>;
export type DataType = 'auto' | 'number' | 'boolean' | 'string' | 'date' | 'url' | 'json';

export type ReferenceConfig = {
tablePropertyName?: string;
featureInfoFormConfig?: PropertyFormItemReadConfig[];
};

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<string, ValueType>;
format?: string;
suffix?: string;
value?: ValueType | ValueType[];
Expand All @@ -41,6 +53,8 @@ export type DisplayFieldProps = {
};

export const DisplayField: React.FC<DisplayFieldProps> = ({
dataType = 'auto',
valueMap,
format = 'DD.MM.YYYY',
suffix,
value,
Expand All @@ -55,30 +69,52 @@ export const DisplayField: React.FC<DisplayFieldProps> = ({

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 (
<Checkbox
checked={value === true || value === 'true'}
checked={value !== 'false' && value !== false}
disabled
/>
);
}

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(', ');
}

Expand All @@ -88,16 +124,21 @@ export const DisplayField: React.FC<DisplayFieldProps> = ({
return protocols.some(protocol => lowerCandidate.startsWith(protocol));
};

if (isString(value) && isUrl(value)) {
displayValue = (
<a
href={value}
target="_blank"
rel='noreferrer'
>
{value}
</a>
);
if (
dataType === 'url' ||
(dataType === 'auto' && isString(value) && isUrl(value))
) {
if (value) {
displayValue = (
<a
href={value?.toString()}
target="_blank"
rel='noreferrer'
>
{value?.toString()}
</a>
);
}
}

const getUpload = (val: ValueType | ValueType[]): UploadFile<ShogunFile>[] | null => {
Expand All @@ -120,7 +161,7 @@ export const DisplayField: React.FC<DisplayFieldProps> = ({

const uploadValue = value && getUpload(value);

if (uploadValue) {
if (dataType === 'auto' && uploadValue) {
if (uploadValue[0].response?.fileType?.startsWith('image/')) {
return (
<ImageUpload
Expand Down Expand Up @@ -152,7 +193,10 @@ export const DisplayField: React.FC<DisplayFieldProps> = ({
return typeof v === 'object' && v !== null;
};

if (value && isJson(value)) {
if (
dataType === 'json' ||
dataType === 'auto' && value && isJson(value)
) {
return (
<ReferenceTable
value={typeof value === 'string' ? value : JSON.stringify(value)}
Expand Down

0 comments on commit 411a1e7

Please sign in to comment.