diff --git a/lib/AuditLog/AuditLogCard.js b/lib/AuditLog/AuditLogCard.js
index 707919509..095dd1802 100644
--- a/lib/AuditLog/AuditLogCard.js
+++ b/lib/AuditLog/AuditLogCard.js
@@ -18,6 +18,7 @@ const AuditLogCard = ({
fieldLabelsMap,
isOriginal,
isCurrentVersion,
+ itemFormatter,
showSharedLabel,
source,
userName,
@@ -89,6 +90,7 @@ const AuditLogCard = ({
onClose={() => setIsModalOpen(false)}
fieldLabelsMap={fieldLabelsMap}
fieldFormatter={fieldFormatter}
+ itemFormatter={itemFormatter}
actionsMap={actionsMap}
columnWidths={columnWidths}
/>
@@ -105,8 +107,9 @@ AuditLogCard.propTypes = {
fieldLabelsMap: PropTypes.object,
isCurrentVersion: PropTypes.bool,
isOriginal: PropTypes.bool,
- showSharedLabel: PropTypes.bool,
+ itemFormatter: PropTypes.func,
modalFieldChanges: PropTypes.arrayOf(PropTypes.object),
+ showSharedLabel: PropTypes.bool,
source: PropTypes.oneOfType([PropTypes.string, PropTypes.node]).isRequired,
userName: PropTypes.oneOfType([PropTypes.string, PropTypes.node]).isRequired,
};
diff --git a/lib/AuditLog/AuditLogModal.js b/lib/AuditLog/AuditLogModal.js
index ead99e827..2c389c580 100644
--- a/lib/AuditLog/AuditLogModal.js
+++ b/lib/AuditLog/AuditLogModal.js
@@ -12,6 +12,7 @@ const AuditLogModal = ({
columnWidths,
contentData,
fieldFormatter,
+ itemFormatter,
fieldLabelsMap,
label,
onClose,
@@ -25,26 +26,27 @@ const AuditLogModal = ({
changedTo: ,
};
- const itemFormatter = (field, i) => {
+ const defaultItemFormatter = (field, i) => {
return (
{fieldFormatter?.[field.name]?.(field.value) || field.value}
);
};
+
const formatter = {
action: item => actionsMap?.[item.changeType] || item.changeType,
field: item => fieldLabelsMap?.[item.fieldName] || item.fieldName,
changedFrom: item => changedFieldsFormatter({
fieldValue: item.oldValue,
fieldName: item.fieldName,
- listItemFormatter: itemFormatter,
+ listItemFormatter: itemFormatter || defaultItemFormatter,
fieldFormatter,
}),
changedTo: item => changedFieldsFormatter({
fieldValue: item.newValue,
fieldName: item.fieldName,
- listItemFormatter: itemFormatter,
+ listItemFormatter: itemFormatter || defaultItemFormatter,
fieldFormatter,
}),
};
@@ -91,6 +93,7 @@ AuditLogModal.propTypes = {
})).isRequired,
fieldFormatter: PropTypes.object,
fieldLabelsMap: PropTypes.object,
+ itemFormatter: PropTypes.func,
label: PropTypes.node.isRequired,
onClose: PropTypes.func,
open: PropTypes.bool.isRequired,
diff --git a/lib/AuditLog/AuditLogPane.js b/lib/AuditLog/AuditLogPane.js
index fa35db304..4ffc15f67 100644
--- a/lib/AuditLog/AuditLogPane.js
+++ b/lib/AuditLog/AuditLogPane.js
@@ -19,6 +19,7 @@ const AuditLogPane = ({
actionsMap,
columnWidths,
fieldFormatter,
+ itemFormatter,
fieldLabelsMap,
handleLoadMore,
isInitialLoading,
@@ -82,13 +83,14 @@ const AuditLogPane = ({
fieldChanges={fieldChanges}
fieldLabelsMap={fieldLabelsMap}
fieldFormatter={fieldFormatter}
+ itemFormatter={itemFormatter}
actionsMap={actionsMap}
columnWidths={columnWidths}
modalFieldChanges={modalFieldChanges}
/>
);
});
- }, [versions, fieldLabelsMap, fieldFormatter, actionsMap, columnWidths, showSharedLabel]);
+ }, [versions, fieldLabelsMap, fieldFormatter, itemFormatter, actionsMap, columnWidths, showSharedLabel]);
return (
({ name, value }))}
+ items={map(fieldValue, (value, name) => ({ name, value, collectionName: fieldName }))}
itemFormatter={listItemFormatter}
listStyle="bullets"
marginBottom0
diff --git a/lib/AuditLog/readme.md b/lib/AuditLog/readme.md
index 9fb679994..6edb86ffe 100644
--- a/lib/AuditLog/readme.md
+++ b/lib/AuditLog/readme.md
@@ -32,6 +32,21 @@ const fieldFormatter = {
primary: value => value.toString(),
};
+const itemFormatter = (fieldLabelsMap, fieldFormatter) => (element, i) => {
+ if (!element) return null;
+
+ const { name: fieldName, value } = element;
+ const label = fieldLabelsMap?.[fieldName] || fieldName;
+ const formattedValue = fieldFormatter?.[fieldName]?.(value) || value;
+
+ return (
+
+ {fieldName && {label}: }
+ {formattedValue}
+
+ );
+};
+
const handleClose = () => console.log('Pane closed');
const handleLoadMore = () => console.log('Load more clicked');
const isLoading = false;
@@ -48,6 +63,7 @@ return (
handleLoadMore={handleLoadMore}
isLoading={isLoading}
isInitialLoading={isInitialLoading}
+ itemFormatter={itemFormatter}
showSharedLabel={showSharedLabel}
fieldLabelsMap={fieldLabelsMap}
fieldFormatter={fieldFormatter}
@@ -68,6 +84,7 @@ handleLoadMore | func | Callback fired when the "Load more" button is clicked
isInitialLoading | bool | Flag that indicates whether data is being loaded for the first time | | false
isLoading | bool | Flag that indicates whether data is being loaded | | false
isLoadMoreVisible | bool | Flag that indicates whether "Load more" button visible or not | true | false
+itemFormatter | func | Formats changed field values of objects or arrays in modal content, used to format oldValue/newValue items of object or array, e.g. showing the field name before the field value. Receives a field object with `name`, `value`, and `collectionName` properties and the item index. Returns a list item element. | `{field.value}` | false
onClose | func | Callback fired when the pane is closed using its dismiss button | | false
showSharedLabel | bool | Flag indicating whether the original version should display "Shared" label | false | false
totalVersions | number | Total number of versions | | false
diff --git a/lib/AuditLog/tests/AuditLogModal-test.js b/lib/AuditLog/tests/AuditLogModal-test.js
index d5437015f..aba933b81 100644
--- a/lib/AuditLog/tests/AuditLogModal-test.js
+++ b/lib/AuditLog/tests/AuditLogModal-test.js
@@ -155,4 +155,101 @@ describe('AuditLogModal', () => {
it('the onClose callback should be fired', () => converge(() => onClose.called));
});
+
+ describe('itemFormatter', () => {
+ describe('when using DEFAULT itemFormatter', () => {
+ const contentDataWithArray = [{
+ changeType: 'MODIFIED',
+ fieldName: 'arrayField',
+ newValue: ['item1', 'item2', 'item3'],
+ oldValue: ['oldItem1', 'oldItem2'],
+ }];
+
+ beforeEach(async () => {
+ await mountWithContext(
+
+
+
+ );
+ });
+
+ it('should render list items with default tags', async () => {
+ await mcl.find(MultiColumnListCell({ row: 0, columnIndex: 2 })).perform(el => {
+ expect(el.querySelectorAll('li')).to.have.length(2);
+ expect(el.querySelectorAll('.custom-item')).to.have.length(0);
+ });
+
+ await mcl.find(MultiColumnListCell({ row: 0, columnIndex: 3 })).perform(el => {
+ expect(el.querySelectorAll('li')).to.have.length(3);
+ expect(el.querySelectorAll('.custom-item')).to.have.length(0);
+ });
+ });
+ });
+
+ describe('when using CUSTOM itemFormatter (object)', () => {
+ const customItemFormatter = (field, i) => {
+ return (
+
+ CUSTOM: {field.value}
+
+ );
+ };
+
+ const contentDataWithObject = [{
+ changeType: 'MODIFIED',
+ fieldName: 'objectField',
+ newValue: {
+ a: 'item1',
+ b: 'item2',
+ c: 'item3',
+ },
+ oldValue: {
+ x: 'oldItem1',
+ y: 'oldItem2',
+ },
+ }];
+
+ beforeEach(async () => {
+ await mountWithContext(
+
+
+
+ );
+ });
+
+ it('should render object values using the custom itemFormatter', async () => {
+ await mcl.find(MultiColumnListCell({ row: 0, columnIndex: 2 })).perform(el => {
+ expect(el.textContent).to.include('CUSTOM: oldItem1');
+ expect(el.textContent).to.include('CUSTOM: oldItem2');
+
+ const customItems = el.querySelectorAll('.custom-item');
+ expect(customItems.length).to.equal(2);
+ });
+
+ await mcl.find(MultiColumnListCell({ row: 0, columnIndex: 3 })).perform(el => {
+ expect(el.textContent).to.include('CUSTOM: item1');
+ expect(el.textContent).to.include('CUSTOM: item2');
+ expect(el.textContent).to.include('CUSTOM: item3');
+
+ const customItems = el.querySelectorAll('.custom-item');
+ expect(customItems.length).to.equal(3);
+ });
+ });
+ });
+ });
});