Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(sanity): adopt bundlePerspective for listing documents #7415

Merged
merged 4 commits into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@
"@playwright/test": "1.44.1",
"@repo/package.config": "workspace:*",
"@repo/tsconfig": "workspace:*",
"@sanity/client": "^6.21.2",
"@sanity/client": "bundle-perspective",
"@sanity/eslint-config-i18n": "1.0.0",
"@sanity/eslint-config-studio": "^4.0.0",
"@sanity/mutate": "^0.8.0",
Expand Down Expand Up @@ -185,6 +185,7 @@
},
"overrides": {
"@npmcli/arborist": "^7.5.4",
"@sanity/client": "bundle-perspective",
"@sanity/ui@2": "$@sanity/ui",
"@typescript-eslint/eslint-plugin": "$@typescript-eslint/eslint-plugin",
"@typescript-eslint/parser": "$@typescript-eslint/parser"
Expand Down
8 changes: 5 additions & 3 deletions packages/sanity/src/core/bundles/util/util.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {type BundleDocument} from '../../store/bundles/types'
import {getVersionFromId, isVersionId} from '../../util'
import {getVersionFromId, isVersionId, resolveBundlePerspective} from '../../util'

/**
* @beta
Expand All @@ -22,11 +22,13 @@ export function getDocumentIsInPerspective(

if (!perspective) return !isVersionId(documentId)

if (!perspective.startsWith('bundle.')) return false
const bundlePerspective = resolveBundlePerspective(perspective)

if (typeof bundlePerspective === 'undefined') return false
// perspective is `bundle.${bundleId}`

if (bundleId === 'Published') return false
return bundleId === perspective.replace('bundle.', '')
return bundleId === bundlePerspective
}

export function versionDocumentExists(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {CommentsContext} from 'sanity/_singletons'
import {useEditState, useSchema, useUserListWithPermissions} from '../../../hooks'
import {useCurrentUser} from '../../../store'
import {useAddonDataset, useWorkspace} from '../../../studio'
import {getPublishedId} from '../../../util'
import {getPublishedId, resolveBundlePerspective} from '../../../util'
import {
type CommentOperationsHookOptions,
useCommentOperations,
Expand Down Expand Up @@ -85,15 +85,11 @@ export const CommentsProvider = memo(function CommentsProvider(props: CommentsPr
const [status, setStatus] = useState<CommentStatus>('open')
const {client, createAddonDataset, isCreatingDataset} = useAddonDataset()

const bundlePerspective = perspective?.startsWith('bundle.')
? perspective.split('bundle.').at(1)
: undefined

const editState = useEditState(
getPublishedId(versionOrPublishedId),
documentType,
'default',
bundlePerspective,
resolveBundlePerspective(perspective),
)
const schemaType = useSchema().get(documentType)
const currentUser = useCurrentUser()
Expand Down
2 changes: 1 addition & 1 deletion packages/sanity/src/core/preview/documentPreviewStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ export function createDocumentPreviewStore({
}

const observeDocumentIdSet = createDocumentIdSetObserver(
versionedClient.withConfig({apiVersion: '2024-07-22'}),
versionedClient.withConfig({apiVersion: 'X'}),
juice49 marked this conversation as resolved.
Show resolved Hide resolved
)

const observeForPreview = createPreviewObserver({observeDocumentTypeFromId, observePaths})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import {WarningOutlineIcon} from '@sanity/icons'
import {type PreviewValue, type SanityDocument} from '@sanity/types'
import {assignWith} from 'lodash'

import {resolveBundlePerspective} from '../../util'

const getMissingDocumentFallback = (item: SanityDocument) => ({
title: <em>{item.title ? String(item.title) : 'Missing document'}</em>,
subtitle: <em>{item.title ? `Missing document ID: ${item._id}` : `Document ID: ${item._id}`}</em>,
Expand Down Expand Up @@ -30,7 +32,7 @@ export const getPreviewValueWithFallback = ({
let snapshot: Partial<SanityDocument> | PreviewValue | null | undefined

switch (true) {
case perspective?.startsWith('bundle.'):
case typeof resolveBundlePerspective(perspective) !== 'undefined':
snapshot = version || draft || published
break
case perspective === 'published':
Expand Down
2 changes: 2 additions & 0 deletions packages/sanity/src/core/search/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ export type SearchOptions = {
cursor?: string
limit?: number
perspective?: string
bundlePerspective?: string
isCrossDataset?: boolean
queryType?: 'prefixLast' | 'prefixNone'
}
Expand Down Expand Up @@ -190,6 +191,7 @@ export type TextSearchParams = {
*/
order?: TextSearchOrder[]
perspective?: string
bundlePerspective?: string
}

