Skip to content

Commit

Permalink
feat(corel): Add review changes screen (#7155)
Browse files Browse the repository at this point in the history
* fix(corel): add prepareForPreview in useDocumentPreviewValues

* feat(corel): add review changes screen

* fix(corel): update ReleaseReview to use new documents history data

* feat(corel): add published document listener to review changes screen

* feat(core): add new useObserveDocument hook

* feat(corel): move active screen state to query params

* chore(corel): make documentDiff component agnostic to releases

* fix(corel): update document diff is changed check

* fix(corel): update useObserveDocument hook, export it as unstable

* chore(corel): add tests to release review screen
  • Loading branch information
pedrobonamin authored and bjoerge committed Jul 17, 2024
1 parent 68333d9 commit fb84570
Show file tree
Hide file tree
Showing 16 changed files with 680 additions and 49 deletions.
17 changes: 11 additions & 6 deletions packages/sanity/src/core/field/diff/components/DiffCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,19 @@ export interface DiffCardProps {
tooltip?: {description?: ReactNode} | boolean
}

const StyledCard = styled(Card)`
interface StyledCardProps {
$annotationColor: {backgroundColor: string; color: string}
}

const StyledCard = styled(Card)<StyledCardProps>`
--diff-card-radius: ${({theme}) => rem(theme.sanity.radius[2])};
--diff-card-bg-color: ${({theme}) => theme.sanity.color.card.enabled.bg};
max-width: 100%;
position: relative;
border-radius: var(--diff-card-radius);
background-color: ${({$annotationColor}) => $annotationColor.backgroundColor};
color: ${({$annotationColor}) => $annotationColor.color};
&:not(del) {
text-decoration: none;
Expand Down Expand Up @@ -100,13 +106,12 @@ export const DiffCard = forwardRef(function DiffCard(
as={as}
className={className}
data-hover={disableHoverEffect || !annotation ? undefined : ''}
data-ui="diff-card"
ref={ref}
radius={1}
style={{
...style,
backgroundColor: color.background,
color: color.text,
}}
// Added annotation color to the card using css to make it possible to override by the ReleaseReview
$annotationColor={{backgroundColor: color.background, color: color.text}}
style={style}
>
{children}
</StyledCard>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ export function FieldChange(
data-revert-field-hover={revertHovered ? '' : undefined}
data-error={change.error ? '' : undefined}
data-revert-all-hover
data-ui="field-diff-inspect-wrapper"
>
{change.error ? (
<ValueError error={change.error} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,11 @@ export function GroupChange(
<Stack
space={1}
as={GroupChangeContainer}
data-ui="group-change-content"
data-revert-group-hover={isRevertButtonHovered ? '' : undefined}
data-portable-text={isPortableText ? '' : undefined}
>
<Stack as={ChangeListWrapper} space={5}>
<Stack as={ChangeListWrapper} space={5} data-ui="group-change-list">
{changes.map((change) => (
<ChangeResolver
key={change.key}
Expand Down
1 change: 1 addition & 0 deletions packages/sanity/src/core/preview/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export * from './components/PreviewLoader'
export * from './components/SanityDefaultPreview'
export * from './documentPreviewStore'
export * from './types'
export {useObserveDocument as unstable_useObserveDocument} from './useObserveDocument'
export * from './useValuePreview'
export {getPreviewPaths} from './utils/getPreviewPaths'
export {getPreviewStateObservable} from './utils/getPreviewStateObservable'
Expand Down
36 changes: 36 additions & 0 deletions packages/sanity/src/core/preview/useObserveDocument.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import {type ObjectSchemaType, type SanityDocument} from '@sanity/types'
import {useMemo} from 'react'
import {useObservable} from 'react-rx'
import {map} from 'rxjs/operators'

import {useDocumentPreviewStore} from '../store/_legacy/datastores'

const INITIAL_STATE = {loading: true, document: null}

/**
* @internal
* @beta
*
* Observes a document by its ID and returns the document and loading state
* it will listen to the document changes.
*/
export function useObserveDocument<T extends SanityDocument>(
documentId: string,
schemaType: ObjectSchemaType,
): {
document: T | null
loading: boolean
} {
const documentPreviewStore = useDocumentPreviewStore()
const observable = useMemo(
() =>
documentPreviewStore
.observePaths(
{_id: documentId},
schemaType.fields.map((field) => [field.name]),
)
.pipe(map((document) => ({loading: false, document: document as T}))),
[documentId, documentPreviewStore, schemaType.fields],
)
return useObservable(observable, INITIAL_STATE)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import {type PreviewValue} from '@sanity/types'
import {Card} from '@sanity/ui'
import {type ForwardedRef, forwardRef, useMemo} from 'react'
import {IntentLink} from 'sanity/router'

import {SanityDefaultPreview} from '../../preview/components/SanityDefaultPreview'
import {getPublishedId} from '../../util/draftUtils'

interface ReleaseDocumentPreviewProps {
documentId: string
documentTypeName: string
releaseName: string
previewValues: PreviewValue
isLoading: boolean
}

export function ReleaseDocumentPreview({
documentId,
documentTypeName,
releaseName,
previewValues,
isLoading,
}: ReleaseDocumentPreviewProps) {
const LinkComponent = useMemo(
() =>
// eslint-disable-next-line @typescript-eslint/no-shadow
forwardRef(function LinkComponent(linkProps, ref: ForwardedRef<HTMLAnchorElement>) {
return (
<IntentLink
{...linkProps}
intent="edit"
params={{
id: getPublishedId(documentId, true),
type: documentTypeName,
}}
searchParams={[['perspective', `bundle.${releaseName}`]]}
ref={ref}
/>
)
}),
[documentId, documentTypeName, releaseName],
)

return (
<Card as={LinkComponent} radius={2} data-as="a">
<SanityDefaultPreview {...previewValues} isPlaceholder={isLoading} />
</Card>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
import {beforeEach, describe, expect, it, jest} from '@jest/globals'
import {render, screen} from '@testing-library/react'

import {queryByDataUi} from '../../../../../test/setup/customQueries'
import {createWrapper} from '../../../bundles/util/tests/createWrapper'
import {useObserveDocument} from '../../../preview/useObserveDocument'
import {ColorSchemeProvider} from '../../../studio/colorScheme'
import {UserColorManagerProvider} from '../../../user-color/provider'
import {releasesUsEnglishLocaleBundle} from '../../i18n'
import {useDocumentPreviewValues} from '../detail/documentTable/useDocumentPreviewValues'
import {type DocumentHistory} from '../detail/documentTable/useReleaseHistory'
import {ReleaseReview} from '../detail/ReleaseReview'

const baseDocument = {
name: 'William Faulkner',
role: 'developer',
awards: ['first award', 'second award'],
favoriteBooks: [
{
_ref: '0b229e82-48e4-4226-a36f-e6b3d874478a',
_type: 'reference',
_key: '23610d43d8e8',
},
],
_id: '1f8caa96-4174-4c91-bb40-cbc96a737fcf',
_rev: 'FvEfB9CaLlljeKWNkRBaf5',
_type: 'author',
_createdAt: '',
_updatedAt: '',
}

const MOCKED_PROPS = {
documents: [
{
favoriteBooks: [
{
_ref: '0daffd51-59c3-4dca-a9ee-1c4db54db87e',
_type: 'reference',
_key: '0d3f45004da0',
},
],
_version: {},
bestFriend: {
_ref: '0c9d9135-0d20-44a1-9ec1-54ea41ce84d1',
_type: 'reference',
},
_rev: 'FvEfB9CaLlljeKWNkQgpz9',
_type: 'author',
role: 'designer',
_createdAt: '2024-07-10T12:10:38Z',
name: 'William Faulkner added',
_id: 'differences.1f8caa96-4174-4c91-bb40-cbc96a737fcf',
_updatedAt: '2024-07-15T10:46:02Z',
},
],
release: {
_updatedAt: '2024-07-12T10:39:32Z',
authorId: 'p8xDvUMxC',
_type: 'bundle',
description: 'To test differences in documents',
hue: 'gray',
title: 'Differences',
_createdAt: '2024-07-10T12:09:56Z',
icon: 'cube',
name: 'differences',
_id: 'd3137faf-ece6-44b5-a2b1-1090967f868e',
_rev: 'j9BPWHem9m3oUugvhMXEGV',
} as const,
documentsHistory: new Map<string, DocumentHistory>([
[
'differences.1f8caa96-4174-4c91-bb40-cbc96a737fcf',
{
history: [],
createdBy: 'p8xDvUMxC',
lastEditedBy: 'p8xDvUMxC',
editors: ['p8xDvUMxC'],
},
],
]),
}

jest.mock('sanity/router', () => ({
...(jest.requireActual('sanity/router') || {}),
IntentLink: jest.fn().mockImplementation((props: any) => <a> {props.children}</a>),
useRouter: jest.fn().mockReturnValue({
state: {bundleName: 'differences'},
navigate: jest.fn(),
}),
}))

jest.mock('../../../preview/useObserveDocument', () => {
return {
useObserveDocument: jest.fn(),
}
})

jest.mock('../detail/documentTable/useDocumentPreviewValues', () => {
return {
useDocumentPreviewValues: jest.fn(),
}
})

const mockedUseObserveDocument = useObserveDocument as jest.Mock<typeof useObserveDocument>
const mockedUseDocumentPreviewValues = useDocumentPreviewValues as jest.Mock<
typeof useDocumentPreviewValues
>

const previewValues = {
_id: 'differences.1f8caa96-4174-4c91-bb40-cbc96a737fcf',
_type: 'author',
_createdAt: '2024-07-10T12:10:38Z',
_updatedAt: '2024-07-15T10:46:02Z',
_version: {},
title: 'William Faulkner differences check 123 asklaks ',
subtitle: 'Designer',
}

describe('ReleaseReview', () => {
describe('when loading baseDocument', () => {
beforeEach(async () => {
mockedUseObserveDocument.mockReturnValue({
document: null,
loading: true,
})
mockedUseDocumentPreviewValues.mockReturnValue({previewValues, isLoading: false})
const wrapper = await createWrapper({
resources: [releasesUsEnglishLocaleBundle],
})
render(<ReleaseReview {...MOCKED_PROPS} />, {wrapper})
})
it("should show the loader when the base document hasn't loaded", () => {
queryByDataUi(document.body, 'Spinner')
})
})
describe('when there is no base document', () => {
beforeEach(async () => {
mockedUseObserveDocument.mockReturnValue({
document: null,
loading: false,
})
mockedUseDocumentPreviewValues.mockReturnValue({previewValues, isLoading: false})
const wrapper = await createWrapper({
resources: [releasesUsEnglishLocaleBundle],
})
render(<ReleaseReview {...MOCKED_PROPS} />, {wrapper})
})
it('should render the new document ui', async () => {
expect(screen.getByText('New document')).toBeInTheDocument()
})
})

describe('when the base document is loaded and there are no changes', () => {
beforeEach(async () => {
mockedUseObserveDocument.mockReturnValue({
document: MOCKED_PROPS.documents[0],
loading: false,
})
mockedUseDocumentPreviewValues.mockReturnValue({previewValues, isLoading: false})
const wrapper = await createWrapper({
resources: [releasesUsEnglishLocaleBundle],
})
render(<ReleaseReview {...MOCKED_PROPS} />, {wrapper})
})
it('should show that there are no changes', async () => {
expect(screen.getByText('No changes')).toBeInTheDocument()
})
})

describe('when the base document is loaded and has changes', () => {
beforeEach(async () => {
mockedUseObserveDocument.mockReturnValue({
document: baseDocument,
loading: false,
})
mockedUseDocumentPreviewValues.mockReturnValue({previewValues, isLoading: false})
const wrapper = await createWrapper({
resources: [releasesUsEnglishLocaleBundle],
})
render(
<ColorSchemeProvider>
<UserColorManagerProvider>
<ReleaseReview {...MOCKED_PROPS} />
</UserColorManagerProvider>
</ColorSchemeProvider>,
{wrapper},
)
})
it('should should show the changes', async () => {
// Find an ins tag with the text "added"
const element = screen.getByText((content, el) => {
return el?.tagName.toLowerCase() === 'ins' && content === 'added'
})

expect(element).toBeInTheDocument()
})
})
})
Loading

0 comments on commit fb84570

Please sign in to comment.