199 lines
6.6 KiB
TypeScript
199 lines
6.6 KiB
TypeScript
import React, { useEffect, useState } from 'react';
|
|
import { useAuth, useConfig } from '@payloadcms/config-provider';
|
|
import { useRouteMatch } from 'react-router-dom';
|
|
import format from 'date-fns/format';
|
|
import usePayloadAPI from '../../../hooks/usePayloadAPI';
|
|
import Eyebrow from '../../elements/Eyebrow';
|
|
import Loading from '../../elements/Loading';
|
|
import { useStepNav } from '../../elements/StepNav';
|
|
import { StepNavItem } from '../../elements/StepNav/types';
|
|
import Meta from '../../utilities/Meta';
|
|
import { LocaleOption, CompareOption, Props } from './types';
|
|
import CompareVersion from './Compare';
|
|
import { mostRecentVersionOption } from './shared';
|
|
import Restore from './Restore';
|
|
import SelectLocales from './SelectLocales';
|
|
import RenderFieldsToDiff from './RenderFieldsToDiff';
|
|
import fieldComponents from './RenderFieldsToDiff/fields';
|
|
|
|
import { Field } from '../../../../fields/config/types';
|
|
import { FieldPermissions } from '../../../../auth';
|
|
|
|
import './index.scss';
|
|
|
|
const baseClass = 'view-version';
|
|
|
|
const VersionView: React.FC<Props> = ({ collection, global }) => {
|
|
const { serverURL, routes: { admin, api }, admin: { dateFormat }, localization } = useConfig();
|
|
const { setStepNav } = useStepNav();
|
|
const { params: { id, versionID } } = useRouteMatch<{ id?: string, versionID: string }>();
|
|
const [compareValue, setCompareValue] = useState<CompareOption>(mostRecentVersionOption);
|
|
const [localeOptions] = useState<LocaleOption[]>(() => (localization?.locales ? localization.locales.map((locale) => ({ label: locale, value: locale })) : []));
|
|
const [locales, setLocales] = useState<LocaleOption[]>(localeOptions);
|
|
const { permissions } = useAuth();
|
|
|
|
let originalDocFetchURL: string;
|
|
let versionFetchURL: string;
|
|
let entityLabel: string;
|
|
let fields: Field[];
|
|
let fieldPermissions: Record<string, FieldPermissions>;
|
|
let compareBaseURL: string;
|
|
let slug: string;
|
|
let parentID: string;
|
|
|
|
if (collection) {
|
|
({ slug } = collection);
|
|
originalDocFetchURL = `${serverURL}${api}/${slug}/${id}`;
|
|
versionFetchURL = `${serverURL}${api}/${slug}/versions/${versionID}`;
|
|
compareBaseURL = `${serverURL}${api}/${slug}/versions`;
|
|
entityLabel = collection.labels.singular;
|
|
parentID = id;
|
|
fields = collection.fields;
|
|
fieldPermissions = permissions.collections[collection.slug].fields;
|
|
}
|
|
|
|
if (global) {
|
|
({ slug } = global);
|
|
originalDocFetchURL = `${serverURL}${api}/globals/${slug}`;
|
|
versionFetchURL = `${serverURL}${api}/globals/${slug}/versions/${versionID}`;
|
|
compareBaseURL = `${serverURL}${api}/globals/${slug}/versions`;
|
|
entityLabel = global.label;
|
|
fields = global.fields;
|
|
fieldPermissions = permissions.globals[global.slug].fields;
|
|
}
|
|
|
|
const useAsTitle = collection?.admin?.useAsTitle || 'id';
|
|
|
|
const compareFetchURL = compareValue?.value === 'mostRecent' ? originalDocFetchURL : `${compareBaseURL}/${compareValue.value}`;
|
|
|
|
const [{ data: doc, isLoading }] = usePayloadAPI(versionFetchURL, { initialParams: { locale: '*', depth: 1 } });
|
|
const [{ data: originalDoc }] = usePayloadAPI(originalDocFetchURL, { initialParams: { depth: 1, draft: 'true' } });
|
|
const [{ data: compareDoc }] = usePayloadAPI(compareFetchURL, { initialParams: { locale: '*', depth: 1, draft: 'true' } });
|
|
|
|
useEffect(() => {
|
|
let nav: StepNavItem[] = [];
|
|
|
|
if (collection) {
|
|
let docLabel = '';
|
|
|
|
if (originalDoc) {
|
|
if (useAsTitle) {
|
|
if (originalDoc[useAsTitle]) {
|
|
docLabel = originalDoc[useAsTitle];
|
|
} else {
|
|
docLabel = '[Untitled]';
|
|
}
|
|
} else {
|
|
docLabel = originalDoc.id;
|
|
}
|
|
}
|
|
|
|
nav = [
|
|
{
|
|
url: `${admin}/collections/${collection.slug}`,
|
|
label: collection.labels.plural,
|
|
},
|
|
{
|
|
label: docLabel,
|
|
url: `${admin}/collections/${collection.slug}/${id}`,
|
|
},
|
|
{
|
|
label: 'Versions',
|
|
url: `${admin}/collections/${collection.slug}/${id}/versions`,
|
|
},
|
|
{
|
|
label: doc?.createdAt ? format(new Date(doc.createdAt), dateFormat) : '',
|
|
},
|
|
];
|
|
}
|
|
|
|
if (global) {
|
|
nav = [
|
|
{
|
|
url: `${admin}/globals/${global.slug}`,
|
|
label: global.label,
|
|
},
|
|
{
|
|
label: 'Versions',
|
|
url: `${admin}/globals/${global.slug}/versions`,
|
|
},
|
|
{
|
|
label: doc?.createdAt ? format(new Date(doc.createdAt), dateFormat) : '',
|
|
},
|
|
];
|
|
}
|
|
|
|
setStepNav(nav);
|
|
}, [setStepNav, collection, global, useAsTitle, dateFormat, doc, originalDoc, admin, id]);
|
|
|
|
let metaTitle: string;
|
|
let metaDesc: string;
|
|
const formattedCreatedAt = doc?.createdAt ? format(new Date(doc.createdAt), dateFormat) : '';
|
|
|
|
if (collection) {
|
|
metaTitle = `Version - ${formattedCreatedAt} - ${doc[useAsTitle]} - ${entityLabel}`;
|
|
metaDesc = `Viewing version for the ${entityLabel} ${doc[useAsTitle]}`;
|
|
}
|
|
|
|
if (global) {
|
|
metaTitle = `Version - ${formattedCreatedAt} - ${entityLabel}`;
|
|
metaDesc = `Viewing version for the global ${entityLabel}`;
|
|
}
|
|
|
|
return (
|
|
<div className={baseClass}>
|
|
<Meta
|
|
title={metaTitle}
|
|
description={metaDesc}
|
|
/>
|
|
<Eyebrow />
|
|
<div className={`${baseClass}__wrap`}>
|
|
<div className={`${baseClass}__intro`}>Version created on:</div>
|
|
<header className={`${baseClass}__header`}>
|
|
<h2>
|
|
{formattedCreatedAt}
|
|
</h2>
|
|
<Restore
|
|
className={`${baseClass}__restore`}
|
|
collection={collection}
|
|
global={global}
|
|
originalDocID={id}
|
|
versionID={versionID}
|
|
versionDate={formattedCreatedAt}
|
|
/>
|
|
</header>
|
|
<div className={`${baseClass}__controls`}>
|
|
{localization && (
|
|
<SelectLocales
|
|
onChange={setLocales}
|
|
options={localeOptions}
|
|
value={locales}
|
|
/>
|
|
)}
|
|
<CompareVersion
|
|
baseURL={compareBaseURL}
|
|
parentID={parentID}
|
|
value={compareValue}
|
|
onChange={setCompareValue}
|
|
/>
|
|
</div>
|
|
{isLoading && (
|
|
<Loading />
|
|
)}
|
|
{doc?.version && (
|
|
<RenderFieldsToDiff
|
|
locales={locales.map((locale) => locale.value)}
|
|
fields={fields}
|
|
fieldComponents={fieldComponents}
|
|
fieldPermissions={fieldPermissions}
|
|
version={doc?.version}
|
|
comparison={compareValue?.value === 'mostRecent' ? compareDoc : compareDoc?.version}
|
|
/>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default VersionView;
|