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 overview facelift and calendar added #7657

Merged
merged 15 commits into from
Oct 23, 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
4 changes: 2 additions & 2 deletions packages/sanity/src/core/i18n/bundles/studio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1144,8 +1144,8 @@ export const studioLocaleStrings = defineLocalesResources('studio', {
'release.action.already-in-release': 'Already in release {{title}}',
/** Action message for when you click to view all versions you can copy the current document to */
'release.action.copy-to': 'Copy version to',
/** Action message for creating releases */
'release.action.create': 'Create release',
/** Action message for creating new releases */
'release.action.create-new': 'New release',
/** Action message for when document is already in release */
'release.action.discard-version': 'Discard version',
/** Description for toast when version discarding failed */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {Flex, Stack, Text, TextArea, TextInput} from '@sanity/ui'
import {useCallback, useMemo, useState} from 'react'

import {Button} from '../../../../ui-components'
import {MONTH_PICKER_VARIANT} from '../../../../ui-components/inputs/DateInputs/calendar/Calendar'
import {type CalendarLabels} from '../../../../ui-components/inputs/DateInputs/calendar/types'
import {DateTimeInput} from '../../../../ui-components/inputs/DateInputs/DateTimeInput'
import {FormFieldHeaderText} from '../../../form'
Expand Down Expand Up @@ -132,6 +133,7 @@ export function ReleaseForm(props: {
{buttonReleaseType === 'scheduled' && (
<DateTimeInput
selectTime
monthPickerVariant={MONTH_PICKER_VARIANT.carousel}
onChange={handleBundlePublishAtChange}
calendarLabels={calendarLabels}
value={publishAt ? new Date(publishAt) : undefined}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import {type ReleasesMetadata} from '../../store/release/useReleasesMetadata'
*/
export interface ReleasesMetadataContextValue {
state: MetadataWrapper
addBundleIdsToListener: (slugs: string[]) => void
removeBundleIdsFromListener: (slugs: string[]) => void
addReleaseIdsToListener: (slugs: string[]) => void
removeReleaseIdsFromListener: (slugs: string[]) => void
}

const DEFAULT_METADATA_STATE: MetadataWrapper = {
Expand All @@ -21,46 +21,46 @@ const DEFAULT_METADATA_STATE: MetadataWrapper = {
loading: false,
}

const BundlesMetadataProviderInner = ({children}: {children: React.ReactNode}) => {
const [listenerBundleIds, setListenerBundleIds] = useState<string[]>([])
const ReleasesMetadataProviderInner = ({children}: {children: React.ReactNode}) => {
const [listenerReleaseIds, setListenerReleaseIds] = useState<string[]>([])
const {getMetadataStateForSlugs$} = useReleasesStore()
const [releasesMetadata, setBundlesMetadata] = useState<Record<string, ReleasesMetadata> | null>(
const [releasesMetadata, setReleasesMetadata] = useState<Record<string, ReleasesMetadata> | null>(
null,
)

const memoObservable = useMemo(
() => getMetadataStateForSlugs$(listenerBundleIds),
[getMetadataStateForSlugs$, listenerBundleIds],
() => getMetadataStateForSlugs$(listenerReleaseIds.map((slug) => slug.split('.')[1])),
[getMetadataStateForSlugs$, listenerReleaseIds],
)

const observedResult = useObservable(memoObservable) || DEFAULT_METADATA_STATE

// patch metadata in local state
useEffect(
() =>
setBundlesMetadata((prevBundleMetadata) => {
if (!observedResult.data) return prevBundleMetadata
setReleasesMetadata((prevReleaseMetadata) => {
if (!observedResult.data) return prevReleaseMetadata

return {...(prevBundleMetadata || {}), ...observedResult.data}
return {...(prevReleaseMetadata || {}), ...observedResult.data}
}),
[observedResult.data],
)

const addBundleIdsToListener = useCallback((addBundleIds: (string | undefined)[]) => {
setListenerBundleIds((prevSlugs) => [
const addReleaseIdsToListener = useCallback((addReleaseIds: (string | undefined)[]) => {
setListenerReleaseIds((prevSlugs) => [
...prevSlugs,
...addBundleIds.filter((releaseId): releaseId is string => typeof releaseId === 'string'),
...addReleaseIds.filter((releaseId): releaseId is string => typeof releaseId === 'string'),
])
}, [])

const removeBundleIdsFromListener = useCallback((releaseIds: string[]) => {
setListenerBundleIds((prevSlugs) => {
const removeReleaseIdsFromListener = useCallback((releaseIds: string[]) => {
setListenerReleaseIds((prevSlugs) => {
const {nextSlugs} = prevSlugs.reduce<{removedSlugs: string[]; nextSlugs: string[]}>(
(acc, slug) => {
const {removedSlugs, nextSlugs: accNextSlugs} = acc
/**
* In cases where multiple consumers are listening to the same release id
* the release id will appear multiple times in listenerBundleIds array
* the release id will appear multiple times in listenerReleaseIds array
* removing should only remove 1 instance of the slug and retain all others
*/
if (releaseIds.includes(slug) && !removedSlugs.includes(slug)) {
Expand All @@ -75,39 +75,39 @@ const BundlesMetadataProviderInner = ({children}: {children: React.ReactNode}) =
}, [])

const context = useMemo<{
addBundleIdsToListener: (slugs: string[]) => void
removeBundleIdsFromListener: (slugs: string[]) => void
addReleaseIdsToListener: (slugs: string[]) => void
removeReleaseIdsFromListener: (slugs: string[]) => void
state: MetadataWrapper
}>(
() => ({
addBundleIdsToListener: addBundleIdsToListener,
removeBundleIdsFromListener: removeBundleIdsFromListener,
addReleaseIdsToListener: addReleaseIdsToListener,
removeReleaseIdsFromListener: removeReleaseIdsFromListener,
state: {...observedResult, data: releasesMetadata},
}),
[addBundleIdsToListener, releasesMetadata, observedResult, removeBundleIdsFromListener],
[addReleaseIdsToListener, releasesMetadata, observedResult, removeReleaseIdsFromListener],
)

return (
<ReleasesMetadataContext.Provider value={context}>{children}</ReleasesMetadataContext.Provider>
)
}

export const BundlesMetadataProvider = ({children}: {children: React.ReactNode}) => {
export const ReleasesMetadataProvider = ({children}: {children: React.ReactNode}) => {
const context = useContext(ReleasesMetadataContext)

// Avoid mounting the provider if it's already provided by a parent
if (context) return children
return <BundlesMetadataProviderInner>{children}</BundlesMetadataProviderInner>
return <ReleasesMetadataProviderInner>{children}</ReleasesMetadataProviderInner>
}

export const useBundlesMetadataProvider = (): ReleasesMetadataContextValue => {
export const useReleasesMetadataProvider = (): ReleasesMetadataContextValue => {
const contextValue = useContext(ReleasesMetadataContext)

return (
contextValue || {
state: DEFAULT_METADATA_STATE,
addBundleIdsToListener: () => null,
removeBundleIdsFromListener: () => null,
addReleaseIdsToListener: () => null,
removeReleaseIdsFromListener: () => null,
}
)
}
16 changes: 12 additions & 4 deletions packages/sanity/src/core/releases/i18n/resources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,14 @@ const releasesLocaleStrings = {
'discard-version-dialog.header': 'Are you sure you want to discard the document version?',
/** Title for dialog for discarding a version of a document */
'discard-version-dialog.title': 'Discard version',
/** Label for the count of added documents in to a release */
'document-count.added': '{{count}} added documents',
/** Label for the count of added documents in to a release when only 1 document added*/
'document-count.added-singular': '{{count}} added document',
/** Label for the count of changed documents in a release */
'document-count.changed': '{{count}} changed documents',
/** Label for the count of changed documents in a release when only 1 document changed */
'document-count.changed-singular': '{{count}} changed document',
/** Text for when documents of a release are loading */
'document-loading': 'Loading documents',
/** Label for when documents in release have validation warnings */
Expand Down Expand Up @@ -141,18 +149,18 @@ const releasesLocaleStrings = {

/** Header for the document table in the release tool - contributors */
'table-header.contributors': 'Contributors',
/** Header for the document table in the release tool - created */
'table-header.created': 'Created',
/** Header for the document table in the release tool - type */
'table-header.type': 'Type',
/** Header for the document table in the release tool - release title */
'table-header.title': 'Release',
/** Header for the document table in the release tool - action */
'table-header.action': 'Action',
/** Header for the document table in the release tool - title */
'table-header.documents': 'Documents',
/** Header for the document table in the release tool - edited */
'table-header.edited': 'Edited',
/** Header for the document table in the release tool - published */
'table-header.published': 'Published',
/** Header for the document table in the release tool - time */
'table-header.time': 'Time',
/** Text for toast when release failed to publish */
'toast.error': "Failed to publish the '<strong>{{title}}</strong>'",
/** Text for toast when release has been published */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ export function GlobalPerspectiveMenu(): JSX.Element {
<MenuItem
icon={AddIcon}
onClick={handleCreateBundleClick}
text={t('release.action.create')}
text={t('release.action.create-new')}
/>
</>
</>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {type LayoutProps} from '../../config'
import {AddonDatasetProvider} from '../../studio'
import {BundlesMetadataProvider} from '../contexts/ReleasesMetadataProvider'
import {ReleasesMetadataProvider} from '../contexts/ReleasesMetadataProvider'

export function ReleasesStudioLayout(props: LayoutProps) {
// TODO: Replace for useReleasesEnabled
Expand All @@ -12,7 +12,7 @@ export function ReleasesStudioLayout(props: LayoutProps) {

return (
<AddonDatasetProvider>
<BundlesMetadataProvider>{props.renderDefault(props)}</BundlesMetadataProvider>
<ReleasesMetadataProvider>{props.renderDefault(props)}</ReleasesMetadataProvider>
</AddonDatasetProvider>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ export const ReleaseMenuButton = ({disabled, release}: ReleaseMenuButtonProps) =
fallbackPlacements: ['top-end'],
placement: 'bottom',
portal: true,
tone: 'default',
}}
/>
{selectedAction === 'edit' && (
Expand Down
18 changes: 5 additions & 13 deletions packages/sanity/src/core/releases/tool/components/Table/Table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import {
useMemo,
useRef,
} from 'react'
import {styled} from 'styled-components'

import {TooltipDelayGroupProvider} from '../../../../../ui-components'
import {LoadingBlock} from '../../../../components'
Expand Down Expand Up @@ -51,19 +50,9 @@ export interface TableProps<TableData, AdditionalRowTableData> {
}) => ReactNode
rowProps?: (datum: TableData) => Partial<TableRowProps>
scrollContainerRef: MutableRefObject<HTMLDivElement | null>
hideTableInlinePadding?: boolean
}

const CustomCard = styled(Card)`
display: flex;
max-width: 1200px;
margin: 0 auto;
::before {
content: '';
display: block;
border: 1px solid red;
position: absolute;
}
`
const ITEM_HEIGHT = 59

/**
Expand Down Expand Up @@ -103,6 +92,7 @@ const TableInner = <TableData, AdditionalRowTableData>({
loading = false,
rowProps = () => ({}),
scrollContainerRef,
hideTableInlinePadding = false,
}: TableProps<TableData, AdditionalRowTableData>) => {
const {searchTerm, sort} = useTableContext()
const virtualizerContainerRef = useRef<HTMLDivElement | null>(null)
Expand Down Expand Up @@ -242,6 +232,8 @@ const TableInner = <TableData, AdditionalRowTableData>({
return <LoadingBlock fill data-testid="table-loading" />
}

const maxInlineSize = (!hideTableInlinePadding && theme.sanity.v2?.container[3]) || 0

return (
<div ref={virtualizerContainerRef}>
<div
Expand All @@ -252,7 +244,7 @@ const TableInner = <TableData, AdditionalRowTableData>({
'paddingBottom': '110px',
'width': '100%',
'position': 'relative',
'--maxInlineSize': rem(theme.sanity.v2?.container[3] ?? 0),
'--maxInlineSize': rem(maxInlineSize),
'--paddingInline': rem(theme.sanity.v2?.space[3] ?? 0),
} as CSSProperties
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ const TableHeaderSearch = ({
*/
export const TableHeader = ({headers, searchDisabled}: TableHeaderProps) => {
return (
<Card as="thead" borderTop borderBottom>
<Card as="thead" borderBottom>
<Flex
as="tr"
style={{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {Card} from '@sanity/ui'
import {type RefObject, useCallback, useMemo} from 'react'

import {useTranslation} from '../../../i18n'
Expand Down Expand Up @@ -66,7 +67,7 @@ export function ReleaseSummary(props: ReleaseSummaryProps) {
)

return (
<>
<Card borderTop ref={scrollContainerRef}>
<Table<DocumentWithHistory>
data={aggregatedData}
emptyState={t('summary.no-documents')}
Expand All @@ -78,6 +79,6 @@ export function ReleaseSummary(props: ReleaseSummaryProps) {
rowProps={getRowProps}
scrollContainerRef={scrollContainerRef}
/>
</>
</Card>
)
}
Loading
Loading