[BREAKING-CHANGE] Add NOT_RECORDED call recording status (#23478)

Adds NOT_RECORDED to the CallRecording status select, for meetings where
nothing was captured (bot never admitted, meeting not started, nobody
joined). First part of twentyhq/core-team-issues#2706, split out so
existing workspaces are upgraded before the call-recorder app starts
writing the new status.

- NOT_RECORDED enum value + standard select option
- 2-26 workspace upgrade command adding the option to existing
workspaces (idempotent, same option id as the standard definition)

App-side classification from Recall sub codes comes in a follow-up PR.

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/23478?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->
This commit is contained in:
nitin
2026-07-29 20:14:51 +05:30
committed by GitHub
parent 4ec65ed08d
commit 742f76e318
7 changed files with 212 additions and 3 deletions
@@ -3,6 +3,7 @@ import { styled } from '@linaria/react';
import { t } from '@lingui/core/macro';
import { useId } from 'react';
import { createPortal } from 'react-dom';
import { assertUnreachable } from 'twenty-shared/utils';
import { AppTooltip, TooltipDelay, TooltipPosition } from 'twenty-ui/surfaces';
import { CallRecordingStatus } from '~/generated/graphql';
@@ -12,6 +13,11 @@ const IN_PROGRESS_CALL_RECORDING_STATUSES: CallRecordingStatus[] = [
CallRecordingStatus.PROCESSING,
];
const UNAVAILABLE_CALL_RECORDING_STATUSES: CallRecordingStatus[] = [
CallRecordingStatus.FAILED,
CallRecordingStatus.NOT_RECORDED,
];
const getCallRecordingStatusLabel = (status: CallRecordingStatus) => {
switch (status) {
case CallRecordingStatus.SCHEDULED:
@@ -26,6 +32,10 @@ const getCallRecordingStatusLabel = (status: CallRecordingStatus) => {
return t`Completed`;
case CallRecordingStatus.FAILED:
return t`Failed`;
case CallRecordingStatus.NOT_RECORDED:
return t`Not recorded`;
default:
return assertUnreachable(status);
}
};
@@ -44,12 +54,12 @@ export const CalendarEventCallRecorderAvatar = ({
status,
}: CalendarEventCallRecorderAvatarProps) => {
const instanceId = useId();
const hasFailed = status === CallRecordingStatus.FAILED;
const hasNoRecording = UNAVAILABLE_CALL_RECORDING_STATUSES.includes(status);
const tooltipAnchorId = `call-recorder-${instanceId.replace(/[^a-zA-Z0-9-_]/g, '-')}`;
return (
<>
<StyledContainer id={tooltipAnchorId} isDisabled={hasFailed}>
<StyledContainer id={tooltipAnchorId} isDisabled={hasNoRecording}>
<AppChip
applicationId={applicationId}
fallbackApplicationData={{ name: t`Call recorder` }}