From d8626cce2e666ac1d3d4cccbb7658da9f32daa70 Mon Sep 17 00:00:00 2001 From: pedrobonamin Date: Tue, 29 Oct 2024 08:47:11 +0100 Subject: [PATCH] feat(core): add versions to references and status icons --- packages/@sanity/types/src/schema/preview.ts | 3 + .../documentStatus/DocumentStatus.tsx | 158 +++++++++--------- .../DocumentStatusIndicator.tsx | 102 +++++++---- .../ReferenceInput/ReferencePreview.tsx | 17 +- .../core/form/inputs/ReferenceInput/types.ts | 2 + .../ReferenceInput/useReferenceInput.tsx | 25 ++- .../inputs/client-adapters/reference.ts | 89 ++++++++-- .../sanity/src/core/i18n/bundles/studio.ts | 5 + .../components/SanityDefaultPreview.tsx | 4 +- packages/sanity/src/core/preview/types.ts | 1 + .../utils/getPreviewStateObservable.ts | 2 +- .../scheduleItem/PreviewWrapper.tsx | 1 + .../utils/paneItemHelpers.tsx | 2 + .../src/core/store/release/useReleases.ts | 10 ++ .../item/SearchResultItemPreview.tsx | 19 +-- .../components/paneItem/PaneItemPreview.tsx | 23 ++- .../document/statusBar/DocumentStatusBar.tsx | 6 +- .../document/statusBar/DocumentStatusLine.tsx | 81 ++++++--- .../sheetList/useDocumentSheetColumns.tsx | 2 +- 19 files changed, 349 insertions(+), 203 deletions(-) diff --git a/packages/@sanity/types/src/schema/preview.ts b/packages/@sanity/types/src/schema/preview.ts index bc72b404992..d297ce1c056 100644 --- a/packages/@sanity/types/src/schema/preview.ts +++ b/packages/@sanity/types/src/schema/preview.ts @@ -10,6 +10,9 @@ export interface PrepareViewOptions { /** @public */ export interface PreviewValue { + _id?: string + _createdAt?: string + _updatedAt?: string title?: string subtitle?: string description?: string diff --git a/packages/sanity/src/core/components/documentStatus/DocumentStatus.tsx b/packages/sanity/src/core/components/documentStatus/DocumentStatus.tsx index c9bf0a12f33..fce1a09004a 100644 --- a/packages/sanity/src/core/components/documentStatus/DocumentStatus.tsx +++ b/packages/sanity/src/core/components/documentStatus/DocumentStatus.tsx @@ -1,29 +1,20 @@ import {type PreviewValue, type SanityDocument} from '@sanity/types' -import {Flex, Text} from '@sanity/ui' +import {type BadgeTone, Flex, Text} from '@sanity/ui' import {useMemo} from 'react' -import {styled} from 'styled-components' +import {useReleases} from 'sanity' -import {useDateTimeFormat, useRelativeTime} from '../../hooks' +import {useRelativeTime} from '../../hooks' import {useTranslation} from '../../i18n' import {type VersionsRecord} from '../../preview/utils/getPreviewStateObservable' -import {type CurrentPerspective} from '../../releases' -import {PerspectiveBadge} from '../perspective/PerspectiveBadge' +import {getReleaseTone, ReleaseAvatar} from '../../releases' interface DocumentStatusProps { - absoluteDate?: boolean draft?: PreviewValue | Partial | null published?: PreviewValue | Partial | null - version?: PreviewValue | Partial | null - // eslint-disable-next-line - versions?: VersionsRecord + versions?: VersionsRecord | Record singleLine?: boolean - currentGlobalBundle?: CurrentPerspective } -const StyledText = styled(Text)` - white-space: nowrap; -` - /** * Displays document status indicating both last published and edited dates in either relative (the default) * or absolute formats. @@ -34,86 +25,87 @@ const StyledText = styled(Text)` * * @internal */ -export function DocumentStatus({ - absoluteDate, - draft, - published, - version, - singleLine, - currentGlobalBundle, -}: DocumentStatusProps) { +export function DocumentStatus({draft, published, versions, singleLine}: DocumentStatusProps) { + const {data: releases} = useReleases() + const versionsList = useMemo(() => Object.entries(versions ?? {}), [versions]) const {t} = useTranslation() - const draftUpdatedAt = draft && '_updatedAt' in draft ? draft._updatedAt : '' - const versionUpdatedAt = version && '_updatedAt' in version ? version._updatedAt : '' - const publishedUpdatedAt = published && '_updatedAt' in published ? published._updatedAt : '' - - const intlDateFormat = useDateTimeFormat({ - dateStyle: 'medium', - timeStyle: 'short', - }) - - const draftDateAbsolute = draftUpdatedAt && intlDateFormat.format(new Date(draftUpdatedAt)) - const publishedDateAbsolute = - publishedUpdatedAt && intlDateFormat.format(new Date(publishedUpdatedAt)) - const versionDateAbsolute = versionUpdatedAt && intlDateFormat.format(new Date(versionUpdatedAt)) - - const draftUpdatedTimeAgo = useRelativeTime(draftUpdatedAt || '', { - minimal: true, - useTemporalPhrase: true, - }) - const publishedUpdatedTimeAgo = useRelativeTime(publishedUpdatedAt || '', { - minimal: true, - useTemporalPhrase: true, - }) - const versionUpdatedTimeAgo = useRelativeTime(versionUpdatedAt || '', { - minimal: true, - useTemporalPhrase: true, - }) - - const publishedDate = absoluteDate ? publishedDateAbsolute : publishedUpdatedTimeAgo - const updatedDate = absoluteDate - ? versionDateAbsolute || draftDateAbsolute - : versionUpdatedTimeAgo || draftUpdatedTimeAgo - - const title = currentGlobalBundle?.metadata?.title - - const documentStatus = useMemo(() => { - if (published && '_id' in published) { - return 'published' - } else if (version && '_id' in version) { - return 'version' - } - - return 'draft' - }, [published, version]) return ( - {version && currentGlobalBundle && ( - + {published && ( + )} - - {!version && !publishedDate && ( - - {t('document-status.not-published')} - - )} - {!version && publishedDate && ( - - {t('document-status.published', {date: publishedDate})} - - )} - {updatedDate && ( - - {t('document-status.edited', {date: updatedDate})} - + {draft && ( + )} + {versionsList.map(([versionName, {snapshot}]) => { + const release = releases?.find((r) => r.name === versionName) + return ( + + ) + })} + + ) +} + +type Mode = 'edited' | 'created' | 'draft' | 'published' + +const labels: Record = { + draft: 'document-status.edited', + published: 'document-status.date', + edited: 'document-status.edited', + created: 'document-status.created', +} + +const VersionStatus = ({ + title, + timestamp, + mode, + tone, +}: { + title: string + mode: Mode + timestamp?: string + tone: BadgeTone +}) => { + const {t} = useTranslation() + + const relativeTime = useRelativeTime(timestamp || '', { + minimal: true, + useTemporalPhrase: true, + }) + + return ( + + + + {title}{' '} + + {t(labels[mode], {date: relativeTime})} + + ) } diff --git a/packages/sanity/src/core/components/documentStatusIndicator/DocumentStatusIndicator.tsx b/packages/sanity/src/core/components/documentStatusIndicator/DocumentStatusIndicator.tsx index 6d85e1986dd..1799d264b1d 100644 --- a/packages/sanity/src/core/components/documentStatusIndicator/DocumentStatusIndicator.tsx +++ b/packages/sanity/src/core/components/documentStatusIndicator/DocumentStatusIndicator.tsx @@ -1,62 +1,92 @@ import {DotIcon} from '@sanity/icons' import {type PreviewValue, type SanityDocument} from '@sanity/types' -import {Text} from '@sanity/ui' -import {useMemo} from 'react' +import {Flex, Text} from '@sanity/ui' +import {type ComponentType, useMemo} from 'react' import {styled} from 'styled-components' import {type VersionsRecord} from '../../preview/utils/getPreviewStateObservable' +import {useReleases} from '../../store/release/useReleases' interface DocumentStatusProps { draft?: PreviewValue | Partial | null published?: PreviewValue | Partial | null - version?: PreviewValue | Partial | null - // eslint-disable-next-line - versions?: VersionsRecord + versions: VersionsRecord | undefined } const Root = styled(Text)` - &[data-status='edited'] { - --card-icon-color: var(--card-badge-caution-dot-color); - } - &[data-status='unpublished'] { + &[data-status='not-published'] { --card-icon-color: var(--card-badge-default-dot-color); opacity: 0.5 !important; } + &[data-status='draft'] { + --card-icon-color: var(--card-badge-caution-dot-color); + } + &[data-status='asap'] { + --card-icon-color: var(--card-badge-critical-dot-color); + } + &[data-status='undecided'] { + --card-icon-color: var(--card-badge-explore-dot-color); + } + &[data-status='scheduled'] { + --card-icon-color: var(--card-badge-primary-dot-color); + } ` +type Status = 'not-published' | 'draft' | 'asap' | 'scheduled' | 'undecided' + /** * Renders a dot indicating the current document status. * - * - Yellow (caution) for published documents with edits - * - Gray (default) for unpublished documents (with or without edits) - * - * No dot will be displayed for published documents without edits or for version documents. - * * @internal */ -export function DocumentStatusIndicator({draft, published, version}: DocumentStatusProps) { - const $draft = Boolean(draft) - const $published = Boolean(published) - const $version = Boolean(version) - - const status = useMemo(() => { - if ($version) return undefined - if ($draft && !$published) return 'unpublished' - return 'edited' - }, [$draft, $published, $version]) - - // Return null if the document is: - // - Published without edits - // - Neither published or without edits (this shouldn't be possible) - // - A version - if ((!$draft && !$published) || (!$draft && $published) || $version) { - return null - } +export function DocumentStatusIndicator({draft, published, versions}: DocumentStatusProps) { + const {data: releases} = useReleases() + const versionsList = useMemo( + () => + versions + ? Object.keys(versions).map((versionName) => { + const release = releases?.find((r) => r.name === versionName) + return release?.metadata.releaseType + }) + : [], + [releases, versions], + ) + + const indicators: { + status: Status + show: boolean + }[] = [ + { + status: draft && !published ? 'not-published' : 'draft', + show: Boolean(draft), + }, + { + status: 'asap', + show: versionsList.includes('asap'), + }, + { + status: 'scheduled', + show: versionsList.includes('scheduled'), + }, + { + status: 'undecided', + show: versionsList.includes('undecided'), + }, + ] - // TODO: Remove debug `status[0]` output. return ( - - - + + {indicators + .filter(({show}) => show) + .map(({status}) => ( + + ))} + ) } + +const Dot: ComponentType<{status: Status}> = ({status}) => ( + + + +) diff --git a/packages/sanity/src/core/form/inputs/ReferenceInput/ReferencePreview.tsx b/packages/sanity/src/core/form/inputs/ReferenceInput/ReferencePreview.tsx index c12802a7b2a..41daf411011 100644 --- a/packages/sanity/src/core/form/inputs/ReferenceInput/ReferencePreview.tsx +++ b/packages/sanity/src/core/form/inputs/ReferenceInput/ReferencePreview.tsx @@ -45,8 +45,6 @@ export function ReferencePreview(props: { [previewId, refType.name], ) - const {draft, published, version} = preview - const previewProps = useMemo( () => ({ children: ( @@ -61,28 +59,31 @@ export function ReferencePreview(props: { ), layout, schemaType: refType, - tooltip: , + tooltip: ( + + ), value: previewStub, }), [ documentPresence, - draft, layout, preview.draft, preview.published, - preview.version, + preview.versions, previewStub, - published, refType, showTypeLabel, - version, ], ) diff --git a/packages/sanity/src/core/form/inputs/ReferenceInput/types.ts b/packages/sanity/src/core/form/inputs/ReferenceInput/types.ts index f9ef755f309..76a5b3fbaec 100644 --- a/packages/sanity/src/core/form/inputs/ReferenceInput/types.ts +++ b/packages/sanity/src/core/form/inputs/ReferenceInput/types.ts @@ -9,6 +9,7 @@ import {type ComponentType, type ReactNode} from 'react' import {type Observable} from 'rxjs' import {type DocumentAvailability} from '../../../preview' +import {type VersionsRecord} from '../../../preview/utils/getPreviewStateObservable' import {type ObjectInputProps} from '../../types' export type PreviewDocumentValue = PreviewValue & { @@ -25,6 +26,7 @@ export interface ReferenceInfo { draft: PreviewDocumentValue | undefined published: PreviewDocumentValue | undefined version: PreviewDocumentValue | undefined + versions: VersionsRecord } } diff --git a/packages/sanity/src/core/form/inputs/ReferenceInput/useReferenceInput.tsx b/packages/sanity/src/core/form/inputs/ReferenceInput/useReferenceInput.tsx index 4b9a99d9872..b957c821a91 100644 --- a/packages/sanity/src/core/form/inputs/ReferenceInput/useReferenceInput.tsx +++ b/packages/sanity/src/core/form/inputs/ReferenceInput/useReferenceInput.tsx @@ -8,10 +8,11 @@ import { useMemo, useRef, } from 'react' +import {usePerspective} from 'sanity' import {type FIXME} from '../../../FIXME' import {useSchema} from '../../../hooks' -import {useDocumentPreviewStore} from '../../../store' +import {useDocumentPreviewStore, useReleases} from '../../../store' import {isNonNullable} from '../../../util' import {useFormValue} from '../../contexts/FormValue' import {useReferenceInputOptions} from '../../studio' @@ -34,6 +35,8 @@ interface Options { export function useReferenceInput(options: Options) { const {path, schemaType, version} = options const schema = useSchema() + const perspective = usePerspective() + const releases = useReleases() const documentPreviewStore = useDocumentPreviewStore() const {EditReferenceLinkComponent, onEditReference, activePath, initialValueTemplateItems} = useReferenceInputOptions() @@ -114,8 +117,24 @@ export function useReferenceInput(options: Options) { }, [disableNew, initialValueTemplateItems, schemaType.to]) const getReferenceInfo = useCallback( - (id: string) => adapter.getReferenceInfo(documentPreviewStore, id, schemaType, {version}), - [documentPreviewStore, schemaType, version], + (id: string) => + adapter.getReferenceInfo( + documentPreviewStore, + id, + schemaType, + {version}, + { + bundleIds: releases.releasesIds, + bundleStack: perspective.bundlesPerspective, + }, + ), + [ + documentPreviewStore, + schemaType, + version, + releases.releasesIds, + perspective.bundlesPerspective, + ], ) return { diff --git a/packages/sanity/src/core/form/studio/inputs/client-adapters/reference.ts b/packages/sanity/src/core/form/studio/inputs/client-adapters/reference.ts index 7b99ea02f59..ccadb4e84bb 100644 --- a/packages/sanity/src/core/form/studio/inputs/client-adapters/reference.ts +++ b/packages/sanity/src/core/form/studio/inputs/client-adapters/reference.ts @@ -1,12 +1,24 @@ import {type SanityClient} from '@sanity/client' import {DEFAULT_MAX_FIELD_DEPTH} from '@sanity/schema/_internal' import {type ReferenceFilterSearchOptions, type ReferenceSchemaType} from '@sanity/types' -import {combineLatest, type Observable, of} from 'rxjs' -import {map, mergeMap, startWith, switchMap} from 'rxjs/operators' +import {omit} from 'lodash' +import {combineLatest, from, type Observable, of} from 'rxjs' +import {map, mergeMap, scan, startWith, switchMap} from 'rxjs/operators' import {type DocumentPreviewStore, getPreviewPaths, prepareForPreview} from '../../../../preview' +import { + type VersionsRecord, + type VersionTuple, +} from '../../../../preview/utils/getPreviewStateObservable' import {createSearch} from '../../../../search' -import {collate, type CollatedHit, getDraftId, getIdPair, isRecord} from '../../../../util' +import { + collate, + type CollatedHit, + getDraftId, + getIdPair, + getVersionId, + isRecord, +} from '../../../../util' import { type PreviewDocumentValue, type ReferenceInfo, @@ -28,6 +40,7 @@ const NOT_FOUND = { reason: 'NOT_FOUND', } as const +// type VersionsPreviewTuple = [bundleId: string, snapshot: PreviewValue | null] /** * Takes an id and a reference schema type, returns metadata about it */ @@ -36,6 +49,7 @@ export function getReferenceInfo( id: string, referenceType: ReferenceSchemaType, {version}: {version?: string} = {}, + perspective: {bundleIds: string[]; bundleStack: string[]} = {bundleIds: [], bundleStack: []}, ): Observable { const {publishedId, draftId, versionId} = getIdPair(id, {version}) @@ -67,6 +81,7 @@ export function getReferenceInfo( draft: undefined, published: undefined, version: undefined, + versions: {}, }, } as const) } @@ -98,6 +113,7 @@ export function getReferenceInfo( draft: undefined, published: undefined, version: undefined, + versions: {}, }, } as const) } @@ -114,6 +130,7 @@ export function getReferenceInfo( draft: undefined, published: undefined, version: undefined, + versions: {}, }, } as const) } @@ -128,16 +145,52 @@ export function getReferenceInfo( refSchemaType, ) - const versionPreview$ = versionId - ? documentPreviewStore.observePaths({_id: versionId}, previewPaths).pipe( - map((result) => - result - ? { - _id: versionId, - ...prepareForPreview(result, refSchemaType), - } - : undefined, + const versions$ = from(perspective.bundleIds).pipe( + mergeMap>((bundleId) => + documentPreviewStore + .observePaths({_id: getVersionId(id, bundleId)}, previewPaths) + .pipe( + // eslint-disable-next-line max-nested-callbacks + map((result) => + result + ? [ + bundleId, + { + snapshot: { + _id: versionId, + ...prepareForPreview(result, refSchemaType), + }, + }, + ] + : [bundleId, {snapshot: null}], + ), ), + ), + scan((byBundleId, [bundleId, value]) => { + if (value.snapshot === null) { + return omit({...byBundleId}, [bundleId]) + } + + return { + ...byBundleId, + [bundleId]: value, + } + }, {}), + startWith({}), + ) + + // Iterate the release stack in descending precedence, returning the highest precedence existing + // version document. + const versionPreview$ = versionId + ? versions$.pipe( + map((versions) => { + for (const bundleId of perspective.bundleStack) { + if (bundleId in versions) { + return versions[bundleId] + } + } + return null + }), startWith(undefined), ) : undefined @@ -146,11 +199,13 @@ export function getReferenceInfo( draftPreview$, publishedPreview$, ...(versionPreview$ ? [versionPreview$] : []), + versions$, ]).pipe( - map(([draft, published, versionValue]) => ({ + map(([draft, published, versionValue, versions]) => ({ draft, published, ...(versionValue ? {version: versionValue} : {}), + versions: versions, })), ) @@ -178,9 +233,11 @@ export function getReferenceInfo( published: (isRecord(value.published) ? value.published : undefined) as | PreviewDocumentValue | undefined, - version: (isRecord(value.version) ? value.version : undefined) as - | PreviewDocumentValue - | undefined, + version: (isRecord(value.version?.snapshot) + ? value.version.snapshot + : undefined) as PreviewDocumentValue | undefined, + + versions: isRecord(value.versions) ? value.versions : {}, }, } }), diff --git a/packages/sanity/src/core/i18n/bundles/studio.ts b/packages/sanity/src/core/i18n/bundles/studio.ts index fd83a4ca6d1..146addbb732 100644 --- a/packages/sanity/src/core/i18n/bundles/studio.ts +++ b/packages/sanity/src/core/i18n/bundles/studio.ts @@ -357,6 +357,11 @@ export const studioLocaleStrings = defineLocalesResources('studio', { /** Title for the default ordering/SortOrder if no orderings are provided and the title field is found */ 'default-orderings.title': 'Sort by Title', + /** Label to show in the document footer indicating the creation date of the document */ + 'document-status.created': 'Created {{date}}', + + /** Label to show in the document status indicating the date of the status */ + 'document-status.date': '{{date}}', /** Label to show in the document footer indicating the last edited date of the document */ 'document-status.edited': 'Edited {{date}}', /** Label to show in the document footer indicating the document is not published*/ diff --git a/packages/sanity/src/core/preview/components/SanityDefaultPreview.tsx b/packages/sanity/src/core/preview/components/SanityDefaultPreview.tsx index 247e059e083..94b325d9135 100644 --- a/packages/sanity/src/core/preview/components/SanityDefaultPreview.tsx +++ b/packages/sanity/src/core/preview/components/SanityDefaultPreview.tsx @@ -132,8 +132,8 @@ export function SanityDefaultPreview(props: SanityDefaultPreviewProps): ReactEle {/* Currently tooltips won't trigger without a wrapping element */}
{children}
diff --git a/packages/sanity/src/core/preview/types.ts b/packages/sanity/src/core/preview/types.ts index f89e5288e4d..37d57011b17 100644 --- a/packages/sanity/src/core/preview/types.ts +++ b/packages/sanity/src/core/preview/types.ts @@ -96,6 +96,7 @@ export interface DraftsModelDocumentAvailability { * document readability for the version document */ version?: DocumentAvailability + // TODO: validate versions availability? } /** diff --git a/packages/sanity/src/core/preview/utils/getPreviewStateObservable.ts b/packages/sanity/src/core/preview/utils/getPreviewStateObservable.ts index b00a5fac17e..12c93ed5fcc 100644 --- a/packages/sanity/src/core/preview/utils/getPreviewStateObservable.ts +++ b/packages/sanity/src/core/preview/utils/getPreviewStateObservable.ts @@ -13,7 +13,7 @@ import {type DocumentPreviewStore} from '../documentPreviewStore' */ export type VersionsRecord = Record -type VersionTuple = [bundleId: string, snapshot: PreparedSnapshot] +export type VersionTuple = [bundleId: string, snapshot: PreparedSnapshot] export interface PreviewState { isLoading?: boolean diff --git a/packages/sanity/src/core/scheduledPublishing/components/scheduleItem/PreviewWrapper.tsx b/packages/sanity/src/core/scheduledPublishing/components/scheduleItem/PreviewWrapper.tsx index abba5514f78..e9431a82b87 100644 --- a/packages/sanity/src/core/scheduledPublishing/components/scheduleItem/PreviewWrapper.tsx +++ b/packages/sanity/src/core/scheduledPublishing/components/scheduleItem/PreviewWrapper.tsx @@ -154,6 +154,7 @@ const PreviewWrapper = (props: Props) => { ) : ( diff --git a/packages/sanity/src/core/scheduledPublishing/utils/paneItemHelpers.tsx b/packages/sanity/src/core/scheduledPublishing/utils/paneItemHelpers.tsx index a060901010e..58d5611d539 100644 --- a/packages/sanity/src/core/scheduledPublishing/utils/paneItemHelpers.tsx +++ b/packages/sanity/src/core/scheduledPublishing/utils/paneItemHelpers.tsx @@ -7,6 +7,7 @@ import {combineLatest, type Observable, of} from 'rxjs' import {map, startWith} from 'rxjs/operators' import {type DocumentPreviewStore} from '../../preview' +import {type VersionsRecord} from '../../preview/utils/getPreviewStateObservable' import {getDraftId, getPublishedId} from '../../util/draftUtils' import {type Schedule} from '../types' @@ -14,6 +15,7 @@ export interface PaneItemPreviewState { isLoading?: boolean draft?: SanityDocument | null published?: SanityDocument | null + versions?: VersionsRecord } export interface PreviewValue { diff --git a/packages/sanity/src/core/store/release/useReleases.ts b/packages/sanity/src/core/store/release/useReleases.ts index 387c36c3c56..13b17b55f08 100644 --- a/packages/sanity/src/core/store/release/useReleases.ts +++ b/packages/sanity/src/core/store/release/useReleases.ts @@ -1,5 +1,6 @@ import {useMemo} from 'react' import {useObservable} from 'react-rx' +import {getBundleIdFromReleaseId} from 'sanity' import {sortReleases} from '../../releases/hooks/utils' import {useReleasesStore} from '../_legacy/datastores' @@ -11,6 +12,10 @@ interface ReleasesState { * Sorted array of releases, excluding archived releases */ data: ReleaseDocument[] + /** + * Sorted array of release IDs, excluding archived releases + */ + releasesIds: string[] /** * Array of archived releases */ @@ -37,8 +42,13 @@ export function useReleases(): ReleasesState { () => Array.from(state.releases.values()).filter((release) => release.state === 'archived'), [state.releases], ) + const releasesIds = useMemo( + () => releasesAsArray.map((release) => getBundleIdFromReleaseId(release._id)), + [releasesAsArray], + ) return { data: releasesAsArray, + releasesIds: releasesIds, archivedReleases, dispatch, error: state.error, diff --git a/packages/sanity/src/core/studio/components/navbar/search/components/searchResults/item/SearchResultItemPreview.tsx b/packages/sanity/src/core/studio/components/navbar/search/components/searchResults/item/SearchResultItemPreview.tsx index 10f68980e90..a751cfa8893 100644 --- a/packages/sanity/src/core/studio/components/navbar/search/components/searchResults/item/SearchResultItemPreview.tsx +++ b/packages/sanity/src/core/studio/components/navbar/search/components/searchResults/item/SearchResultItemPreview.tsx @@ -3,7 +3,7 @@ import {type SchemaType} from '@sanity/types' import {Badge, Box, Flex} from '@sanity/ui' import {useMemo} from 'react' import {useObservable} from 'react-rx' -import {getBundleIdFromReleaseId, getPublishedId} from 'sanity' +import {getPublishedId} from 'sanity' import {styled} from 'styled-components' import {type GeneralPreviewLayoutKey} from '../../../../../../../components' @@ -61,10 +61,10 @@ export function SearchResultItemPreview({ const observable = useMemo( () => getPreviewStateObservable(documentPreviewStore, schemaType, getPublishedId(documentId), '', { - bundleIds: (releases.data ?? []).map((release) => getBundleIdFromReleaseId(release._id)), + bundleIds: releases.releasesIds, bundleStack: bundlesPerspective, }), - [releases.data, bundlesPerspective, documentId, documentPreviewStore, schemaType], + [documentPreviewStore, schemaType, documentId, releases.releasesIds, bundlesPerspective], ) const { @@ -96,19 +96,12 @@ export function SearchResultItemPreview({ {presence && presence.length > 0 && } {showBadge && {schemaType.title}} - + ) - }, [draft, isLoading, presence, published, schemaType.title, showBadge, version, versions]) + }, [draft, isLoading, presence, published, schemaType.title, showBadge, versions]) - const tooltip = ( - - ) + const tooltip = return ( diff --git a/packages/sanity/src/structure/components/paneItem/PaneItemPreview.tsx b/packages/sanity/src/structure/components/paneItem/PaneItemPreview.tsx index 0564599c7e0..8e524046614 100644 --- a/packages/sanity/src/structure/components/paneItem/PaneItemPreview.tsx +++ b/packages/sanity/src/structure/components/paneItem/PaneItemPreview.tsx @@ -10,7 +10,6 @@ import { DocumentStatus, DocumentStatusIndicator, type GeneralPreviewLayoutKey, - getBundleIdFromReleaseId, getPreviewStateObservable, getPreviewValueWithFallback, isRecord, @@ -52,10 +51,17 @@ export function PaneItemPreview(props: PaneItemPreviewProps) { const previewStateObservable = useMemo( () => getPreviewStateObservable(props.documentPreviewStore, schemaType, value._id, title, { - bundleIds: (releases.data ?? []).map((release) => getBundleIdFromReleaseId(release._id)), + bundleIds: releases.releasesIds, bundleStack: bundlesPerspective, }), - [props.documentPreviewStore, schemaType, value._id, title, releases.data, bundlesPerspective], + [ + props.documentPreviewStore, + schemaType, + value._id, + title, + releases.releasesIds, + bundlesPerspective, + ], ) const { @@ -79,19 +85,12 @@ export function PaneItemPreview(props: PaneItemPreviewProps) { {presence && presence.length > 0 && } - + ) - const tooltip = ( - - ) + const tooltip = return ( - {showingRevision ? ( - - ) : ( - - )} + {showingRevision ? : } diff --git a/packages/sanity/src/structure/panes/document/statusBar/DocumentStatusLine.tsx b/packages/sanity/src/structure/panes/document/statusBar/DocumentStatusLine.tsx index 4c3cd9a0f19..524a5b14fdd 100644 --- a/packages/sanity/src/structure/panes/document/statusBar/DocumentStatusLine.tsx +++ b/packages/sanity/src/structure/panes/document/statusBar/DocumentStatusLine.tsx @@ -1,6 +1,17 @@ import {Flex} from '@sanity/ui' -import {useEffect, useLayoutEffect, useState} from 'react' -import {DocumentStatus, DocumentStatusIndicator, usePerspective, useSyncState} from 'sanity' +import {useEffect, useLayoutEffect, useMemo, useState} from 'react' +import {useObservable} from 'react-rx' +import {of} from 'rxjs' +import { + DocumentStatus, + getBundleIdFromReleaseId, + getPreviewStateObservable, + useDocumentPreviewStore, + usePerspective, + useReleases, + useSchema, + useSyncState, +} from 'sanity' import {Tooltip} from '../../../../ui-components' import {useDocumentPane} from '../useDocumentPane' @@ -9,17 +20,29 @@ import {DocumentStatusPulse} from './DocumentStatusPulse' const SYNCING_TIMEOUT = 1000 const SAVED_TIMEOUT = 3000 -interface DocumentStatusLineProps { - singleLine?: boolean -} - -export function DocumentStatusLine({singleLine}: DocumentStatusLineProps) { +export function DocumentStatusLine() { const {documentId, documentType, editState, value} = useDocumentPane() - const [status, setStatus] = useState<'saved' | 'syncing' | null>(null) + const documentPreviewStore = useDocumentPreviewStore() + const schema = useSchema() + const schemaType = schema.get(documentType) + const releases = useReleases() + const {currentGlobalBundle, bundlesPerspective} = usePerspective() + const previewStateObservable = useMemo( + () => + schemaType + ? getPreviewStateObservable(documentPreviewStore, schemaType, value._id, 'Untitled', { + bundleIds: (releases.data ?? []).map((release) => + getBundleIdFromReleaseId(release._id), + ), + bundleStack: bundlesPerspective, + }) + : of({versions: {}}), + [documentPreviewStore, schemaType, value._id, releases.data, bundlesPerspective], + ) + const {versions} = useObservable(previewStateObservable, {versions: {}}) const syncState = useSyncState(documentId, documentType, {version: editState?.bundleId}) - const {currentGlobalBundle} = usePerspective() const lastUpdated = value?._updatedAt @@ -50,34 +73,46 @@ export function DocumentStatusLine({singleLine}: DocumentStatusLineProps) { } }, [syncState.isSyncing, lastUpdated]) + const getMode = () => { + if (currentGlobalBundle?._id === 'published') { + return 'published' + } + if (editState?.version) { + return 'version' + } + if (editState?.draft) { + return 'draft' + } + return 'published' + } + const mode = getMode() + if (status) { return } - return ( } placement="top" > - - + + {/* Shows only 1 line of document status */} diff --git a/packages/sanity/src/structure/panes/documentList/sheetList/useDocumentSheetColumns.tsx b/packages/sanity/src/structure/panes/documentList/sheetList/useDocumentSheetColumns.tsx index 8574ae6ae0a..3f648aa1186 100644 --- a/packages/sanity/src/structure/panes/documentList/sheetList/useDocumentSheetColumns.tsx +++ b/packages/sanity/src/structure/panes/documentList/sheetList/useDocumentSheetColumns.tsx @@ -50,7 +50,7 @@ const PreviewCell = (props: { const displayValue = (draft?.title ?? published?.title ?? 'Untitled') as string return ( - + {displayValue} )