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

fix: creating new release immediately pins as perspective #8620

Open
wants to merge 11 commits into
base: next
Choose a base branch
from
Open
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export interface ExcludedPerspectiveValue {
* @internal
*/
export function useExcludedPerspective(): ExcludedPerspectiveValue {
const {navigateStickyParams} = useRouter()
const {navigate} = useRouter()
const {excludedPerspectives} = usePerspective()

const toggleExcludedPerspective = useCallback(
Expand All @@ -29,9 +29,9 @@ export function useExcludedPerspective(): ExcludedPerspectiveValue {
? existingPerspectives.filter((id) => id !== excluded)
: [...existingPerspectives, excluded]

navigateStickyParams({excludedPerspectives: nextExcludedPerspectives.toString()})
navigate(null, {stickyParams: {excludedPerspectives: nextExcludedPerspectives.toString()}})
},
[excludedPerspectives, navigateStickyParams],
[excludedPerspectives, navigate],
)

const isPerspectiveExcluded = useCallback(
Expand Down
8 changes: 5 additions & 3 deletions packages/sanity/src/core/perspective/useSetPerspective.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ export function useSetPerspective() {
const router = useRouter()
const setPerspective = useCallback(
(releaseId: 'published' | 'drafts' | ReleaseId | undefined) => {
router.navigateStickyParams({
excludedPerspectives: '',
perspective: releaseId === 'drafts' ? '' : releaseId,
router.navigate(null, {
stickyParams: {
excludedPerspectives: '',
perspective: releaseId === 'drafts' ? '' : releaseId,
},
})
},
[router],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {type FormEvent, useCallback, useState} from 'react'

import {Button, Dialog} from '../../../../ui-components'
import {useTranslation} from '../../../i18n'
import {useSetPerspective} from '../../../perspective/useSetPerspective'
import {CreatedRelease, type OriginInfo} from '../../__telemetry__/releases.telemetry'
import {useCreateReleaseMetadata} from '../../hooks/useCreateReleaseMetadata'
import {releasesLocaleNamespace} from '../../i18n'
Expand All @@ -26,6 +27,7 @@ export function CreateReleaseDialog(props: CreateReleaseDialogProps): React.JSX.
const {onCancel, onSubmit, origin} = props
const toast = useToast()
const {createRelease} = useReleaseOperations()
const setPerspective = useSetPerspective()
const {t} = useTranslation()
const {t: tRelease} = useTranslation(releasesLocaleNamespace)
const telemetry = useTelemetry()
Expand Down Expand Up @@ -73,6 +75,8 @@ export function CreateReleaseDialog(props: CreateReleaseDialogProps): React.JSX.
await new Promise((resolve) => setTimeout(resolve, 1000))
// TODO: Remove the upper part

setPerspective(getReleaseIdFromReleaseDocumentId(release._id))

onSubmit(getReleaseIdFromReleaseDocumentId(release._id))
} catch (err) {
if (isReleaseLimitError(err)) {
Expand All @@ -97,6 +101,7 @@ export function CreateReleaseDialog(props: CreateReleaseDialogProps): React.JSX.
createRelease,
telemetry,
origin,
setPerspective,
onSubmit,
onCancel,
t,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,16 @@ export function ReleasesOverview() {
const handleOnCreateRelease = useCallback(
(createdReleaseId: string) => {
setIsCreateReleaseDialogOpen(false)
router.navigate({releaseId: createdReleaseId})

router.navigate(
{releaseId: createdReleaseId},
{
stickyParams: {
excludedPerspectives: '',
perspective: createdReleaseId,
},
},
)
},
[router],
)
Expand Down
17 changes: 13 additions & 4 deletions packages/sanity/src/router/RouteScope.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ export const RouteScope = function RouteScope(props: RouteScopeProps): React.JSX
}, [parentRouter.state])

const resolveNextParentState = useCallback(
(_nextState: RouterState) => {
const {_searchParams, ...nextState} = _nextState
(_nextState: RouterState | null) => {
const {_searchParams, ...nextState} = _nextState || {}
const nextParentState = addScope(parentStateRef.current, scope, nextState)
if (__unsafe_disableScopedSearchParams) {
// Move search params to parent scope
Expand All @@ -95,8 +95,17 @@ export const RouteScope = function RouteScope(props: RouteScopeProps): React.JSX
)

const navigate = useCallback(
(nextState: RouterState, options?: NavigateOptions) =>
parent_navigate(resolveNextParentState(nextState), options),
(nextState: RouterState | null, options?: NavigateOptions) =>
/**
* OH NO!! This isn't good
* There needs to be some special case to handle options.stickyParams
* But... not sure what
*/
parent_navigate(
// as in, if you are doing what navigateStickyParams does, then nextState is null
options?.stickyParams && nextState === null ? null : resolveNextParentState(nextState),
options,
),
[parent_navigate, resolveNextParentState],
)

Expand Down
64 changes: 39 additions & 25 deletions packages/sanity/src/router/RouterProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {RouterContext} from 'sanity/_singletons'
import {STICKY_PARAMS} from './stickyParams'
import {
type IntentParameters,
type NavigateBaseOptions,
type NavigateOptions,
type Router,
type RouterContextValue,
Expand Down Expand Up @@ -118,46 +119,40 @@ export function RouterProvider(props: RouterProviderProps): React.JSX.Element {
[routerProp, state],
)

const handleNavigateStickyParams = useCallback(
(params: Record<string, string | undefined>, options: NavigateOptions = {}) => {
const hasInvalidParam = Object.keys(params).some((param) => !STICKY_PARAMS.includes(param))
const navigate = useCallback(
(nextState: Record<string, unknown> | null, options: NavigateOptions = {}) => {
const currentParams = Array.isArray(state._searchParams) ? state._searchParams : []
const nextStickyParams =
options.stickyParams ??
Object.fromEntries(currentParams.filter(([key]) => STICKY_PARAMS.includes(key)))

const hasInvalidParam = Object.keys(nextStickyParams).some(
(param) => !STICKY_PARAMS.includes(param),
)
if (hasInvalidParam) {
throw new Error('One or more parameters are not sticky')
}

const allNextSearchParams = [...(state._searchParams || []), ...Object.entries(params)]

const searchParams = Object.entries(
allNextSearchParams.reduce<SearchParam>(
(deduppedSearchParams, [key, value]) => ({
...deduppedSearchParams,
[key]: value,
}),
[] as unknown as SearchParam,
),
)
const baseState = nextState ?? state
const nextParams = Array.isArray(baseState._searchParams) ? baseState._searchParams : []
const mergedParams = mergeStickyParams([...currentParams, ...nextParams], nextStickyParams)

// Trigger the navigation with updated _searchParams
onNavigate({
path: resolvePathFromState({
...state,
_searchParams: searchParams,
}),
path: resolvePathFromState({...baseState, _searchParams: mergedParams}),
replace: options.replace,
})
},
[onNavigate, resolvePathFromState, state],
)

const navigate = useCallback(
(nextState: Record<string, unknown>, options: NavigateOptions = {}) => {
onNavigate({path: resolvePathFromState(nextState), replace: options.replace})
},
[onNavigate, resolvePathFromState],
const handleNavigateStickyParams = useCallback(
(params: NavigateOptions['stickyParams'], options: NavigateBaseOptions = {}) =>
navigate(null, {stickyParams: params, ...options}),
[navigate],
)

const navigateIntent = useCallback(
(intentName: string, params?: IntentParameters, options: NavigateOptions = {}) => {
(intentName: string, params?: IntentParameters, options: NavigateBaseOptions = {}) => {
onNavigate({path: resolveIntentLink(intentName, params), replace: options.replace})
},
[onNavigate, resolveIntentLink],
Expand Down Expand Up @@ -212,6 +207,25 @@ function replaceStickyParam(
return value === undefined || value == '' ? filtered : [...filtered, [param, value]]
}

function mergeStickyParams(
currentParams: SearchParam[],
newParams?: Record<string, string | undefined>,
): SearchParam[] {
if (!newParams) return currentParams

// Remove old sticky params before merging new ones
const filteredParams = currentParams.filter(([key]) => !Object.hasOwn(newParams, key))

// Type guard function to filter out undefined values
const isValidSearchParam = (entry: [string, string | undefined]): entry is [string, string] =>
entry[1] !== undefined

// Convert newParams into the correct SearchParam format
const newEntries = Object.entries(newParams).filter(isValidSearchParam)

return [...filteredParams, ...newEntries]
}

function findParam(searchParams: SearchParam[], key: string): string | undefined {
const entry = searchParams.find(([k]) => k === key)
return entry ? entry[1] : undefined
Expand Down
Loading
Loading