Skip to content

Commit

Permalink
feat(tasks): add telemetry events to tasks
Browse files Browse the repository at this point in the history
  • Loading branch information
pedrobonamin committed Apr 8, 2024
1 parent d45b210 commit 73fcbed
Show file tree
Hide file tree
Showing 6 changed files with 140 additions and 39 deletions.
60 changes: 60 additions & 0 deletions packages/sanity/src/tasks/__telemetry__/tasks.telemetry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import {defineEvent} from '@sanity/telemetry'

// Task is created.
export const TaskCreated = defineEvent({
name: 'Task Created',
version: 1,
description: 'A task is created',
})

// Task status changed. %from% - %to%
export const TaskStatusChanged = defineEvent<{
from: string
to: string
}>({
name: 'Task Status Changed',
version: 1,
description: 'Task status changed',
})

// A comment is added in a task
export const TaskCommentAdded = defineEvent({
name: 'Task comment added',
version: 1,
description: 'A comment was added in a task',
})

// A reply is added
export const TaskCommentReplyAdded = defineEvent({
name: 'Task comment reply added',
version: 1,
description: 'A reply was added to a comment in a task',
})

// A task is duplicated
export const TaskDuplicated = defineEvent({
name: 'Task duplicated',
version: 1,
description: 'A task is duplicated',
})

// A task is removed
export const TaskRemoved = defineEvent({
name: 'Task removed',
version: 1,
description: 'A task is removed',
})

// The link to a task is copied
export const TaskLinkCopied = defineEvent({
name: 'Task link copied',
version: 1,
description: 'The link to a task is copied',
})

// User visited the studio through a link with a task
export const TaskLinkOpened = defineEvent({
name: 'Task link opened',
version: 1,
description: 'User visited the studio through a link with a task',
})
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {useTelemetry} from '@sanity/telemetry/react'
import {Box, Flex, Stack, Text} from '@sanity/ui'
import {uuid} from '@sanity/uuid'
import {AnimatePresence, motion, type Variants} from 'framer-motion'
Expand All @@ -24,6 +25,7 @@ import {
type CommentUpdatePayload,
useComments,
} from '../../../../../structure/comments'
import {TaskCommentAdded, TaskCommentReplyAdded} from '../../../../__telemetry__/tasks.telemetry'
import {tasksLocaleNamespace} from '../../../../i18n'
import {type TaskDocument} from '../../types'
import {getMentionedUsers} from '../form/utils'
Expand Down Expand Up @@ -65,7 +67,7 @@ type Activity =
export function TasksActivityLog(props: TasksActivityLogProps) {
const {value, onChange, path, activityData = []} = props
const currentUser = useCurrentUser()

const telemetry = useTelemetry()
const {title: workspaceTitle, basePath} = useWorkspace()
const {comments, mentionOptions, operation, getComment} = useComments()
const [commentToDeleteId, setCommentToDeleteId] = useState<string | null>(null)
Expand Down Expand Up @@ -116,9 +118,11 @@ export function TasksActivityLog(props: TasksActivityLogProps) {

onChange(set(notification.subscribers, ['subscribers']))

operation.create(nextComment)
operation.create(nextComment).then(() => {
telemetry.log(TaskCommentAdded)
})
},
[operation, handleGetNotificationValue, onChange],
[handleGetNotificationValue, onChange, operation, telemetry],
)

const handleCommentReply = useCallback(
Expand All @@ -129,20 +133,24 @@ export function TasksActivityLog(props: TasksActivityLogProps) {

onChange(set(notification.subscribers, ['subscribers']))

operation.create({
id: commentId,
type: 'task',
message: nextComment.message,
parentCommentId: nextComment.parentCommentId,
reactions: EMPTY_ARRAY,
status: 'open',
threadId: nextComment.threadId,
context: {
notification,
},
})
operation
.create({
id: commentId,
type: 'task',
message: nextComment.message,
parentCommentId: nextComment.parentCommentId,
reactions: EMPTY_ARRAY,
status: 'open',
threadId: nextComment.threadId,
context: {
notification,
},
})
.then(() => {
telemetry.log(TaskCommentReplyAdded)
})
},
[operation, handleGetNotificationValue, onChange],
[handleGetNotificationValue, onChange, operation, telemetry],
)

