Skip to content

Commit

Permalink
chore(tasks): move CommentsSetupProvider to core (#5767)
Browse files Browse the repository at this point in the history
* chore(tasks): move CommentsSetupProvider to core

* chore(core): rename commentsSetup to addOnDataset/setup

* chore(core): rename commentSetup to addonDataset

* chore(core): rename isRunningSetup to isCreatingDataset
  • Loading branch information
pedrobonamin authored Feb 23, 2024
1 parent 477b60c commit dbff227
Show file tree
Hide file tree
Showing 22 changed files with 215 additions and 208 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import {createContext} from 'react'

import {type AddonDatasetContextValue} from './types'

/**
* @beta
* @hidden
*/
export const AddonDatasetContext = createContext<AddonDatasetContextValue | null>(null)
130 changes: 130 additions & 0 deletions packages/sanity/src/core/studio/addonDataset/AddonDatasetProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import {type SanityClient} from '@sanity/client'
import {useCallback, useEffect, useMemo, useState} from 'react'

import {useClient} from '../../hooks'
import {DEFAULT_STUDIO_CLIENT_OPTIONS} from '../../studioClient'
import {useWorkspace} from '../workspace'
import {AddonDatasetContext} from './AddonDatasetContext'
import {type AddonDatasetContextValue} from './types'

const API_VERSION = 'v2023-11-13'

interface AddonDatasetSetupProviderProps {
children: React.ReactNode
}

/**
* This provider sets the addon dataset client, currently called `comments` dataset.
* It also exposes a `createAddonDataset` function that can be used to create the addon dataset if it does not exist.
* @beta
* @hidden
*/
export function AddonDatasetProvider(props: AddonDatasetSetupProviderProps) {
const {children} = props
const {dataset, projectId} = useWorkspace()
const originalClient = useClient(DEFAULT_STUDIO_CLIENT_OPTIONS)
const [addonDatasetClient, setAddonDatasetClient] = useState<SanityClient | null>(null)
const [isCreatingDataset, setIsCreatingDataset] = useState<boolean>(false)

const getAddonDatasetName = useCallback(async (): Promise<string | undefined> => {
const res = await originalClient.withConfig({apiVersion: API_VERSION}).request({
uri: `/projects/${projectId}/datasets?datasetProfile=comments&addonFor=${dataset}`,
tag: 'sanity.studio',
})

// The response is an array containing the addon dataset. We only expect
// one addon dataset to be returned, so we return the name of the first
// addon dataset in the array.
return res?.[0]?.name
}, [dataset, originalClient, projectId])

const handleCreateClient = useCallback(
(addonDatasetName: string) => {
const client = originalClient.withConfig({
apiVersion: API_VERSION,
dataset: addonDatasetName,
projectId,
requestTagPrefix: 'sanity.studio',
useCdn: false,
withCredentials: true,
})

return client
},
[originalClient, projectId],
)

const handleCreateAddonDataset = useCallback(async (): Promise<SanityClient | null> => {
setIsCreatingDataset(true)

// Before running the setup, we check if the addon dataset already exists.
// The addon dataset might already exist if another user has already run
// the setup, but the current user has not refreshed the page yet and
// therefore don't have a client for the addon dataset yet.
try {
const addonDatasetName = await getAddonDatasetName()

if (addonDatasetName) {
const client = handleCreateClient(addonDatasetName)
setAddonDatasetClient(client)
setIsCreatingDataset(false)
return client
}
} catch (_) {
// If the dataset does not exist we will get an error, but we can ignore
// it since we will create the dataset in the next step.
}

try {
// 1. Create the addon dataset
const res = await originalClient.withConfig({apiVersion: API_VERSION}).request({
uri: `/comments/${dataset}/setup`,
method: 'POST',
})

const datasetName = res?.datasetName

// 2. We can't continue if the addon dataset name is not returned
if (!datasetName) {
setIsCreatingDataset(false)
return null
}

// 3. Create a client for the addon dataset and set it in the context value
// so that the consumers can use it to execute comment operations and set up
// the real time listener for the addon dataset.
const client = handleCreateClient(datasetName)
setAddonDatasetClient(client)

// 4. Return the client so that the caller can use it to execute operations
return client
} catch (err) {
throw err
} finally {
setIsCreatingDataset(false)
}
}, [dataset, getAddonDatasetName, handleCreateClient, originalClient])

useEffect(() => {
// On mount, we check if the addon dataset already exists. If it does, we create
// a client for it and set it in the context value so that the consumers can use
// it to execute comment operations and set up the real time listener for the addon
// dataset.
getAddonDatasetName().then((addonDatasetName) => {
if (!addonDatasetName) return
const client = handleCreateClient(addonDatasetName)
setAddonDatasetClient(client)
})
}, [getAddonDatasetName, handleCreateClient])

const ctxValue = useMemo(
(): AddonDatasetContextValue => ({
client: addonDatasetClient,
createAddonDataset: handleCreateAddonDataset,
isCreatingDataset,
}),
[addonDatasetClient, handleCreateAddonDataset, isCreatingDataset],
)

return <AddonDatasetContext.Provider value={ctxValue}>{children}</AddonDatasetContext.Provider>
}
4 changes: 4 additions & 0 deletions packages/sanity/src/core/studio/addonDataset/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from './AddonDatasetContext'
export * from './AddonDatasetProvider'
export * from './types'
export * from './useAddonDataset'
17 changes: 17 additions & 0 deletions packages/sanity/src/core/studio/addonDataset/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import {type SanityClient} from '@sanity/client'

/**
* @beta
* @hidden
*/
export interface AddonDatasetContextValue {
/**
* Addon dataset client, currently called `comments` dataset.
*/
client: SanityClient | null
isCreatingDataset: boolean
/**
* Function to create the addon dataset if it does not exist.
*/
createAddonDataset: () => Promise<SanityClient | null>
}
18 changes: 18 additions & 0 deletions packages/sanity/src/core/studio/addonDataset/useAddonDataset.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import {useContext} from 'react'

import {AddonDatasetContext} from './AddonDatasetContext'
import {type AddonDatasetContextValue} from './types'

/**
* @beta
* @hidden
*/
export function useAddonDataset(): AddonDatasetContextValue {
const ctx = useContext(AddonDatasetContext)

if (!ctx) {
throw new Error('useAddonDataset: missing context value')
}

return ctx
}
1 change: 1 addition & 0 deletions packages/sanity/src/core/studio/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './activeWorkspaceMatcher'
export * from './addonDataset'
export * from './colorScheme'
export * from './components'
export * from './renderStudio'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ function CommentFieldInner(
const {
comments,
isCommentsOpen,
isRunningSetup,
isCreatingDataset,
mentionOptions,
onCommentsOpen,
operation,
Expand Down Expand Up @@ -262,7 +262,7 @@ function CommentFieldInner(
count={Number(count)}
currentUser={currentUser}
fieldTitle={fieldTitle}
isRunningSetup={isRunningSetup}
isCreatingDataset={isCreatingDataset}
mentionOptions={mentionOptions}
onChange={setValue}
onClick={handleClick}
Expand All @@ -286,7 +286,7 @@ function CommentFieldInner(
handleDiscard,
open,
value,
isRunningSetup,
isCreatingDataset,
hasComments,
],
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ interface CommentsFieldButtonProps {
count: number
currentUser: CurrentUser
fieldTitle: string
isRunningSetup: boolean
isCreatingDataset: boolean
mentionOptions: UserListWithPermissionsHookValue
onChange: (value: PortableTextBlock[]) => void
onClick?: () => void
Expand All @@ -52,7 +52,7 @@ export function CommentsFieldButton(props: CommentsFieldButtonProps) {
count,
currentUser,
fieldTitle,
isRunningSetup,
isCreatingDataset,
mentionOptions,
onChange,
onClick,
Expand Down Expand Up @@ -157,7 +157,7 @@ export function CommentsFieldButton(props: CommentsFieldButtonProps) {
onKeyDown={handleInputKeyDown}
onSubmit={handleSubmit}
placeholder={placeholder}
readOnly={isRunningSetup}
readOnly={isCreatingDataset}
ref={commentInputHandle}
value={value}
/>
Expand All @@ -178,7 +178,7 @@ export function CommentsFieldButton(props: CommentsFieldButtonProps) {
<div>
<Button
aria-label={t('field-button.aria-label-add')}
disabled={isRunningSetup}
disabled={isCreatingDataset}
icon={AddCommentIcon}
mode="bleed"
onClick={onClick}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ function CommentsInspectorInner(

const {isDismissed, setDismissed} = useCommentsOnboarding()

const {comments, getComment, isRunningSetup, mentionOptions, setStatus, status, operation} =
const {comments, getComment, isCreatingDataset, mentionOptions, setStatus, status, operation} =
useComments()

const {isTopLayer} = useLayer()
Expand Down Expand Up @@ -401,7 +401,7 @@ function CommentsInspectorInner(
onReactionSelect={handleReactionSelect}
onReply={handleReply}
onStatusChange={handleStatusChange}
readOnly={isRunningSetup}
readOnly={isCreatingDataset}
ref={commentsListHandleRef}
selectedPath={selectedPath}
status={status}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import {type LayoutProps, useFeatureEnabled} from 'sanity'
import {AddonDatasetProvider, type LayoutProps, useFeatureEnabled} from 'sanity'

import {ConditionalWrapper} from '../../../../ui-components/conditionalWrapper'
import {CommentsOnboardingProvider, CommentsSetupProvider, CommentsUpsellProvider} from '../../src'
import {CommentsOnboardingProvider, CommentsUpsellProvider} from '../../src'

export function CommentsStudioLayout(props: LayoutProps) {
const {enabled, isLoading} = useFeatureEnabled('studioComments')

return (
<CommentsSetupProvider>
<AddonDatasetProvider>
<CommentsOnboardingProvider>
<ConditionalWrapper
condition={!enabled && !isLoading}
Expand All @@ -17,6 +17,6 @@ export function CommentsStudioLayout(props: LayoutProps) {
{props.renderDefault(props)}
</ConditionalWrapper>
</CommentsOnboardingProvider>
</CommentsSetupProvider>
</AddonDatasetProvider>
)
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
/* eslint-disable react/jsx-handler-names */
import {useSelect, useString} from '@sanity/ui-workshop'
import {useMemo} from 'react'
import {useCurrentUser} from 'sanity'
import {AddonDatasetProvider, useCurrentUser} from 'sanity'

import {ConditionalWrapper} from '../../../../ui-components/conditionalWrapper'
import {CommentsList, CommentsUpsellPanel} from '../components'
import {
CommentsEnabledProvider,
CommentsProvider,
CommentsSetupProvider,
CommentsUpsellProvider,
} from '../context'
import {CommentsEnabledProvider, CommentsProvider, CommentsUpsellProvider} from '../context'
import {useComments, useCommentsUpsell} from '../hooks'
import {type CommentsUIMode} from '../types'

Expand All @@ -28,7 +23,7 @@ export default function CommentsProviderStory() {
const _mode = useSelect('_mode', MODES) || ('default' as keyof typeof MODES)

return (
<CommentsSetupProvider>
<AddonDatasetProvider>
<CommentsEnabledProvider documentType={_type} documentId={_id}>
<CommentsProvider documentType={_type} documentId={_id}>
<ConditionalWrapper
Expand All @@ -40,7 +35,7 @@ export default function CommentsProviderStory() {
</ConditionalWrapper>
</CommentsProvider>
</CommentsEnabledProvider>
</CommentsSetupProvider>
</AddonDatasetProvider>
)
}

Expand Down
Loading

0 comments on commit dbff227

Please sign in to comment.