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) => (
+ {cell.labelAlias} |
+ ))}
+
+
+
+ {tableBodyRows.map((row, index) => (
+
+ {properties?.map((cell) => (
+
+ {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(' | ');