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
352 lines
11 KiB
Plaintext
352 lines
11 KiB
Plaintext
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
import { formatDate } from '@payloadcms/ui/shared';
|
|
import { getClientConfig } from '@payloadcms/ui/utilities/getClientConfig';
|
|
import { getClientSchemaMap } from '@payloadcms/ui/utilities/getClientSchemaMap';
|
|
import { getSchemaMap } from '@payloadcms/ui/utilities/getSchemaMap';
|
|
import { notFound } from 'next/navigation.js';
|
|
import { hasDraftsEnabled } from 'payload/shared';
|
|
import React from 'react';
|
|
import { DefaultVersionView } from './Default/index.js';
|
|
import { fetchLatestVersion, fetchVersion, fetchVersions } from './fetchVersions.js';
|
|
import { RenderDiff } from './RenderFieldsToDiff/index.js';
|
|
import { getVersionLabel } from './VersionPillLabel/getVersionLabel.js';
|
|
import { VersionPillLabel } from './VersionPillLabel/VersionPillLabel.js';
|
|
export async function VersionView(props) {
|
|
const {
|
|
hasPublishedDoc,
|
|
i18n,
|
|
initPageResult,
|
|
routeSegments,
|
|
searchParams
|
|
} = props;
|
|
const {
|
|
collectionConfig,
|
|
docID: id,
|
|
globalConfig,
|
|
permissions,
|
|
req,
|
|
req: {
|
|
payload,
|
|
payload: {
|
|
config,
|
|
config: {
|
|
localization
|
|
}
|
|
} = {},
|
|
user
|
|
} = {}
|
|
} = initPageResult;
|
|
const versionToID = routeSegments[routeSegments.length - 1];
|
|
const collectionSlug = collectionConfig?.slug;
|
|
const globalSlug = globalConfig?.slug;
|
|
const draftsEnabled = hasDraftsEnabled(collectionConfig || globalConfig);
|
|
// Resolve user's current locale for version label comparison (not 'all')
|
|
const userLocale = searchParams.locale || (req.locale !== 'all' ? req.locale : localization && localization.defaultLocale);
|
|
const localeCodesFromParams = searchParams.localeCodes ? JSON.parse(searchParams.localeCodes) : null;
|
|
const versionFromIDFromParams = searchParams.versionFrom;
|
|
const modifiedOnly = searchParams.modifiedOnly === 'false' ? false : true;
|
|
const docPermissions = collectionSlug ? permissions.collections[collectionSlug] : permissions.globals[globalSlug];
|
|
const versionTo = await fetchVersion({
|
|
id: versionToID,
|
|
collectionSlug,
|
|
depth: 1,
|
|
globalSlug,
|
|
locale: 'all',
|
|
overrideAccess: false,
|
|
req,
|
|
user
|
|
});
|
|
if (!versionTo) {
|
|
return notFound();
|
|
}
|
|
const [previousVersionResult, versionFromResult, currentlyPublishedVersion, latestDraftVersion, previousPublishedVersionResult] = await Promise.all([
|
|
// Previous version (the one before the versionTo)
|
|
fetchVersions({
|
|
collectionSlug,
|
|
// If versionFromIDFromParams is provided, the previous version is only used in the version comparison dropdown => depth 0 is enough.
|
|
// If it's not provided, this is used as `versionFrom` in the comparison, which expects populated data => depth 1 is needed.
|
|
depth: versionFromIDFromParams ? 0 : 1,
|
|
draft: true,
|
|
globalSlug,
|
|
limit: 1,
|
|
locale: 'all',
|
|
overrideAccess: false,
|
|
parentID: id,
|
|
req,
|
|
sort: '-updatedAt',
|
|
user,
|
|
where: {
|
|
and: [{
|
|
updatedAt: {
|
|
less_than: versionTo.updatedAt
|
|
}
|
|
}]
|
|
}
|
|
}),
|
|
// Version from ID from params
|
|
versionFromIDFromParams ? fetchVersion({
|
|
id: versionFromIDFromParams,
|
|
collectionSlug,
|
|
depth: 1,
|
|
globalSlug,
|
|
locale: 'all',
|
|
overrideAccess: false,
|
|
req,
|
|
user
|
|
}) : Promise.resolve(null),
|
|
// Currently published version - do note: currently published != latest published, as an unpublished version can be the latest published
|
|
hasPublishedDoc ? fetchLatestVersion({
|
|
collectionSlug,
|
|
depth: 0,
|
|
globalSlug,
|
|
locale: req.locale,
|
|
overrideAccess: false,
|
|
parentID: id,
|
|
req,
|
|
status: 'published',
|
|
user
|
|
}) : Promise.resolve(null),
|
|
// Latest draft version
|
|
draftsEnabled ? fetchLatestVersion({
|
|
collectionSlug,
|
|
depth: 0,
|
|
globalSlug,
|
|
locale: 'all',
|
|
overrideAccess: false,
|
|
parentID: id,
|
|
req,
|
|
status: 'draft',
|
|
user
|
|
}) : Promise.resolve(null),
|
|
// Previous published version
|
|
// Only query for published versions if drafts are enabled (since _status field only exists with drafts)
|
|
draftsEnabled ? fetchVersions({
|
|
collectionSlug,
|
|
depth: 0,
|
|
draft: true,
|
|
globalSlug,
|
|
limit: 1,
|
|
locale: 'all',
|
|
overrideAccess: false,
|
|
parentID: id,
|
|
req,
|
|
sort: '-updatedAt',
|
|
user,
|
|
where: {
|
|
and: [{
|
|
updatedAt: {
|
|
less_than: versionTo.updatedAt
|
|
}
|
|
}, {
|
|
'version._status': {
|
|
equals: 'published'
|
|
}
|
|
}]
|
|
}
|
|
}) : Promise.resolve(null)]);
|
|
const previousVersion = previousVersionResult?.docs?.[0] ?? null;
|
|
const versionFrom = versionFromResult ||
|
|
// By default, we'll compare the previous version. => versionFrom = version previous to versionTo
|
|
previousVersion;
|
|
// Previous published version before the versionTo
|
|
const previousPublishedVersion = previousPublishedVersionResult?.docs?.[0] ?? null;
|
|
let selectedLocales = [];
|
|
if (localization) {
|
|
let locales = [];
|
|
if (localeCodesFromParams) {
|
|
for (const code of localeCodesFromParams) {
|
|
const locale = localization.locales.find(locale => locale.code === code);
|
|
if (!locale) {
|
|
continue;
|
|
}
|
|
locales.push(locale);
|
|
}
|
|
} else {
|
|
locales = localization.locales;
|
|
}
|
|
if (localization.filterAvailableLocales) {
|
|
locales = (await localization.filterAvailableLocales({
|
|
locales,
|
|
req
|
|
})) || [];
|
|
}
|
|
selectedLocales = locales.map(locale => locale.code);
|
|
}
|
|
const schemaMap = getSchemaMap({
|
|
collectionSlug,
|
|
config,
|
|
globalSlug,
|
|
i18n
|
|
});
|
|
const clientSchemaMap = getClientSchemaMap({
|
|
collectionSlug,
|
|
config: getClientConfig({
|
|
config: payload.config,
|
|
i18n,
|
|
importMap: payload.importMap,
|
|
user
|
|
}),
|
|
globalSlug,
|
|
i18n,
|
|
payload,
|
|
schemaMap
|
|
});
|
|
const RenderedDiff = RenderDiff({
|
|
clientSchemaMap,
|
|
customDiffComponents: {},
|
|
entitySlug: collectionSlug || globalSlug,
|
|
fields: (collectionConfig || globalConfig)?.fields,
|
|
fieldsPermissions: docPermissions?.fields,
|
|
i18n,
|
|
modifiedOnly,
|
|
parentIndexPath: '',
|
|
parentIsLocalized: false,
|
|
parentPath: '',
|
|
parentSchemaPath: '',
|
|
req,
|
|
selectedLocales,
|
|
versionFromSiblingData: {
|
|
...versionFrom?.version,
|
|
updatedAt: versionFrom?.updatedAt
|
|
},
|
|
versionToSiblingData: {
|
|
...versionTo.version,
|
|
updatedAt: versionTo.updatedAt
|
|
}
|
|
});
|
|
const versionToCreatedAtFormatted = versionTo.updatedAt ? formatDate({
|
|
date: typeof versionTo.updatedAt === 'string' ? new Date(versionTo.updatedAt) : versionTo.updatedAt,
|
|
i18n,
|
|
pattern: config.admin.dateFormat
|
|
}) : '';
|
|
const formatPill = ({
|
|
doc,
|
|
labelOverride,
|
|
labelStyle,
|
|
labelSuffix
|
|
}) => {
|
|
return /*#__PURE__*/_jsx(VersionPillLabel, {
|
|
currentlyPublishedVersion: currentlyPublishedVersion,
|
|
doc: doc,
|
|
labelFirst: true,
|
|
labelOverride: labelOverride,
|
|
labelStyle: labelStyle ?? 'text',
|
|
labelSuffix: labelSuffix,
|
|
latestDraftVersion: latestDraftVersion
|
|
}, doc.id);
|
|
};
|
|
// SelectComparison Options:
|
|
//
|
|
// Previous version: always, unless doesn't exist. Can be the same as previously published
|
|
// Latest draft: only if no newer published exists (latestDraftVersion)
|
|
// Currently published: always, if exists
|
|
// Previously published: if there is a prior published version older than versionTo
|
|
// Specific Version: only if not already present under other label (= versionFrom)
|
|
let versionFromOptions = [];
|
|
// Previous version
|
|
if (previousVersion?.id) {
|
|
versionFromOptions.push({
|
|
doc: previousVersion,
|
|
labelOverride: i18n.t('version:previousVersion'),
|
|
updatedAt: new Date(previousVersion.updatedAt),
|
|
value: previousVersion.id
|
|
});
|
|
}
|
|
// Latest Draft
|
|
const publishedNewerThanDraft = currentlyPublishedVersion?.updatedAt > latestDraftVersion?.updatedAt;
|
|
if (latestDraftVersion && !publishedNewerThanDraft) {
|
|
versionFromOptions.push({
|
|
doc: latestDraftVersion,
|
|
updatedAt: new Date(latestDraftVersion.updatedAt),
|
|
value: latestDraftVersion.id
|
|
});
|
|
}
|
|
// Currently Published
|
|
if (currentlyPublishedVersion) {
|
|
versionFromOptions.push({
|
|
doc: currentlyPublishedVersion,
|
|
updatedAt: new Date(currentlyPublishedVersion.updatedAt),
|
|
value: currentlyPublishedVersion.id
|
|
});
|
|
}
|
|
// Previous Published
|
|
if (previousPublishedVersion && currentlyPublishedVersion?.id !== previousPublishedVersion.id) {
|
|
versionFromOptions.push({
|
|
doc: previousPublishedVersion,
|
|
labelOverride: i18n.t('version:previouslyPublished'),
|
|
updatedAt: new Date(previousPublishedVersion.updatedAt),
|
|
value: previousPublishedVersion.id
|
|
});
|
|
}
|
|
// Specific Version
|
|
if (versionFrom?.id && !versionFromOptions.some(option => option.value === versionFrom.id)) {
|
|
// Only add "specific version" if it is not already in the options
|
|
versionFromOptions.push({
|
|
doc: versionFrom,
|
|
labelOverride: i18n.t('version:specificVersion'),
|
|
updatedAt: new Date(versionFrom.updatedAt),
|
|
value: versionFrom.id
|
|
});
|
|
}
|
|
versionFromOptions = versionFromOptions.sort((a, b) => {
|
|
// Sort by updatedAt, newest first
|
|
if (a && b) {
|
|
return b.updatedAt.getTime() - a.updatedAt.getTime();
|
|
}
|
|
return 0;
|
|
});
|
|
const versionToIsVersionFrom = versionFrom?.id === versionTo.id;
|
|
const versionFromComparisonOptions = [];
|
|
for (const option of versionFromOptions) {
|
|
const isVersionTo = option.value === versionTo.id;
|
|
if (isVersionTo && !versionToIsVersionFrom) {
|
|
continue;
|
|
}
|
|
const alreadyAdded = versionFromComparisonOptions.some(existingOption => existingOption.value === option.value);
|
|
if (alreadyAdded) {
|
|
continue;
|
|
}
|
|
const otherOptionsWithSameID = versionFromOptions.filter(existingOption => existingOption.value === option.value && existingOption !== option);
|
|
// Merge options with same ID to the same option
|
|
const labelSuffix = otherOptionsWithSameID?.length ? /*#__PURE__*/_jsxs("span", {
|
|
children: [' (', otherOptionsWithSameID.map((optionWithSameID, index) => {
|
|
const label = optionWithSameID.labelOverride || getVersionLabel({
|
|
currentLocale: userLocale,
|
|
currentlyPublishedVersion,
|
|
latestDraftVersion,
|
|
t: i18n.t,
|
|
version: optionWithSameID.doc
|
|
}).label;
|
|
return /*#__PURE__*/_jsxs(React.Fragment, {
|
|
children: [index > 0 ? ', ' : '', label]
|
|
}, `${optionWithSameID.value}-${index}`);
|
|
}), ')']
|
|
}, `${option.value}-suffix`) : undefined;
|
|
versionFromComparisonOptions.push({
|
|
label: formatPill({
|
|
doc: option.doc,
|
|
labelOverride: option.labelOverride,
|
|
labelSuffix
|
|
}),
|
|
value: option.value
|
|
});
|
|
}
|
|
return /*#__PURE__*/_jsx(DefaultVersionView, {
|
|
canUpdate: docPermissions?.update,
|
|
modifiedOnly: modifiedOnly,
|
|
RenderedDiff: RenderedDiff,
|
|
selectedLocales: selectedLocales,
|
|
versionFromCreatedAt: versionFrom?.createdAt,
|
|
versionFromID: versionFrom?.id,
|
|
versionFromOptions: versionFromComparisonOptions,
|
|
versionToCreatedAt: versionTo.createdAt,
|
|
versionToCreatedAtFormatted: versionToCreatedAtFormatted,
|
|
VersionToCreatedAtLabel: formatPill({
|
|
doc: versionTo,
|
|
labelStyle: 'pill'
|
|
}),
|
|
versionToID: versionTo.id,
|
|
versionToStatus: versionTo.version?._status
|
|
});
|
|
}
|
|
//# sourceMappingURL=index.js.map |