diff --git a/frontend/src/lib/components/ActivityLog/humanizeActivity.tsx b/frontend/src/lib/components/ActivityLog/humanizeActivity.tsx index ff3045894b810..f52417705f8d6 100644 --- a/frontend/src/lib/components/ActivityLog/humanizeActivity.tsx +++ b/frontend/src/lib/components/ActivityLog/humanizeActivity.tsx @@ -46,7 +46,7 @@ export type ActivityLogItem = { created_at: string scope: ActivityScope item_id?: string - detail: ActivityLogDetail + detail?: ActivityLogDetail unread?: boolean // when used as a notification is_system?: boolean // when auto-created e.g. an exported image when sharing an insight } @@ -140,7 +140,7 @@ export function defaultDescriber( asNotification = false, resource?: string | JSX.Element ): HumanizedChange { - resource = resource || logItem.detail.name || `a ${humanizeScope(logItem.scope, true)}` + resource = resource || logItem.detail?.name || `a ${humanizeScope(logItem.scope, true)}` if (logItem.activity == 'deleted') { return { @@ -169,7 +169,7 @@ export function defaultDescriber( ) } - const commentContent = logItem.detail.changes?.[0].after as string | undefined + const commentContent = logItem.detail?.changes?.[0].after as string | undefined return { description, diff --git a/frontend/src/scenes/data-management/dataManagementDescribers.tsx b/frontend/src/scenes/data-management/dataManagementDescribers.tsx index b53f9911b693b..f36d04c0321a7 100644 --- a/frontend/src/scenes/data-management/dataManagementDescribers.tsx +++ b/frontend/src/scenes/data-management/dataManagementDescribers.tsx @@ -72,8 +72,8 @@ const dataManagementActionsMapping: Record< function nameAndLink(logItem?: ActivityLogItem): JSX.Element { return logItem?.item_id ? ( - {logItem?.detail.name || 'unknown'} - ) : logItem?.detail.name ? ( + {logItem?.detail?.name || 'unknown'} + ) : logItem?.detail?.name ? ( <>{logItem?.detail.name} ) : ( <>unknown @@ -106,7 +106,7 @@ export function dataManagementActivityDescriber(logItem: ActivityLogItem, asNoti ) - for (const change of logItem.detail.changes || []) { + for (const change of logItem.detail?.changes || []) { if (!change?.field || !dataManagementActionsMapping[change.field]) { continue // updates have to have a "field" to be described } diff --git a/frontend/src/scenes/feature-flags/activityDescriptions.tsx b/frontend/src/scenes/feature-flags/activityDescriptions.tsx index c1604013f8f8b..f9e652cb6c34a 100644 --- a/frontend/src/scenes/feature-flags/activityDescriptions.tsx +++ b/frontend/src/scenes/feature-flags/activityDescriptions.tsx @@ -267,11 +267,11 @@ export function flagActivityDescriber(logItem: ActivityLogItem, asNotification?: let changeSuffix: Description = ( <> on {asNotification && ' the flag '} - {nameOrLinkToFlag(logItem?.item_id, logItem?.detail.name)} + {nameOrLinkToFlag(logItem?.item_id, logItem.detail?.name)} ) - for (const change of logItem.detail.changes || []) { + for (const change of logItem.detail?.changes || []) { if (!change?.field) { continue // feature flag updates have to have a "field" to be described } diff --git a/frontend/src/scenes/notebooks/Notebook/NotebookHistory.tsx b/frontend/src/scenes/notebooks/Notebook/NotebookHistory.tsx index 7ffd9e158e242..d1a543d1b42f5 100644 --- a/frontend/src/scenes/notebooks/Notebook/NotebookHistory.tsx +++ b/frontend/src/scenes/notebooks/Notebook/NotebookHistory.tsx @@ -20,7 +20,7 @@ import { ActivityScope } from '~/types' import { notebookLogic } from './notebookLogic' const getFieldChange = (logItem: ActivityLogItem, field: string): any => { - return logItem.detail.changes?.find((x) => x.field === field)?.after + return logItem.detail?.changes?.find((x) => x.field === field)?.after } function NotebookHistoryList({ onItemClick }: { onItemClick: (logItem: ActivityLogItem) => void }): JSX.Element { @@ -101,7 +101,7 @@ export function NotebookHistory(): JSX.Element { const { setShowHistory, setPreviewContent } = useActions(notebookLogic) const onRevert = (logItem: ActivityLogItem): void => { - const content = logItem.detail.changes?.find((x) => x.field === 'content')?.after + const content = logItem.detail?.changes?.find((x) => x.field === 'content')?.after if (!content) { lemonToast.error('Could not revert to this version') diff --git a/frontend/src/scenes/notebooks/Notebook/notebookActivityDescriber.tsx b/frontend/src/scenes/notebooks/Notebook/notebookActivityDescriber.tsx index 1756eb91c275d..51b5f6a5f7133 100644 --- a/frontend/src/scenes/notebooks/Notebook/notebookActivityDescriber.tsx +++ b/frontend/src/scenes/notebooks/Notebook/notebookActivityDescriber.tsx @@ -27,9 +27,9 @@ const notebookActionsMapping: Record< function nameAndLink(logItem?: ActivityLogItem): JSX.Element { return logItem?.detail?.short_id ? ( - {logItem?.detail.name || 'unknown'} - ) : logItem?.detail.name ? ( - <>{logItem?.detail.name} + {logItem.detail.name || 'unknown'} + ) : logItem?.detail?.name ? ( + <>{logItem.detail.name} ) : ( Untitled ) @@ -45,7 +45,7 @@ export function notebookActivityDescriber(logItem: ActivityLogItem, asNotificati let changes: Description[] = [] let changeSuffix: Description = <>on {nameAndLink(logItem)} - for (const change of logItem.detail.changes || []) { + for (const change of logItem.detail?.changes || []) { if (!change?.field || !notebookActionsMapping[change.field]) { continue // not all notebook fields are describable } diff --git a/frontend/src/scenes/persons/activityDescriptions.tsx b/frontend/src/scenes/persons/activityDescriptions.tsx index ae904bd5a88d0..17593817aff72 100644 --- a/frontend/src/scenes/persons/activityDescriptions.tsx +++ b/frontend/src/scenes/persons/activityDescriptions.tsx @@ -19,7 +19,7 @@ export function personActivityDescriber(logItem: ActivityLogItem, asNotification return { description: ( <> - {userNameForLogItem(logItem)} deleted the person: {logItem.detail.name} + {userNameForLogItem(logItem)} deleted the person: {logItem.detail?.name} ), } @@ -39,7 +39,7 @@ export function personActivityDescriber(logItem: ActivityLogItem, asNotification } } if (logItem.activity === 'people_merged_into') { - if (logItem.detail.merge?.source) { + if (logItem.detail?.merge?.source) { return { description: ( {userNameForLogItem(logItem)} merged } - listParts={logItem.detail.merge.source.flatMap((di) => ( + listParts={logItem.detail?.merge.source.flatMap((di) => ( @@ -61,7 +61,7 @@ export function personActivityDescriber(logItem: ActivityLogItem, asNotification } if (logItem.activity === 'split_person') { - const distinctIds: string[] | undefined = logItem.detail.changes?.[0].after?.['distinct_ids'] + const distinctIds: string[] | undefined = logItem.detail?.changes?.[0].after?.['distinct_ids'] if (distinctIds) { return { description: ( diff --git a/frontend/src/scenes/plugins/pluginActivityDescriptions.tsx b/frontend/src/scenes/plugins/pluginActivityDescriptions.tsx index a4889604735c1..1a87bd2f7fd70 100644 --- a/frontend/src/scenes/plugins/pluginActivityDescriptions.tsx +++ b/frontend/src/scenes/plugins/pluginActivityDescriptions.tsx @@ -21,7 +21,7 @@ export function pluginActivityDescriber(logItem: ActivityLogItem, asNotification return { description: ( <> - {userNameForLogItem(logItem)} installed the app: {logItem.detail.name} + {userNameForLogItem(logItem)} installed the app: {logItem.detail?.name} ), } @@ -31,7 +31,7 @@ export function pluginActivityDescriber(logItem: ActivityLogItem, asNotification return { description: ( <> - {userNameForLogItem(logItem)} uninstalled the app: {logItem.detail.name} + {userNameForLogItem(logItem)} uninstalled the app: {logItem.detail?.name} ), } @@ -39,7 +39,7 @@ export function pluginActivityDescriber(logItem: ActivityLogItem, asNotification if (logItem.activity == 'enabled') { const changes: (string | JSX.Element)[] = [] - for (const change of logItem.detail.changes || []) { + for (const change of logItem.detail?.changes || []) { const newValue = change.after === SECRET_FIELD_VALUE ? '' : change.after changes.push( <> @@ -53,8 +53,8 @@ export function pluginActivityDescriber(logItem: ActivityLogItem, asNotification listParts={changes} prefix={ <> - {userNameForLogItem(logItem)} enabled the app: {logItem.detail.name}{' '} - with config ID {logItem.item_id} + {userNameForLogItem(logItem)} enabled the app:{' '} + {logItem.detail?.name} with config ID {logItem.item_id} {changes.length > 0 ? ', with' : '.'} } @@ -67,14 +67,14 @@ export function pluginActivityDescriber(logItem: ActivityLogItem, asNotification return { description: ( <> - {userNameForLogItem(logItem)} disabled the app: {logItem.detail.name} with + {userNameForLogItem(logItem)} disabled the app: {logItem.detail?.name} with config ID {logItem.item_id}. ), } } - if (logItem.activity == 'job_triggered' && logItem.detail.trigger?.job_type == 'Export historical events V2') { + if (logItem.activity == 'job_triggered' && logItem.detail?.trigger?.job_type == 'Export historical events V2') { const [startDate, endDate] = logItem.detail.trigger.payload.dateRange return { description: ( @@ -86,23 +86,23 @@ export function pluginActivityDescriber(logItem: ActivityLogItem, asNotification } } - if (logItem.activity == 'job_triggered' && logItem.detail.trigger) { + if (logItem.activity == 'job_triggered' && logItem.detail?.trigger) { return { description: ( <> {userNameForLogItem(logItem)} triggered job:{' '} - {logItem.detail.trigger.job_type} with config ID {logItem.item_id}. + {logItem.detail?.trigger.job_type} with config ID {logItem.item_id}. ), extendedDescription: ( <> - Payload: {JSON.stringify(logItem.detail.trigger.payload, null, 2)} + Payload: {JSON.stringify(logItem.detail?.trigger.payload, null, 2)} ), } } - if (logItem.activity == 'export_success' && logItem.detail.trigger) { + if (logItem.activity == 'export_success' && logItem.detail?.trigger) { const { dateFrom, dateTo } = logItem.detail.trigger.payload const startDate = dayjs(dateFrom).format('YYYY-MM-DD') // :TRICKY: Internally export date range is non-inclusive so transform it to be inclusive @@ -117,7 +117,7 @@ export function pluginActivityDescriber(logItem: ActivityLogItem, asNotification } } - if (logItem.activity == 'export_fail' && logItem.detail.trigger) { + if (logItem.activity == 'export_fail' && logItem.detail?.trigger) { const { dateFrom, dateTo } = logItem.detail.trigger.payload const startDate = dayjs(dateFrom).format('YYYY-MM-DD') // :TRICKY: Internally export date range is non-inclusive so transform it to be inclusive @@ -135,7 +135,7 @@ export function pluginActivityDescriber(logItem: ActivityLogItem, asNotification if (logItem.activity == 'config_updated') { const changes: (string | JSX.Element)[] = [] - for (const change of logItem.detail.changes || []) { + for (const change of logItem.detail?.changes || []) { let changeWording: string | JSX.Element = '' const changeBefore = change.before === SECRET_FIELD_VALUE ? '' : change.before const changeAfter = change.after === SECRET_FIELD_VALUE ? '' : change.after @@ -168,7 +168,7 @@ export function pluginActivityDescriber(logItem: ActivityLogItem, asNotification listParts={changes} suffix={ <> - on app {logItem.detail.name} with config ID {logItem.item_id}. + on app {logItem.detail?.name} with config ID {logItem.item_id}. } /> @@ -177,7 +177,7 @@ export function pluginActivityDescriber(logItem: ActivityLogItem, asNotification } if (logItem.activity.startsWith('attachment_')) { - for (const change of logItem.detail.changes || []) { + for (const change of logItem.detail?.changes || []) { let changeWording: string | JSX.Element = '' if (logItem.activity === 'attachment_created') { @@ -213,7 +213,7 @@ export function pluginActivityDescriber(logItem: ActivityLogItem, asNotification description: ( <> {userNameForLogItem(logItem)} {changeWording} on app:{' '} - {logItem.detail.name} with config ID {logItem.item_id} + {logItem.detail?.name} with config ID {logItem.item_id} ), } diff --git a/frontend/src/scenes/saved-insights/activityDescriptions.tsx b/frontend/src/scenes/saved-insights/activityDescriptions.tsx index bca2dacda8cbe..feb72e5ef65e3 100644 --- a/frontend/src/scenes/saved-insights/activityDescriptions.tsx +++ b/frontend/src/scenes/saved-insights/activityDescriptions.tsx @@ -64,7 +64,7 @@ const insightActionsMapping: Record< description: [ <> renamed {asNotification && 'the insight '}"{change?.before}" to{' '} - "{nameOrLinkToInsight(logItem?.detail.short_id, change?.after as string)}" + "{nameOrLinkToInsight(logItem.detail?.short_id, change?.after as string)}" , ], suffix: <>, @@ -96,7 +96,7 @@ const insightActionsMapping: Record< {asNotification && ' the insight '} , ], - suffix: <>{nameOrLinkToInsight(logItem?.detail.short_id, logItem?.detail.name)}, + suffix: <>{nameOrLinkToInsight(logItem.detail?.short_id, logItem.detail?.name)}, } }, short_id: function onShortId(change, _, asNotification) { @@ -114,7 +114,7 @@ const insightActionsMapping: Record< description: [ <> renamed {asNotification && ' the insight '}"{change?.before}" to{' '} - "{nameOrLinkToInsight(logItem?.detail.short_id, change?.after as string)}" + "{nameOrLinkToInsight(logItem.detail?.short_id, change?.after as string)}" , ], suffix: <>, @@ -140,7 +140,7 @@ const insightActionsMapping: Record< , ], - suffix: <>{nameOrLinkToInsight(logItem?.detail.short_id, logItem?.detail.name)}, + suffix: <>{nameOrLinkToInsight(logItem.detail?.short_id, logItem.detail?.name)}, } }, tags: function onTags(change) { @@ -185,7 +185,7 @@ const insightActionsMapping: Record< prefix={ <> added {asNotification && ' the insight '} - {nameOrLinkToInsight(logItem?.detail.short_id, logItem?.detail.name)} to + {nameOrLinkToInsight(logItem.detail?.short_id, logItem.detail?.name)} to } listParts={addedDashboards.map((d) => ( @@ -199,7 +199,7 @@ const insightActionsMapping: Record< prefix={ <> removed {asNotification && ' the insight '} - {nameOrLinkToInsight(logItem?.detail.short_id, logItem?.detail.name)} from + {nameOrLinkToInsight(logItem.detail?.short_id, logItem.detail?.name)} from } listParts={removedDashboards.map((d) => ( @@ -255,7 +255,7 @@ export function insightActivityDescriber(logItem: ActivityLogItem, asNotificatio description: ( <> {userNameForLogItem(logItem)} created the insight:{' '} - {nameOrLinkToInsight(logItem?.detail.short_id, logItem?.detail.name)} + {nameOrLinkToInsight(logItem.detail?.short_id, logItem.detail?.name)} ), } @@ -266,7 +266,7 @@ export function insightActivityDescriber(logItem: ActivityLogItem, asNotificatio description: ( <> {userNameForLogItem(logItem)} deleted {asNotification ? 'your' : 'the'} insight:{' '} - {logItem.detail.name} + {logItem.detail?.name} ), } @@ -276,7 +276,7 @@ export function insightActivityDescriber(logItem: ActivityLogItem, asNotificatio return { description: ( <> - PostHog exported {asNotification ? 'your' : 'the'} insight: {logItem.detail.name}{' '} + PostHog exported {asNotification ? 'your' : 'the'} insight: {logItem.detail?.name}{' '} as an image for the shared insight link. ), @@ -288,7 +288,7 @@ export function insightActivityDescriber(logItem: ActivityLogItem, asNotificatio description: ( <> {userNameForLogItem(logItem)} shared {asNotification ? 'your' : 'the'} insight:{' '} - {logItem.detail.name}. + {logItem.detail?.name}. ), } @@ -299,7 +299,7 @@ export function insightActivityDescriber(logItem: ActivityLogItem, asNotificatio description: ( <> {userNameForLogItem(logItem)} deleted shared link for{' '} - {asNotification ? 'your' : 'the'} insight: {logItem.detail.name}. + {asNotification ? 'your' : 'the'} insight: {logItem.detail?.name}. ), } @@ -311,12 +311,12 @@ export function insightActivityDescriber(logItem: ActivityLogItem, asNotificatio let changeSuffix: Description = ( <> on {asNotification && ' the insight '} - {nameOrLinkToInsight(logItem?.detail.short_id, logItem?.detail.name)} + {nameOrLinkToInsight(logItem.detail?.short_id, logItem.detail?.name)} ) try { - for (const change of logItem.detail.changes || []) { + for (const change of logItem.detail?.changes || []) { if (!change?.field || !insightActionsMapping[change.field]) { continue // insight updates have to have a "field" to be described } @@ -357,7 +357,7 @@ export function insightActivityDescriber(logItem: ActivityLogItem, asNotificatio } } if (logItem.activity === 'exported') { - const exportFormat = logItem.detail.changes?.[0]?.after + const exportFormat = logItem.detail?.changes?.[0]?.after let exportType = 'in an unknown format' if (typeof exportFormat === 'string') { exportType = exportFormat.split('/')[1] @@ -367,11 +367,11 @@ export function insightActivityDescriber(logItem: ActivityLogItem, asNotificatio description: ( <> {userNameForLogItem(logItem)} exported{' '} - {nameOrLinkToInsight(logItem?.detail.short_id, logItem?.detail.name)} as a {exportType} + {nameOrLinkToInsight(logItem.detail?.short_id, logItem.detail?.name)} as a {exportType} ), } } - return defaultDescriber(logItem, asNotification, nameOrLinkToInsight(logItem?.detail.short_id)) + return defaultDescriber(logItem, asNotification, nameOrLinkToInsight(logItem.detail?.short_id)) }