Skip to content

Commit 7afcdb4

Browse files
authored
feat(sanity): add always present document action to copy url to clipboard (#7416)
* feat: add always present document action to copy url to clipboard * chore: add comment to menuitems * feat: add check for navigator presence * feat: add tracking for copy document URL * fix: update to use intent URL instead of just current URL * feat: resolve intent link on demand * revert: go back to just copying current URL * chore: add comment explanation
1 parent 17a7b1d commit 7afcdb4

File tree

5 files changed

+45
-1
lines changed

5 files changed

+45
-1
lines changed

packages/sanity/src/structure/i18n/resources.ts

+4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import {defineLocalesResources} from 'sanity'
77
* @internal
88
*/
99
const structureLocaleStrings = defineLocalesResources('structure', {
10+
/** Label for the "Copy Document URL" document action */
11+
'action.copy-document-url.label': 'Copy Document URL',
1012
/** Tooltip when action button is disabled because the operation is not ready */
1113
'action.delete.disabled.not-ready': 'Operation not ready',
1214
/** Tooltip when action button is disabled because the document does not exist */
@@ -349,6 +351,8 @@ const structureLocaleStrings = defineLocalesResources('structure', {
349351
/** The text when a generic operation succeeded (fallback, generally not shown) */
350352
'panes.document-operation-results.operation-success':
351353
'Successfully performed {{context}} on document',
354+
/** The text when copy URL operation succeeded */
355+
'panes.document-operation-results.operation-success_copy-url': 'Document URL copied to clipboard',
352356
/** The text when a delete operation succeeded */
353357
'panes.document-operation-results.operation-success_delete':
354358
'The document was successfully deleted',

packages/sanity/src/structure/panes/document/DocumentPaneProvider.tsx

+22
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/* eslint-disable camelcase */
22
import {isActionEnabled} from '@sanity/schema/_internal'
3+
import {useTelemetry} from '@sanity/telemetry/react'
34
import {
45
type ObjectSchemaType,
56
type Path,
@@ -47,6 +48,7 @@ import {usePaneRouter} from '../../components'
4748
import {structureLocaleNamespace} from '../../i18n'
4849
import {type PaneMenuItem} from '../../types'
4950
import {useStructureTool} from '../../useStructureTool'
51+
import {DocumentURLCopied} from './__telemetry__'
5052
import {
5153
DEFAULT_MENU_ITEM_GROUPS,
5254
EMPTY_PARAMS,
@@ -400,13 +402,30 @@ export const DocumentPaneProvider = memo((props: DocumentPaneProviderProps) => {
400402
[inspectOpen, params, setPaneParams],
401403
)
402404

405+
const telemetry = useTelemetry()
406+
403407
const handleMenuAction = useCallback(
404408
(item: PaneMenuItem) => {
405409
if (item.action === 'production-preview' && previewUrl) {
406410
window.open(previewUrl)
407411
return true
408412
}
409413

414+
if (item.action === 'copy-document-url' && navigator) {
415+
telemetry.log(DocumentURLCopied)
416+
// Chose to copy the user's current URL instead of
417+
// the document's edit intent link because
418+
// of bugs when resolving a document that has
419+
// multiple access paths within Structure
420+
navigator.clipboard.writeText(window.location.toString())
421+
pushToast({
422+
id: 'copy-document-url',
423+
status: 'info',
424+
title: t('panes.document-operation-results.operation-success_copy-url'),
425+
})
426+
return true
427+
}
428+
410429
if (item.action === 'inspect') {
411430
toggleLegacyInspect(true)
412431
return true
@@ -434,13 +453,16 @@ export const DocumentPaneProvider = memo((props: DocumentPaneProviderProps) => {
434453
return false
435454
},
436455
[
456+
t,
437457
closeInspector,
438458
handleHistoryOpen,
439459
inspectorName,
440460
inspectors,
441461
openInspector,
442462
previewUrl,
443463
toggleLegacyInspect,
464+
pushToast,
465+
telemetry,
444466
],
445467
)
446468

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import {defineEvent} from '@sanity/telemetry'
2+
3+
/**
4+
* @internal
5+
*/
6+
export const DocumentURLCopied = defineEvent({
7+
name: 'DocumentURLCopied',
8+
version: 1,
9+
description: 'User copied document URL to clipboard',
10+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './documentPanes.telemetry'

packages/sanity/src/structure/panes/document/menuItems.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {EarthAmericasIcon, JsonIcon} from '@sanity/icons'
1+
import {EarthAmericasIcon, JsonIcon, LinkIcon} from '@sanity/icons'
22
import {type DocumentInspector, type DocumentInspectorMenuItem, type TFunction} from 'sanity'
33

44
import {type PaneMenuItem, type StructureToolFeatures} from '../../types'
@@ -72,6 +72,13 @@ export function getMenuItems(params: GetMenuItemsParams): PaneMenuItem[] {
7272
].filter(Boolean) as PaneMenuItem[]
7373

7474
return [
75+
// Always present document menu item to copy current url to clipboard
76+
{
77+
action: 'copy-document-url',
78+
showAsAction: true,
79+
title: params.t('action.copy-document-url.label'),
80+
icon: LinkIcon,
81+
},
7582
...inspectorItems,
7683

7784
// TODO: convert to inspector or document view?

0 commit comments

Comments
 (0)