Skip to content

Commit

Permalink
fix(corel): refactor version history to fetch all release documents (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
pedrobonamin authored and bjoerge committed Aug 16, 2024
1 parent ef17591 commit c81ef33
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 81 deletions.
10 changes: 9 additions & 1 deletion packages/sanity/src/core/releases/tool/detail/ReleaseDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {type BundleDocument} from '../../../store/bundles/types'
import {API_VERSION} from '../../../tasks/constants'
import {BundleMenuButton} from '../../components/BundleMenuButton/BundleMenuButton'
import {type ReleasesRouterState} from '../../types/router'
import {useReleaseHistory} from './documentTable/useReleaseHistory'
import {ReleaseOverview} from './ReleaseOverview'

type Screen = 'overview' | 'review'
Expand All @@ -29,6 +30,8 @@ export const ReleaseDetail = () => {
const {data, loading} = useBundles()
const {documents: bundleDocuments, loading: documentsLoading} =
useFetchBundleDocuments(parsedBundleName)
const history = useReleaseHistory(bundleDocuments)

const bundle = data?.find((storeBundle) => storeBundle.name === parsedBundleName)
const bundleHasDocuments = !!bundleDocuments.length
const showPublishButton = loading || !bundle?.publishedAt
Expand Down Expand Up @@ -120,7 +123,12 @@ export const ReleaseDetail = () => {
) : (
<>
{activeScreen === 'overview' && (
<ReleaseOverview documents={bundleDocuments} release={bundle} />
<ReleaseOverview
documents={bundleDocuments}
release={bundle}
documentsHistory={history.documentsHistory}
collaborators={history.collaborators}
/>
)}
</>
)}
Expand Down
17 changes: 10 additions & 7 deletions packages/sanity/src/core/releases/tool/detail/ReleaseOverview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,17 @@ import {type BundleDocument} from '../../../store/bundles/types'
import {useAddonDataset} from '../../../studio/addonDataset/useAddonDataset'
import {Chip} from '../../components/Chip'
import {DocumentTable} from './documentTable'
import {type DocumentHistory} from './documentTable/useReleaseHistory'

export function ReleaseOverview(props: {documents: SanityDocument[]; release: BundleDocument}) {
const {documents, release} = props
export function ReleaseOverview(props: {
documents: SanityDocument[]
documentsHistory: Map<string, DocumentHistory>
collaborators: string[]
release: BundleDocument
}) {
const {documents, documentsHistory, release, collaborators} = props
const {client} = useAddonDataset()
/**
* This state is created here but will be updated by the DocumentRow component when fetching the history
*/
const [collaborators, setCollaborators] = useState<string[]>([])

const [iconValue, setIconValue] = useState<BundleIconEditorPickerValue>({
hue: release.hue ?? 'gray',
icon: release.icon ?? 'documents',
Expand Down Expand Up @@ -132,7 +135,7 @@ export function ReleaseOverview(props: {documents: SanityDocument[]; release: Bu
<DocumentTable
documents={documents}
release={release}
setCollaborators={setCollaborators}
documentsHistory={documentsHistory}
/>
)}
</Stack>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,15 @@
import {CheckmarkCircleIcon, EmptyIcon, Progress50Icon} from '@sanity/icons'
import {type SanityDocument} from '@sanity/types'
import {AvatarStack, Box, Card, Flex, Text} from '@sanity/ui'
import {
type Dispatch,
type ForwardedRef,
forwardRef,
type SetStateAction,
useEffect,
useMemo,
} from 'react'
import {type ForwardedRef, forwardRef, useMemo} from 'react'
import {getPublishedId, RelativeTime, SanityDefaultPreview, UserAvatar} from 'sanity'
import {IntentLink} from 'sanity/router'

import {Tooltip} from '../../../../../ui-components'
import {type BundleDocument} from '../../../../store/bundles/types'
import {DocumentActions} from './DocumentActions'
import {useDocumentPreviewValues} from './useDocumentPreviewValues'
import {useVersionHistory} from './useVersionHistory'
import {type DocumentHistory} from './useReleaseHistory'

const DOCUMENT_STATUS = {
ready: {
Expand Down Expand Up @@ -63,19 +56,22 @@ export function DocumentRow(props: {
searchTerm: string
document: SanityDocument
release: BundleDocument
setCollaborators: Dispatch<SetStateAction<string[]>>
history: DocumentHistory | undefined
}) {
const {document, release, searchTerm, setCollaborators} = props
const {
document,
release,
searchTerm,
history = {
editors: [],
createdBy: undefined,
lastEditedBy: undefined,
},
} = props
const documentId = document._id
const documentTypeName = document._type
const {previewValues, isLoading} = useDocumentPreviewValues({document, release})

const history = useVersionHistory(documentId, document?._rev)

useEffect(() => {
setCollaborators((pre) => Array.from(new Set([...pre, ...history.editors])))
}, [history.editors, setCollaborators])

const LinkComponent = useMemo(
() =>
// eslint-disable-next-line @typescript-eslint/no-shadow
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import {type SanityDocument} from '@sanity/types'
import {Stack} from '@sanity/ui'
import {type Dispatch, type SetStateAction, useMemo, useState} from 'react'
import {useMemo, useState} from 'react'
import {styled} from 'styled-components'

import {type BundleDocument} from '../../../../store/bundles/types'
import {DocumentHeader} from './DocumentHeader'
import {DocumentRow} from './DocumentRow'
import {type DocumentSort} from './types'
import {type DocumentHistory} from './useReleaseHistory'

const RowStack = styled(Stack)({
'& > *:not(:first-child)': {
Expand All @@ -23,10 +24,10 @@ const RowStack = styled(Stack)({

export function DocumentTable(props: {
documents: SanityDocument[]
documentsHistory: Map<string, DocumentHistory>
release: BundleDocument
setCollaborators: Dispatch<SetStateAction<string[]>>
}) {
const {documents, release, setCollaborators} = props
const {documents, release, documentsHistory} = props
// Filter will happen at the DocumentRow level because we don't have access here to the preview values.
const [searchTerm, setSearchTerm] = useState<string>('')
const [sort, setSort] = useState<DocumentSort>({property: '_updatedAt', order: 'desc'})
Expand Down Expand Up @@ -66,7 +67,7 @@ export function DocumentTable(props: {
document={d}
key={d._id}
release={release}
setCollaborators={setCollaborators}
history={documentsHistory.get(d._id)}
/>
))}
</RowStack>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import {useCallback, useEffect, useMemo, useState} from 'react'
import {
type BundleDocument,
getPublishedId,
type TransactionLogEventWithEffects,
useClient,
} from 'sanity'

import {getJsonStream} from '../../../../store/_legacy/history/history/getJsonStream'
import {API_VERSION} from '../../../../tasks/constants'

export type DocumentHistory = {
history: TransactionLogEventWithEffects[]
createdBy: string
lastEditedBy: string
editors: string[]
}

// TODO: Update this to contemplate the _revision change on any of the internal bundle documents, and fetch only the history of that document if changes.
export function useReleaseHistory(bundleDocuments: BundleDocument[]): {
documentsHistory: Map<string, DocumentHistory>
collaborators: string[]
loading: boolean
} {
const client = useClient({apiVersion: API_VERSION})
const {dataset, token} = client.config()
const [history, setHistory] = useState<TransactionLogEventWithEffects[]>([])
const queryParams = `tag=sanity.studio.tasks.history&effectFormat=mendoza&excludeContent=true&includeIdentifiedDocumentsOnly=true`
const bundleDocumentsIds = useMemo(() => bundleDocuments.map((doc) => doc._id), [bundleDocuments])

const publishedIds = bundleDocumentsIds.map((id) => getPublishedId(id)).join(',')
const transactionsUrl = client.getUrl(
`/data/history/${dataset}/transactions/${publishedIds}?${queryParams}`,
)

const fetchAndParseAll = useCallback(async () => {
if (!publishedIds) return
const transactions: TransactionLogEventWithEffects[] = []
const stream = await getJsonStream(transactionsUrl, token)
const reader = stream.getReader()
let result
for (;;) {
result = await reader.read()
if (result.done) {
break
}
if ('error' in result.value) {
throw new Error(result.value.error.description || result.value.error.type)
}
transactions.push(result.value)
}
setHistory(transactions)
}, [publishedIds, transactionsUrl, token])

useEffect(() => {
fetchAndParseAll()
// When revision changes, update the history.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [fetchAndParseAll])

return useMemo(() => {
const collaborators: string[] = []
const documentsHistory = new Map<string, DocumentHistory>()
if (!history.length) {
return {documentsHistory, collaborators, loading: true}
}
history.forEach((item) => {
const documentId = item.documentIDs[0]
let documentHistory = documentsHistory.get(documentId)
if (!collaborators.includes(item.author)) {
collaborators.push(item.author)
}
// eslint-disable-next-line no-negated-condition
if (!documentHistory) {
documentHistory = {
history: [item],
createdBy: item.author,
lastEditedBy: item.author,
editors: [item.author],
}
documentsHistory.set(documentId, documentHistory)
} else {
// @ts-expect-error TransactionLogEventWithEffects has no property 'mutations' but it's returned from the API
const isCreate = item.mutations.some((mutation) => 'create' in mutation)
if (isCreate) documentHistory.createdBy = item.author
if (!documentHistory.editors.includes(item.author)) {
documentHistory.editors.push(item.author)
}
// The last item in the history is the last edited by, transaction log is ordered by timestamp
documentHistory.lastEditedBy = item.author
// always add history item
documentHistory.history.push(item)
}
})

return {documentsHistory, collaborators, loading: false}
}, [history])
}

This file was deleted.

0 comments on commit c81ef33

Please sign in to comment.