design-comuni-plone-theme
Version:
Volto Theme for Italia design guidelines
208 lines (195 loc) • 6.01 kB
JSX
/**
* Diff field component.
* @module components/manage/Diff/DiffField
*/
/* CUSTOMIZATIONS
- Overhaul all logic and html, use something that actually does the job
- Still need to test dates, images not being shown correctly, might revert
to filename if the solution to this bug is not quick and easy
- Backend has to fix history, RelList fields not appearing in response
*/
import React, { useMemo } from 'react';
import { isEqual } from 'lodash';
import PropTypes from 'prop-types';
import { Table } from 'semantic-ui-react';
import { useSelector } from 'react-redux';
import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
import {
blockIsNotEmptyPlaceholder,
SSRRenderHtml,
} from 'design-comuni-plone-theme/helpers';
/**
* Enhanced diff words utility
* @function diffWords
* @param oneStr Field one
* @param twoStr Field two
*/
const readable_date_format = {
dateStyle: 'full',
timeStyle: 'short',
};
const booleanMapping = {
true: 'Si',
false: 'No',
};
/**
* Diff field component.
* @function DiffField
* @param {*} one Field one
* @param {*} two Field two
* @param {Object} schema Field schema
* @returns {string} Markup of the component.
*/
const DiffField = ({
one,
two,
contentOne,
contentTwo,
view,
schema,
diffLib,
htmlDiffLib,
field,
store,
history,
}) => {
const language = useSelector((state) => state.intl.locale);
const diff2 = (prev, curr) =>
htmlDiffLib.default.execute(
prev ? String(prev) : '',
curr ? String(curr) : '',
);
const diffs = useMemo(() => {
let parts;
if (isEqual(one, two) || field === 'blocks_layout') return null;
if (schema?.widget) {
switch (schema.widget) {
case 'richtext':
parts = diff2(one?.data, two?.data);
break;
case 'datetime':
parts = diff2(
new Intl.DateTimeFormat(language, readable_date_format).format(
new Date(one),
),
new Intl.DateTimeFormat(language, readable_date_format).format(
new Date(two),
),
);
break;
case 'blocks':
if (
(!blockIsNotEmptyPlaceholder(one) &&
!blockIsNotEmptyPlaceholder(two)) ||
!!!store
)
break;
const first = SSRRenderHtml(history, store, one, schema.widget);
const second = SSRRenderHtml(history, store, two, schema.widget);
parts = diff2(first, second);
break;
case 'json':
if (isEqual(contentOne, contentTwo)) break;
const bOne = SSRRenderHtml(history, store, contentOne, schema.widget);
const bTwo = SSRRenderHtml(history, store, contentTwo, schema.widget);
parts = diff2(bOne, bTwo);
break;
default:
parts = diff2(one, two);
break;
}
} else if (schema.type === 'object' && store) {
if (field.includes('image') && isEqual(one?.filename, two?.filename))
return;
const first = SSRRenderHtml(history, store, one, field);
const second = SSRRenderHtml(history, store, two, field);
parts = diff2(first, second);
} else if (schema.type === 'array') {
const oneArray = (one || []).map((i) => i?.title || i).join(', ');
const twoArray = (two || []).map((j) => j?.title || j).join(', ');
parts = diff2(oneArray, twoArray);
} else if (
schema?.type === 'boolean' &&
!isEqual(booleanMapping[!!one], booleanMapping[!!two])
) {
parts = diff2(booleanMapping[!!one], booleanMapping[!!two]);
} else {
parts = diff2(one, two);
}
return parts;
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [one, two, schema, field, language, store, history]);
return store && diffs ? (
<Table compact data-testid="DiffField" className="diffField">
<Table.Header>
<Table.Row>
<Table.HeaderCell colSpan={2}>{schema.title}</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
{view === 'split' && (
<Table.Row>
<Table.Cell width={8} verticalAlign="top">
<div
className="previous-state"
dangerouslySetInnerHTML={{
__html: SSRRenderHtml(
history,
store,
schema?.type === 'boolean'
? booleanMapping[!!one]
: schema?.widget === 'json'
? contentOne
: one,
schema?.widget ??
(schema?.type === 'object' && field.includes('image')
? field
: schema?.type),
),
}}
/>
</Table.Cell>
<Table.Cell width={8} verticalAlign="top">
<div
className="current-state"
dangerouslySetInnerHTML={{
__html: diffs,
}}
/>
</Table.Cell>
</Table.Row>
)}
{view === 'unified' && (
<Table.Row>
<Table.Cell width={16} verticalAlign="top">
<div
className="current-state"
dangerouslySetInnerHTML={{
__html: diffs,
}}
/>
</Table.Cell>
</Table.Row>
)}
</Table.Body>
</Table>
) : null;
};
/**
* Property types.
* @property {Object} propTypes Property types.
* @static
*/
DiffField.propTypes = {
one: PropTypes.any.isRequired,
two: PropTypes.any.isRequired,
contentOne: PropTypes.any,
contentTwo: PropTypes.any,
view: PropTypes.string.isRequired,
schema: PropTypes.shape({
widget: PropTypes.string,
type: PropTypes.string,
title: PropTypes.string,
}).isRequired,
};
export default injectLazyLibs(['htmlDiffLib'])(DiffField);