export type TextSearchResponse<Attributes = Record<string, unknown>> = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,14 @@ export const createTextSearch: SearchStrategyFactory<TextSearchResults> = (
searchOptions.includeDrafts === false && "!(_id in path('drafts.**'))",
factoryOptions.filter ? `(${factoryOptions.filter})` : false,
searchTerms.filter ? `(${searchTerms.filter})` : false,
// Versions are collated server-side using the `bundlePerspective` option. Therefore, they
// must not be fetched individually.
'!(_id in path("versions.**"))',
].filter((baseFilter): baseFilter is string => Boolean(baseFilter))

const textSearchParams: TextSearchParams = {
perspective: searchOptions.perspective,
bundlePerspective: searchOptions.bundlePerspective,
query: {
string: getQueryString(searchTerms.query, searchOptions),
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ describe('createSearchQuery', () => {

expect(query).toEqual(
`// findability-mvi:${FINDABILITY_MVI}\n` +
'*[_type in $__types && (_id match $t0 || _type match $t0 || title match $t0)]' +
'*[_type in $__types && (_id match $t0 || _type match $t0 || title match $t0) && !(_id in path("versions.**"))]' +
'| order(_id asc)' +
'[0...$__limit]' +
'{_type, _id, _version, ...select(_type == "basic-schema-test" => { "w0": _id,"w1": _type,"w2": title })}',
Expand Down Expand Up @@ -106,7 +106,7 @@ describe('createSearchQuery', () => {
})

expect(query).toContain(
'*[_type in $__types && (_id match $t0 || _type match $t0 || title match $t0 || object.field match $t0)]',
'*[_type in $__types && (_id match $t0 || _type match $t0 || title match $t0 || object.field match $t0) && !(_id in path("versions.**"))]',
)
})

Expand All @@ -117,7 +117,7 @@ describe('createSearchQuery', () => {
})

expect(query).toContain(
'*[_type in $__types && (_id match $t0 || _type match $t0 || title match $t0) && (_id match $t1 || _type match $t1 || title match $t1)]',
'*[_type in $__types && (_id match $t0 || _type match $t0 || title match $t0) && (_id match $t1 || _type match $t1 || title match $t1) && !(_id in path("versions.**"))]',
)
expect(params.t0).toEqual('term0*')
expect(params.t1).toEqual('term1*')
Expand Down Expand Up @@ -147,7 +147,7 @@ describe('createSearchQuery', () => {

const result = [
`// findability-mvi:${FINDABILITY_MVI}\n` +
'*[_type in $__types && (_id match $t0 || _type match $t0 || title match $t0)]{_type, _id, _version, object{field}}',
'*[_type in $__types && (_id match $t0 || _type match $t0 || title match $t0) && !(_id in path("versions.**"))]{_type, _id, _version, object{field}}',
'|order(_id asc)[0...$__limit]',
'{_type, _id, _version, ...select(_type == "basic-schema-test" => { "w0": _id,"w1": _type,"w2": title })}',
].join('')
Expand Down Expand Up @@ -193,7 +193,7 @@ describe('createSearchQuery', () => {
)

expect(query).toContain(
'*[_type in $__types && (_id match $t0 || _type match $t0 || title match $t0) && (randomCondition == $customParam)]',
'*[_type in $__types && (_id match $t0 || _type match $t0 || title match $t0) && (randomCondition == $customParam) && !(_id in path("versions.**"))]',
)
expect(params.customParam).toEqual('custom')
})
Expand Down Expand Up @@ -241,7 +241,7 @@ describe('createSearchQuery', () => {

expect(query).toEqual(
`// findability-mvi:${FINDABILITY_MVI}\n` +
'*[_type in $__types && (_id match $t0 || _type match $t0 || title match $t0)]' +
'*[_type in $__types && (_id match $t0 || _type match $t0 || title match $t0) && !(_id in path("versions.**"))]' +
'| order(exampleField desc)' +
'[0...$__limit]' +
'{_type, _id, _version, ...select(_type == "basic-schema-test" => { "w0": _id,"w1": _type,"w2": title })}',
Expand Down Expand Up @@ -275,7 +275,7 @@ describe('createSearchQuery', () => {

const result = [
`// findability-mvi:${FINDABILITY_MVI}\n`,
'*[_type in $__types && (_id match $t0 || _type match $t0 || title match $t0)]| ',
'*[_type in $__types && (_id match $t0 || _type match $t0 || title match $t0) && !(_id in path("versions.**"))]| ',
'order(exampleField desc,anotherExampleField asc,lower(mapWithField) asc)',
'[0...$__limit]{_type, _id, _version, ...select(_type == "basic-schema-test" => { "w0": _id,"w1": _type,"w2": title })}',
].join('')
Expand All @@ -291,7 +291,7 @@ describe('createSearchQuery', () => {

expect(query).toEqual(
`// findability-mvi:${FINDABILITY_MVI}\n` +
'*[_type in $__types && (_id match $t0 || _type match $t0 || title match $t0)]' +
'*[_type in $__types && (_id match $t0 || _type match $t0 || title match $t0) && !(_id in path("versions.**"))]' +
'| order(_id asc)' +
'[0...$__limit]' +
'{_type, _id, _version, ...select(_type == "basic-schema-test" => { "w0": _id,"w1": _type,"w2": title })}',
Expand Down Expand Up @@ -403,7 +403,7 @@ describe('createSearchQuery', () => {
* This is an improvement over before, where an illegal term was used (number-as-string, ala ["0"]),
* which lead to no hits at all. */
`// findability-mvi:${FINDABILITY_MVI}\n` +
'*[_type in $__types && (_id match $t0 || _type match $t0 || cover[].cards[].title match $t0) && (_id match $t1 || _type match $t1 || cover[].cards[].title match $t1)]' +
'*[_type in $__types && (_id match $t0 || _type match $t0 || cover[].cards[].title match $t0) && (_id match $t1 || _type match $t1 || cover[].cards[].title match $t1) && !(_id in path("versions.**"))]' +
'| order(_id asc)' +
'[0...$__limit]' +
// at this point we could refilter using cover[0].cards[0].title.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,9 @@ export function createSearchQuery(
...createConstraints(terms, specs),
filter ? `(${filter})` : '',
searchTerms.filter ? `(${searchTerms.filter})` : '',
// Versions are collated server-side using the `bundlePerspective` option. Therefore, they must
// not be fetched individually.
'!(_id in path("versions.**"))',
].filter(Boolean)

const selections = specs.map((spec) => {
Expand Down Expand Up @@ -186,7 +189,11 @@ export function createSearchQuery(
__limit: limit,
...(params || {}),
},
options: {tag, perspective: searchOpts.perspective},
options: {
tag,
perspective: searchOpts.perspective,
bundlePerspective: searchOpts.bundlePerspective,
},
searchSpec: specs,
terms,
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {type SanityDocumentLike} from '@sanity/types'
import {Box, type ResponsiveMarginProps, type ResponsivePaddingProps} from '@sanity/ui'
import {type MouseEvent, useCallback, useMemo} from 'react'
import {useIntentLink} from 'sanity/router'
import {useIntentLink, useRouter} from 'sanity/router'

import {type GeneralPreviewLayoutKey, PreviewCard} from '../../../../../../../components'
import {useSchema} from '../../../../../../../hooks'
Expand Down Expand Up @@ -31,7 +31,7 @@ export function SearchResultItem({
const schema = useSchema()
const type = schema.get(documentType)
const documentPresence = useDocumentPresence(documentId)

const perspective = useRouter().stickyParams.perspective
const params = useMemo(() => ({id: documentId, type: type?.name}), [documentId, type?.name])
const {onClick: onIntentClick, href} = useIntentLink({
intent: 'edit',
Expand Down Expand Up @@ -65,6 +65,7 @@ export function SearchResultItem({
<SearchResultItemPreview
documentId={documentId}
layout={layout}
perspective={perspective}
presence={documentPresence}
schemaType={type}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {getPublishedId, getVersionFromId, isVersionId} from 'sanity'
import {getPublishedId, resolveBundlePerspective} from 'sanity'
import {styled} from 'styled-components'

import {type GeneralPreviewLayoutKey} from '../../../../../../../components'
Expand All @@ -19,6 +19,7 @@ import {type DocumentPresence, useDocumentPreviewStore} from '../../../../../../

interface SearchResultItemPreviewProps {
documentId: string
perspective?: string
layout?: GeneralPreviewLayoutKey
presence?: DocumentPresence[]
schemaType: SchemaType
Expand All @@ -29,7 +30,8 @@ interface SearchResultItemPreviewProps {
* Temporary workaround: force all nested boxes on iOS to use `background-attachment: scroll`
* to allow <Skeleton> components to render correctly within virtual lists.
*/
const SearchResultItemPreviewBox = styled(Box)`
const SearchResultItemPreviewBox = styled(Box)<{$isInPerspective: boolean}>`
opacity: ${(props) => (props.$isInPerspective ? 1 : 0.5)};
@supports (-webkit-overflow-scrolling: touch) {
* [data-ui='Box'] {
background-attachment: scroll;
Expand All @@ -43,6 +45,7 @@ const SearchResultItemPreviewBox = styled(Box)`
export function SearchResultItemPreview({
documentId,
layout,
perspective,
presence,
schemaType,
showBadge = true,
Expand All @@ -56,15 +59,16 @@ export function SearchResultItemPreview({
schemaType,
getPublishedId(documentId),
'',
getVersionFromId(documentId),
resolveBundlePerspective(perspective),
),
[documentId, documentPreviewStore, schemaType],
[documentId, documentPreviewStore, perspective, schemaType],
)

const {draft, published, isLoading, version} = useObservable(observable, {
draft: null,
isLoading: true,
published: null,
version: null,
})

const sanityDocument = useMemo(() => {
Expand All @@ -80,24 +84,22 @@ export function SearchResultItemPreview({
<Flex align="center" gap={3}>
{presence && presence.length > 0 && <DocumentPreviewPresence presence={presence} />}
{showBadge && <Badge>{schemaType.title}</Badge>}
<DocumentStatusIndicator draft={draft} published={published} />
<DocumentStatusIndicator draft={draft} published={published} version={version} />
</Flex>
)
}, [draft, isLoading, presence, published, schemaType.title, showBadge])
}, [draft, isLoading, presence, published, schemaType.title, showBadge, version])

const tooltip = <DocumentStatus draft={draft} published={published} />
const tooltip = <DocumentStatus draft={draft} published={published} version={version} />

return (
<SearchResultItemPreviewBox>
<SearchResultItemPreviewBox $isInPerspective={!perspective || Boolean(version)}>
<SanityDefaultPreview
{...getPreviewValueWithFallback({
draft,
published,
version,
value: sanityDocument,
perspective: isVersionId(documentId)
? `bundle.${getVersionFromId(documentId)}`
: undefined,
perspective,
})}
isPlaceholder={isLoading ?? true}
layout={layout || 'default'}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import {isEqual} from 'lodash'
import {type ReactNode, useEffect, useMemo, useReducer, useRef, useState} from 'react'
import {DRAFTS_FOLDER} from 'sanity'
import {SearchContext} from 'sanity/_singletons'
import {useRouter} from 'sanity/router'

import {type CommandListHandle} from '../../../../../../components'
import {useSchema} from '../../../../../../hooks'
import {type SearchTerms} from '../../../../../../search'
import {useCurrentUser} from '../../../../../../store'
import {resolvePerspectiveOptions} from '../../../../../../util/resolvePerspective'
import {useSource} from '../../../../../source'
import {SEARCH_LIMIT} from '../../constants'
import {type RecentSearch} from '../../datastores/recentSearches'
Expand All @@ -30,7 +33,7 @@ interface SearchProviderProps {
export function SearchProvider({children, fullscreen}: SearchProviderProps) {
const [onClose, setOnClose] = useState<(() => void) | null>(null)
const [searchCommandList, setSearchCommandList] = useState<CommandListHandle | null>(null)

const perspective = useRouter().stickyParams.perspective
const schema = useSchema()
const currentUser = useCurrentUser()
const {
Expand Down Expand Up @@ -140,6 +143,9 @@ export function SearchProvider({children, fullscreen}: SearchProviderProps) {
skipSortByScore: ordering.ignoreScore,
...(ordering.sort ? {sort: [ordering.sort]} : {}),
cursor: cursor || undefined,
...resolvePerspectiveOptions(perspective, (perspectives, isSystemPerspective) =>
isSystemPerspective ? perspectives : perspectives.concat(DRAFTS_FOLDER),
),
},
terms: {
...terms,
Expand All @@ -165,6 +171,7 @@ export function SearchProvider({children, fullscreen}: SearchProviderProps) {
searchState.terms,
terms,
cursor,
perspective,
])

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/sanity/src/core/studioClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ import {type SourceClientOptions} from './config'
* @internal
*/
export const DEFAULT_STUDIO_CLIENT_OPTIONS: SourceClientOptions = {
apiVersion: '2024-05-28',
apiVersion: 'X',
}
Loading
Loading