Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 20s
Build & Deploy / 🧪 QA (push) Failing after 34s
Build & Deploy / 🏗️ Build (push) Has started running
Build & Deploy / 🚀 Deploy (push) Has been cancelled
Build & Deploy / 🧪 Smoke Test (push) Has been cancelled
Build & Deploy / ⚡ Lighthouse (push) Has been cancelled
Build & Deploy / 🔔 Notify (push) Has been cancelled
242 lines
7.2 KiB
Plaintext
242 lines
7.2 KiB
Plaintext
import { fieldShouldBeLocalized, groupHasName } from 'payload/shared';
|
|
import { fieldHasChanges } from './fieldHasChanges.js';
|
|
import { getFieldsForRowComparison } from './getFieldsForRowComparison.js';
|
|
/**
|
|
* Recursively counts the number of changed fields between comparison and
|
|
* version data for a given set of fields.
|
|
*/
|
|
export function countChangedFields({
|
|
config,
|
|
fields,
|
|
locales,
|
|
parentIsLocalized,
|
|
valueFrom,
|
|
valueTo
|
|
}) {
|
|
let count = 0;
|
|
fields.forEach(field => {
|
|
// Don't count the id field since it is not displayed in the UI
|
|
if ('name' in field && field.name === 'id') {
|
|
return;
|
|
}
|
|
const fieldType = field.type;
|
|
switch (fieldType) {
|
|
// Iterable fields are arrays and blocks fields. We iterate over each row and
|
|
// count the number of changed fields in each.
|
|
case 'array':
|
|
case 'blocks':
|
|
{
|
|
if (locales && fieldShouldBeLocalized({
|
|
field,
|
|
parentIsLocalized
|
|
})) {
|
|
locales.forEach(locale => {
|
|
const valueFromRows = valueFrom?.[field.name]?.[locale] ?? [];
|
|
const valueToRows = valueTo?.[field.name]?.[locale] ?? [];
|
|
count += countChangedFieldsInRows({
|
|
config,
|
|
field,
|
|
locales,
|
|
parentIsLocalized: parentIsLocalized || field.localized,
|
|
valueFromRows,
|
|
valueToRows
|
|
});
|
|
});
|
|
} else {
|
|
const valueFromRows = valueFrom?.[field.name] ?? [];
|
|
const valueToRows = valueTo?.[field.name] ?? [];
|
|
count += countChangedFieldsInRows({
|
|
config,
|
|
field,
|
|
locales,
|
|
parentIsLocalized: parentIsLocalized || field.localized,
|
|
valueFromRows,
|
|
valueToRows
|
|
});
|
|
}
|
|
break;
|
|
}
|
|
// Regular fields without nested fields.
|
|
case 'checkbox':
|
|
case 'code':
|
|
case 'date':
|
|
case 'email':
|
|
case 'join':
|
|
case 'json':
|
|
case 'number':
|
|
case 'point':
|
|
case 'radio':
|
|
case 'relationship':
|
|
case 'richText':
|
|
case 'select':
|
|
case 'text':
|
|
case 'textarea':
|
|
case 'upload':
|
|
{
|
|
// Fields that have a name and contain data. We can just check if the data has changed.
|
|
if (locales && fieldShouldBeLocalized({
|
|
field,
|
|
parentIsLocalized
|
|
})) {
|
|
locales.forEach(locale => {
|
|
if (fieldHasChanges(valueTo?.[field.name]?.[locale], valueFrom?.[field.name]?.[locale])) {
|
|
count++;
|
|
}
|
|
});
|
|
} else if (fieldHasChanges(valueTo?.[field.name], valueFrom?.[field.name])) {
|
|
count++;
|
|
}
|
|
break;
|
|
}
|
|
// Fields that have nested fields, but don't nest their fields' data.
|
|
case 'collapsible':
|
|
case 'row':
|
|
{
|
|
count += countChangedFields({
|
|
config,
|
|
fields: field.fields,
|
|
locales,
|
|
parentIsLocalized: parentIsLocalized || field.localized,
|
|
valueFrom,
|
|
valueTo
|
|
});
|
|
break;
|
|
}
|
|
// Fields that have nested fields and nest their fields' data.
|
|
case 'group':
|
|
{
|
|
if (groupHasName(field)) {
|
|
if (locales && fieldShouldBeLocalized({
|
|
field,
|
|
parentIsLocalized
|
|
})) {
|
|
locales.forEach(locale => {
|
|
count += countChangedFields({
|
|
config,
|
|
fields: field.fields,
|
|
locales,
|
|
parentIsLocalized: parentIsLocalized || field.localized,
|
|
valueFrom: valueFrom?.[field.name]?.[locale],
|
|
valueTo: valueTo?.[field.name]?.[locale]
|
|
});
|
|
});
|
|
} else {
|
|
count += countChangedFields({
|
|
config,
|
|
fields: field.fields,
|
|
locales,
|
|
parentIsLocalized: parentIsLocalized || field.localized,
|
|
valueFrom: valueFrom?.[field.name],
|
|
valueTo: valueTo?.[field.name]
|
|
});
|
|
}
|
|
} else {
|
|
// Unnamed group field: data is NOT nested under `field.name`
|
|
count += countChangedFields({
|
|
config,
|
|
fields: field.fields,
|
|
locales,
|
|
parentIsLocalized: parentIsLocalized || field.localized,
|
|
valueFrom,
|
|
valueTo
|
|
});
|
|
}
|
|
break;
|
|
}
|
|
// Each tab in a tabs field has nested fields. The fields data may be
|
|
// nested or not depending on the existence of a name property.
|
|
case 'tabs':
|
|
{
|
|
field.tabs.forEach(tab => {
|
|
if ('name' in tab && locales && tab.localized) {
|
|
// Named localized tab
|
|
locales.forEach(locale => {
|
|
count += countChangedFields({
|
|
config,
|
|
fields: tab.fields,
|
|
locales,
|
|
parentIsLocalized: parentIsLocalized || tab.localized,
|
|
valueFrom: valueFrom?.[tab.name]?.[locale],
|
|
valueTo: valueTo?.[tab.name]?.[locale]
|
|
});
|
|
});
|
|
} else if ('name' in tab) {
|
|
// Named tab
|
|
count += countChangedFields({
|
|
config,
|
|
fields: tab.fields,
|
|
locales,
|
|
parentIsLocalized: parentIsLocalized || tab.localized,
|
|
valueFrom: valueFrom?.[tab.name],
|
|
valueTo: valueTo?.[tab.name]
|
|
});
|
|
} else {
|
|
// Unnamed tab
|
|
count += countChangedFields({
|
|
config,
|
|
fields: tab.fields,
|
|
locales,
|
|
parentIsLocalized: parentIsLocalized || tab.localized,
|
|
valueFrom,
|
|
valueTo
|
|
});
|
|
}
|
|
});
|
|
break;
|
|
}
|
|
// UI fields don't have data and are not displayed in the version view
|
|
// so we can ignore them.
|
|
case 'ui':
|
|
{
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
const _exhaustiveCheck = fieldType;
|
|
throw new Error(`Unexpected field.type in countChangedFields : ${String(fieldType)}`);
|
|
}
|
|
}
|
|
});
|
|
return count;
|
|
}
|
|
export function countChangedFieldsInRows({
|
|
config,
|
|
field,
|
|
locales,
|
|
parentIsLocalized,
|
|
valueFromRows = [],
|
|
valueToRows = []
|
|
}) {
|
|
let count = 0;
|
|
let i = 0;
|
|
while (valueFromRows[i] || valueToRows[i]) {
|
|
const valueFromRow = valueFromRows?.[i] || {};
|
|
const valueToRow = valueToRows?.[i] || {};
|
|
const {
|
|
fields: rowFields
|
|
} = getFieldsForRowComparison({
|
|
baseVersionField: {
|
|
type: 'text',
|
|
fields: [],
|
|
path: '',
|
|
schemaPath: ''
|
|
},
|
|
config,
|
|
field,
|
|
row: i,
|
|
valueFromRow,
|
|
valueToRow
|
|
});
|
|
count += countChangedFields({
|
|
config,
|
|
fields: rowFields,
|
|
locales,
|
|
parentIsLocalized: parentIsLocalized || field.localized,
|
|
valueFrom: valueFromRow,
|
|
valueTo: valueToRow
|
|
});
|
|
i++;
|
|
}
|
|
return count;
|
|
}
|
|
//# sourceMappingURL=countChangedFields.js.map |