From e5c45961e6f5ff46e75b15a7dcc68e1e1b530c7b Mon Sep 17 00:00:00 2001 From: Vadym Shchekotilin <86330150+vashjs@users.noreply.github.com> Date: Wed, 28 Feb 2024 13:52:52 +0100 Subject: [PATCH] UIPQB-75 Display grouped fields within a list row (#88) --- CHANGELOG.md | 1 + .../DynamicTable/DynamicTable.css | 14 ++++ .../ResultViewer/DynamicTable/DynamicTable.js | 36 ++++++++ .../DynamicTable/DynamicTable.test.js | 82 +++++++++++++++++++ src/QueryBuilder/ResultViewer/helpers.js | 8 +- 5 files changed, 139 insertions(+), 2 deletions(-) create mode 100644 src/QueryBuilder/ResultViewer/DynamicTable/DynamicTable.css create mode 100644 src/QueryBuilder/ResultViewer/DynamicTable/DynamicTable.js create mode 100644 src/QueryBuilder/ResultViewer/DynamicTable/DynamicTable.test.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 46d245f1..bd17c464 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,3 +47,4 @@ * [UIPQB-55](https://issues.folio.org/browse/UIPQB-55) Regular expressions are incorrect for contains and starts_with operators * [UIPQB-70](https://issues.folio.org/browse/UIPQB-70) Array fields support verification * [UIPQB-71](https://issues.folio.org/browse/UIPQB-71) Allow dropdown menus for array types +* [UIPQB-75](https://issues.folio.org/browse/UIPQB-75) Display grouped fields within a list row diff --git a/src/QueryBuilder/ResultViewer/DynamicTable/DynamicTable.css b/src/QueryBuilder/ResultViewer/DynamicTable/DynamicTable.css new file mode 100644 index 00000000..17f302b2 --- /dev/null +++ b/src/QueryBuilder/ResultViewer/DynamicTable/DynamicTable.css @@ -0,0 +1,14 @@ +.DynamicTable { + width: calc(100% + calc(2 * var(--gutter-static-two-thirds))); + margin: calc(-1 * var(--gutter-static-one-third)) calc(-1 * var(--gutter-static-two-thirds)); + border-collapse: collapse; +} + +.DynamicTable td { + vertical-align: top; +} + + +.DynamicTable th, .DynamicTable td { + padding: var(--gutter-static-one-third) var(--gutter-static-two-thirds); +} diff --git a/src/QueryBuilder/ResultViewer/DynamicTable/DynamicTable.js b/src/QueryBuilder/ResultViewer/DynamicTable/DynamicTable.js new file mode 100644 index 00000000..bbac8151 --- /dev/null +++ b/src/QueryBuilder/ResultViewer/DynamicTable/DynamicTable.js @@ -0,0 +1,36 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import css from './DynamicTable.css'; + +export const DynamicTable = ({ properties, values }) => { + const tableBodyRows = JSON.parse(values); + + if (!tableBodyRows.length) return null; + + return ( + + + {properties?.map((cell) => ( + + ))} + + + + {tableBodyRows.map((row, index) => ( + + {properties?.map((cell) => ( + + ))} + + ))} + +
{cell.labelAlias}
+ {row[cell.property]} +
+ ); +}; + +DynamicTable.propTypes = { + properties: PropTypes.arrayOf(PropTypes.object), + values: PropTypes.string, +}; diff --git a/src/QueryBuilder/ResultViewer/DynamicTable/DynamicTable.test.js b/src/QueryBuilder/ResultViewer/DynamicTable/DynamicTable.test.js new file mode 100644 index 00000000..0ab7cc5f --- /dev/null +++ b/src/QueryBuilder/ResultViewer/DynamicTable/DynamicTable.test.js @@ -0,0 +1,82 @@ +import React from 'react'; +import { render } from '@testing-library/react'; +import { DynamicTable } from './DynamicTable'; + +describe('DynamicTable component', () => { + const properties = [ + { + 'name': 'code', + 'dataType': { + 'dataType': 'stringType', + }, + 'labelAlias': 'Code', + 'property': 'code', + }, + { + 'name': 'distribution_type', + 'dataType': { + 'dataType': 'stringType', + }, + 'labelAlias': 'Distribution type', + 'property': 'distributionType', + }, + { + 'name': 'encumbrance', + 'dataType': { + 'dataType': 'rangedUUIDType', + }, + 'labelAlias': 'Encumbrance', + 'property': 'encumbrance', + }, + { + 'name': 'fund_id', + 'dataType': { + 'dataType': 'rangedUUIDType', + }, + 'labelAlias': 'Fund ID', + 'property': 'fundId', + }, + { + 'name': 'value', + 'dataType': { + 'dataType': 'numberType', + }, + 'labelAlias': 'Value', + 'property': 'value', + }, + ]; + + const values = '[{"code": "STATE-MONOSER", "value": 100.0, "fundId": "bbd4a5e1-c9f3-44b9-bfdf-d184e04f0ba0", "encumbrance": "eb506834-6c70-4239-8d1a-6414a5b08010", "distributionType": "percentage"}]'; + + it('render null value if there are no rows', () => { + const { container } = render(); + + expect(container).toBeEmptyDOMElement(); + }); + + it('renders table with correct properties and values', () => { + const { getByText } = render(); + + properties.forEach(property => { + const label = getByText(property.labelAlias); + + expect(label).toBeInTheDocument(); + }); + + const codeValue = getByText('STATE-MONOSER'); + + expect(codeValue).toBeInTheDocument(); + + const encumbranceValue = getByText('eb506834-6c70-4239-8d1a-6414a5b08010'); + + expect(encumbranceValue).toBeInTheDocument(); + + const fundIdValue = getByText('bbd4a5e1-c9f3-44b9-bfdf-d184e04f0ba0'); + + expect(fundIdValue).toBeInTheDocument(); + + const numberValue = getByText('100'); + + expect(numberValue).toBeInTheDocument(); + }); +}); diff --git a/src/QueryBuilder/ResultViewer/helpers.js b/src/QueryBuilder/ResultViewer/helpers.js index 04f70c75..6bedb1ae 100644 --- a/src/QueryBuilder/ResultViewer/helpers.js +++ b/src/QueryBuilder/ResultViewer/helpers.js @@ -1,5 +1,6 @@ import { FormattedDate } from 'react-intl'; import { DATA_TYPES } from '../../constants/dataTypes'; +import { DynamicTable } from './DynamicTable/DynamicTable'; export const getTableMetadata = (entityType) => { const defaultColumns = entityType?.columns?.map((cell) => ({ @@ -9,6 +10,7 @@ export const getTableMetadata = (entityType) => { readOnly: false, selected: cell.visibleByDefault, dataType: cell.dataType.dataType, + properties: cell.dataType.itemDataType?.properties, })) || []; const columnMapping = defaultColumns?.reduce((acc, { value, label }) => { @@ -19,10 +21,12 @@ export const getTableMetadata = (entityType) => { const defaultVisibleColumns = defaultColumns?.filter(col => col.selected).map(col => col.value) || []; const formatter = defaultColumns.reduce((formatted, column) => { - const { value, dataType } = column; + const { value, dataType, properties } = column; formatted[value] = (item) => { - if (dataType === DATA_TYPES.DateType) { + if (properties?.length) { + return ; + } else if (dataType === DATA_TYPES.DateType) { return item[value] ? : ''; } else if (dataType === DATA_TYPES.ArrayType) { return item[value]?.join(' | ');