const handleCommentCreateRetry = useCallback(
Expand All @@ -156,20 +164,24 @@ export function TasksActivityLog(props: TasksActivityLogProps) {

onChange(set(notification.subscribers, ['subscribers']))

operation.create({
type: 'task',
id: comment._id,
message: comment.message,
parentCommentId: comment.parentCommentId,
reactions: comment.reactions || EMPTY_ARRAY,
status: comment.status,
threadId: comment.threadId,
context: {
notification,
},
})
operation
.create({
type: 'task',
id: comment._id,
message: comment.message,
parentCommentId: comment.parentCommentId,
reactions: comment.reactions || EMPTY_ARRAY,
status: comment.status,
threadId: comment.threadId,
context: {
notification,
},
})
.then(() => {
telemetry.log(TaskCommentReplyAdded)
})
},
[getComment, operation, handleGetNotificationValue, onChange],
[getComment, handleGetNotificationValue, onChange, operation, telemetry],
)

const handleCommentReact = useCallback(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {CheckmarkIcon, CircleIcon} from '@sanity/icons'
import {useTelemetry} from '@sanity/telemetry/react'
import {Menu} from '@sanity/ui'
import {type ForwardedRef, forwardRef} from 'react'
import {type ForwardedRef, forwardRef, useCallback} from 'react'
import {
type FormPatch,
isString,
Expand All @@ -12,6 +13,7 @@ import {
} from 'sanity'

import {Button, MenuButton, MenuItem} from '../../../../../../ui-components'
import {TaskStatusChanged} from '../../../../../__telemetry__/tasks.telemetry'
import {tasksLocaleNamespace} from '../../../../../i18n'
import {TASK_STATUS} from '../../../constants/TaskStatus'

Expand Down Expand Up @@ -45,6 +47,16 @@ interface StatusSelectorProps {

export function StatusSelector(props: StatusSelectorProps) {
const {value, onChange, options, path} = props
const telemetry = useTelemetry()

const handleStatusChange = useCallback(
(next?: string) => {
onChange(set(next, path))
telemetry.log(TaskStatusChanged, {from: value, to: next})
},
[onChange, path, telemetry, value],
)

return (
<MenuButton
button={<StatusMenuButton value={value} options={options} />}
Expand All @@ -62,7 +74,7 @@ export function StatusSelector(props: StatusSelectorProps) {
pressed={isSelected}
iconRight={isSelected && <CheckmarkIcon />}
// eslint-disable-next-line react/jsx-no-bind
onClick={() => onChange(set(option.value, path))}
onClick={() => handleStatusChange(option.value)}
/>
)
})}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import {TrashIcon} from '@sanity/icons'
import {useTelemetry} from '@sanity/telemetry/react'
import {Box, Flex, Switch, Text, useToast} from '@sanity/ui'
import {useCallback, useState} from 'react'
import {type ObjectInputProps, set, useTranslation} from 'sanity'

import {Button} from '../../../../../../ui-components'
import {TaskCreated} from '../../../../../__telemetry__/tasks.telemetry'
import {tasksLocaleNamespace} from '../../../../../i18n'
import {useTasksNavigation} from '../../../context'
import {useRemoveTask} from '../../../hooks/useRemoveTask'
Expand All @@ -26,16 +28,18 @@ const getTaskSubscribers = (task: TaskDocument): string[] => {
return subscribers
}
export function FormCreate(props: ObjectInputProps) {
const [createMore, setCreateMore] = useState(false)
const {onChange} = props
const {
setViewMode,
setActiveTab,
state: {viewMode},
} = useTasksNavigation()

const toast = useToast()
const telemetry = useTelemetry()

const [createMore, setCreateMore] = useState(false)
const handleCreateMore = useCallback(() => setCreateMore((p) => !p), [])
const {onChange} = props

const value = props.value as TaskDocument
const onRemove = useCallback(() => {
setViewMode({type: 'list'})
Expand All @@ -62,12 +66,14 @@ export function FormCreate(props: ObjectInputProps) {
setActiveTab('subscribed')
}

telemetry.log(TaskCreated)

toast.push({
closable: true,
status: 'success',
title: t('form.status.success'),
})
}, [setViewMode, setActiveTab, onChange, createMore, toast, value, t])
}, [value, onChange, createMore, telemetry, toast, t, setViewMode, setActiveTab])

return (
<>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {CopyIcon, LinkIcon, TrashIcon} from '@sanity/icons'
import {useTelemetry} from '@sanity/telemetry/react'
import {Box, Card, Flex, Menu, MenuDivider, Stack} from '@sanity/ui'
// eslint-disable-next-line camelcase
import {getTheme_v2} from '@sanity/ui/theme'
Expand All @@ -19,6 +20,7 @@ import {css, styled} from 'styled-components'

import {CommentsProvider} from '../../../../../../structure/comments'
import {MenuButton, MenuItem, TooltipDelayGroupProvider} from '../../../../../../ui-components'
import {TaskDuplicated, TaskRemoved} from '../../../../../__telemetry__/tasks.telemetry'
import {tasksLocaleNamespace} from '../../../../../i18n'
import {useTasksNavigation} from '../../../context'
import {useActivityLog} from '../../../hooks/useActivityLog'
Expand All @@ -43,14 +45,18 @@ const FirstRow = styled(Flex)((props) => {

function FormActionsMenu({id, value}: {id: string; value: TaskDocument}) {
const {setViewMode, handleCopyLinkToTask} = useTasksNavigation()
const telemetry = useTelemetry()

const onTaskRemoved = useCallback(() => {
setViewMode({type: 'list'})
}, [setViewMode])
telemetry.log(TaskRemoved)
}, [setViewMode, telemetry])
const removeTask = useRemoveTask({id, onRemoved: onTaskRemoved})

const duplicateTask = useCallback(() => {
setViewMode({type: 'duplicate', duplicateTaskValues: value})
}, [setViewMode, value])
telemetry.log(TaskDuplicated)
}, [setViewMode, telemetry, value])

const {t} = useTranslation(tasksLocaleNamespace)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import {useTelemetry} from '@sanity/telemetry/react'
import {useToast} from '@sanity/ui'
import {uuid} from '@sanity/uuid'
import {type ReactNode, useCallback, useEffect, useReducer} from 'react'
import {useRouter} from 'sanity/router'

import {TaskLinkCopied, TaskLinkOpened} from '../../../../__telemetry__/tasks.telemetry'
import {TasksNavigationContext} from './TasksNavigationContext'
import {type Action, type SidebarTabsIds, type State, type ViewModeOptions} from './types'

Expand Down Expand Up @@ -73,6 +75,7 @@ export const TasksNavigationProvider = ({children}: {children: ReactNode}) => {
const [state, dispatch] = useReducer(reducer, initialState)
const router = useRouter()
const toast = useToast()
const telemetry = useTelemetry()

const setViewMode = useCallback((viewMode: ViewModeOptions) => {
switch (viewMode.type) {
Expand Down Expand Up @@ -126,6 +129,7 @@ export const TasksNavigationProvider = ({children}: {children: ReactNode}) => {
status: 'info',
title: 'Copied link to clipboard',
})
telemetry.log(TaskLinkCopied)
})
.catch(() => {
toast.push({
Expand All @@ -134,7 +138,7 @@ export const TasksNavigationProvider = ({children}: {children: ReactNode}) => {
title: 'Failed to copy link to clipboard',
})
})
}, [state.selectedTask, state.viewMode, toast])
}, [state.selectedTask, state.viewMode, telemetry, toast])

// This is casted to a string to make it stable across renders so it doesn't trigger multiple times the effect.
const searchParamsAsString = new URLSearchParams(router.state._searchParams).toString()
Expand All @@ -152,9 +156,10 @@ export const TasksNavigationProvider = ({children}: {children: ReactNode}) => {
const selectedTask = searchParams.get('selectedTask')
if (viewMode === 'edit' && selectedTask) {
dispatch({type: 'EDIT_TASK', payload: {id: selectedTask}})
telemetry.log(TaskLinkOpened)
}
}
}, [searchParamsAsString])
}, [searchParamsAsString, telemetry])

return (
<TasksNavigationContext.Provider
Expand Down

0 comments on commit 73fcbed

Please sign in to comment.