Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
pedrobonamin committed Nov 23, 2024
1 parent 4632d2c commit 4f48a9d
Show file tree
Hide file tree
Showing 19 changed files with 176 additions and 92 deletions.
1 change: 1 addition & 0 deletions packages/sanity/src/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export {
isReleaseScheduledOrScheduling,
LATEST,
type ReleaseDocument,
RELEASES_INTENT,
useDocumentVersions,
usePerspective,
useReleases,
Expand Down
1 change: 1 addition & 0 deletions packages/sanity/src/core/releases/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export * from '../store/user'
export * from './__telemetry__/releases.telemetry'
export * from './components'
export * from './hooks'
export {RELEASES_INTENT} from './plugin'
export * from './store'
export * from './util/const'
export * from './util/createReleaseId'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export interface ReleaseOperationsStore {

const IS_CREATE_VERSION_ACTION_SUPPORTED = false
// todo: change to `metadata` once the relevant PR has been deployed
const METADATA_PROPERTY_NAME = 'userMetadata'
const METADATA_PROPERTY_NAME = 'metadata'

export function createReleaseOperationsStore(options: {
client: SanityClient
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ function migrateWith(client: SanityClient) {
actionType: 'sanity.action.release.edit',
releaseId,
patch: {
set: {userMetadata: tmpDoc.metadata},
set: {metadata: tmpDoc.metadata},
},
}).catch((err) => {
if (err instanceof ClientError) {
Expand Down
10 changes: 5 additions & 5 deletions packages/sanity/src/core/store/events/getDocumentChanges.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,23 +163,23 @@ export function getDocumentChanges({
// We need to expose this differently, as we need to also expose the transactions for versions and drafts, this implementation only works for published.
// We need to find a way to listen to the incoming transactions and in the case of published documents, refetch the events when a new transaction comes in.
// For versions and drafts we can keep the list of transactions updated just by the received transactions.
if (!since) {
return of({loading: false, diff: null})
}

return from(
getDocumentTransactions({
documentId,
client,
toTransaction: to._rev,
fromTransaction: since._rev,
fromTransaction: since?._rev || to._rev,
}),
).pipe(
map((transactions) => {
return {
loading: false,
diff: calculateDiff({
initialDoc: since,
initialDoc:
since ||
// Useful when inspecting initial creation value of a version document and the `created` event is selected as the to-event
({_id: documentId, _type: to._type} as SanityDocument),
finalDoc: to,
transactions,
events: events,
Expand Down
14 changes: 9 additions & 5 deletions packages/sanity/src/core/store/events/getDocumentTransactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@ export async function getDocumentTransactions({
// reverse: 'true',
limit: TRANSLOG_ENTRY_LIMIT.toString(),
// https://www.sanity.io/docs/history-api#fromTransaction-db53ef83c809
fromTransaction,
fromTransaction: fromTransaction,
})

// fromTransaction,
if (toTransaction) {
queryParams.append('toTransaction', toTransaction)
}
Expand All @@ -45,6 +47,7 @@ export async function getDocumentTransactions({
)
const transactions: TransactionLogEventWithEffects[] = []

const skipFromTransaction = fromTransaction !== toTransaction
const stream = await getJsonStream(transactionsUrl, clientConfig.token)
const reader = stream.getReader()
for (;;) {
Expand All @@ -55,14 +58,15 @@ export async function getDocumentTransactions({
if ('error' in result.value) {
throw new Error(result.value.error.description || result.value.error.type)
}
if (result.value.id === fromTransaction) continue
if (result.value.id === fromTransaction && skipFromTransaction) continue
else transactions.push(result.value)
}

if (
transactions.length ===
// The transaction received with the id fromTransaction is not included in the list but it's returned by the API; remove that from the count
TRANSLOG_ENTRY_LIMIT - 1
skipFromTransaction
? // The transaction received with the id fromTransaction is not included in the list but it's returned by the API; remove that from the count
transactions.length === TRANSLOG_ENTRY_LIMIT - 1
: transactions.length === TRANSLOG_ENTRY_LIMIT
) {
// We have received the max values, we need to fetch the next batch. (Unless we have reached the toTransaction)
if (
Expand Down
1 change: 1 addition & 0 deletions packages/sanity/src/core/store/events/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,7 @@ export interface EventsStoreRevision {
}

export interface EventsStore {
enabled: true
events: DocumentGroupEvent[]
nextCursor: string | null
loading: boolean
Expand Down
57 changes: 33 additions & 24 deletions packages/sanity/src/core/store/events/useEventsStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {getDocumentTransactions} from './getDocumentTransactions'
import {getEditEvents, getEffectState} from './getEditEvents'
import {
type DocumentGroupEvent,
type EditDocumentVersionEvent,
type EventsStore,
type EventsStoreRevision,
isCreateDocumentVersionEvent,
Expand Down Expand Up @@ -141,8 +142,8 @@ export function useEventsStore({
}: {
documentId: string
documentType: string
rev?: string
since?: string
rev?: string | '@lastEdited'
since?: string | '@lastPublished'
}): EventsStore {
const client = useClient(DEFAULT_STUDIO_CLIENT_OPTIONS)

Expand Down Expand Up @@ -329,37 +330,42 @@ export function useEventsStore({
}, [state$, eventsObservable$, remoteTransactions$, documentId])

const {events, loading, error, nextCursor} = useObservable(observable$, INITIAL_VALUE)

const revisionId = useMemo(() => {
if (rev === '@lastEdited') {
const editEvent = events.find((event) => isEditDocumentVersionEvent(event)) as
| EditDocumentVersionEvent
| undefined
if (editEvent) return editEvent.revisionId
}
return rev
}, [events, rev])
const revision$ = useMemo(
() => getDocumentAtRevision({client, documentId, revisionId: rev}),
[rev, client, documentId],
() => getDocumentAtRevision({client, documentId, revisionId: revisionId}),
[client, documentId, revisionId],
)
const revision = useObservable(revision$, null)

const sinceId = useMemo(() => {
if (since && since !== '@lastPublished') return since
if (!events) return null

if (since === '@lastPublished') {
// TODO: Find the last published event
}

// We want to try to infer the since Id from the events, we want to compare to the last event that happened before the rev as fallback
if (!events) return null
if (!rev) {
if (!revisionId) {
// rev has not been selected, the user will be seeing the last version of the document.
// we need to select the event that comes after
return events.slice(1).find((event) => 'revisionId' in event)?.revisionId || null
return events[1]?.id
}

// If the user has a rev, we should show here the id of the event that is the previous event to the rev.
const revisionEventIndex = events.findIndex(
(event) => 'revisionId' in event && event.revisionId === rev,
)
if (revisionEventIndex === -1) {
return null
}
// If the user has selected a revisionId, we should show here the id of the event that is the previous event to the rev selected.
const revisionEventIndex = events.findIndex((e) => e.id === revisionId)
if (revisionEventIndex === -1) return null

return (
events.slice(revisionEventIndex + 1).find((event) => 'revisionId' in event)?.revisionId ||
null
)
}, [events, rev, since])
return events[revisionEventIndex + 1]?.id || null
}, [events, revisionId, since])

const since$ = useMemo(
() => getDocumentAtRevision({client, documentId, revisionId: sinceId}),
Expand All @@ -385,15 +391,15 @@ export function useEventsStore({
const findRangeForSince = useCallback(
(nextSince: string): [string | null, string | null] => {
if (!events) return [null, null]
if (!rev) return [nextSince, null]
const revisionIndex = events.findIndex((event) => event.id === rev)
if (!revisionId) return [nextSince, null]
const revisionIndex = events.findIndex((event) => event.id === revisionId)
const sinceIndex = events.findIndex((event) => event.id === nextSince)
if (sinceIndex === -1 || revisionIndex === -1) return [nextSince, null]
if (sinceIndex < revisionIndex) return [nextSince, null]
if (sinceIndex === revisionIndex) return [nextSince, null]
return [nextSince, rev]
return [nextSince, revisionId]
},
[events, rev],
[events, revisionId],
)

const changesList = useCallback(
Expand All @@ -410,8 +416,11 @@ export function useEventsStore({
},
[client, events, documentId],
)
console.log('revision', revision)
console.log('EVENTS', events)

return {
enabled: true,
events: events,
nextCursor: nextCursor,
loading: loading,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ function DocumentPaneInner(props: DocumentPaneProviderProps) {
)
}

console.log('OPTIONS', options)
return (
<HistoryProvider documentId={options.id} documentType={options.type}>
<DocumentPaneProvider
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,11 @@ export const DocumentPaneProvider = memo((props: DocumentPaneProviderProps) => {
const documentType = options.type
const params = useUnique(paneRouter.params) || EMPTY_PARAMS
const {perspective, currentGlobalBundle} = usePerspective()
const seeingHistoricVersion = Boolean(params.historyVersion)

const bundlePerspective = resolveBundlePerspective(perspective)
const bundlePerspective = seeingHistoricVersion
? params.historyVersion
: resolveBundlePerspective(perspective)

/* Version and the global perspective should match.
* If user clicks on add document, and then switches to another version, he should click again on create document.
Expand Down Expand Up @@ -288,10 +291,20 @@ export const DocumentPaneProvider = memo((props: DocumentPaneProviderProps) => {
const {t} = useTranslation(structureLocaleNamespace)

const inspectOpen = params.inspect === 'on'
const compareValue: Partial<SanityDocument> | null =
eventsStore?.sinceRevision?.document || changesOpen
? sinceAttributes
: editState?.published || null
const compareValue: Partial<SanityDocument> | null = useMemo(() => {
if (eventsStore?.enabled) {
return changesOpen
? eventsStore?.sinceRevision?.document || null
: editState?.published || null
}
return changesOpen ? sinceAttributes : editState?.published || null
}, [
changesOpen,
editState?.published,
eventsStore?.enabled,
eventsStore?.sinceRevision?.document,
sinceAttributes,
])

const fieldActions: DocumentFieldAction[] = useMemo(
() => (schemaType ? fieldActionsResolver({documentId, documentType, schemaType}) : []),
Expand Down
38 changes: 24 additions & 14 deletions packages/sanity/src/structure/panes/document/HistoryProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {useContext, useState} from 'react'
import {useContext, useMemo, useState} from 'react'
import {
type EventsStore,
getDraftId,
Expand All @@ -7,6 +7,7 @@ import {
resolveBundlePerspective,
useEventsStore,
usePerspective,
useReleases,
useSource,
useTimelineStore,
} from 'sanity'
Expand Down Expand Up @@ -58,26 +59,35 @@ function LegacyStoreProvider({
}

function EventsStoreProvider(props: LegacyStoreProviderProps) {
const {params = EMPTY_PARAMS, setParams} = usePaneRouter()
const {params = EMPTY_PARAMS} = usePaneRouter()

const {perspective} = usePerspective()
const bundlePerspective = resolveBundlePerspective(perspective)
const documentId =
// eslint-disable-next-line no-nested-ternary
typeof perspective === 'undefined'
? getDraftId(props.documentId)
: // eslint-disable-next-line no-nested-ternary
perspective === 'published'
? getPublishedId(props.documentId)
: bundlePerspective
? getVersionId(props.documentId, bundlePerspective)
: props.documentId
const {archivedReleases} = useReleases()
const {rev, since, historyVersion} = params

const documentId = useMemo(() => {
if (historyVersion && archivedReleases.some((release) => release.name === historyVersion)) {
// Check if we have a release that matches with this historyVersion
return getVersionId(props.documentId, historyVersion)
}
if (typeof perspective === 'undefined') {
return getDraftId(props.documentId)
}
if (perspective === 'published') {
return getPublishedId(props.documentId)
}
if (bundlePerspective) {
return getVersionId(props.documentId, bundlePerspective)
}
return props.documentId
}, [archivedReleases, historyVersion, bundlePerspective, perspective, props.documentId])

const eventsStore = useEventsStore({
documentId,
documentType: props.documentType,
rev: params.rev,
since: params.since,
rev: rev,
since: since,
})

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
} from 'sanity'
import {css, styled} from 'styled-components'

import {PaneContent, usePane, usePaneLayout} from '../../../components'
import {PaneContent, usePane, usePaneLayout, usePaneRouter} from '../../../components'
import {isLiveEditEnabled} from '../../../components/paneItem/helpers'
import {useStructureTool} from '../../../useStructureTool'
import {DocumentInspectorPanel} from '../documentInspector'
Expand All @@ -26,6 +26,7 @@ import {
import {AddToReleaseBanner} from './banners/AddToReleaseBanner'
import {DraftLiveEditBanner} from './banners/DraftLiveEditBanner'
import {FormView} from './documentViews'
import {ArchivedReleaseDocumentBanner} from './banners/ArchivedReleaseDocumentBanner'

interface DocumentPanelProps {
footerHeight: number | null
Expand Down Expand Up @@ -71,6 +72,7 @@ export const DocumentPanel = function DocumentPanel(props: DocumentPanelProps) {
existsInBundle,
documentType,
} = useDocumentPane()
const {params} = usePaneRouter()
const {collapsed: layoutCollapsed} = usePaneLayout()
const {collapsed} = usePane()
const parentPortal = usePortal()
Expand Down Expand Up @@ -150,6 +152,9 @@ export const DocumentPanel = function DocumentPanel(props: DocumentPanelProps) {
: false

const banners = useMemo(() => {
if (params?.historyVersion) {
return <ArchivedReleaseDocumentBanner documentId={documentId} />
}
if ((!existsInBundle && currentPerspectiveIsRelease) || isScheduledRelease) {
return (
<AddToReleaseBanner
Expand Down Expand Up @@ -197,6 +202,7 @@ export const DocumentPanel = function DocumentPanel(props: DocumentPanelProps) {
requiredPermission,
schemaType,
value._id,
params
])

return (
Expand Down
Loading

0 comments on commit 4f48a9d

Please sign in to comment.