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(releases, core): supporting banner display for remote deleted bundles #7371

Merged
merged 5 commits into from
Aug 19, 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
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import {CheckmarkIcon} from '@sanity/icons'
import {Box, Flex, Menu, MenuButton, MenuDivider, MenuItem, Spinner, Text} from '@sanity/ui'
import {type ReactElement, useCallback, useMemo} from 'react'
// eslint-disable-next-line no-restricted-imports -- MenuItem requires props, only supported by @sanity/ui
import {Box, Flex, Menu, MenuDivider, MenuItem, Spinner, Text} from '@sanity/ui'
import {memo, type ReactElement, useCallback, useMemo} from 'react'
import {styled} from 'styled-components'

import {Tooltip} from '../../../ui-components'
import {MenuButton, Tooltip} from '../../../ui-components'
import {useTranslation} from '../../i18n'
import {type BundleDocument} from '../../store/bundles/types'
import {useBundles} from '../../store/bundles/useBundles'
Expand Down Expand Up @@ -32,7 +33,7 @@ interface BundleListProps {
/**
* @internal
*/
export function BundleMenu(props: BundleListProps): JSX.Element {
export const BundlesMenu = memo(function BundlesMenu(props: BundleListProps): ReactElement {
const {bundles, loading, actions, button, perspective} = props
const {deletedBundles} = useBundles()
const {currentGlobalBundle, setPerspective} = usePerspective(perspective)
Expand Down Expand Up @@ -166,4 +167,4 @@ export function BundleMenu(props: BundleListProps): JSX.Element {
/>
</>
)
}
})
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import {beforeEach, describe, expect, it, jest} from '@jest/globals'
import {Button} from '@sanity/ui'
import {fireEvent, render, screen, within} from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import {act} from 'react'
import {type BundleDocument, useBundles} from 'sanity'

import {createTestProvider} from '../../../../../test/testUtils/TestProvider'
import {Button} from '../../../../ui-components'
import {usePerspective} from '../../hooks/usePerspective'
import {LATEST} from '../../util/const'
import {BundleMenu} from '../BundleMenu'
import {BundlesMenu} from '../BundlesMenu'

jest.mock('../../hooks/usePerspective', () => ({
usePerspective: jest.fn().mockReturnValue({
Expand All @@ -27,9 +27,9 @@ jest.mock('../../../store/bundles/useBundles', () => ({

const mockUseBundles = useBundles as jest.Mock<typeof useBundles>

describe('BundleMenu', () => {
describe('BundlesMenu', () => {
const mockUsePerspective = usePerspective as jest.Mock
const ButtonTest = <Button>Button Test</Button>
const ButtonTest = <Button text="Button Test" />
const mockBundles: BundleDocument[] = [
{
hue: 'magenta',
Expand Down Expand Up @@ -77,7 +77,7 @@ describe('BundleMenu', () => {

it('should render loading spinner when loading is true', async () => {
const wrapper = await createTestProvider()
render(<BundleMenu button={ButtonTest} bundles={[]} loading />, {
render(<BundlesMenu button={ButtonTest} bundles={[]} loading />, {
wrapper,
})

Expand All @@ -93,7 +93,7 @@ describe('BundleMenu', () => {

it('should render latest bundle menu item when bundles are null', async () => {
const wrapper = await createTestProvider()
render(<BundleMenu button={ButtonTest} bundles={null} loading={false} />, {
render(<BundlesMenu button={ButtonTest} bundles={null} loading={false} />, {
wrapper,
})

Expand All @@ -111,7 +111,7 @@ describe('BundleMenu', () => {
...bundle,
archivedAt: '2024-07-29T01:49:56.066Z',
}))
render(<BundleMenu button={ButtonTest} bundles={archivedBundles} loading={false} />, {
render(<BundlesMenu button={ButtonTest} bundles={archivedBundles} loading={false} />, {
wrapper,
})

Expand All @@ -130,7 +130,7 @@ describe('BundleMenu', () => {
})

const wrapper = await createTestProvider()
render(<BundleMenu button={ButtonTest} bundles={[]} loading={false} />, {
render(<BundlesMenu button={ButtonTest} bundles={[]} loading={false} />, {
wrapper,
})

Expand All @@ -149,7 +149,7 @@ describe('BundleMenu', () => {
})

const wrapper = await createTestProvider()
render(<BundleMenu button={ButtonTest} bundles={mockBundles} loading={false} />, {
render(<BundlesMenu button={ButtonTest} bundles={mockBundles} loading={false} />, {
wrapper,
})

Expand All @@ -163,7 +163,7 @@ describe('BundleMenu', () => {

it('should render bundle menu items when bundles are provided', async () => {
const wrapper = await createTestProvider()
render(<BundleMenu button={ButtonTest} bundles={mockBundles} loading={false} />, {
render(<BundlesMenu button={ButtonTest} bundles={mockBundles} loading={false} />, {
wrapper,
})

Expand All @@ -184,7 +184,7 @@ describe('BundleMenu', () => {
})

const wrapper = await createTestProvider()
render(<BundleMenu button={ButtonTest} bundles={mockBundles} loading={false} />, {
render(<BundlesMenu button={ButtonTest} bundles={mockBundles} loading={false} />, {
wrapper,
})

Expand All @@ -201,7 +201,7 @@ describe('BundleMenu', () => {

const wrapper = await createTestProvider()
render(
<BundleMenu button={ButtonTest} bundles={mockBundles} loading={false} actions={actions} />,
<BundlesMenu button={ButtonTest} bundles={mockBundles} loading={false} actions={actions} />,
{
wrapper,
},
Expand Down Expand Up @@ -229,7 +229,7 @@ describe('BundleMenu', () => {
},
})
const wrapper = await createTestProvider()
render(<BundleMenu button={ButtonTest} bundles={mockBundles} loading={false} />, {
render(<BundlesMenu button={ButtonTest} bundles={mockBundles} loading={false} />, {
wrapper,
})

Expand All @@ -256,7 +256,7 @@ describe('BundleMenu', () => {
})
const wrapper = await createTestProvider()
render(
<BundleMenu
<BundlesMenu
button={ButtonTest}
bundles={[
...mockBundles,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import {ArrowRightIcon} from '@sanity/icons'
import {Box, Button, Dialog, Flex, useToast} from '@sanity/ui'
import {Box, Flex, useToast} from '@sanity/ui'
import {type FormEvent, useCallback, useState} from 'react'
import {useTranslation} from 'sanity'

import {Button, Dialog} from '../../../../ui-components'
import {type BundleDocument} from '../../../store/bundles/types'
import {useBundleOperations} from '../../../store/bundles/useBundleOperations'
import {usePerspective} from '../../hooks/usePerspective'
Expand Down Expand Up @@ -90,20 +91,14 @@ export function BundleDetailsDialog(props: BundleDetailsDialogProps): JSX.Elemen
formAction === 'edit' ? t('bundle.dialog.edit.title') : t('bundle.dialog.create.title')

return (
<Dialog
animate
header={dialogTitle}
id="create-bundle-dialog"
onClose={onCancel}
zOffset={5000}
width={1}
>
<Dialog header={dialogTitle} id="create-bundle-dialog" onClose={onCancel} width={1}>
<form onSubmit={handleOnSubmit}>
<Box padding={6}>
<Box padding={4}>
<BundleForm onChange={handleOnChange} value={value} />
</Box>
<Flex justify="flex-end" padding={3}>
<Flex justify="flex-end" paddingTop={5}>
<Button
size="large"
disabled={!value.title?.trim() || isSubmitting}
iconRight={ArrowRightIcon}
type="submit"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,11 @@
import {COLOR_HUES, type ColorHueKey} from '@sanity/color'
import {icons, type IconSymbol, SearchIcon} from '@sanity/icons'
import {
Avatar,
Box,
Button,
Container,
Flex,
Popover,
Stack,
TextInput,
useClickOutside,
} from '@sanity/ui'
import {Avatar, Box, Container, Flex, Stack, TextInput, useClickOutside} from '@sanity/ui'
import {useCallback, useState} from 'react'
import {useTranslation} from 'sanity'
import {styled} from 'styled-components'

import {Button, Popover, TooltipDelayGroupProvider} from '../../../../ui-components'
import {type BundleDocument} from '../../../store/bundles/types'
import {BundleBadge} from '../BundleBadge'

Expand Down Expand Up @@ -75,18 +66,24 @@ export function BundleIconEditorPicker(props: {
content={
<Container data-testid="popover-content">
<Flex gap={1} padding={1}>
{COLOR_HUES.map((hue) => (
<Button
key={hue}
mode="bleed"
onClick={handleHueChange(hue)}
padding={1}
selected={value.hue === hue}
data-testid={`hue-button-${hue}`}
>
<Avatar color={hue} size={0} />
</Button>
))}
<TooltipDelayGroupProvider>
RitaDias marked this conversation as resolved.
Show resolved Hide resolved
{COLOR_HUES.map((hue) => (
<Button
tooltipProps={{content: hue.replace(/-/g, ' ')}}
key={hue}
mode="bleed"
onClick={handleHueChange(hue)}
paddingY={1}
style={{padding: 0}}
selected={value.hue === hue}
data-testid={`hue-button-${hue}`}
>
<Box style={{margin: '0 -4px'}}>
<Avatar color={hue} size={0} style={{padding: 0}} />
</Box>
</Button>
))}
</TooltipDelayGroupProvider>
</Flex>
<StyledStack>
<Box padding={1}>
Expand All @@ -101,18 +98,22 @@ export function BundleIconEditorPicker(props: {
/>
</Box>
<IconPickerFlex gap={1} overflow="auto" padding={1} wrap="wrap">
{Object.entries(icons)
.filter(([key]) => !iconSearchQuery || key.includes(iconSearchQuery.toLowerCase()))
.map(([key, icon]) => (
<Button
icon={icon}
key={key}
mode="bleed"
onClick={handleIconChange(key as IconSymbol)}
padding={2}
data-testId={`icon-button-${key}`}
/>
))}
<TooltipDelayGroupProvider>
{Object.entries(icons)
.filter(
([key]) => !iconSearchQuery || key.includes(iconSearchQuery.toLowerCase()),
)
.map(([key, icon]) => (
<Button
tooltipProps={{content: key.replace(/-/g, ' ')}}
icon={icon}
key={key}
mode="bleed"
onClick={handleIconChange(key as IconSymbol)}
data-testId={`icon-button-${key}`}
/>
))}
</TooltipDelayGroupProvider>
</IconPickerFlex>
</StyledStack>
</Container>
Expand All @@ -124,15 +125,17 @@ export function BundleIconEditorPicker(props: {
>
<div>
<Button
tooltipProps={{content: t('bundle.form.search-icon-tooltip')}}
mode="bleed"
onClick={handleOnPickerOpen}
padding={0}
ref={setButton}
selected={open}
radius="full"
style={{borderRadius: '50%'}}
data-testid="icon-picker-button"
>
<BundleBadge hue={value.hue} icon={value.icon} />
<Box style={{margin: -8}}>
<BundleBadge hue={value.hue} icon={value.icon} />
</Box>
</Button>
</div>
</Popover>
Expand Down
2 changes: 1 addition & 1 deletion packages/sanity/src/core/bundles/components/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export * from './BundleBadge'
export * from './BundleMenu'
export * from './BundlesMenu'
export * from './panes/BundleActions'
9 changes: 7 additions & 2 deletions packages/sanity/src/core/i18n/bundles/studio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,14 +115,15 @@ export const studioLocaleStrings = defineLocalesResources('studio', {
/** Text shown in usage dialog for an image asset when there are zero, one or more documents using the *unnamed* image **/
'asset-source.usage-list.documents-using-image_unnamed_zero': 'No documents are using this image',

/** Label when a release has been deleted by a different user */
'banners.deleted-bundle-banner.text':
"The '<strong>{{title}}</strong>' release has been deleted.",
/** Action message to add document to release */
'bundle.action.add-to-release': 'Add to {{title}}',
/** Action message for when document is already in release */
'bundle.action.already-in-release': 'Already in release {{title}}',
/** Action message for creating releases */
'bundle.action.create': 'Create release',
/** Label when a release has been deleted by a different user */
'bundle.deleted-toast-title': "The '<strong>{{title}}</strong>' release has been deleted",
/** Label for tooltip on deleted release */
'bundle.deleted-tooltip': 'This release has been deleted',
/** Title for creating releases dialog */
Expand All @@ -133,8 +134,12 @@ export const studioLocaleStrings = defineLocalesResources('studio', {
'bundle.form.description': 'Description',
/** Placeholder for the icon and colour picker */
'bundle.form.search-icon': 'Search icons',
/** Tooltip label for the icon display */
'bundle.form.search-icon-tooltip': 'Select release icon',
/** Label for the title form field when creating releases */
'bundle.form.title': 'Title',
/** Tooltip for the dropdown to show all versions of document */
'bundle.version-list.tooltip': 'See all document versions',

/** Action message for navigating to next month */
'calendar.action.go-to-next-month': 'Go to next month',
Expand Down
2 changes: 1 addition & 1 deletion packages/sanity/src/core/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export {
BundleActions,
BundleBadge,
BundleMenu,
BundlesMenu,
getBundleSlug,
getDocumentIsInPerspective,
LATEST,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import {
TrashIcon,
UnarchiveIcon,
} from '@sanity/icons'
import {Button, Menu, MenuButton, Spinner, Text, useToast} from '@sanity/ui'
import {Menu, Spinner, Text, useToast} from '@sanity/ui'
import {useState} from 'react'
import {useTranslation} from 'sanity'
import {useRouter} from 'sanity/router'

import {Dialog, MenuItem} from '../../../../ui-components'
import {Button, Dialog, MenuButton, MenuItem} from '../../../../ui-components'
import {BundleDetailsDialog} from '../../../bundles/components/dialog/BundleDetailsDialog'
import {type BundleDocument} from '../../../store/bundles/types'
import {useBundleOperations} from '../../../store/bundles/useBundleOperations'
Expand Down Expand Up @@ -80,7 +80,7 @@ export const BundleMenuButton = ({disabled, bundle, documentCount}: BundleMenuBu
disabled={bundleMenuDisabled || isPerformingOperation}
icon={isPerformingOperation ? Spinner : EllipsisHorizontalIcon}
mode="bleed"
padding={2}
tooltipProps={{content: t('menu.tooltip')}}
aria-label={t('menu.label')}
data-testid="release-menu-button"
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import {ErrorOutlineIcon} from '@sanity/icons'
import {type PreviewValue} from '@sanity/types'
import {Card, Text, Tooltip} from '@sanity/ui'
import {Card, Text} from '@sanity/ui'
import {type ForwardedRef, forwardRef, useMemo} from 'react'
import {DocumentPreviewPresence, useDocumentPresence} from 'sanity'
import {IntentLink} from 'sanity/router'

import {Tooltip} from '../../../ui-components'
import {useTranslation} from '../../i18n'
import {SanityDefaultPreview} from '../../preview/components/SanityDefaultPreview'
import {getPublishedId} from '../../util/draftUtils'
Expand Down
Loading
Loading