From 046858d8e486f69078ccda4f21eaf7790a97fbec Mon Sep 17 00:00:00 2001 From: Pedro Bonamin Date: Mon, 11 Mar 2024 20:00:26 +0100 Subject: [PATCH] feat(tasks): update tasks activity log to display values --- .../activity/TaskActivityEditedAt.tsx | 37 +--- .../activity/TasksActivityCreatedAt.tsx | 3 +- .../components/activity/TasksActivityLog.tsx | 133 ++++++------- .../activity/helpers/groupChanges.test.ts | 105 ++++++++++ .../activity/helpers/groupChanges.ts | 39 ++++ .../components/activity/helpers/index.tsx | 186 ++++++++++++++---- .../activity/helpers/parseTransactions.ts | 34 ++-- .../form/addonWorkspace/taskSchema.tsx | 6 +- .../components/form/fields/StatusSelector.tsx | 19 +- .../tasks/src/tasks/constants/TaskStatus.tsx | 6 + 10 files changed, 400 insertions(+), 168 deletions(-) create mode 100644 packages/sanity/src/tasks/src/tasks/components/activity/helpers/groupChanges.test.ts create mode 100644 packages/sanity/src/tasks/src/tasks/components/activity/helpers/groupChanges.ts create mode 100644 packages/sanity/src/tasks/src/tasks/constants/TaskStatus.tsx diff --git a/packages/sanity/src/tasks/src/tasks/components/activity/TaskActivityEditedAt.tsx b/packages/sanity/src/tasks/src/tasks/components/activity/TaskActivityEditedAt.tsx index 01f52f42c006..d611aa5fd400 100644 --- a/packages/sanity/src/tasks/src/tasks/components/activity/TaskActivityEditedAt.tsx +++ b/packages/sanity/src/tasks/src/tasks/components/activity/TaskActivityEditedAt.tsx @@ -1,44 +1,19 @@ -import {DotIcon} from '@sanity/icons' import {Box, Flex, Text} from '@sanity/ui' import {memo} from 'react' import {Tooltip} from '../../../../../ui-components' -import {getStringForKey, UpdatedTimeAgo} from './helpers' +import {getChangeDetails, UpdatedTimeAgo, UserName} from './helpers' +import {type FieldChange} from './helpers/parseTransactions' interface EditedAtProps { - activity: { - author: string - field: string - from?: string | null - to?: string | null - timestamp: string - } + activity: FieldChange } export const EditedAt = memo( function EditedAt(props: EditedAtProps) { const {activity} = props - let key: string = activity.field - let showToValue: boolean = key === 'dueDate' || key === 'status' || key === 'targetContent' - - //If the status is changed to be done - if (activity.field === 'status' && activity.to === 'done') { - key = 'statusDone' - showToValue = true - } - //If a task is unassigned - it goes from having a assignee to be unassigned - if (activity.field === 'assignedTo' && !!activity.to && activity.from) { - key = 'unassigned' - } - - //Set the due date for the first time - if (activity.field === 'dueDate' && (activity.from === null || undefined) && activity.to) { - key = 'dueDateSet' - showToValue = true - } - const {formattedDate, timeAgo} = UpdatedTimeAgo(activity.timestamp) - const {icon, string} = getStringForKey(key) || {icon: null, string: ''} + const {icon, text, changeTo} = getChangeDetails(activity) return ( @@ -48,9 +23,7 @@ export const EditedAt = memo( - {activity.author} - {string} {showToValue && {activity.to}}{' '} - {' '} + {text} {changeTo} •{' '} diff --git a/packages/sanity/src/tasks/src/tasks/components/activity/TasksActivityCreatedAt.tsx b/packages/sanity/src/tasks/src/tasks/components/activity/TasksActivityCreatedAt.tsx index 323e531eb03d..2f48c101f7c5 100644 --- a/packages/sanity/src/tasks/src/tasks/components/activity/TasksActivityCreatedAt.tsx +++ b/packages/sanity/src/tasks/src/tasks/components/activity/TasksActivityCreatedAt.tsx @@ -1,4 +1,3 @@ -import {DotIcon} from '@sanity/icons' import {Flex, Text, TextSkeleton} from '@sanity/ui' import {memo} from 'react' import {useUser} from 'sanity' @@ -31,7 +30,7 @@ export const TasksActivityCreatedAt = memo( {loading ? : user?.displayName ?? 'Unknown user'}{' '} - created this task {' '} + created this task •{' '} diff --git a/packages/sanity/src/tasks/src/tasks/components/activity/TasksActivityLog.tsx b/packages/sanity/src/tasks/src/tasks/components/activity/TasksActivityLog.tsx index 288df839477b..d882d14e73a8 100644 --- a/packages/sanity/src/tasks/src/tasks/components/activity/TasksActivityLog.tsx +++ b/packages/sanity/src/tasks/src/tasks/components/activity/TasksActivityLog.tsx @@ -1,18 +1,19 @@ import {Box, Flex, Stack, Text} from '@sanity/ui' import {uuid} from '@sanity/uuid' import {AnimatePresence, motion, type Variants} from 'framer-motion' -import {Fragment, useCallback, useEffect, useMemo, useState} from 'react' +import {useCallback, useEffect, useMemo, useState} from 'react' import { type FormPatch, LoadingBlock, type PatchEvent, type Path, - useCurrentUser, + type TransactionLogEventWithEffects, useClient, - TransactionLogEventWithEffects, + useCurrentUser, } from 'sanity' import styled from 'styled-components' +import {getJsonStream} from '../../../../../core/store/_legacy/history/history/getJsonStream' import { type CommentBaseCreatePayload, type CommentCreatePayload, @@ -25,27 +26,29 @@ import { useComments, } from '../../../../../structure/comments' import {type TaskDocument} from '../../types' +import {CurrentWorkspaceProvider} from '../form/CurrentWorkspaceProvider' +import {type FieldChange, trackFieldChanges} from './helpers/parseTransactions' import {EditedAt} from './TaskActivityEditedAt' import {TasksActivityCommentInput} from './TasksActivityCommentInput' import {TasksActivityCreatedAt} from './TasksActivityCreatedAt' import {ActivityItem} from './TasksActivityItem' import {TasksSubscribers} from './TasksSubscribers' -import {getJsonStream} from '../../../../../core/store/_legacy/history/history/getJsonStream' -import {FieldChange, trackFieldChanges} from './helpers/parseTransactions' function useActivityLog(task: TaskDocument) { const [changes, setChanges] = useState([]) const client = useClient() - const clientConfig = client.config() - let queryParams = `tag=sanity.studio.tasks.history&effectFormat=mendoza&excludeContent=true&includeIdentifiedDocumentsOnly=true&reverse=true` + const {dataset, token} = client.config() + + const queryParams = `tag=sanity.studio.tasks.history&effectFormat=mendoza&excludeContent=true&includeIdentifiedDocumentsOnly=true&reverse=true` + const transactionsUrl = client.getUrl( + `/data/history/${dataset}/transactions/${task._id}?${queryParams}`, + ) const fetchAndParse = useCallback( async (newestTaskDocument: TaskDocument) => { const transactions: TransactionLogEventWithEffects[] = [] - const transactionsUrl = client.getUrl( - `/data/history/${clientConfig.dataset}/transactions/${newestTaskDocument._id}?${queryParams}`, - ) - const stream = await getJsonStream(transactionsUrl, clientConfig.token) + + const stream = await getJsonStream(transactionsUrl, token) const reader = stream.getReader() let result for (;;) { @@ -60,9 +63,13 @@ function useActivityLog(task: TaskDocument) { } const fieldsToTrack: (keyof Omit)[] = [ + 'createdByUser', + 'title', + 'description', + 'dueBy', 'assignedTo', 'status', - 'subscribers', + 'target', ] const parsedChanges = await trackFieldChanges( @@ -73,14 +80,14 @@ function useActivityLog(task: TaskDocument) { setChanges(parsedChanges) }, - [client, clientConfig, queryParams], + [transactionsUrl, token], ) - // TODO: Probably don't want this to fire every time the task updates useEffect(() => { fetchAndParse(task) - }, [fetchAndParse, task]) - + // Task is updated on every change, wait until the revision changes to update the activity log. + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [fetchAndParse, task._rev]) return {changes} } @@ -106,14 +113,6 @@ interface TasksActivityLogProps { value: TaskDocument } -interface ActivityLogItem { - author: string - field: string - from: string - timestamp: string - to?: string -} - type Activity = | { _type: 'comment' @@ -122,7 +121,7 @@ type Activity = } | { _type: 'activity' - payload: ActivityLogItem + payload: FieldChange timestamp: string } @@ -209,13 +208,12 @@ export function TasksActivityLog(props: TasksActivityLogProps) { [operation], ) - // TODO: Get the task real activity. - const activityData: ActivityLogItem[] = useActivityLog(value) + const activityData = useActivityLog(value).changes const activity: Activity[] = useMemo(() => { const taskActivity: Activity[] = activityData.map((item) => ({ _type: 'activity' as const, - payload: item as ActivityLogItem, + payload: item, timestamp: item.timestamp, })) const commentsActivity: Activity[] = taskComments.map((comment) => ({ @@ -260,48 +258,45 @@ export function TasksActivityLog(props: TasksActivityLogProps) { )} {currentUser && ( - - {taskComments.length > 0 && ( - - {activity.map((item) => { - if (item._type === 'activity') { - return - } - - return ( - + + {activity.map((item) => { + if (item._type === 'activity') { + return + } + return ( + + - - - ) - })} - - )} - - - + mentionOptions={mentionOptions} + mode="default" // TODO: set dynamic mode? + onCreateRetry={handleCommentCreateRetry} + onDelete={handleCommentRemove} + onEdit={handleCommentEdit} + onReactionSelect={handleCommentReact} + onReply={handleCommentReply} + parentComment={item.payload.parentComment} + replies={item.payload.replies} + /> + + ) + })} + + + + )} )} diff --git a/packages/sanity/src/tasks/src/tasks/components/activity/helpers/groupChanges.test.ts b/packages/sanity/src/tasks/src/tasks/components/activity/helpers/groupChanges.test.ts new file mode 100644 index 000000000000..b540d374e87e --- /dev/null +++ b/packages/sanity/src/tasks/src/tasks/components/activity/helpers/groupChanges.test.ts @@ -0,0 +1,105 @@ +import {describe, expect, it} from '@jest/globals' + +import {groupChanges} from './groupChanges' +import {type FieldChange} from './parseTransactions' + +describe('Tests grouping the changes', () => { + it('Should group the changes done by the same user in the title field', () => { + const changes: FieldChange[] = [ + { + field: 'title', + to: 'Prepare the tasks PR no', + from: 'Prepare the tasks PR', + timestamp: '2024-03-11T08:31:12.619628Z', + author: 'piIz2Gfg5', + }, + { + field: 'title', + from: 'Prepare the tasks PR no', + to: 'Prepare the tasks PR now', + timestamp: '2024-03-11T08:31:13.627854Z', + author: 'piIz2Gfg5', + }, + ] + const output = groupChanges(changes) + expect(output).toEqual([ + { + field: 'title', + from: 'Prepare the tasks PR', + to: 'Prepare the tasks PR now', + timestamp: '2024-03-11T08:31:13.627854Z', + author: 'piIz2Gfg5', + }, + ]) + }) + it('Should group the changes done by the same user in the title field, with a max of 5 minutes.', () => { + const changes: FieldChange[] = [ + { + field: 'title', + to: 'Prepare the tasks PR no', + from: 'Prepare the tasks PR', + timestamp: '2024-03-11T08:31:12.619628Z', + author: 'piIz2Gfg5', + }, + { + field: 'title', + from: 'Prepare the tasks PR no', + to: 'Prepare the tasks PR now', + timestamp: '2024-03-11T08:31:13.627854Z', + author: 'piIz2Gfg5', + }, + { + field: 'title', + from: 'Prepare the tasks PR now', + to: 'Prepare the tasks PR', + timestamp: '2024-03-11T08:38:13.627854Z', + author: 'piIz2Gfg5', + }, + ] + const output = groupChanges(changes) + expect(output).toEqual([ + { + field: 'title', + from: 'Prepare the tasks PR', + to: 'Prepare the tasks PR now', + timestamp: '2024-03-11T08:31:13.627854Z', + author: 'piIz2Gfg5', + }, + { + field: 'title', + from: 'Prepare the tasks PR now', + to: 'Prepare the tasks PR', + timestamp: '2024-03-11T08:38:13.627854Z', + author: 'piIz2Gfg5', + }, + ]) + }) + it('Should not group the changes if the user did changes to other fields in between', () => { + const changes: FieldChange[] = [ + { + field: 'title', + to: 'Prepare the tasks PR no', + from: 'Prepare the tasks PR', + timestamp: '2024-03-11T08:31:12.619628Z', + author: 'piIz2Gfg5', + }, + { + field: 'assignedTo', + from: 'old', + to: 'new', + timestamp: '2024-03-11T08:31:13.627854Z', + author: 'piIz2Gfg5', + }, + { + field: 'title', + from: 'Prepare the tasks PR no', + to: 'Prepare the tasks PR now', + timestamp: '2024-03-11T08:31:13.627854Z', + author: 'piIz2Gfg5', + }, + ] + const output = groupChanges(changes) + + expect(output).toEqual(changes) + }) +}) diff --git a/packages/sanity/src/tasks/src/tasks/components/activity/helpers/groupChanges.ts b/packages/sanity/src/tasks/src/tasks/components/activity/helpers/groupChanges.ts new file mode 100644 index 000000000000..702b3cca807a --- /dev/null +++ b/packages/sanity/src/tasks/src/tasks/components/activity/helpers/groupChanges.ts @@ -0,0 +1,39 @@ +import {type TaskDocument} from '../../../types' +import {type FieldChange} from './parseTransactions' + +const FIELDS_TO_GROUP: (keyof TaskDocument)[] = ['title', 'description', 'target'] +const MINUTES_TO_GROUP = 5 +export function groupChanges(changes: FieldChange[]): FieldChange[] { + // If we have two or more changes done by the same user in a similar timestamp +- X minutes, in any of the fields specified we group them together. + const groupedChanges: FieldChange[] = [] + for (const change of changes) { + const lastChangeProcessed = groupedChanges[groupedChanges.length - 1] + if (!lastChangeProcessed) { + groupedChanges.push(change) + continue + } + if (!FIELDS_TO_GROUP.includes(change.field)) { + groupedChanges.push(change) + continue + } + if ( + lastChangeProcessed.author === change.author && + lastChangeProcessed.field === change.field + ) { + // Check the timestamp difference + const lastChangeDate = new Date(lastChangeProcessed.timestamp) + const changeDate = new Date(change.timestamp) + const diff = Math.abs(lastChangeDate.getTime() - changeDate.getTime()) + const minutes = Math.floor(diff / 60000) + if (minutes <= MINUTES_TO_GROUP) { + // We keep the from value and update the to value, and the date. + lastChangeProcessed.to = change.to + lastChangeProcessed.timestamp = change.timestamp + continue + } + } + groupedChanges.push(change) + } + + return groupedChanges +} diff --git a/packages/sanity/src/tasks/src/tasks/components/activity/helpers/index.tsx b/packages/sanity/src/tasks/src/tasks/components/activity/helpers/index.tsx index a6bf4adf3f8c..e59b7001a338 100644 --- a/packages/sanity/src/tasks/src/tasks/components/activity/helpers/index.tsx +++ b/packages/sanity/src/tasks/src/tasks/components/activity/helpers/index.tsx @@ -1,27 +1,28 @@ -import { - CalendarIcon, - CheckmarkCircleIcon, - CircleIcon, - EditIcon, - LinkIcon, - UserIcon, -} from '@sanity/icons' +import {CalendarIcon, CircleIcon, EditIcon, LinkIcon, UserIcon} from '@sanity/icons' +import {TextSkeleton} from '@sanity/ui' import {type ReactElement} from 'react' import { type RelativeTimeOptions, useDateTimeFormat, type UseDateTimeFormatOptions, useRelativeTime, + useSchema, + useUser, } from 'sanity' +import {IntentLink} from 'sanity/router' +import styled from 'styled-components' -interface KeyStringMapValue { - string: string - icon: ReactElement - link?: ReactElement -} +import {TASK_STATUS} from '../../../constants/TaskStatus' +import {useDocumentPreviewValues} from '../../../hooks/useDocumentPreviewValues' +import {type TaskTarget} from '../../../types' +import {type FieldChange} from './parseTransactions' const DATE_FORMAT_OPTIONS: UseDateTimeFormatOptions = { - dateStyle: 'medium', + month: 'long', + day: '2-digit', + minute: '2-digit', + hour: '2-digit', + second: '2-digit', } const RELATIVE_TIME_OPTIONS: RelativeTimeOptions = { @@ -29,36 +30,147 @@ const RELATIVE_TIME_OPTIONS: RelativeTimeOptions = { useTemporalPhrase: true, } +const Strong = styled.strong` + font-weight: 600; +` + export function UpdatedTimeAgo(timestamp: string) { + const date = new Date(timestamp) const dateFormatter = useDateTimeFormat(DATE_FORMAT_OPTIONS) - const formattedDate = dateFormatter.format(new Date(timestamp)) + const formattedDate = dateFormatter.format(date) - const updatedTimeAgo = useRelativeTime(formattedDate || '', RELATIVE_TIME_OPTIONS) + const updatedTimeAgo = useRelativeTime(date || '', RELATIVE_TIME_OPTIONS) return {timeAgo: updatedTimeAgo, formattedDate} } -export function getStringForKey(key: string): KeyStringMapValue | undefined { - const keyStringMap: {[key: string]: KeyStringMapValue} = { - assignedTo: {string: 'assigned to', icon: }, - unassigned: {string: 'unassigned this task', icon: }, - dueDate: {string: 'changed the due date to', icon: }, - dueDateSet: { - string: 'set the due date to', - icon: , - }, - description: {string: 'updated the task description', icon: }, - title: {string: 'updated the task title', icon: }, - targetContent: {string: 'set the target content to', icon: }, - statusDone: { - string: 'changed status to', - icon: , - }, - status: { - string: 'changed status to', - icon: , - }, +export function UserName({userId}: {userId: string}) { + const [user, isLoading] = useUser(userId) + return isLoading ? : {user?.displayName} +} + +const DUE_BY_DATE_OPTIONS: UseDateTimeFormatOptions = { + month: 'short', + day: 'numeric', +} + +function DueByChange({date}: {date: string}) { + const dueBy = new Date(date) + const dateFormatter = useDateTimeFormat(DUE_BY_DATE_OPTIONS) + const formattedDate = dateFormatter.format(dueBy) + return {formattedDate} +} + +const LinkWrapper = styled.span` + > a { + color: var(--card-fg-muted-color); + text-decoration: underline; + text-underline-offset: 1px; + font-weight: 600; + } +` + +function TargetContentChange({target}: {target: TaskTarget}) { + const schema = useSchema() + const documentId = target.document._ref + const documentType = target.documentType + const documentSchema = schema.get(documentType) + const {isLoading, value} = useDocumentPreviewValues({ + documentId, + documentType, + }) + + if (isLoading) { + return + } + if (!documentSchema) { + return null } - return keyStringMap[key] + return ( + + + {value?.title} + + + ) +} + +export function getChangeDetails(activity: FieldChange): { + text: string + icon: ReactElement + changeTo?: ReactElement +} { + switch (activity.field) { + case 'status': { + const statusTitle = TASK_STATUS.find((s) => s.value === activity.to)?.title + return { + text: 'changed status to', + icon: TASK_STATUS.find((s) => s.value === activity.to)?.icon || , + changeTo: {statusTitle}, + } + } + case 'target': + if (!activity.to) + return { + text: 'removed target content', + icon: , + changeTo: undefined, + } + return { + text: 'set target content to', + icon: , + changeTo: , + } + case 'dueBy': + if (!activity.from) { + return { + text: 'set the due date to', + icon: , + changeTo: , + } + } + if (!activity.to) { + return { + text: 'removed the due date', + icon: , + changeTo: undefined, + } + } + return { + text: 'changed the due date to', + icon: , + changeTo: , + } + case 'assignedTo': + if (!activity.to) { + return { + text: 'unassigned this task', + icon: , + changeTo: undefined, + } + } + return { + text: 'assigned to', + icon: , + changeTo: , + } + case 'description': + return { + text: 'updated the task description', + icon: , + changeTo: undefined, + } + case 'title': + return { + text: 'updated the task title', + icon: , + changeTo: undefined, + } + default: + return { + text: '', + icon: , + } + } } diff --git a/packages/sanity/src/tasks/src/tasks/components/activity/helpers/parseTransactions.ts b/packages/sanity/src/tasks/src/tasks/components/activity/helpers/parseTransactions.ts index fbab5a524de7..1c394718fed5 100644 --- a/packages/sanity/src/tasks/src/tasks/components/activity/helpers/parseTransactions.ts +++ b/packages/sanity/src/tasks/src/tasks/components/activity/helpers/parseTransactions.ts @@ -1,12 +1,15 @@ import {applyPatch} from 'mendoza' -import {TaskDocument} from '../../../types' -import {TransactionLogEventWithEffects} from 'sanity' +import {type TransactionLogEventWithEffects} from 'sanity' + +import {type TaskDocument} from '../../../types' +import {groupChanges} from './groupChanges' export interface FieldChange { field: keyof TaskDocument from: any to: any timestamp: string + author: string } function omitRev(document: TaskDocument) { @@ -16,19 +19,18 @@ function omitRev(document: TaskDocument) { /** * Tracks changes to specified fields across document versions by applying patches in reverse. - * @param newestDocument The latest state of the document. - * @param transactions An array of transactions containing patches. - * @param fieldsToTrack The fields to track for changes. + * @param newestDocument - The latest state of the document. + * @param transactions - An array of transactions containing patches. + * @param fieldsToTrack - The fields to track for changes. * @returns An array of changes for the tracked fields. */ -export async function trackFieldChanges( +export function trackFieldChanges( newestDocument: TaskDocument, transactions: TransactionLogEventWithEffects[], fieldsToTrack: (keyof Omit)[], -): Promise { +): FieldChange[] { // Sort transactions by timestamp in descending order // transactions.sort((a, b) => b.timestamp.localeCompare(a.timestamp)); - let currentDocument: Omit = omitRev(newestDocument) const changes: FieldChange[] = [] let previousDocument = currentDocument @@ -44,14 +46,16 @@ export async function trackFieldChanges( previousDocument = applyPatch(currentDocument, effect.revert) // Track changes for specified fields + // eslint-disable-next-line no-loop-func fieldsToTrack.forEach((field) => { // TODO: fix no-loop-func eslint error if (previousDocument?.[field] !== currentDocument?.[field]) { changes.push({ field, - from: currentDocument?.[field], - to: previousDocument?.[field], + from: previousDocument?.[field], + to: currentDocument?.[field], timestamp, + author: transaction.author, }) } }) @@ -60,8 +64,14 @@ export async function trackFieldChanges( currentDocument = previousDocument } - // Return changes sorted by timestamp in ascending order - return changes.sort((a, b) => a.timestamp.localeCompare(b.timestamp)) + const changesSortedByTimestamp = changes.sort((a, b) => a.timestamp.localeCompare(b.timestamp)) + // Find the moment the task was created by the user. + const createdByUserIndex = changesSortedByTimestamp.findIndex( + (change) => change.field === 'createdByUser', + ) + + // Return changes sorted by timestamp in ascending order from the moment the task was created. + return groupChanges(changesSortedByTimestamp.slice(createdByUserIndex + 1)) } // Test to verify changes are correctly identified diff --git a/packages/sanity/src/tasks/src/tasks/components/form/addonWorkspace/taskSchema.tsx b/packages/sanity/src/tasks/src/tasks/components/form/addonWorkspace/taskSchema.tsx index 63d350c841e9..659b2e47c3d3 100644 --- a/packages/sanity/src/tasks/src/tasks/components/form/addonWorkspace/taskSchema.tsx +++ b/packages/sanity/src/tasks/src/tasks/components/form/addonWorkspace/taskSchema.tsx @@ -1,5 +1,6 @@ import {type ArrayFieldProps, defineField, defineType, type ObjectFieldProps} from 'sanity' +import {TASK_STATUS} from '../../../constants/TaskStatus' import {type FormMode} from '../../../types' import { AssigneeCreateFormField, @@ -139,10 +140,7 @@ export const taskSchema = (mode: FormMode) => name: 'status', title: 'Status', options: { - list: [ - {value: 'open', title: 'To Do'}, - {value: 'closed', title: 'Done'}, - ], + list: TASK_STATUS.map((s) => ({value: s.value, title: s.title})), }, hidden: true, }, diff --git a/packages/sanity/src/tasks/src/tasks/components/form/fields/StatusSelector.tsx b/packages/sanity/src/tasks/src/tasks/components/form/fields/StatusSelector.tsx index 16d1dcc1a7c8..932a874e0fa4 100644 --- a/packages/sanity/src/tasks/src/tasks/components/form/fields/StatusSelector.tsx +++ b/packages/sanity/src/tasks/src/tasks/components/form/fields/StatusSelector.tsx @@ -1,6 +1,6 @@ -import {CheckmarkCircleIcon, CheckmarkIcon, CircleIcon} from '@sanity/icons' +import {CheckmarkIcon, CircleIcon} from '@sanity/icons' import {Menu} from '@sanity/ui' -import {type ForwardedRef, forwardRef, type ReactNode} from 'react' +import {type ForwardedRef, forwardRef} from 'react' import { type FormPatch, isString, @@ -11,12 +11,7 @@ import { } from 'sanity' import {Button, MenuButton, MenuItem} from '../../../../../../ui-components' - -// TODO: support customizing icons and options. -const OPTION_ICONS: Record = { - closed: , - open: , -} +import {TASK_STATUS} from '../../../constants/TaskStatus' export const StatusMenuButton = forwardRef(function StatusMenuButton( props: {value: string | undefined; options: TitledListValue[]}, @@ -24,12 +19,13 @@ export const StatusMenuButton = forwardRef(function StatusMenuButton( ) { const {value, options} = props const selectedOption = options.find((option) => option.value === value) + const icon = TASK_STATUS.find((status) => status.value === value)?.icon return (