diff --git a/demo/collections/Autosave.ts b/demo/collections/Autosave.ts new file mode 100644 index 0000000000..83dc2bbb92 --- /dev/null +++ b/demo/collections/Autosave.ts @@ -0,0 +1,68 @@ +import { CollectionConfig } from '../../src/collections/config/types'; + +const Autosave: CollectionConfig = { + slug: 'autosave-posts', + labels: { + singular: 'Autosave Post', + plural: 'Autosave Posts', + }, + admin: { + useAsTitle: 'title', + defaultColumns: [ + 'title', + 'description', + 'createdAt', + ], + }, + versions: { + maxPerDoc: 5, + retainDeleted: false, + drafts: { + autosave: { + interval: 5, + }, + }, + }, + access: { + read: ({ req: { user } }) => { + if (user) { + return true; + } + + return { + or: [ + { + _status: { + equals: 'published', + }, + }, + { + _status: { + exists: false, + }, + }, + ], + }; + }, + readVersions: ({ req: { user } }) => Boolean(user), + }, + fields: [ + { + name: 'title', + label: 'Title', + type: 'text', + required: true, + unique: true, + localized: true, + }, + { + name: 'description', + label: 'Description', + type: 'textarea', + required: true, + }, + ], + timestamps: true, +}; + +export default Autosave; diff --git a/demo/collections/Localized.ts b/demo/collections/Localized.ts index 4ae59d6f75..8876c6cbb2 100644 --- a/demo/collections/Localized.ts +++ b/demo/collections/Localized.ts @@ -43,37 +43,8 @@ const LocalizedPosts: CollectionConfig = { ], enableRichTextRelationship: true, }, - versions: { - maxPerDoc: 5, - retainDeleted: false, - drafts: { - autosave: { - interval: 5, - }, - }, - }, access: { - read: ({ req: { user } }) => { - if (user) { - return true; - } - - return { - or: [ - { - _status: { - equals: 'published', - }, - }, - { - _status: { - exists: false, - }, - }, - ], - }; - }, - readVersions: ({ req: { user } }) => Boolean(user), + read: () => true, }, fields: [ { diff --git a/demo/payload.config.ts b/demo/payload.config.ts index 33d48b8004..72d84729a5 100644 --- a/demo/payload.config.ts +++ b/demo/payload.config.ts @@ -4,6 +4,7 @@ import { buildConfig } from '../src/config/build'; import Admin from './collections/Admin'; import AllFields from './collections/AllFields'; import AutoLabel from './collections/AutoLabel'; +import Autosave from './collections/Autosave'; import Code from './collections/Code'; import Conditions from './collections/Conditions'; // import CustomComponents from './collections/CustomComponents'; @@ -85,6 +86,7 @@ export default buildConfig({ Admin, AllFields, AutoLabel, + Autosave, Code, Conditions, // CustomComponents, diff --git a/src/admin/components/elements/Pill/index.scss b/src/admin/components/elements/Pill/index.scss index 83b98e0e95..13e0fec497 100644 --- a/src/admin/components/elements/Pill/index.scss +++ b/src/admin/components/elements/Pill/index.scss @@ -11,6 +11,7 @@ border-radius: $style-radius-s; padding: 0 base(.25); padding-left: base(.0875 + .25); + cursor: default; &:active, &:focus { @@ -37,12 +38,14 @@ } &--style-light { - &:hover { - background: lighten($color-light-gray, 3%); - } + &.pill--has-action { + &:hover { + background: lighten($color-light-gray, 3%); + } - &:active { - background: lighten($color-light-gray, 5%); + &:active { + background: lighten($color-light-gray, 5%); + } } } @@ -51,6 +54,14 @@ color: $color-dark-gray; } + &--style-warning { + background: $color-yellow; + } + + &--style-success { + background: $color-green; + } + &--style-dark { background: $color-dark-gray; color: white; @@ -59,12 +70,14 @@ @include color-svg(white); } - &:hover { - background: lighten($color-dark-gray, 3%); - } + &.pill--has-action { + &:hover { + background: lighten($color-dark-gray, 3%); + } - &:active { - background: lighten($color-dark-gray, 5%); + &:active { + background: lighten($color-dark-gray, 5%); + } } } } diff --git a/src/admin/components/elements/Pill/types.ts b/src/admin/components/elements/Pill/types.ts index ded6e6db74..9aab40aea9 100644 --- a/src/admin/components/elements/Pill/types.ts +++ b/src/admin/components/elements/Pill/types.ts @@ -4,7 +4,7 @@ export type Props = { icon?: React.ReactNode, alignIcon?: 'left' | 'right', onClick?: () => void, - pillStyle?: 'light' | 'dark' | 'light-gray', + pillStyle?: 'light' | 'dark' | 'light-gray' | 'warning' | 'success', } export type RenderedTypeProps = { diff --git a/src/admin/components/views/Version/Compare/index.tsx b/src/admin/components/views/Version/Compare/index.tsx index 2fef4ba8bc..6244780e09 100644 --- a/src/admin/components/views/Version/Compare/index.tsx +++ b/src/admin/components/views/Version/Compare/index.tsx @@ -5,7 +5,7 @@ import format from 'date-fns/format'; import { Props } from './types'; import ReactSelect from '../../../elements/ReactSelect'; import { PaginatedDocs } from '../../../../../mongoose/types'; -import { publishedVersionOption } from '../shared'; +import { mostRecentVersionOption } from '../shared'; import './index.scss'; @@ -14,7 +14,7 @@ const baseClass = 'compare-version'; const maxResultsPerRequest = 10; const baseOptions = [ - publishedVersionOption, + mostRecentVersionOption, ]; const CompareVersion: React.FC = (props) => { diff --git a/src/admin/components/views/Version/RenderFieldsToDiff/fields/Text/index.tsx b/src/admin/components/views/Version/RenderFieldsToDiff/fields/Text/index.tsx index 29139ec821..5c27477d75 100644 --- a/src/admin/components/views/Version/RenderFieldsToDiff/fields/Text/index.tsx +++ b/src/admin/components/views/Version/RenderFieldsToDiff/fields/Text/index.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import ReactDiffViewer from 'react-diff-viewer'; +import ReactDiffViewer, { DiffMethod } from 'react-diff-viewer'; import Label from '../../Label'; import { Props } from '../types'; @@ -7,7 +7,7 @@ import './index.scss'; const baseClass = 'text-diff'; -const Text: React.FC = ({ field, locale, version, comparison, isRichText = false }) => { +const Text: React.FC = ({ field, locale, version, comparison, isRichText = false, diffMethod }) => { let placeholder = ''; if (version === comparison) placeholder = '[no value]'; @@ -20,7 +20,6 @@ const Text: React.FC = ({ field, locale, version, comparison, isRichText if (typeof comparison === 'object') comparisonToRender = JSON.stringify(comparison, null, 2); } - return (
> export type Props = { + diffMethod?: DiffMethod fieldComponents: FieldComponents version: any comparison: any diff --git a/src/admin/components/views/Version/RenderFieldsToDiff/index.tsx b/src/admin/components/views/Version/RenderFieldsToDiff/index.tsx index 571f9b13bd..f628f35439 100644 --- a/src/admin/components/views/Version/RenderFieldsToDiff/index.tsx +++ b/src/admin/components/views/Version/RenderFieldsToDiff/index.tsx @@ -1,9 +1,11 @@ import React from 'react'; +import { DiffMethod } from 'react-diff-viewer'; import { Props } from './types'; import { fieldAffectsData, fieldHasSubFields } from '../../../../../fields/config/types'; import Nested from './fields/Nested'; import './index.scss'; +import { diffMethods } from './fields/diffMethods'; const baseClass = 'render-field-diffs'; @@ -20,6 +22,7 @@ const RenderFieldsToDiff: React.FC = ({ const Component = fieldComponents[field.type]; const isRichText = field.type === 'richText'; + const diffMethod: DiffMethod = diffMethods[field.type] || 'CHARS'; if (Component) { if (fieldAffectsData(field)) { @@ -46,6 +49,7 @@ const RenderFieldsToDiff: React.FC = ({ >
= ({ key={i} > = ({ 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(publishedVersionOption); + const [compareValue, setCompareValue] = useState(mostRecentVersionOption); const [localeOptions] = useState(() => (localization?.locales ? localization.locales.map((locale) => ({ label: locale, value: locale })) : [])); const [locales, setLocales] = useState(localeOptions); const { permissions } = useAuth(); @@ -63,11 +63,12 @@ const VersionView: React.FC = ({ collection, global }) => { } const useAsTitle = collection?.admin?.useAsTitle || 'id'; - const compareFetchURL = compareValue?.value === 'published' ? originalDocFetchURL : `${compareBaseURL}/${compareValue.value}`; + + 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 } }); - const [{ data: compareDoc }] = usePayloadAPI(compareFetchURL, { 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[] = []; @@ -186,7 +187,7 @@ const VersionView: React.FC = ({ collection, global }) => { fieldComponents={fieldComponents} fieldPermissions={fieldPermissions} version={doc?.version} - comparison={compareValue?.value === 'published' ? compareDoc : compareDoc?.version} + comparison={compareValue?.value === 'mostRecent' ? compareDoc : compareDoc?.version} /> )}
diff --git a/src/admin/components/views/Version/shared.ts b/src/admin/components/views/Version/shared.ts index 66a0353621..aa4762a6cd 100644 --- a/src/admin/components/views/Version/shared.ts +++ b/src/admin/components/views/Version/shared.ts @@ -1,4 +1,4 @@ -export const publishedVersionOption = { - label: 'Most recently published', - value: 'published', +export const mostRecentVersionOption = { + label: 'Most recent', + value: 'mostRecent', }; diff --git a/src/admin/components/views/Versions/columns.tsx b/src/admin/components/views/Versions/columns.tsx index 86c78b478a..454d7ed531 100644 --- a/src/admin/components/views/Versions/columns.tsx +++ b/src/admin/components/views/Versions/columns.tsx @@ -39,12 +39,12 @@ const TextCell: React.FC = ({ children }) => ( export const getColumns = (collection: SanitizedCollectionConfig, global: SanitizedGlobalConfig): Column[] => [ { - accessor: 'createdAt', + accessor: 'updatedAt', components: { Heading: ( ), renderCell: (row, data) => ( @@ -83,10 +83,10 @@ export const getColumns = (collection: SanitizedCollectionConfig, global: Saniti renderCell: (row, data) => ( {row?.autosave && ( - - Autosave - - )} + + Autosave + + )} ), }, diff --git a/src/admin/components/views/Versions/index.tsx b/src/admin/components/views/Versions/index.tsx index 9924a4fe24..88670a8ff5 100644 --- a/src/admin/components/views/Versions/index.tsx +++ b/src/admin/components/views/Versions/index.tsx @@ -44,7 +44,7 @@ const Versions: React.FC = ({ collection, global }) => { } const useAsTitle = collection?.admin?.useAsTitle || 'id'; - const [{ data: doc }] = usePayloadAPI(docURL); + const [{ data: doc }] = usePayloadAPI(docURL, { initialParams: { draft: 'true' } }); const [{ data: versionsData, isLoading: isLoadingVersions }, { setParams }] = usePayloadAPI(fetchURL); useEffect(() => { diff --git a/src/admin/components/views/collections/Edit/Default.tsx b/src/admin/components/views/collections/Edit/Default.tsx index 2e66db0106..b1566f8dae 100644 --- a/src/admin/components/views/collections/Edit/Default.tsx +++ b/src/admin/components/views/collections/Edit/Default.tsx @@ -20,6 +20,8 @@ import VersionsCount from '../../../elements/VersionsCount'; import Upload from './Upload'; import { Props } from './types'; import Autosave from '../../../elements/Autosave'; +import Select from '../../../forms/field-types/Select'; +import { statuses } from '../../../../../versions/baseFields'; import './index.scss'; @@ -159,6 +161,14 @@ const DefaultEditView: React.FC = (props) => { {!isLoading && (
+ {collection.versions?.drafts && ( +