@sanity/sdk-react 0.0.0-alpha.20 → 0.0.0-alpha.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +276 -207
- package/dist/index.js +90 -75
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/_exports/index.ts +11 -11
- package/src/components/Login/LoginLinks.test.tsx +2 -2
- package/src/components/Login/LoginLinks.tsx +2 -2
- package/src/components/auth/AuthBoundary.test.tsx +2 -2
- package/src/components/auth/LoginCallback.test.tsx +3 -3
- package/src/components/auth/LoginCallback.tsx +4 -4
- package/src/hooks/auth/useCurrentUser.tsx +1 -0
- package/src/hooks/auth/useHandleAuthCallback.test.tsx +16 -0
- package/src/hooks/auth/{useHandleCallback.tsx → useHandleAuthCallback.tsx} +6 -6
- package/src/hooks/auth/useLogOut.test.tsx +2 -2
- package/src/hooks/client/useClient.ts +1 -0
- package/src/hooks/comlink/useManageFavorite.test.ts +9 -4
- package/src/hooks/comlink/useManageFavorite.ts +42 -13
- package/src/hooks/comlink/useRecordDocumentHistoryEvent.test.ts +7 -3
- package/src/hooks/comlink/useRecordDocumentHistoryEvent.ts +39 -12
- package/src/hooks/dashboard/useNavigateToStudioDocument.test.ts +178 -0
- package/src/hooks/dashboard/useNavigateToStudioDocument.ts +31 -5
- package/src/hooks/dashboard/useStudioWorkspacesByResourceId.test.tsx +5 -1
- package/src/hooks/dashboard/useStudioWorkspacesByResourceId.ts +4 -3
- package/src/hooks/datasets/useDatasets.ts +6 -3
- package/src/hooks/document/useApplyDocumentActions.test.ts +25 -0
- package/src/hooks/document/{useApplyActions.ts → useApplyDocumentActions.ts} +13 -12
- package/src/hooks/document/{usePermissions.ts → useDocumentPermissions.ts} +8 -6
- package/src/hooks/document/useDocumentSyncStatus.ts +4 -1
- package/src/hooks/document/useEditDocument.test.ts +8 -8
- package/src/hooks/document/useEditDocument.ts +2 -2
- package/src/hooks/{infiniteList/useInfiniteList.test.tsx → documents/useDocuments.test.tsx} +9 -9
- package/src/hooks/{infiniteList/useInfiniteList.ts → documents/useDocuments.ts} +10 -10
- package/src/hooks/{paginatedList/usePaginatedList.test.tsx → paginatedDocuments/usePaginatedDocuments.test.tsx} +14 -14
- package/src/hooks/{paginatedList/usePaginatedList.ts → paginatedDocuments/usePaginatedDocuments.ts} +7 -7
- package/src/hooks/preview/usePreview.tsx +2 -2
- package/src/hooks/projection/useProjection.ts +2 -2
- package/src/hooks/projects/useProject.ts +4 -1
- package/src/hooks/projects/useProjects.ts +7 -3
- package/src/hooks/auth/useHandleCallback.test.tsx +0 -16
- package/src/hooks/document/useApplyActions.test.ts +0 -25
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sanity/sdk-react",
|
|
3
|
-
"version": "0.0.0-alpha.
|
|
3
|
+
"version": "0.0.0-alpha.21",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Sanity SDK React toolkit for Content OS",
|
|
6
6
|
"keywords": [
|
|
@@ -43,11 +43,11 @@
|
|
|
43
43
|
"prettier": "@sanity/prettier-config",
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"@sanity/logos": "^2.1.13",
|
|
46
|
-
"@sanity/message-protocol": "^0.
|
|
46
|
+
"@sanity/message-protocol": "^0.6.0",
|
|
47
47
|
"@sanity/types": "^3.78.1",
|
|
48
48
|
"react-error-boundary": "^5.0.0",
|
|
49
49
|
"rxjs": "^7.8.1",
|
|
50
|
-
"@sanity/sdk": "0.0.0-alpha.
|
|
50
|
+
"@sanity/sdk": "0.0.0-alpha.20"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@sanity/browserslist-config": "^1.0.5",
|
package/src/_exports/index.ts
CHANGED
|
@@ -7,7 +7,7 @@ export {useAuthState} from '../hooks/auth/useAuthState'
|
|
|
7
7
|
export {useAuthToken} from '../hooks/auth/useAuthToken'
|
|
8
8
|
export {useCurrentUser} from '../hooks/auth/useCurrentUser'
|
|
9
9
|
export {useDashboardOrganizationId} from '../hooks/auth/useDashboardOrganizationId'
|
|
10
|
-
export {
|
|
10
|
+
export {useHandleAuthCallback} from '../hooks/auth/useHandleAuthCallback'
|
|
11
11
|
export {useLoginUrls} from '../hooks/auth/useLoginUrls'
|
|
12
12
|
export {useLogOut} from '../hooks/auth/useLogOut'
|
|
13
13
|
export {useClient} from '../hooks/client/useClient'
|
|
@@ -29,22 +29,22 @@ export {useSanityInstance} from '../hooks/context/useSanityInstance'
|
|
|
29
29
|
export {useNavigateToStudioDocument} from '../hooks/dashboard/useNavigateToStudioDocument'
|
|
30
30
|
export {useStudioWorkspacesByResourceId} from '../hooks/dashboard/useStudioWorkspacesByResourceId'
|
|
31
31
|
export {useDatasets} from '../hooks/datasets/useDatasets'
|
|
32
|
-
export {
|
|
32
|
+
export {useApplyDocumentActions} from '../hooks/document/useApplyDocumentActions'
|
|
33
33
|
export {useDocument} from '../hooks/document/useDocument'
|
|
34
34
|
export {useDocumentEvent} from '../hooks/document/useDocumentEvent'
|
|
35
|
+
export {useDocumentPermissions} from '../hooks/document/useDocumentPermissions'
|
|
35
36
|
export {useDocumentSyncStatus} from '../hooks/document/useDocumentSyncStatus'
|
|
36
37
|
export {useEditDocument} from '../hooks/document/useEditDocument'
|
|
37
|
-
export {usePermissions} from '../hooks/document/usePermissions'
|
|
38
38
|
export {
|
|
39
|
-
type
|
|
40
|
-
type
|
|
41
|
-
|
|
42
|
-
} from '../hooks/
|
|
39
|
+
type DocumentsOptions,
|
|
40
|
+
type DocumentsResponse,
|
|
41
|
+
useDocuments,
|
|
42
|
+
} from '../hooks/documents/useDocuments'
|
|
43
43
|
export {
|
|
44
|
-
type
|
|
45
|
-
type
|
|
46
|
-
|
|
47
|
-
} from '../hooks/
|
|
44
|
+
type PaginatedDocumentsOptions,
|
|
45
|
+
type PaginatedDocumentsResponse,
|
|
46
|
+
usePaginatedDocuments,
|
|
47
|
+
} from '../hooks/paginatedDocuments/usePaginatedDocuments'
|
|
48
48
|
export {
|
|
49
49
|
usePreview,
|
|
50
50
|
type UsePreviewOptions,
|
|
@@ -36,8 +36,8 @@ vi.mock('../../hooks/auth/useAuthState', () => ({
|
|
|
36
36
|
useAuthState: vi.fn(() => 'logged-out'),
|
|
37
37
|
}))
|
|
38
38
|
|
|
39
|
-
vi.mock('../../hooks/auth/
|
|
40
|
-
|
|
39
|
+
vi.mock('../../hooks/auth/useHandleAuthCallback', () => ({
|
|
40
|
+
useHandleAuthCallback: vi.fn(),
|
|
41
41
|
}))
|
|
42
42
|
|
|
43
43
|
describe('LoginLinks', () => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {type ReactElement} from 'react'
|
|
2
2
|
|
|
3
3
|
import {useAuthState} from '../../hooks/auth/useAuthState'
|
|
4
|
-
import {
|
|
4
|
+
import {useHandleAuthCallback} from '../../hooks/auth/useHandleAuthCallback'
|
|
5
5
|
import {useLoginUrls} from '../../hooks/auth/useLoginUrls'
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -26,7 +26,7 @@ import {useLoginUrls} from '../../hooks/auth/useLoginUrls'
|
|
|
26
26
|
export const LoginLinks = (): ReactElement => {
|
|
27
27
|
const loginUrls = useLoginUrls()
|
|
28
28
|
const authState = useAuthState()
|
|
29
|
-
|
|
29
|
+
useHandleAuthCallback()
|
|
30
30
|
|
|
31
31
|
if (authState.type === 'logging-in') {
|
|
32
32
|
return <div className="sc-login-links__logging-in">Logging in...</div>
|
|
@@ -13,8 +13,8 @@ vi.mock('../../hooks/auth/useAuthState', () => ({
|
|
|
13
13
|
vi.mock('../../hooks/auth/useLoginUrls', () => ({
|
|
14
14
|
useLoginUrls: vi.fn(() => [{title: 'Provider A', url: 'https://provider-a.com/auth'}]),
|
|
15
15
|
}))
|
|
16
|
-
vi.mock('../../hooks/auth/
|
|
17
|
-
|
|
16
|
+
vi.mock('../../hooks/auth/useHandleAuthCallback', () => ({
|
|
17
|
+
useHandleAuthCallback: vi.fn(() => async () => {}),
|
|
18
18
|
}))
|
|
19
19
|
vi.mock('../../hooks/auth/useLogOut', () => ({
|
|
20
20
|
useLogOut: vi.fn(() => async () => {}),
|
|
@@ -3,9 +3,9 @@ import {afterAll, beforeAll, beforeEach, describe, expect, it, vi} from 'vitest'
|
|
|
3
3
|
|
|
4
4
|
import {renderWithWrappers} from './authTestHelpers'
|
|
5
5
|
|
|
6
|
-
// Mock `
|
|
7
|
-
vi.mock('../../hooks/auth/
|
|
8
|
-
|
|
6
|
+
// Mock `useHandleAuthCallback`
|
|
7
|
+
vi.mock('../../hooks/auth/useHandleAuthCallback', () => ({
|
|
8
|
+
useHandleAuthCallback: vi.fn(() => async (url: string) => {
|
|
9
9
|
const parsedUrl = new URL(url)
|
|
10
10
|
const sid = new URLSearchParams(parsedUrl.hash.slice(1)).get('sid')
|
|
11
11
|
if (sid === 'valid') {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {useEffect} from 'react'
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {useHandleAuthCallback} from '../../hooks/auth/useHandleAuthCallback'
|
|
4
4
|
import {LoginLayout, type LoginLayoutProps} from './LoginLayout'
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -12,18 +12,18 @@ import {LoginLayout, type LoginLayoutProps} from './LoginLayout'
|
|
|
12
12
|
* @alpha
|
|
13
13
|
*/
|
|
14
14
|
export function LoginCallback({header, footer}: LoginLayoutProps): React.ReactNode {
|
|
15
|
-
const
|
|
15
|
+
const handleAuthCallback = useHandleAuthCallback()
|
|
16
16
|
|
|
17
17
|
useEffect(() => {
|
|
18
18
|
const url = new URL(location.href)
|
|
19
|
-
|
|
19
|
+
handleAuthCallback(url.toString()).then((replacementLocation) => {
|
|
20
20
|
if (replacementLocation) {
|
|
21
21
|
// history API with `replaceState` is used to prevent a reload but still
|
|
22
22
|
// remove the short-lived token from the URL
|
|
23
23
|
history.replaceState(null, '', replacementLocation)
|
|
24
24
|
}
|
|
25
25
|
})
|
|
26
|
-
}, [
|
|
26
|
+
}, [handleAuthCallback])
|
|
27
27
|
|
|
28
28
|
return (
|
|
29
29
|
<LoginLayout header={header} footer={footer}>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {handleAuthCallback} from '@sanity/sdk'
|
|
2
|
+
import {identity} from 'rxjs'
|
|
3
|
+
import {describe, it} from 'vitest'
|
|
4
|
+
|
|
5
|
+
import {createCallbackHook} from '../helpers/createCallbackHook'
|
|
6
|
+
|
|
7
|
+
vi.mock('../helpers/createCallbackHook', () => ({createCallbackHook: vi.fn(identity)}))
|
|
8
|
+
vi.mock('@sanity/sdk', () => ({handleAuthCallback: vi.fn()}))
|
|
9
|
+
|
|
10
|
+
describe('useHandleAuthCallback', () => {
|
|
11
|
+
it('calls `createCallbackHook` with `handleAuthCallback`', async () => {
|
|
12
|
+
const {useHandleAuthCallback} = await import('./useHandleAuthCallback')
|
|
13
|
+
expect(createCallbackHook).toHaveBeenCalledWith(handleAuthCallback)
|
|
14
|
+
expect(useHandleAuthCallback).toBe(handleAuthCallback)
|
|
15
|
+
})
|
|
16
|
+
})
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {handleAuthCallback} from '@sanity/sdk'
|
|
2
2
|
|
|
3
3
|
import {createCallbackHook} from '../helpers/createCallbackHook'
|
|
4
4
|
|
|
@@ -10,7 +10,7 @@ import {createCallbackHook} from '../helpers/createCallbackHook'
|
|
|
10
10
|
* This hook provides access to the authentication store's callback handler,
|
|
11
11
|
* which processes auth redirects by extracting the session ID and fetching the
|
|
12
12
|
* authentication token. If fetching the long-lived token is successful,
|
|
13
|
-
* `
|
|
13
|
+
* `handleAuthCallback` will return a Promise that resolves a new location that
|
|
14
14
|
* removes the short-lived token from the URL. Use this in combination with
|
|
15
15
|
* `history.replaceState` or your own router's `replace` function to update the
|
|
16
16
|
* current location without triggering a reload.
|
|
@@ -18,13 +18,13 @@ import {createCallbackHook} from '../helpers/createCallbackHook'
|
|
|
18
18
|
* @example
|
|
19
19
|
* ```tsx
|
|
20
20
|
* function AuthCallback() {
|
|
21
|
-
* const
|
|
21
|
+
* const handleAuthCallback = useHandleAuthCallback()
|
|
22
22
|
* const router = useRouter() // Example router
|
|
23
23
|
*
|
|
24
24
|
* useEffect(() => {
|
|
25
25
|
* async function processCallback() {
|
|
26
26
|
* // Handle the callback and get the cleaned URL
|
|
27
|
-
* const newUrl = await
|
|
27
|
+
* const newUrl = await handleAuthCallback(window.location.href)
|
|
28
28
|
*
|
|
29
29
|
* if (newUrl) {
|
|
30
30
|
* // Replace URL without triggering navigation
|
|
@@ -33,7 +33,7 @@ import {createCallbackHook} from '../helpers/createCallbackHook'
|
|
|
33
33
|
* }
|
|
34
34
|
*
|
|
35
35
|
* processCallback().catch(console.error)
|
|
36
|
-
* }, [
|
|
36
|
+
* }, [handleAuthCallback, router])
|
|
37
37
|
*
|
|
38
38
|
* return <div>Completing login...</div>
|
|
39
39
|
* }
|
|
@@ -42,4 +42,4 @@ import {createCallbackHook} from '../helpers/createCallbackHook'
|
|
|
42
42
|
* @returns A callback handler function that processes OAuth redirects
|
|
43
43
|
* @public
|
|
44
44
|
*/
|
|
45
|
-
export const
|
|
45
|
+
export const useHandleAuthCallback = createCallbackHook(handleAuthCallback)
|
|
@@ -7,8 +7,8 @@ import {createCallbackHook} from '../helpers/createCallbackHook'
|
|
|
7
7
|
vi.mock('../helpers/createCallbackHook', () => ({createCallbackHook: vi.fn(identity)}))
|
|
8
8
|
vi.mock('@sanity/sdk', () => ({logout: vi.fn()}))
|
|
9
9
|
|
|
10
|
-
describe('
|
|
11
|
-
it('calls `createCallbackHook` with `
|
|
10
|
+
describe('useLogOut', () => {
|
|
11
|
+
it('calls `createCallbackHook` with `logout`', async () => {
|
|
12
12
|
const {useLogOut} = await import('./useLogOut')
|
|
13
13
|
expect(createCallbackHook).toHaveBeenCalledWith(logout)
|
|
14
14
|
expect(useLogOut).toBe(logout)
|
|
@@ -19,8 +19,9 @@ describe('useManageFavorite', () => {
|
|
|
19
19
|
let statusCallback: ((status: Status) => void) | null = null
|
|
20
20
|
|
|
21
21
|
const mockDocumentHandle = {
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
documentId: 'mock-id',
|
|
23
|
+
documentType: 'mock-type',
|
|
24
|
+
resourceType: 'studio' as const,
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
function createMockNode() {
|
|
@@ -55,10 +56,12 @@ describe('useManageFavorite', () => {
|
|
|
55
56
|
result.current.favorite()
|
|
56
57
|
})
|
|
57
58
|
|
|
58
|
-
expect(node.post).toHaveBeenCalledWith('
|
|
59
|
+
expect(node.post).toHaveBeenCalledWith('dashboard/v1/events/favorite/mutate', {
|
|
59
60
|
documentId: 'mock-id',
|
|
60
61
|
documentType: 'mock-type',
|
|
61
62
|
eventType: 'added',
|
|
63
|
+
resourceType: 'studio',
|
|
64
|
+
resourceId: undefined,
|
|
62
65
|
})
|
|
63
66
|
expect(result.current.isFavorited).toBe(true)
|
|
64
67
|
})
|
|
@@ -70,10 +73,12 @@ describe('useManageFavorite', () => {
|
|
|
70
73
|
result.current.unfavorite()
|
|
71
74
|
})
|
|
72
75
|
|
|
73
|
-
expect(node.post).toHaveBeenCalledWith('
|
|
76
|
+
expect(node.post).toHaveBeenCalledWith('dashboard/v1/events/favorite/mutate', {
|
|
74
77
|
documentId: 'mock-id',
|
|
75
78
|
documentType: 'mock-type',
|
|
76
79
|
eventType: 'removed',
|
|
80
|
+
resourceType: 'studio',
|
|
81
|
+
resourceId: undefined,
|
|
77
82
|
})
|
|
78
83
|
expect(result.current.isFavorited).toBe(false)
|
|
79
84
|
})
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import {type Status} from '@sanity/comlink'
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import {
|
|
3
|
+
type CanvasResource,
|
|
4
|
+
type Events,
|
|
5
|
+
type MediaResource,
|
|
6
|
+
SDK_CHANNEL_NAME,
|
|
7
|
+
SDK_NODE_NAME,
|
|
8
|
+
type StudioResource,
|
|
9
|
+
} from '@sanity/message-protocol'
|
|
10
|
+
import {type FrameMessage} from '@sanity/sdk'
|
|
4
11
|
import {useCallback, useState} from 'react'
|
|
5
12
|
|
|
6
13
|
import {useWindowConnection} from './useWindowConnection'
|
|
@@ -14,27 +21,34 @@ interface ManageFavorite {
|
|
|
14
21
|
isConnected: boolean
|
|
15
22
|
}
|
|
16
23
|
|
|
24
|
+
interface UseManageFavoriteProps {
|
|
25
|
+
documentId: string
|
|
26
|
+
documentType: string
|
|
27
|
+
resourceId?: string
|
|
28
|
+
resourceType: StudioResource['type'] | MediaResource['type'] | CanvasResource['type']
|
|
29
|
+
}
|
|
30
|
+
|
|
17
31
|
/**
|
|
18
32
|
* @beta
|
|
19
33
|
*
|
|
20
34
|
* ## useManageFavorite
|
|
21
35
|
* This hook provides functionality to add and remove documents from favorites,
|
|
22
36
|
* and tracks the current favorite status of the document.
|
|
23
|
-
* @category
|
|
37
|
+
* @category Dashboard Communication
|
|
24
38
|
* @param documentHandle - The document handle containing document ID and type, like `{_id: '123', _type: 'book'}`
|
|
25
39
|
* @returns An object containing:
|
|
26
40
|
* - `favorite` - Function to add document to favorites
|
|
27
41
|
* - `unfavorite` - Function to remove document from favorites
|
|
28
42
|
* - `isFavorited` - Boolean indicating if document is currently favorited
|
|
29
|
-
* - `isConnected` - Boolean indicating if connection to
|
|
43
|
+
* - `isConnected` - Boolean indicating if connection to Dashboard UI is established
|
|
30
44
|
*
|
|
31
45
|
* @example
|
|
32
46
|
* ```tsx
|
|
33
47
|
* function MyDocumentAction(props: DocumentActionProps) {
|
|
34
|
-
* const {
|
|
48
|
+
* const {documentId, documentType} = props
|
|
35
49
|
* const {favorite, unfavorite, isFavorited, isConnected} = useManageFavorite({
|
|
36
|
-
*
|
|
37
|
-
*
|
|
50
|
+
* documentId,
|
|
51
|
+
* documentType
|
|
38
52
|
* })
|
|
39
53
|
*
|
|
40
54
|
* return (
|
|
@@ -47,7 +61,12 @@ interface ManageFavorite {
|
|
|
47
61
|
* }
|
|
48
62
|
* ```
|
|
49
63
|
*/
|
|
50
|
-
export function useManageFavorite({
|
|
64
|
+
export function useManageFavorite({
|
|
65
|
+
documentId,
|
|
66
|
+
documentType,
|
|
67
|
+
resourceId,
|
|
68
|
+
resourceType,
|
|
69
|
+
}: UseManageFavoriteProps): ManageFavorite {
|
|
51
70
|
const [isFavorited, setIsFavorited] = useState(false) // should load this from a comlink fetch
|
|
52
71
|
const [status, setStatus] = useState<Status>('idle')
|
|
53
72
|
const {sendMessage} = useWindowConnection<Events.FavoriteMessage, FrameMessage>({
|
|
@@ -56,17 +75,27 @@ export function useManageFavorite({_id, _type}: DocumentHandle): ManageFavorite
|
|
|
56
75
|
onStatus: setStatus,
|
|
57
76
|
})
|
|
58
77
|
|
|
78
|
+
if (resourceType !== 'studio' && !resourceId) {
|
|
79
|
+
throw new Error('resourceId is required for media-library and canvas resources')
|
|
80
|
+
}
|
|
81
|
+
|
|
59
82
|
const handleFavoriteAction = useCallback(
|
|
60
83
|
(action: 'added' | 'removed', setFavoriteState: boolean) => {
|
|
61
|
-
if (!
|
|
84
|
+
if (!documentId || !documentType || !resourceType) return
|
|
62
85
|
|
|
63
86
|
try {
|
|
64
87
|
const message: Events.FavoriteMessage = {
|
|
65
|
-
type: '
|
|
88
|
+
type: 'dashboard/v1/events/favorite/mutate',
|
|
66
89
|
data: {
|
|
67
90
|
eventType: action,
|
|
68
|
-
documentId
|
|
69
|
-
documentType
|
|
91
|
+
documentId,
|
|
92
|
+
documentType,
|
|
93
|
+
resourceType,
|
|
94
|
+
// Resource Id should exist for media-library and canvas resources
|
|
95
|
+
resourceId: resourceId!,
|
|
96
|
+
},
|
|
97
|
+
response: {
|
|
98
|
+
success: true,
|
|
70
99
|
},
|
|
71
100
|
}
|
|
72
101
|
|
|
@@ -82,7 +111,7 @@ export function useManageFavorite({_id, _type}: DocumentHandle): ManageFavorite
|
|
|
82
111
|
throw error
|
|
83
112
|
}
|
|
84
113
|
},
|
|
85
|
-
[
|
|
114
|
+
[documentId, documentType, resourceId, resourceType, sendMessage],
|
|
86
115
|
)
|
|
87
116
|
|
|
88
117
|
const favorite = useCallback(() => handleFavoriteAction('added', true), [handleFavoriteAction])
|
|
@@ -19,8 +19,10 @@ describe('useRecordDocumentHistoryEvent', () => {
|
|
|
19
19
|
let statusCallback: ((status: Status) => void) | null = null
|
|
20
20
|
|
|
21
21
|
const mockDocumentHandle = {
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
documentId: 'mock-id',
|
|
23
|
+
documentType: 'mock-type',
|
|
24
|
+
resourceType: 'studio' as const,
|
|
25
|
+
resourceId: 'mock-resource-id',
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
function createMockNode() {
|
|
@@ -58,10 +60,12 @@ describe('useRecordDocumentHistoryEvent', () => {
|
|
|
58
60
|
|
|
59
61
|
result.current.recordEvent('viewed')
|
|
60
62
|
|
|
61
|
-
expect(node.post).toHaveBeenCalledWith('
|
|
63
|
+
expect(node.post).toHaveBeenCalledWith('dashboard/v1/events/history', {
|
|
62
64
|
eventType: 'viewed',
|
|
63
65
|
documentId: 'mock-id',
|
|
64
66
|
documentType: 'mock-type',
|
|
67
|
+
resourceType: 'studio',
|
|
68
|
+
resourceId: 'mock-resource-id',
|
|
65
69
|
})
|
|
66
70
|
})
|
|
67
71
|
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import {type Status} from '@sanity/comlink'
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import {
|
|
3
|
+
type CanvasResource,
|
|
4
|
+
type Events,
|
|
5
|
+
type MediaResource,
|
|
6
|
+
SDK_CHANNEL_NAME,
|
|
7
|
+
SDK_NODE_NAME,
|
|
8
|
+
type StudioResource,
|
|
9
|
+
} from '@sanity/message-protocol'
|
|
10
|
+
import {type FrameMessage} from '@sanity/sdk'
|
|
4
11
|
import {useCallback, useState} from 'react'
|
|
5
12
|
|
|
6
13
|
import {useWindowConnection} from './useWindowConnection'
|
|
@@ -10,6 +17,16 @@ interface DocumentInteractionHistory {
|
|
|
10
17
|
isConnected: boolean
|
|
11
18
|
}
|
|
12
19
|
|
|
20
|
+
/**
|
|
21
|
+
* @public
|
|
22
|
+
*/
|
|
23
|
+
interface UseRecordDocumentHistoryEventProps {
|
|
24
|
+
documentId: string
|
|
25
|
+
documentType: string
|
|
26
|
+
resourceType: StudioResource['type'] | MediaResource['type'] | CanvasResource['type']
|
|
27
|
+
resourceId?: string
|
|
28
|
+
}
|
|
29
|
+
|
|
13
30
|
/**
|
|
14
31
|
* @public
|
|
15
32
|
* Hook for managing document interaction history in Sanity Studio.
|
|
@@ -23,10 +40,12 @@ interface DocumentInteractionHistory {
|
|
|
23
40
|
* @example
|
|
24
41
|
* ```tsx
|
|
25
42
|
* function MyDocumentAction(props: DocumentActionProps) {
|
|
26
|
-
* const {
|
|
43
|
+
* const {documentId, documentType, resourceType, resourceId} = props
|
|
27
44
|
* const {recordEvent, isConnected} = useRecordDocumentHistoryEvent({
|
|
28
|
-
*
|
|
29
|
-
*
|
|
45
|
+
* documentId,
|
|
46
|
+
* documentType,
|
|
47
|
+
* resourceType,
|
|
48
|
+
* resourceId,
|
|
30
49
|
* })
|
|
31
50
|
*
|
|
32
51
|
* return (
|
|
@@ -40,9 +59,11 @@ interface DocumentInteractionHistory {
|
|
|
40
59
|
* ```
|
|
41
60
|
*/
|
|
42
61
|
export function useRecordDocumentHistoryEvent({
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
62
|
+
documentId,
|
|
63
|
+
documentType,
|
|
64
|
+
resourceType,
|
|
65
|
+
resourceId,
|
|
66
|
+
}: UseRecordDocumentHistoryEventProps): DocumentInteractionHistory {
|
|
46
67
|
const [status, setStatus] = useState<Status>('idle')
|
|
47
68
|
const {sendMessage} = useWindowConnection<Events.HistoryMessage, FrameMessage>({
|
|
48
69
|
name: SDK_NODE_NAME,
|
|
@@ -50,15 +71,21 @@ export function useRecordDocumentHistoryEvent({
|
|
|
50
71
|
onStatus: setStatus,
|
|
51
72
|
})
|
|
52
73
|
|
|
74
|
+
if (resourceType !== 'studio' && !resourceId) {
|
|
75
|
+
throw new Error('resourceId is required for media-library and canvas resources')
|
|
76
|
+
}
|
|
77
|
+
|
|
53
78
|
const recordEvent = useCallback(
|
|
54
79
|
(eventType: 'viewed' | 'edited' | 'created' | 'deleted') => {
|
|
55
80
|
try {
|
|
56
81
|
const message: Events.HistoryMessage = {
|
|
57
|
-
type: '
|
|
82
|
+
type: 'dashboard/v1/events/history',
|
|
58
83
|
data: {
|
|
59
84
|
eventType,
|
|
60
|
-
documentId
|
|
61
|
-
documentType
|
|
85
|
+
documentId,
|
|
86
|
+
documentType,
|
|
87
|
+
resourceType,
|
|
88
|
+
resourceId: resourceId!,
|
|
62
89
|
},
|
|
63
90
|
}
|
|
64
91
|
|
|
@@ -69,7 +96,7 @@ export function useRecordDocumentHistoryEvent({
|
|
|
69
96
|
throw error
|
|
70
97
|
}
|
|
71
98
|
},
|
|
72
|
-
[
|
|
99
|
+
[documentId, documentType, resourceId, resourceType, sendMessage],
|
|
73
100
|
)
|
|
74
101
|
|
|
75
102
|
return {
|