From 3681afe8537f688a61440fc399bb25be653a3daa Mon Sep 17 00:00:00 2001 From: pedrobonamin Date: Wed, 4 Sep 2024 15:44:22 +0200 Subject: [PATCH 1/3] fix(core): update intent link for releases tool --- .../sanity/src/core/releases/plugin/index.ts | 7 +- .../header/DocumentHeaderTitle.tsx | 2 +- .../perspective/DocumentPerspectiveMenu.tsx | 67 ++++++++++++------- 3 files changed, 48 insertions(+), 28 deletions(-) diff --git a/packages/sanity/src/core/releases/plugin/index.ts b/packages/sanity/src/core/releases/plugin/index.ts index 6b8295a3408..a227cdf721a 100644 --- a/packages/sanity/src/core/releases/plugin/index.ts +++ b/packages/sanity/src/core/releases/plugin/index.ts @@ -26,12 +26,13 @@ export const releases = definePlugin({ title: 'Releases', component: ReleasesTool, router: route.create('/', [route.create('/:bundleId')]), - canHandleIntent: (intent, params) => { - return Boolean(intent === 'release' && params.slug) + canHandleIntent: (intent) => { + // If intent is release, open the releases tool. + return Boolean(intent === 'release') }, getIntentState(intent, params) { if (intent === 'release') { - return {bundleId: params.slug} + return {bundleId: params.id} } return null }, diff --git a/packages/sanity/src/structure/panes/document/documentPanel/header/DocumentHeaderTitle.tsx b/packages/sanity/src/structure/panes/document/documentPanel/header/DocumentHeaderTitle.tsx index d976580004b..330985ac635 100644 --- a/packages/sanity/src/structure/panes/document/documentPanel/header/DocumentHeaderTitle.tsx +++ b/packages/sanity/src/structure/panes/document/documentPanel/header/DocumentHeaderTitle.tsx @@ -62,7 +62,7 @@ export const DocumentHeaderTitle = memo(function DocumentHeaderTitle(): ReactEle )} - + diff --git a/packages/sanity/src/structure/panes/document/documentPanel/header/perspective/DocumentPerspectiveMenu.tsx b/packages/sanity/src/structure/panes/document/documentPanel/header/perspective/DocumentPerspectiveMenu.tsx index 40b53ffb82b..4740a8fe26a 100644 --- a/packages/sanity/src/structure/panes/document/documentPanel/header/perspective/DocumentPerspectiveMenu.tsx +++ b/packages/sanity/src/structure/panes/document/documentPanel/header/perspective/DocumentPerspectiveMenu.tsx @@ -1,32 +1,61 @@ import {ChevronDownIcon} from '@sanity/icons' // eslint-disable-next-line no-restricted-imports -- Bundle Button requires more fine-grained styling than studio button import {Box, Button} from '@sanity/ui' -import {memo, useCallback, useMemo} from 'react' -import {BundleBadge, BundlesMenu, usePerspective, useTranslation} from 'sanity' -import {useRouter} from 'sanity/router' -import {styled} from 'styled-components' +// eslint-disable-next-line camelcase +import {getTheme_v2} from '@sanity/ui/theme' +import {memo, useMemo} from 'react' +import {BundleBadge, type BundleDocument, BundlesMenu, usePerspective, useTranslation} from 'sanity' +import {IntentLink} from 'sanity/router' +import {css, styled} from 'styled-components' import {Button as StudioButton} from '../../../../../../ui-components' import {usePaneRouter} from '../../../../../components' import {useDocumentPane} from '../../../useDocumentPane' -const BadgeButton = styled(Button)({ - cursor: 'pointer', +const BadgeButton = styled(Button)((props) => { + const theme = getTheme_v2(props.theme) + const mode = props.mode || 'default' + const tone = props.tone || 'default' + const color = theme.color.button[mode][tone] + + return css` + cursor: pointer; + border-radius: 999px !important; + @media (hover: hover) { + &:hover { + text-decoration: none !important; + background-color: ${color.hovered.bg}; + } + } + ` }) +const ReleaseLink = ({release}: {release: Partial}) => { + const {hue, title, icon, _id: releaseId} = release + + return ( + + + + ) +} + export const DocumentPerspectiveMenu = memo(function DocumentPerspectiveMenu() { const paneRouter = usePaneRouter() const {t} = useTranslation() const {currentGlobalBundle} = usePerspective(paneRouter.perspective) const {documentVersions, existsInBundle} = useDocumentPane() - const {title, hue, icon, _id: bundleId} = currentGlobalBundle - - const router = useRouter() - - const handleBundleClick = useCallback(() => { - router.navigateIntent('release', {id: bundleId}) - }, [router, bundleId]) const bundlesMenuButton = useMemo( () => ( @@ -41,17 +70,7 @@ export const DocumentPerspectiveMenu = memo(function DocumentPerspectiveMenu() { return ( <> - {currentGlobalBundle && existsInBundle && ( - - - - )} + {currentGlobalBundle && existsInBundle && } {/** TODO IS THIS STILL NEEDED? VS THE PICKER IN STUDIO NAVBAR? */} From 528ab4dbcd738b38c7cf44492e43ffca6ca1f97e Mon Sep 17 00:00:00 2001 From: pedrobonamin Date: Wed, 4 Sep 2024 16:11:27 +0200 Subject: [PATCH 2/3] chore(core): rename releases tool bundleId param to releaseId --- .../BundleMenuButton/BundleMenuButton.tsx | 4 ++-- .../sanity/src/core/releases/i18n/resources.ts | 2 +- packages/sanity/src/core/releases/plugin/index.ts | 4 ++-- .../sanity/src/core/releases/tool/ReleasesTool.tsx | 4 ++-- .../core/releases/tool/detail/ReleaseDetail.tsx | 14 +++++++------- .../tool/detail/__tests__/ReleaseDetail.test.tsx | 4 ++-- .../tool/detail/__tests__/ReleaseReview.test.tsx | 2 +- .../tool/overview/ReleasesOverviewColumnDefs.tsx | 2 +- .../overview/__tests__/ReleasesOverview.test.tsx | 2 +- packages/sanity/src/core/releases/types/router.ts | 2 +- 10 files changed, 20 insertions(+), 20 deletions(-) diff --git a/packages/sanity/src/core/releases/components/BundleMenuButton/BundleMenuButton.tsx b/packages/sanity/src/core/releases/components/BundleMenuButton/BundleMenuButton.tsx index be7e62eab4b..a3febb6b88e 100644 --- a/packages/sanity/src/core/releases/components/BundleMenuButton/BundleMenuButton.tsx +++ b/packages/sanity/src/core/releases/components/BundleMenuButton/BundleMenuButton.tsx @@ -57,9 +57,9 @@ export const BundleMenuButton = ({disabled, bundle, documentCount}: BundleMenuBu ), }) setDiscardStatus('idle') - if (router.state.bundleId) { + if (router.state.releaseId) { // navigate back to bundle overview - router.navigate({bundleId: undefined}) + router.navigate({releaseId: undefined}) } } catch (e) { setDiscardStatus('error') diff --git a/packages/sanity/src/core/releases/i18n/resources.ts b/packages/sanity/src/core/releases/i18n/resources.ts index d0cd665bd74..5adba03de23 100644 --- a/packages/sanity/src/core/releases/i18n/resources.ts +++ b/packages/sanity/src/core/releases/i18n/resources.ts @@ -80,7 +80,7 @@ const releasesLocaleStrings = { /** Text for when no releases are found */ 'no-releases': 'No Releases', /** Text for when a release is not found */ - 'not-found': 'Release not found: {{bundleId}}', + 'not-found': 'Release not found: {{releaseId}}', /** Description for the release tool */ 'overview.description': diff --git a/packages/sanity/src/core/releases/plugin/index.ts b/packages/sanity/src/core/releases/plugin/index.ts index a227cdf721a..4b90e424bfa 100644 --- a/packages/sanity/src/core/releases/plugin/index.ts +++ b/packages/sanity/src/core/releases/plugin/index.ts @@ -25,14 +25,14 @@ export const releases = definePlugin({ name: 'releases', title: 'Releases', component: ReleasesTool, - router: route.create('/', [route.create('/:bundleId')]), + router: route.create('/', [route.create('/:releaseId')]), canHandleIntent: (intent) => { // If intent is release, open the releases tool. return Boolean(intent === 'release') }, getIntentState(intent, params) { if (intent === 'release') { - return {bundleId: params.id} + return {releaseId: params.id} } return null }, diff --git a/packages/sanity/src/core/releases/tool/ReleasesTool.tsx b/packages/sanity/src/core/releases/tool/ReleasesTool.tsx index 43a2d885d8f..0017e91bf5c 100644 --- a/packages/sanity/src/core/releases/tool/ReleasesTool.tsx +++ b/packages/sanity/src/core/releases/tool/ReleasesTool.tsx @@ -6,8 +6,8 @@ import {ReleasesOverview} from './overview/ReleasesOverview' export function ReleasesTool() { const router = useRouter() - const {bundleId} = router.state - if (bundleId) return + const {releaseId} = router.state + if (releaseId) return return } diff --git a/packages/sanity/src/core/releases/tool/detail/ReleaseDetail.tsx b/packages/sanity/src/core/releases/tool/detail/ReleaseDetail.tsx index c639aa7bed6..45f0550c784 100644 --- a/packages/sanity/src/core/releases/tool/detail/ReleaseDetail.tsx +++ b/packages/sanity/src/core/releases/tool/detail/ReleaseDetail.tsx @@ -36,18 +36,18 @@ export const ReleaseDetail = () => { const activeScreen = getActiveScreen(router) - const {bundleId}: ReleasesRouterState = router.state + const {releaseId: releaseIdRaw}: ReleasesRouterState = router.state - const parsedBundleId = decodeURIComponent(bundleId || '') + const releaseId = decodeURIComponent(releaseIdRaw || '') const {data, loading, deletedBundles} = useBundles() - const deletedBundle = deletedBundles[parsedBundleId] + const deletedBundle = deletedBundles[releaseId] - const {loading: documentsLoading, results} = useBundleDocuments(parsedBundleId) + const {loading: documentsLoading, results} = useBundleDocuments(releaseId) const documentIds = results.map((result) => result.document?._id) - const history = useReleaseHistory(documentIds, parsedBundleId) + const history = useReleaseHistory(documentIds, releaseId) - const bundle = data?.find((storeBundle) => storeBundle._id === parsedBundleId) + const bundle = data?.find((storeBundle) => storeBundle._id === releaseId) const bundleHasDocuments = !!results.length const showPublishButton = loading || !bundle?.publishedAt const isPublishButtonDisabled = loading || !bundle || !bundleHasDocuments @@ -222,7 +222,7 @@ export const ReleaseDetail = () => { - {t('not-found', {bundleId})} + {t('not-found', {releaseId})} diff --git a/packages/sanity/src/core/releases/tool/detail/__tests__/ReleaseDetail.test.tsx b/packages/sanity/src/core/releases/tool/detail/__tests__/ReleaseDetail.test.tsx index f71abe47ff6..55a36a852a2 100644 --- a/packages/sanity/src/core/releases/tool/detail/__tests__/ReleaseDetail.test.tsx +++ b/packages/sanity/src/core/releases/tool/detail/__tests__/ReleaseDetail.test.tsx @@ -59,10 +59,10 @@ const renderTest = async () => { return render( , diff --git a/packages/sanity/src/core/releases/tool/detail/__tests__/ReleaseReview.test.tsx b/packages/sanity/src/core/releases/tool/detail/__tests__/ReleaseReview.test.tsx index 6371e84fe67..c9ca04ad766 100644 --- a/packages/sanity/src/core/releases/tool/detail/__tests__/ReleaseReview.test.tsx +++ b/packages/sanity/src/core/releases/tool/detail/__tests__/ReleaseReview.test.tsx @@ -126,7 +126,7 @@ jest.mock('sanity/router', () => ({ ...(jest.requireActual('sanity/router') || {}), IntentLink: jest.fn().mockImplementation((props: any) => {props.children}), useRouter: jest.fn().mockReturnValue({ - state: {bundleId: 'differences'}, + state: {releaseId: 'differences'}, navigate: jest.fn(), }), })) diff --git a/packages/sanity/src/core/releases/tool/overview/ReleasesOverviewColumnDefs.tsx b/packages/sanity/src/core/releases/tool/overview/ReleasesOverviewColumnDefs.tsx index 0c7134f10e5..1e09d6175cd 100644 --- a/packages/sanity/src/core/releases/tool/overview/ReleasesOverviewColumnDefs.tsx +++ b/packages/sanity/src/core/releases/tool/overview/ReleasesOverviewColumnDefs.tsx @@ -20,7 +20,7 @@ const ReleaseNameCell: Column['cell'] = ({cellProps, datum: bundle} : { as: 'a', // navigate to bundle detail - onClick: () => router.navigate({bundleId: bundle._id}), + onClick: () => router.navigate({releaseId: bundle._id}), } return ( diff --git a/packages/sanity/src/core/releases/tool/overview/__tests__/ReleasesOverview.test.tsx b/packages/sanity/src/core/releases/tool/overview/__tests__/ReleasesOverview.test.tsx index 0b5e6db060d..6e81b23d90d 100644 --- a/packages/sanity/src/core/releases/tool/overview/__tests__/ReleasesOverview.test.tsx +++ b/packages/sanity/src/core/releases/tool/overview/__tests__/ReleasesOverview.test.tsx @@ -284,7 +284,7 @@ describe('ReleasesOverview', () => { const bundleRow = screen.getAllByTestId('table-row')[1] fireEvent.click(within(bundleRow).getByText('Bundle 1')) - expect(useRouter().navigate).toHaveBeenCalledWith({bundleId: 'b1abcdefg'}) + expect(useRouter().navigate).toHaveBeenCalledWith({releaseId: 'b1abcdefg'}) }) }) }) diff --git a/packages/sanity/src/core/releases/types/router.ts b/packages/sanity/src/core/releases/types/router.ts index 944c228dcec..864beb9f7f5 100644 --- a/packages/sanity/src/core/releases/types/router.ts +++ b/packages/sanity/src/core/releases/types/router.ts @@ -1,5 +1,5 @@ import {type RouterState} from 'sanity/router' export interface ReleasesRouterState extends RouterState { - bundleId?: string + releaseId?: string } From dc3400ce3470ed961a41232cbe8401c35b7cce44 Mon Sep 17 00:00:00 2001 From: pedrobonamin Date: Wed, 4 Sep 2024 17:10:19 +0200 Subject: [PATCH 3/3] chore(core): update DocumentPerspectiveMenu test --- .../DocumentPerspectiveMenu.test.tsx | 65 +++++++++---------- 1 file changed, 32 insertions(+), 33 deletions(-) diff --git a/packages/sanity/src/structure/panes/document/documentPanel/header/perspective/__tests__/DocumentPerspectiveMenu.test.tsx b/packages/sanity/src/structure/panes/document/documentPanel/header/perspective/__tests__/DocumentPerspectiveMenu.test.tsx index 176f26e6eed..987fe8588c0 100644 --- a/packages/sanity/src/structure/panes/document/documentPanel/header/perspective/__tests__/DocumentPerspectiveMenu.test.tsx +++ b/packages/sanity/src/structure/panes/document/documentPanel/header/perspective/__tests__/DocumentPerspectiveMenu.test.tsx @@ -1,7 +1,8 @@ import {beforeEach, describe, expect, it, jest} from '@jest/globals' -import {fireEvent, render, screen} from '@testing-library/react' +import {render, screen} from '@testing-library/react' +import {type HTMLProps} from 'react' import {type BundleDocument, usePerspective} from 'sanity' -import {useRouter} from 'sanity/router' +import {type IntentLinkProps} from 'sanity/router' import {createTestProvider} from '../../../../../../../../test/testUtils/TestProvider' import {type DocumentPaneContextValue} from '../../../../DocumentPaneContext' @@ -22,24 +23,34 @@ jest.mock('sanity', () => { } }) -jest.mock('sanity/router', () => ({ - useRouter: jest.fn().mockReturnValue({ - navigateIntent: jest.fn(), - stickyParams: {}, - }), - route: { - create: jest.fn(), - }, - IntentLink: jest.fn(), -})) +const IntentLinkMock = (props: IntentLinkProps & HTMLProps) => { + const {params = {}, intent, ...rest} = props + const stringParams = params + ? Object.entries(params) + .map(([key, value]) => `${key}=${value}`) + .join('&') + : '' + + return +} + +jest.mock('sanity/router', () => { + return { + useRouter: jest.fn().mockReturnValue({ + stickyParams: {}, + }), + route: { + create: jest.fn(), + }, + IntentLink: IntentLinkMock, + } +}) jest.mock('../../../../useDocumentPane') const mockUseDocumentPane = useDocumentPane as jest.MockedFunction< () => Partial > -const mockUseRouter = useRouter as jest.MockedFunction -const navigateIntent = mockUseRouter().navigateIntent as jest.Mock const mockUsePerspective = usePerspective as jest.Mock @@ -90,45 +101,33 @@ describe('DocumentPerspectiveMenu', () => { const wrapper = await createTestProvider() render(, {wrapper}) - expect(screen.getByTestId('button-document-release')).toBeInTheDocument() + const linkButton = screen.getByRole('link', {name: 'Spring Drop'}) + expect(linkButton).toBeInTheDocument() + expect(linkButton).toHaveAttribute('href', '/intent/release/id=spring-drop') + expect(linkButton).toHaveTextContent('Spring Drop') }) it('should not render the bundle badge if the document does not exist in the bundle', async () => { - mockUseDocumentPane.mockReturnValue({ - existsInBundle: false, - }) - - const wrapper = await createTestProvider() - render(, {wrapper}) - - expect(screen.queryByTestId('button-document-release')).toBeNull() - }) - - it('should navigate to the release intent when the bundle badge is clicked', async () => { mockUseDocumentPane.mockReturnValue({ documentVersions: [ { + _id: 'spring-drop', title: 'Spring Drop', hue: 'magenta', icon: 'heart-filled', _type: 'release', authorId: '', - _id: 'spring-drop', _createdAt: '', _updatedAt: '', _rev: '', }, ], - existsInBundle: true, + existsInBundle: false, }) const wrapper = await createTestProvider() render(, {wrapper}) - expect(screen.queryByTestId('button-document-release')).toBeInTheDocument() - fireEvent.click(screen.getByTestId('button-document-release')) - - expect(navigateIntent).toHaveBeenCalledTimes(1) - expect(navigateIntent).toHaveBeenCalledWith('release', {id: 'spring-drop'}) + expect(screen.queryByRole('link', {name: 'Spring Drop'})).toBeNull() }) })