Commit Graph
9493 Commits
Author SHA1 Message Date
Félix MalfaitandGitHub fb41b116a4 Add Quick Lead workflow integration tests (#16862)
## Description

This PR adds integration tests for the Quick Lead workflow, including a
complete end-to-end test with full workflow execution.

### Key Changes

1. **Enabled SyncDriver for integration tests** - Jobs are now processed
synchronously in tests
   - Modified `create-app.ts` to use `SyncDriver` instead of `BullMQ`
- Added `MessageQueueExplorer` to discover and register workflow job
handlers
   - This enables complete workflow execution in integration tests

2. **Added integration tests for Quick Lead workflow**:
   - Verify workflow exists and is active
- Verify workflow version has correct structure (MANUAL trigger, FORM
step, CREATE_RECORD steps)
- Test workflow triggering creates workflow run with correct initial
state
   - Test stop workflow run on a running workflow
- **Full end-to-end test**: trigger → submit form → verify Company and
Person records created

### Test Coverage

The complete end-to-end test verifies:
- Workflow triggers and is in RUNNING status (waiting on FORM step)
- Form submission with test data succeeds
- Workflow completes successfully with all steps in SUCCESS status
- Company record is created with correct name and domain
- Person record is created with correct name and email
- Records are properly cleaned up after test

### How to Run Tests

```bash
npx nx run twenty-server:test:integration -- --testPathPattern="quick-lead-workflow"
```

Or with database reset:

```bash
npx nx run twenty-server:test:integration:with-db-reset -- --testPathPattern="quick-lead-workflow"
```
2025-12-30 18:02:04 +01:00
a2872b02ed Deleted at improvement (#16732)
Disable Deactivate option for all standard fields

#16706 

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Prevents deactivation UI for standard system fields on the field edit
page.
> 
> - Introduces `canFieldBeDeactivated` to flag standard fields
(`createdAt`, `createdBy`, `deletedAt`, `updatedAt`)
> - Hides the "Danger zone" (deactivate/activate/delete controls) when
`!isLabelIdentifier && !readonly && !canFieldBeDeactivated`
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
b309815700. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
2025-12-30 16:52:17 +00:00
61addf8b62 fix(email threads): linkify Email body so that URL links are properly formatted (#16415)
Closes #16396

Added [linkify-react](https://www.npmjs.com/package/linkify-react) and
[linkifyjs](https://www.npmjs.com/package/linkifyjs?activeTab=versions)
to dependancies.
Both are widely used libraries with millions of weekly downloads. 
Both of them have 0 dependancies on other packages, so should be safe to
use.

### Before
URLs were shown as plain text

<img width="395" height="699" alt="Screenshot 2025-12-09 at 12 25 03 PM"
src="https://github.com/user-attachments/assets/772e6d03-8c48-45a1-985c-f775bbd3465c"
/>


### After
URLs are shown as link and are clickable now.

<img width="367" height="641" alt="Screenshot 2025-12-09 at 2 50 29 PM"
src="https://github.com/user-attachments/assets/d15bf23a-7cae-4cd4-b9da-e99706c7db38"
/>

<img width="376" height="656" alt="Screenshot 2025-12-09 at 2 50 46 PM"
src="https://github.com/user-attachments/assets/ba112a65-7550-47e3-b42f-83b94c08bfa6"
/>

---------

Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
2025-12-30 16:49:31 +00:00
MarieandGitHub 64d75d0b79 Fix E2E tests + Skip chromatic (#16838)
- Always skip chromatic job (we dont check the outcome)
- Fix workflow creation test
- Run E2E tests before merge (to enable through repo rulesets)
2025-12-30 15:57:38 +00:00
Paul RastoinandGitHub 1128331cc1 Fix field item type tag (#16860)
# Introduction
This has been fixed on main already 1 hour ago, this PR now only passes
the field application id instead of the object applicationId that could
be different for example when creating a custom field on a standard
object

For the moment not introducing any logic around application integrity
directly and still relying on the isCustom and standardId definition
This will have to be refactored once we deprecate the standardId
2025-12-30 15:02:07 +00:00
Baptiste DevessierandGitHub aac70c679f Field widget fix dropdowns (#16855)
## Before


https://github.com/user-attachments/assets/a78f6561-a519-455e-a838-c4e138fb336f

## After


https://github.com/user-attachments/assets/ec704406-b16b-491a-8a88-8aa6fe25254b

Closes https://github.com/twentyhq/core-team-issues/issues/2023
2025-12-30 14:43:58 +00:00
WeikoandGitHub ab95437065 Create query runner context from request context instead of schema builder internal context (#16858)
## Context
This PR refactors how authentication context is handled in the GraphQL
resolver layer. Previously, the auth context was baked into the schema
builder context at schema creation time. Now, the auth context is
extracted from the request at query execution time, enabling better
schema caching.

## Implementation
- Removed user-specific data from schema cache key: The schema cache key
no longer includes userId and apiKeyId, allowing the same schema to be
shared across all users in a workspace
- Cache key simplified from
${workspaceId}-${userId}-${apiKeyId}-${url}-${cacheVersion} to
${workspaceId}-${url}-${cacheVersion}
- Removed authContext from WorkspaceSchemaBuilderContext: The schema
builder context is now purely about object/field metadata, not about who
is accessing it
- Created createQueryRunnerContext utility: A new helper that combines
the schema builder context with the auth context from the actual request
- Updated all resolver factories: All 15 resolver factories now use
createQueryRunnerContext to build the full context needed by query
runners at execution time

## Benefits
- Improved cache efficiency: GraphQL schemas are now cached per
workspace rather than per user, significantly reducing memory usage and
schema regeneration
- Cleaner separation of concerns: Schema building (metadata-driven) is
now separate from query execution (auth-driven)
- Fresh auth context: Auth context is always retrieved from the current
request, ensuring it reflects the latest state
- Reduced complexity: Simplified the schema creation path by removing
unnecessary auth checks

## Next steps
- Introduce a hash in redis and expose it in the req object so the yoga
patch can access the hash and use it during its own cache key
computation. This way we will be able to invalidate the local cache in
yoga graphql schema generation without restarting pods.
2025-12-30 15:16:57 +01:00
Paul RastoinandGitHub e3ffdb0c2b [BREAKING_CHANGE_NESTED_WORKSPACE]Refactor FlatEntity typing in aim of introducing UniversalFlatEntity (#16701)
# Introduction
Added a `WorkspaceRelated` and `AllNonWorkspaceRelatedEntity` to
simplify the `FlatEntityFrom` that now do not expect a string literal to
omit and itself builds the related many to one entities foreign key
aggregators

We now have the type grain over relation to syncable or just workspace
related entities

Added a migrations that sets the fk on missing entities

## Next
In upcoming PR we will be able to introduce such below type
```ts
import { type CastRecordTypeOrmDatePropertiesToString } from 'src/engine/metadata-modules/flat-entity/types/cast-record-typeorm-date-properties-to-string.type';
import { type ExtractEntityManyToOneEntityRelationProperties } from 'src/engine/metadata-modules/flat-entity/types/extract-entity-many-to-one-entity-relation-properties.type';
import { type ExtractEntityOneToManyEntityRelationProperties } from 'src/engine/metadata-modules/flat-entity/types/extract-entity-one-to-many-entity-relation-properties.type';
import { type ExtractEntityRelatedEntityProperties } from 'src/engine/metadata-modules/flat-entity/types/extract-entity-related-entity-properties.type';
import { type RemoveSuffix } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/remove-suffix.type';
import { type SyncableEntity } from 'src/engine/workspace-manager/workspace-sync/types/syncable-entity.interface';

export type UniversalFlatEntityFrom<TEntity extends SyncableEntity> = Omit<
  TEntity,
  | `${ExtractEntityManyToOneEntityRelationProperties<TEntity> & string}Id`
  | ExtractEntityRelatedEntityProperties<TEntity>
  | 'application'
  | 'workspaceId'
  | 'applicationId'
  | keyof CastRecordTypeOrmDatePropertiesToString<TEntity>
> &
  CastRecordTypeOrmDatePropertiesToString<TEntity> & {
    [P in ExtractEntityManyToOneEntityRelationProperties<TEntity> &
      string as `${RemoveSuffix<P, 's'>}UniversalIdentifier`]: string;
  } & {
    [P in ExtractEntityOneToManyEntityRelationProperties<
      TEntity,
      SyncableEntity
    > &
      string as `${RemoveSuffix<P, 's'>}UniversalIdentifiers`]: string[];
  };

```
2025-12-30 13:47:02 +00:00
720348c583 Add upgrade commands to backfill updatedBy field and view fields (#16845)
---
prastoin edit
## Introduction
As we're deprecating the sync metadata we cannot rely on it anymore in
order to create the new standard updatedBy field
In this PR we introduce a command that will backfill the dynamic field
on both workspace standard and custom objects, for standard object it
will create a standard fields ( twenty-standard app scoped ) and for
custom one it will create a custom field ( worksapce-custom-app scoped )

## Testing method
Checkout `1.14.0` `yarn` and `npx nx database:reset twenty-server`
checkout PR and `yarn` `npx nx build twenty-server` and `yarn
database:migrate:prod` finally running the command

#### Before
<img width="2244" height="1464" alt="image"
src="https://github.com/user-attachments/assets/2fb866cd-13b8-4152-99b8-1fcc813b1d46"
/>

#### After
<img width="2244" height="1464" alt="image"
src="https://github.com/user-attachments/assets/b836ac06-c7b8-4add-bee1-bc1963418f29"
/>


#### Logs
```ts
[Nest] 20678  - 12/30/2025, 1:47:35 PM     LOG [BackfillUpdatedByFieldCommand] Found 12 objects that need updatedBy field
[EntityBuilder fieldMetadata] matrix computation: 3.994ms
[EntityBuilder fieldMetadata] creation validation: 1.822ms
[EntityBuilder fieldMetadata] deletion validation: 0.016ms
[EntityBuilder fieldMetadata] update validation: 0.009ms
[EntityBuilder fieldMetadata] entity processing: 6.098ms
[EntityBuilder fieldMetadata] validateAndBuild: 10.217ms
[EntityBuilder index] matrix computation: 0.857ms
[EntityBuilder index] creation validation: 0.003ms
[EntityBuilder index] deletion validation: 0.017ms
[EntityBuilder index] update validation: 0.008ms
[EntityBuilder index] entity processing: 4.721ms
[EntityBuilder index] validateAndBuild: 5.632ms
[Runner] Initial cache retrieval: 0.07ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForMetadata: 7.69ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForWorkspaceSchema: 10.531ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForMetadata: 5.354ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForWorkspaceSchema: 6.134ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForMetadata: 2.507ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForWorkspaceSchema: 3.745ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForMetadata: 1.113ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForWorkspaceSchema: 1.585ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForMetadata: 1.223ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForWorkspaceSchema: 2.221ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForMetadata: 5.375ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForWorkspaceSchema: 5.943ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForMetadata: 1.363ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForWorkspaceSchema: 1.997ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForMetadata: 2.03ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForWorkspaceSchema: 2.982ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForMetadata: 0.88ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForWorkspaceSchema: 2.977ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForMetadata: 9.638ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForWorkspaceSchema: 11.297ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForMetadata: 1.581ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForWorkspaceSchema: 2.248ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForMetadata: 0.847ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForWorkspaceSchema: 1.732ms
[Runner] Transaction execution: 82.555ms
[Runner] Cache invalidation flatFieldMetadataMaps,flatIndexMaps,flatObjectMetadataMaps: 89.247ms
[Runner] Total execution: 171.963ms
[Nest] 20678  - 12/30/2025, 1:47:35 PM     LOG [BackfillUpdatedByFieldCommand] Successfully backfilled updatedBy field for 12 objects in workspace 20202020-1c25-4d02-bf25-6aeccf7ea419
[Nest] 20678  - 12/30/2025, 1:47:35 PM     LOG [BackfillUpdatedByFieldCommand] Running command on workspace 3b8e6458-5fc1-4e63-8563-008ccddaa6db 2/2
[Nest] 20678  - 12/30/2025, 1:47:35 PM     LOG [BackfillUpdatedByFieldCommand] Starting backfill of updatedBy field for workspace 3b8e6458-5fc1-4e63-8563-008ccddaa6db
[Nest] 20678  - 12/30/2025, 1:47:35 PM     LOG [BackfillUpdatedByFieldCommand] Found 10 objects that need updatedBy field
[EntityBuilder fieldMetadata] matrix computation: 3.224ms
[EntityBuilder fieldMetadata] creation validation: 0.969ms
[EntityBuilder fieldMetadata] deletion validation: 0.014ms
[EntityBuilder fieldMetadata] update validation: 0.002ms
[EntityBuilder fieldMetadata] entity processing: 5.149ms
[EntityBuilder fieldMetadata] validateAndBuild: 8.472ms
[EntityBuilder index] matrix computation: 0.785ms
[EntityBuilder index] creation validation: 0.002ms
[EntityBuilder index] deletion validation: 0.014ms
[EntityBuilder index] update validation: 0.002ms
[EntityBuilder index] entity processing: 3.818ms
[EntityBuilder index] validateAndBuild: 4.637ms
[Runner] Initial cache retrieval: 0.05ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForMetadata: 2.964ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForWorkspaceSchema: 3.902ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForMetadata: 1.502ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForWorkspaceSchema: 2.039ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForMetadata: 2.673ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForWorkspaceSchema: 3.403ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForMetadata: 1.143ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForWorkspaceSchema: 2.123ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForMetadata: 2.033ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForWorkspaceSchema: 2.954ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForMetadata: 1.826ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForWorkspaceSchema: 2.903ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForMetadata: 1.495ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForWorkspaceSchema: 2.106ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForMetadata: 14.014ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForWorkspaceSchema: 14.373ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForMetadata: 1.669ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForWorkspaceSchema: 2.48ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForMetadata: 0.62ms
[BaseWorkspaceMigrationRunnerActionHandlerService] create_field executeForWorkspaceSchema: 1.048ms
[Runner] Transaction execution: 73.222ms
[Runner] Cache invalidation flatFieldMetadataMaps,flatIndexMaps,flatObjectMetadataMaps: 37.703ms
[Runner] Total execution: 111.071ms
```
---

---------

Co-authored-by: prastoin <paul@twenty.com>
2025-12-30 14:05:26 +01:00
Harshit SinghandGitHub a0491e4755 fix: images are not included in PDF exports (#16076)
## Description

- This PR address issue https://github.com/twentyhq/twenty/issues/15998
- The issue was that images are stored as signed urls and the backend
signed these with JWT
- BlockNote `resolveFileUrl` uses a public CORS proxy that couldn’t
access authenticated/signed URLs



## Visual Appearance



https://github.com/user-attachments/assets/12936451-d91d-4371-bcf7-8a2c2bb68e9c
2025-12-30 11:29:30 +01:00
a2827494a1 Support actor filtering in workflows (#16783)
Fixes https://github.com/twentyhq/twenty/issues/15782

Find records
<img width="422" height="423" alt="Capture d’écran 2025-12-23 à 16 23
49"
src="https://github.com/user-attachments/assets/5856de06-d608-46f6-97a6-8f382f355a44"
/>

Filters
<img width="422" height="271" alt="Capture d’écran 2025-12-23 à 16 23
32"
src="https://github.com/user-attachments/assets/fcc10b6e-f1ec-497a-8593-d599164d4e4b"
/>

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Adds full support for filtering on `ACTOR` composite fields across UI
and server.
> 
> - Front-end: handles `ACTOR` in advanced filters and workflow filters;
`source` uses multi-select options from `FieldActorSource`,
`workspaceMemberId` uses `FormSingleRecordPicker`, others default to
text
> - Updates operand mapping for `ACTOR` (`source`→`SELECT`,
`workspaceMemberId`→`RELATION`, else `TEXT`)
> - Server: adds `ACTOR` evaluation with subfield-specific logic
(delegates to select/relation/text evaluators)
> - Simplifies `AdvancedFilterFieldSelectMenu` by removing
workflow-specific field filtering
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
7a8164cd2d. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Félix Malfait <felix@twenty.com>
2025-12-30 09:34:08 +00:00
d39f105a03 i18n - translations (#16849)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2025-12-30 10:21:48 +01:00
MarieandGitHub 19c9f957b1 Improve userFriendlyMessage devX (#16815)
Two challenges with error messages
- always provide a useful/meaningful error message for the end user
instead of the generic one. eg: show "Wrong password" and not "An error
occured"
- avoid technical details unless error regards a technical feature. eg:
show "An error occured" and not "Invalid post-hook payload."; but do
show "Invalid issuer URL." as it occurs while configuring SSO

What this PR does
- Make userFriendlyMessage mandatory for widely used
GraphqlQueryRunnerException and CommonQueryRunnerException, so that
developers are forced to ask themselves what the error message should
be, and as it contains very wide error codes (eg: "Bad request") which
should not be mapped to just one default message
- Keep userFriendlyMessage optional for service-specific exceptions (eg:
workflowStepExecutorException), but convert the error code to
userFriendlyMessage mapper to a switch case function with a typecheck
ensuring that all codes are mapped to a message. These default messages
are still overridable where they are thrown.
2025-12-30 09:08:43 +00:00
7522ff6675 i18n - translations (#16848)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2025-12-30 10:03:15 +01:00
418377b867 i18n - translations (#16847)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2025-12-30 09:51:57 +01:00
Félix MalfaitandGitHub 4f1f0eb177 Redesign Object/Field tables (#16844)
Redesign the data model pages for more clarity / better distinction
between fields and relations
2025-12-30 09:49:55 +01:00
8d130908c2 Allow user to update profile picture (#16812)
Fixes [#16805](https://github.com/twentyhq/twenty/issues/16805)

User was not able to update his own profile picture it showed permisson
error while doing so.

Updated permission so that user is able to edit profile picture

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Ensures profile picture uploads succeed only with appropriate
permissions and clearer errors.
> 
> - Tightens `UploadProfilePicturePermissionGuard` to handle missing
`workspace`, allow during workspace creation, and permit uploads when
user has `WORKSPACE_MEMBERS` or `PROFILE_INFORMATION` settings;
otherwise throws a `PermissionsException` with a user-friendly message
> - In `user-workspace.resolver.ts`, validates the upload result and
throws an error if no files were returned
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
3766bac15e. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Félix Malfait <felix@twenty.com>
2025-12-30 09:46:10 +01:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Abdullah
3096769616 build(deps): bump @monaco-editor/react from 4.6.0 to 4.7.0 (#16829)
Bumps
[@monaco-editor/react](https://github.com/suren-atoyan/monaco-react)
from 4.6.0 to 4.7.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/suren-atoyan/monaco-react/releases"><code>@​monaco-editor/react</code>'s
releases</a>.</em></p>
<blockquote>
<h2>v4.7.0</h2>
<ul>
<li>package: update <code>@monaco-editor/loader</code> to the latest
(<code>v1.5.0</code>) version (this uses <code>monaco-editor</code>
<code>v0.52.2</code>)</li>
<li>package: inherit all changes from <code>v4.7.0-rc.0</code></li>
</ul>
<h2>v4.7.0-rc.0</h2>
<ul>
<li>package: add support for react/react-dom <code>v19</code> as a peer
dependency</li>
<li>playground: update playground's React version to 19</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/suren-atoyan/monaco-react/blob/master/CHANGELOG.md"><code>@​monaco-editor/react</code>'s
changelog</a>.</em></p>
<blockquote>
<h2>4.7.0</h2>
<ul>
<li>package: update <code>@​monaco-editor/loader</code> to the latest
(v1.5.0) version (this uses monaco-editor v0.52.2)</li>
<li>package: inherit all changes from v4.7.0-rc.0</li>
</ul>
<h2>4.7.0-rc.0</h2>
<ul>
<li>package: add support for react/react-dom v19 as a peer
dependency</li>
<li>playground: update playground's React version to 19</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/suren-atoyan/monaco-react/commit/eb120e66378471315620fe5339b73ba003f199ad"><code>eb120e6</code></a>
update package to 4.7.0 version</li>
<li><a
href="https://github.com/suren-atoyan/monaco-react/commit/cdd070c9f080caf4a9a7b13c2c34fa4e10edc9bf"><code>cdd070c</code></a>
update snapshots</li>
<li><a
href="https://github.com/suren-atoyan/monaco-react/commit/55a063e45d2f2672884b77059ac97850758764ae"><code>55a063e</code></a>
update <code>@​monaco-editor/loader</code> to the latest (v1.5.0)
version</li>
<li><a
href="https://github.com/suren-atoyan/monaco-react/commit/52e8c75616e09730b7b1a0b5822385212a082ce8"><code>52e8c75</code></a>
update package to 4.7.0-rc.o version</li>
<li><a
href="https://github.com/suren-atoyan/monaco-react/commit/e72be4edc1b4492eae9f7d85671ee61a43a6aee8"><code>e72be4e</code></a>
add react 19 to peerDependencies</li>
<li><a
href="https://github.com/suren-atoyan/monaco-react/commit/642be903a9dd21d6fe639ab5c92c234dad77c813"><code>642be90</code></a>
update playground's react version to 19</li>
<li><a
href="https://github.com/suren-atoyan/monaco-react/commit/ceee344fbe26285dabb0fe90985fe18ec867211c"><code>ceee344</code></a>
Add Monaco-React AI Bot in Readme (<a
href="https://redirect.github.com/suren-atoyan/monaco-react/issues/655">#655</a>)</li>
<li><a
href="https://github.com/suren-atoyan/monaco-react/commit/f7cac39fbad0f062dc66458831aaf57a7126dd40"><code>f7cac39</code></a>
add electron blog post link</li>
<li><a
href="https://github.com/suren-atoyan/monaco-react/commit/ea601cf9f6fe9f2cc0c6271d6a9cde9a332b6dc0"><code>ea601cf</code></a>
add tea constitution file</li>
<li><a
href="https://github.com/suren-atoyan/monaco-react/commit/3327f3c368cb6d56c02f2df8a9d45177ce6f52e9"><code>3327f3c</code></a>
add GitHub sponsor button</li>
<li>See full diff in <a
href="https://github.com/suren-atoyan/monaco-react/compare/v4.6.0...v4.7.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@monaco-editor/react&package-manager=npm_and_yarn&previous-version=4.6.0&new-version=4.7.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Abdullah <125115953+mabdullahabaid@users.noreply.github.com>
2025-12-29 20:01:05 +01:00
Félix MalfaitandGitHub 3a673f99ba Disable updated By 2 (#16840)
Prepare for release, will re-enable them
2025-12-29 18:57:17 +01:00
e5e5ae8e1d fix: guard against invalid date and undefined links field value (#16039)
closes https://github.com/twentyhq/twenty/issues/15854

- Add `isValid()` check in `formatDateISOStringToDateTime` before
calling `formatInTimeZone`
- Add `isDefined()` guard in `getFieldLinkDefinedLinks` (mirrors
`phonesUtils` pattern)

before:


https://github.com/user-attachments/assets/1eb89fa4-70b6-4794-8860-0a42522598b5



https://github.com/user-attachments/assets/781c7d37-c435-4832-98d4-8e6925b51e10



after:


https://github.com/user-attachments/assets/b1c22d25-4e8e-45c3-af98-be1684a5962e



https://github.com/user-attachments/assets/ce084a9d-03b8-4f88-8522-a32cb1b7cf2f

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
2025-12-29 17:03:24 +00:00
Félix MalfaitandGitHub b56dcd8c22 Temporarily disable updatedBy (#16839)
To avoid breaking workflows during release
2025-12-29 17:06:16 +01:00
ba7a060195 i18n - translations (#16836)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2025-12-29 16:01:01 +01:00
4135a6473a [BREAKING_CHANGE_DASHBOARDS][DASHBOARD_CACHE_FLUSH_REQUIRED] Refactor page layout widget configuration type (#16671)
# Introduction
In this pull-request we're refactoring the page layout widget
configuration entity to be containing its discriminated key simplifying
underlying code and maintainability
- Made the configuration and title non nullable
- Introduced a generic predicate for the `widgetConfigurationType`
- Upgraded command to remove `graphType` and insert new
`configurationType` to existing entries
- Migrated frontend to new type system

---------

Co-authored-by: bosiraphael <raphael.bosi@gmail.com>
Co-authored-by: Raphaël Bosi <71827178+bosiraphael@users.noreply.github.com>
2025-12-29 15:46:59 +01:00
2b9728230a Correctly separate widgets in side-column mode. (#16804)
Had to close the other PR since I messed up re-basing somehow:
https://github.com/twentyhq/twenty/pull/16668/files.

Moved changes to this new PR in order to resolve comments from the
previous PR and also match the field-design to that on Figma.

---------

Co-authored-by: Baptiste Devessier <baptiste@devessier.fr>
2025-12-29 15:00:33 +01:00
Abdullah.andGitHub bee58fd03d feat: use side-column variant for all widgets on mobile and side panel (#16822)
Closes [1957](https://github.com/twentyhq/core-team-issues/issues/1957).

`getWidgetCardVariant` now returns `side-panel` for mobile and right
drawer instead of returning `record-page`.

Added stories to WidgetRenderer.stories.tsx because WidgetRenderer is
where getWidgetCardVariant is called and the variant is applied. These
stories test the actual behavior (mobile/side panel triggering
side-column variant) rather than just visual appearance, following the
existing pattern of individual behavior-testing stories in this file.
2025-12-29 14:02:52 +01:00
MarieandGitHub bb18f78f1b [Fix] Fix NaN position in notes resulting in not being able to create notes (#16818)
Following [discord
thread](https://discord.com/channels/1130383047699738754/1453910755387899996/1453910755387899996),
reproductible on twenty-eng


https://github.com/user-attachments/assets/ae7f363d-87e1-44fa-8fe2-ee78412d62a7

Records positions are computed at record creation, depending on the
position arg from the request, being equal to `last`, `first`, or not
present.
When being equal to last, as it is done when creating a note from the
product, the position is calculated using `.maximum()` function which
uses postgres' MAX function. If there is a `NaN` value among the list,
the MAX will return `NaN` too. So if for some reason there is a NaN
somewhere in the position column, all subsequent records being created
with last position argument will be created with NaN value. Until [this
PR](https://github.com/twentyhq/twenty/pull/16630), where we introduced
a validation on position at record creation which throws when NaN is
trying to be introduced as a position, this was going silent. (fyi
@etiennejouan , not on you at all but for info)

Looking into twenty-eng workspace, I found note records with NaN
position dating back to august 2025, making it hard to understand and
debug why they were introduced with NaN position. So I did not find the
real root cause, but I suggest to
- update record-position.service to fix the issue for subsequent records
that go through this service (which is what is currently broken)
- run a command to fix the existing records with NaN position for Notes,
as it is where the issue happened for both the user reporting the issue
on discord, and us on twenty-eng. So hopefully the problem was limited
to Notes
2025-12-29 13:55:20 +01:00
ee0e2ed854 i18n - translations (#16832)
Created by Github action

---------

Co-authored-by: Félix Malfait <felix@twenty.com>
Co-authored-by: github-actions <github-actions@twenty.com>
2025-12-29 11:01:07 +01:00
343b74666f i18n - translations (#16831)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2025-12-29 10:22:32 +01:00
01e0502fcf feat: add updatedBy field to track last record modifier (#16807)
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> Implements last-modifier tracking and unified actor injection.
> 
> - New `ActorFromAuthContextService` replaces createdBy-only logic;
pre-query hooks now inject both `createdBy` and `updatedBy` on create
and `updatedBy` on update
> - Add `updatedBy` standard field to core/custom objects (e.g.,
`person`, `company`, `task`, `note`, `attachment`, `dashboard`,
`workflow`, `workflowRun`) with IDs, metadata builders, and ORM entity
fields
> - Record CRUD: `create` now sets both `createdBy` and `updatedBy`;
`update` sets `updatedBy`; workflow actions use a shared workflow actor
builder; REST base handler uses the new actor service
> - Seeder data and snapshots updated to include `updatedBy`; GraphQL
result formatting adds defaults/handling for empty composite fields
(incl. actor)
> - Frontend `useUpdateOneRecord` upserts returned record into the local
store after mutation
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
1f283778e9. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
Co-authored-by: Félix Malfait <felix@twenty.com>
2025-12-29 09:05:17 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Abdullah
0da5cf29de Bump eslint from 9.32.0 to 9.39.2 (#16736)
Bumps [eslint](https://github.com/eslint/eslint) from 9.32.0 to 9.39.2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/eslint/eslint/releases">eslint's
releases</a>.</em></p>
<blockquote>
<h2>v9.39.2</h2>
<h2>Bug Fixes</h2>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/57058331946568164449c5caabe2cf206e4fb5d9"><code>5705833</code></a>
fix: warn when <code>eslint-env</code> configuration comments are found
(<a
href="https://redirect.github.com/eslint/eslint/issues/20381">#20381</a>)
(sethamus)</li>
</ul>
<h2>Build Related</h2>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/506f1549a64aa65bdddc75c71cb62f0ab94b5a23"><code>506f154</code></a>
build: add .scss files entry to knip (<a
href="https://redirect.github.com/eslint/eslint/issues/20391">#20391</a>)
(Milos Djermanovic)</li>
</ul>
<h2>Chores</h2>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/7ca0af7f9f89dd4a01736dae01931c45d528171b"><code>7ca0af7</code></a>
chore: upgrade to <code>@eslint/js@9.39.2</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/20394">#20394</a>)
(Francesco Trotta)</li>
<li><a
href="https://github.com/eslint/eslint/commit/c43ce24ff0ce073ec4ad691cd5a50171dfe6cf1e"><code>c43ce24</code></a>
chore: package.json update for <code>@​eslint/js</code> release
(Jenkins)</li>
<li><a
href="https://github.com/eslint/eslint/commit/4c9858e47bb9146cf20f546a562bc58a9ee3dae1"><code>4c9858e</code></a>
ci: add <code>v9.x-dev</code> branch (<a
href="https://redirect.github.com/eslint/eslint/issues/20382">#20382</a>)
(Milos Djermanovic)</li>
</ul>
<h2>v9.39.1</h2>
<h2>Bug Fixes</h2>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/650753ee3976784343ceb40170619dab1aa9fe0d"><code>650753e</code></a>
fix: Only pass node to JS lang visitor methods (<a
href="https://redirect.github.com/eslint/eslint/issues/20283">#20283</a>)
(Nicholas C. Zakas)</li>
</ul>
<h2>Documentation</h2>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/51b51f4f1ce82ef63264c4e45d9ef579bcd73f8e"><code>51b51f4</code></a>
docs: add a section on when to use extends vs cascading (<a
href="https://redirect.github.com/eslint/eslint/issues/20268">#20268</a>)
(Tanuj Kanti)</li>
<li><a
href="https://github.com/eslint/eslint/commit/b44d42699dcd1729b7ecb50ca70e4c1c17f551f1"><code>b44d426</code></a>
docs: Update README (GitHub Actions Bot)</li>
</ul>
<h2>Chores</h2>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/92db329211c8da5ce8340a4d4c05ce9c12845381"><code>92db329</code></a>
chore: update <code>@eslint/js</code> version to 9.39.1 (<a
href="https://redirect.github.com/eslint/eslint/issues/20284">#20284</a>)
(Francesco Trotta)</li>
<li><a
href="https://github.com/eslint/eslint/commit/c7ebefc9eaf99b76b30b0d3cf9960807a47367c4"><code>c7ebefc</code></a>
chore: package.json update for <code>@​eslint/js</code> release
(Jenkins)</li>
<li><a
href="https://github.com/eslint/eslint/commit/61778f6ca33c0f63962a91d6a75a4fa5db9f47d2"><code>61778f6</code></a>
chore: update eslint-config-eslint dependency <code>@​eslint/js</code>
to ^9.39.0 (<a
href="https://redirect.github.com/eslint/eslint/issues/20275">#20275</a>)
(renovate[bot])</li>
<li><a
href="https://github.com/eslint/eslint/commit/d9ca2fcd9ad63331bfd329a69534e1ff04f231e8"><code>d9ca2fc</code></a>
ci: Add rangeStrategy to eslint group in renovate config (<a
href="https://redirect.github.com/eslint/eslint/issues/20266">#20266</a>)
(唯然)</li>
<li><a
href="https://github.com/eslint/eslint/commit/009e5076ff5a4bd845f55e17676e3bb88f47c280"><code>009e507</code></a>
test: fix version tests for ESLint v10 (<a
href="https://redirect.github.com/eslint/eslint/issues/20274">#20274</a>)
(Milos Djermanovic)</li>
</ul>
<h2>v9.39.0</h2>
<h2>Features</h2>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/cc57d87a3f119e9d39c55e044e526ae067fa31ce"><code>cc57d87</code></a>
feat: update error loc to key in <code>no-dupe-class-members</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/20259">#20259</a>)
(Tanuj Kanti)</li>
<li><a
href="https://github.com/eslint/eslint/commit/126552fcf35da3ddcefa527db06dabc54c04041c"><code>126552f</code></a>
feat: update error location in <code>for-direction</code> and
<code>no-dupe-args</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/20258">#20258</a>)
(Tanuj Kanti)</li>
<li><a
href="https://github.com/eslint/eslint/commit/167d0970d3802a66910e9820f31dcd717fab0b2a"><code>167d097</code></a>
feat: update <code>complexity</code> rule to highlight only static block
header (<a
href="https://redirect.github.com/eslint/eslint/issues/20245">#20245</a>)
(jaymarvelz)</li>
</ul>
<h2>Bug Fixes</h2>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/15f5c7c168d0698683943f51dd617f14a5e6815c"><code>15f5c7c</code></a>
fix: forward traversal <code>step.args</code> to visitors (<a
href="https://redirect.github.com/eslint/eslint/issues/20253">#20253</a>)
(jaymarvelz)</li>
<li><a
href="https://github.com/eslint/eslint/commit/5a1a534e877f7c4c992885867f923df307c3929d"><code>5a1a534</code></a>
fix: allow JSDoc comments in object-shorthand rule (<a
href="https://redirect.github.com/eslint/eslint/issues/20167">#20167</a>)
(Nitin Kumar)</li>
<li><a
href="https://github.com/eslint/eslint/commit/e86b813eb660f1a5adc8e143a70d9b683cd12362"><code>e86b813</code></a>
fix: Use more types from <code>@​eslint/core</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/20257">#20257</a>)
(Nicholas C. Zakas)</li>
<li><a
href="https://github.com/eslint/eslint/commit/927272d1f0d5683b029b729d368a96527f283323"><code>927272d</code></a>
fix: correct <code>Scope</code> typings (<a
href="https://redirect.github.com/eslint/eslint/issues/20198">#20198</a>)
(jaymarvelz)</li>
<li><a
href="https://github.com/eslint/eslint/commit/37f76d9c539bb6fc816fedb7be4486b71a58620a"><code>37f76d9</code></a>
fix: use <code>AST.Program</code> type for Program node (<a
href="https://redirect.github.com/eslint/eslint/issues/20244">#20244</a>)
(Francesco Trotta)</li>
<li><a
href="https://github.com/eslint/eslint/commit/ae07f0b3334ebd22ae2e7b09bca5973b96aa9768"><code>ae07f0b</code></a>
fix: unify timing report for concurrent linting (<a
href="https://redirect.github.com/eslint/eslint/issues/20188">#20188</a>)
(jaymarvelz)</li>
<li><a
href="https://github.com/eslint/eslint/commit/b165d471be6062f4475b972155b02654a974a0e9"><code>b165d47</code></a>
fix: correct <code>Rule</code> typings (<a
href="https://redirect.github.com/eslint/eslint/issues/20199">#20199</a>)
(jaymarvelz)</li>
<li><a
href="https://github.com/eslint/eslint/commit/fb97cda70d87286a7dbd2457f578ef578d6905e8"><code>fb97cda</code></a>
fix: improve error message for missing fix function in suggestions (<a
href="https://redirect.github.com/eslint/eslint/issues/20218">#20218</a>)
(jaymarvelz)</li>
</ul>
<h2>Documentation</h2>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/d3e81e30ee6be5a21151b7a17ef10a714b6059c0"><code>d3e81e3</code></a>
docs: Always recommend to include a files property (<a
href="https://redirect.github.com/eslint/eslint/issues/20158">#20158</a>)
(Percy Ma)</li>
<li><a
href="https://github.com/eslint/eslint/commit/0f0385f1404dcadaba4812120b1ad02334dbd66a"><code>0f0385f</code></a>
docs: use consistent naming recommendation (<a
href="https://redirect.github.com/eslint/eslint/issues/20250">#20250</a>)
(Alex M. Spieslechner)</li>
<li><a
href="https://github.com/eslint/eslint/commit/a3b145609ac649fac837c8c0515cbb2a9321ca40"><code>a3b1456</code></a>
docs: Update README (GitHub Actions Bot)</li>
<li><a
href="https://github.com/eslint/eslint/commit/cf5f2dd58dd98084a21da04fe7b9054b9478d552"><code>cf5f2dd</code></a>
docs: fix correct tag of <code>no-useless-constructor</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/20255">#20255</a>)
(Tanuj Kanti)</li>
<li><a
href="https://github.com/eslint/eslint/commit/10b995c8e5473de8d66d3cd99d816e046f35e3ec"><code>10b995c</code></a>
docs: add TS options and examples for <code>nofunc</code> in
<code>no-use-before-define</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/20249">#20249</a>)
(Tanuj Kanti)</li>
<li><a
href="https://github.com/eslint/eslint/commit/2584187e4a305ea7a98e1a5bd4dca2a60ad132f8"><code>2584187</code></a>
docs: remove repetitive word in comment (<a
href="https://redirect.github.com/eslint/eslint/issues/20242">#20242</a>)
(reddaisyy)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/9278324aa0023d223874825b0d4b6ac75783096a"><code>9278324</code></a>
9.39.2</li>
<li><a
href="https://github.com/eslint/eslint/commit/542266ad3c58b47066d4b8ae61d419b423acee8f"><code>542266a</code></a>
Build: changelog update for 9.39.2</li>
<li><a
href="https://github.com/eslint/eslint/commit/7ca0af7f9f89dd4a01736dae01931c45d528171b"><code>7ca0af7</code></a>
chore: upgrade to <code>@eslint/js@9.39.2</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/20394">#20394</a>)</li>
<li><a
href="https://github.com/eslint/eslint/commit/c43ce24ff0ce073ec4ad691cd5a50171dfe6cf1e"><code>c43ce24</code></a>
chore: package.json update for <code>@​eslint/js</code> release</li>
<li><a
href="https://github.com/eslint/eslint/commit/57058331946568164449c5caabe2cf206e4fb5d9"><code>5705833</code></a>
fix: warn when <code>eslint-env</code> configuration comments are found
(<a
href="https://redirect.github.com/eslint/eslint/issues/20381">#20381</a>)</li>
<li><a
href="https://github.com/eslint/eslint/commit/506f1549a64aa65bdddc75c71cb62f0ab94b5a23"><code>506f154</code></a>
build: add .scss files entry to knip (<a
href="https://redirect.github.com/eslint/eslint/issues/20391">#20391</a>)</li>
<li><a
href="https://github.com/eslint/eslint/commit/4c9858e47bb9146cf20f546a562bc58a9ee3dae1"><code>4c9858e</code></a>
ci: add <code>v9.x-dev</code> branch (<a
href="https://redirect.github.com/eslint/eslint/issues/20382">#20382</a>)</li>
<li><a
href="https://github.com/eslint/eslint/commit/e2772811a8595d161870835ff04822b25a2cdf45"><code>e277281</code></a>
9.39.1</li>
<li><a
href="https://github.com/eslint/eslint/commit/4cdf397b30b2b749865ea0fcf4d30eb8ba458896"><code>4cdf397</code></a>
Build: changelog update for 9.39.1</li>
<li><a
href="https://github.com/eslint/eslint/commit/92db329211c8da5ce8340a4d4c05ce9c12845381"><code>92db329</code></a>
chore: update <code>@eslint/js</code> version to 9.39.1 (<a
href="https://redirect.github.com/eslint/eslint/issues/20284">#20284</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/eslint/eslint/compare/v9.32.0...v9.39.2">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=eslint&package-manager=npm_and_yarn&previous-version=9.32.0&new-version=9.39.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Abdullah <125115953+mabdullahabaid@users.noreply.github.com>
2025-12-29 12:24:55 +05:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
3278950415 build(deps-dev): bump msw-storybook-addon from 2.0.5 to 2.0.6 (#16830)
Bumps
[msw-storybook-addon](https://github.com/mswjs/msw-storybook-addon/tree/HEAD/packages/msw-addon)
from 2.0.5 to 2.0.6.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/mswjs/msw-storybook-addon/releases">msw-storybook-addon's
releases</a>.</em></p>
<blockquote>
<h2>v2.0.6</h2>
<h4>🐛 Bug Fix</h4>
<ul>
<li>fix: add a <code>@deprecated</code> tag to the
<code>mswDecorator</code> <a
href="https://redirect.github.com/mswjs/msw-storybook-addon/pull/178">#178</a>
(<a
href="https://github.com/connorshea"><code>@​connorshea</code></a>)</li>
</ul>
<h4>Authors: 1</h4>
<ul>
<li>Connor Shea (<a
href="https://github.com/connorshea"><code>@​connorshea</code></a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/mswjs/msw-storybook-addon/blob/main/packages/msw-addon/CHANGELOG.md">msw-storybook-addon's
changelog</a>.</em></p>
<blockquote>
<h1>v2.0.6 (Fri Oct 10 2025)</h1>
<h4>🐛 Bug Fix</h4>
<ul>
<li>fix: add a <code>@deprecated</code> tag to the
<code>mswDecorator</code> <a
href="https://redirect.github.com/mswjs/msw-storybook-addon/pull/178">#178</a>
(<a
href="https://github.com/connorshea"><code>@​connorshea</code></a>)</li>
</ul>
<h4>Authors: 1</h4>
<ul>
<li>Connor Shea (<a
href="https://github.com/connorshea"><code>@​connorshea</code></a>)</li>
</ul>
<hr />
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/mswjs/msw-storybook-addon/commit/ae7ce4de01bf9665a03816f3ca4908feb5f90653"><code>ae7ce4d</code></a>
Update CHANGELOG.md [skip ci]</li>
<li><a
href="https://github.com/mswjs/msw-storybook-addon/commit/0b9594003ce8226767d51b444bad505db401c387"><code>0b95940</code></a>
fix: add a <code>@deprecated</code> tag to the <code>mswDecorator</code>
(<a
href="https://github.com/mswjs/msw-storybook-addon/tree/HEAD/packages/msw-addon/issues/178">#178</a>)</li>
<li>See full diff in <a
href="https://github.com/mswjs/msw-storybook-addon/commits/v2.0.6/packages/msw-addon">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=msw-storybook-addon&package-manager=npm_and_yarn&previous-version=2.0.5&new-version=2.0.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-29 12:22:47 +05:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
3005f7ba41 build(deps): bump @opentelemetry/auto-instrumentations-node from 0.60.0 to 0.60.1 (#16828)
Bumps
[@opentelemetry/auto-instrumentations-node](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/HEAD/packages/auto-instrumentations-node)
from 0.60.0 to 0.60.1.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/open-telemetry/opentelemetry-js-contrib/releases"><code>@​opentelemetry/auto-instrumentations-node</code>'s
releases</a>.</em></p>
<blockquote>
<h2>instrumentation-aws-lambda: v0.60.1</h2>
<h2><a
href="https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-aws-lambda-v0.60.0...instrumentation-aws-lambda-v0.60.1">0.60.1</a>
(2025-11-24)</h2>
<h3>Dependencies</h3>
<ul>
<li>The following workspace dependencies were updated
<ul>
<li>devDependencies
<ul>
<li><code>@​opentelemetry/propagator-aws-xray</code> bumped from ^2.1.3
to ^2.1.4</li>
<li><code>@​opentelemetry/propagator-aws-xray-lambda</code> bumped from
^0.55.3 to ^0.55.4</li>
</ul>
</li>
</ul>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/open-telemetry/opentelemetry-js-contrib/blob/main/packages/auto-instrumentations-node/CHANGELOG.md"><code>@​opentelemetry/auto-instrumentations-node</code>'s
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/open-telemetry/opentelemetry-js-contrib/compare/auto-instrumentations-node-v0.60.0...auto-instrumentations-node-v0.60.1">0.60.1</a>
(2025-06-05)</h2>
<h3>Dependencies</h3>
<ul>
<li>The following workspace dependencies were updated
<ul>
<li>dependencies
<ul>
<li><code>@​opentelemetry/instrumentation-hapi</code> bumped from
^0.48.0 to ^0.49.0</li>
<li><code>@​opentelemetry/instrumentation-koa</code> bumped from ^0.50.0
to ^0.50.1</li>
<li><code>@​opentelemetry/instrumentation-mongodb</code> bumped from
^0.55.0 to ^0.55.1</li>
<li><code>@​opentelemetry/instrumentation-net</code> bumped from ^0.46.0
to ^0.46.1</li>
<li><code>@​opentelemetry/instrumentation-redis</code> bumped from
^0.49.0 to ^0.49.1</li>
<li><code>@​opentelemetry/instrumentation-restify</code> bumped from
^0.48.0 to ^0.48.1</li>
<li><code>@​opentelemetry/instrumentation-undici</code> bumped from
^0.13.0 to ^0.13.1</li>
</ul>
</li>
</ul>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/open-telemetry/opentelemetry-js-contrib/commits/auto-instrumentations-node-v0.60.1/packages/auto-instrumentations-node">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@opentelemetry/auto-instrumentations-node&package-manager=npm_and_yarn&previous-version=0.60.0&new-version=0.60.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-29 05:40:40 +01:00
Félix MalfaitandGitHub 1b6a0cd05a fix(billing): redirect to Stripe payment method setup when subscribing without payment method (#16827)
## Summary

When users click 'Subscribe Now' during a trial period without a payment
method configured, they previously saw an unhelpful error message: "No
payment method found. Please update your billing details."

This PR improves the UX by redirecting users directly to Stripe's
billing portal payment method update flow, where they can add their
payment information. After adding a payment method, users are redirected
back to the billing settings page and can click 'Subscribe Now' again to
successfully activate their subscription.

## Changes

### Backend
- **stripe-billing-portal.service.ts**: Added
`createBillingPortalSessionForPaymentMethodUpdate` method that creates a
Stripe billing portal session with `flow_data.type:
'payment_method_update'`
- **billing-portal.workspace-service.ts**: Added
`computeBillingPortalSessionURLForPaymentMethodUpdate` method to build
the portal URL
- **billing-end-trial-period.output.ts**: Added optional
`billingPortalUrl` field to the GraphQL output DTO
- **billing-subscription.service.ts**: Modified `endTrialPeriod` to
return `stripeCustomerId` when no payment method exists
- **billing.resolver.ts**: Updated resolver to orchestrate billing
portal URL generation when no payment method

### Frontend
- **useEndSubscriptionTrialPeriod.ts**: Redirect to billing portal URL
instead of showing error snackbar
- **endSubscriptionTrialPeriod.ts**: Added `billingPortalUrl` to
mutation response fields

## User Flow

1. User clicks "Subscribe Now" during trial
2. Backend checks for payment method
3. If no payment method → redirect to Stripe billing portal payment
method update page
4. User adds payment method in Stripe
5. User is redirected back to `/settings/billing`
6. User clicks "Subscribe Now" again to activate subscription
2025-12-29 05:39:53 +01:00
6bd14dc847 i18n - translations (#16825)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2025-12-28 16:00:59 +01:00
Félix MalfaitandGitHub 7021a51747 feat(billing): implement credit rollover from one billing period to another (#16802)
## Summary
This PR implements credit rollover functionality for billing, allowing
unused credits from one billing period to carry over to the next (capped
at the current period's subscription tier cap).

## Changes

### New Services
- **StripeCreditGrantService**: Interacts with Stripe's Billing Credits
API to create credit grants, retrieve customer credit balances, and void
grants
- **BillingCreditRolloverService**: Contains the rollover logic -
calculates unused credits and creates new grants for the next period
- **BillingWebhookCreditGrantService**: Handles
`billing.credit_grant.created` and `billing.credit_grant.updated`
webhooks to update billing alerts

### Modified Services
- **StripeBillingAlertService**: Updated to include credit balance when
calculating usage threshold alerts
- **BillingUsageService**: Returns rollover credits to the frontend for
display
- **BillingSubscriptionService**: Queries credit balance when creating
billing alerts
- **BillingWebhookInvoiceService**: Triggers rollover processing on
`invoice.finalized` webhook

### Frontend
- Updated `SettingsBillingCreditsSection` to display base credits,
rollover credits, and total available
- Updated GraphQL query to fetch new `rolloverCredits` and
`totalGrantedCredits` fields

### Stripe SDK Upgrade
- Upgraded from v17.3.1 to v19.3.1 to get proper types for
billing.credit_grant events
- Fixed breaking changes: invoice.subscription path, subscription period
fields location, removed properties

## How it works

1. When `invoice.finalized` webhook is received for
`subscription_cycle`, the system:
   - Calculates usage from the previous period
   - Determines unused credits (tier cap - usage)
   - Caps rollover at current tier cap
   - Creates a Stripe credit grant with expiration at end of new period

2. When credit grants are created/updated/voided:
   - Billing alerts are recreated with the updated credit balance

3. The UI displays:
   - Base credits (from subscription tier)
   - Rollover credits (from previous periods)
   - Total available credits

## Edge Cases Handled
- Credit grant voided: `billing.credit_grant.updated` webhook triggers
alert update
- Credit grant expired: Stripe's `creditBalanceSummary` API excludes
expired grants
- No unused credits: Rollover service skips grant creation
- Customer ID as object: Controller extracts `.id` from expanded
customer
2025-12-28 15:42:18 +01:00
Abdul RahmanandGitHub 952dee955c fix: Stop autoscroll when user manually scrolls up during streaming (#16795)
https://github.com/user-attachments/assets/2ca908ca-63b8-4895-9ed7-7beaeea13ca9
2025-12-27 09:19:44 +01:00
MarieandGitHub 7400a3051c Small improvements with views (#16821)
- when a view is deleted, it is removed from left menu + from list views
in dropdown
- deactivated fields are not suggested as options to group records by
for a view (only in FE, not forbidden by BE)
2025-12-27 07:11:04 +01:00
Félix MalfaitandGitHub 265345fd69 fix: prevent infinite loop when metadata version cache is empty (#16816)
## Context

After flushing the Redis cache (e.g., via `cache:flush` command), users
get stuck in an infinite loop showing "Your workspace has been updated
with a new data model. Please refresh the page." - refreshing the page
doesn't help.

## Root Cause

When the cache is flushed, `getMetadataVersion()` returns `undefined`.
The version comparison in the error handler then becomes:

```typescript
requestMetadataVersion !== `${currentMetadataVersion}`
// Evaluates to: "5" !== "undefined" → always true
```

This triggers the schema mismatch error on every request, even after
page refresh.

## History

| Date | Commit | What Happened |
|------|--------|---------------|
| Aug 2024 | #6691 (`17a1760afd`) | Introduced the
`${currentMetadataVersion}` template literal that converts `undefined`
to the string `"undefined"` |
| Dec 2025 | #16536 (`0035fc1145`) | Removed the safety check that would
throw an early error when cache is empty, allowing `undefined` to
propagate |

## Fix

Add `isDefined(currentMetadataVersion)` check before comparing versions.
If the server doesn't have a cached version, we shouldn't treat it as a
mismatch - the schema factory already handles populating the cache when
it actually needs the version.

```typescript
if (
  requestMetadataVersion &&
  isDefined(currentMetadataVersion) &&  // ← Added this check
  requestMetadataVersion !== `${currentMetadataVersion}`
) {
```

## Testing

1. Flush the cache: `npx nx run twenty-server:command cache:flush`
2. Refresh the page
3. Verify no infinite loop occurs and app loads normally
2025-12-27 07:09:44 +01:00
bbdad09399 i18n - translations (#16823)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2025-12-26 19:01:17 +01:00
c020f71ba1 Add "number of decimal" on currency field. (#16439)
Closes [571](https://github.com/twentyhq/core-team-issues/issues/571).

Replicates the behavior of number field and allows specifying the number
of decimals for currency field.

<img width="931" height="858" alt="image"
src="https://github.com/user-attachments/assets/f5100d58-b1b0-4a88-a090-e98b2feeebd0"
/>

Currencies around the world have a maximum of three decimal places -
BHD, KWD etc. However, I have added a maximum of five decimal places in
case someone wants to use the currency field type for displaying things
like `per-second-billing` or `exchange rates`.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Adds configurable decimals (0–5) for currency fields, updating
settings UI, types/schema, display/aggregate formatting, and input
precision.
> 
> - **Currency field settings**:
> - Add `decimals` (0–5) to `FieldCurrencyMetadata.settings` and
validate via `currencyFieldSettingsSchema`.
> - Update `SettingsDataModelFieldCurrencyForm` to manage `format`
(short/full) and `decimals` with counter when `full`; wire defaults via
`useCurrencySettingsFormInitialValues`.
> - **Display & aggregation**:
> - `CurrencyDisplay` and
`transformAggregateRawValueIntoAggregateDisplayValue` honor `decimals`
when `format` is `full`; keep short format using `formatToShortNumber`.
> - **Input**:
>   - Increase currency `IMaskInput` precision with `scale=5`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
959a8fc1ea. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
2025-12-26 22:53:43 +05:00
28dc3e470e i18n - translations (#16814)
Created by Github action

Co-authored-by: github-actions <github-actions@twenty.com>
2025-12-26 09:39:27 +01:00
874e4e4666 i18n - translations (#16813)
Created by Github action

Co-authored-by: github-actions <github-actions@twenty.com>
2025-12-26 09:22:02 +01:00
6547c11862 i18n - docs translations (#16799)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2025-12-25 10:12:14 +01:00
Baptiste DevessierandGitHub 06d0ac13c4 Ensure record fields uniqueness across widgets (#16781)
This PR dissociates record inputs so that several inputs for the same
record field can live on the same page.

## Simple values demo


https://github.com/user-attachments/assets/a8c224d8-4cd6-4fe3-9cf8-01f6bdd2fca9

## Relations demo


https://github.com/user-attachments/assets/87267a8b-8ce5-41ce-8a78-cba2384828bb

## Doesn't break Record Table


https://github.com/user-attachments/assets/bcdd2b05-7cb4-4ed2-9093-58be3e04e43e

## Doesn't break Show Page


https://github.com/user-attachments/assets/f9ab9e14-012c-451e-a35f-01a165523f95
2025-12-24 17:01:10 +01:00
Félix MalfaitandGitHub 6a4974e285 feat: enforce credit limits via Stripe alerts for all billing scenarios (#16801)
## Summary

This PR ensures usage alerts are created for all billing scenarios.

## Background

Per [Stripe
documentation](https://docs.stripe.com/billing/subscriptions/usage-based/alerts),
usage alerts are **one-time per customer** - they trigger once and only
consider usage reported after the alert is created. This means we need
to create a new alert whenever:

1.  Subscription is created (trial) - Already implemented
2.  Trial ends (user becomes Active subscriber) - **Added in this PR**
3.  Credit tier changes (upgrade) - **Added in this PR**
4.  **New billing cycle starts** - **Critical fix in this PR!**

## The Issue

Previously, the invoice webhook reset `hasReachedCurrentPeriodCap =
false` at cycle end, but didn't create a new alert. This meant after the
first billing period, there was no alert to trigger and users could
exceed their limit without being blocked.

## Changes

### 1. Invoice Webhook (`billing-webhook-invoice.service.ts`)
When invoice is finalized for `subscription_cycle`:
- Reset `hasReachedCurrentPeriodCap = false`  (already done)
- **NEW**: Create alert at the current tier cap

### 2. End Trial Period (`billing-subscription.service.ts`)
In `endTrialPeriod()`:
- **NEW**: Create alert at the paid tier cap (not trial cap)

### 3. Credit Tier Upgrades (`billing-subscription.service.ts`)
In `changeMeteredPrice()`, when upgrading immediately (not scheduled for
period end):
- **NEW**: Reset `hasReachedCurrentPeriodCap = false`
- **NEW**: Create alert at new tier cap

### 4. Alert Title Update (`stripe-billing-alert.service.ts`)
Changed from "Trial usage cap" to "Usage cap" since alerts are now used
for all scenarios.

## Stripe Alert Limits

- Max 25 alerts per meter+customer combination
- Alerts only evaluate usage reported after creation
- One-time alerts trigger once per customer

With monthly billing cycles + occasional tier changes, we should stay
well under the 25 alert limit.

## Testing

- TypeScript typechecking passes
- Backend services properly inject new dependencies
2025-12-24 16:32:31 +01:00
MarieandGitHub 66daf69a5d [Tests E2E] Attempt to improve speed (#16755)
This PR presents an attempt to increase the speed of the tests to run,
by using the same front-end built for Front and E2E CIs. It implied
merging front and E2E in one CI, but allowed to still have two different
status, and to have E2E run even if no front files have changed.

Also now using depot to build FE. 

<img width="270" height="546" alt="image"
src="https://github.com/user-attachments/assets/d9eccc62-4494-4102-ad4e-241fec4bd4ea"
/>
2025-12-24 16:30:48 +01:00
Rajdeep DasandGitHub dc1bf8dac9 Fix Hide empty groups in List view when Group By is enabled (#16752)
Fixed inconsistency where List view (Group By) still showed empty groups
while Kanban hides them.
Update `visibleRecordGroupIdsComponentFamilySelector` now filters out
groups with zero records using
`recordIndexRecordIdsByGroupComponentFamilyState` and
`recordIndexShouldHideEmptyRecordGroupsComponentState`, ensuring empty
groups are consistently hidden across views.

Fixes #16212
2025-12-24 16:01:57 +01:00
5d6c39ec7e i18n - translations (#16800)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2025-12-24 15:47:58 +01:00
BhoomaahamsoandGitHub 08527930d7 fix: 🐛 visible fields count updates when toggling field (#16789)
Fixes: #16734

Solution:
The ObjectOptionsDropdownDefaultView was reading from
recordIndexFieldDefinitionsState via useObjectOptionsForBoard, while
field visibility changes update currentRecordFieldsComponentState. This
caused the "X shown" count to remain stale after hiding fields.

Changed to use visibleRecordFieldsComponentSelector (same state source
used by ViewFieldsVisibleDropdownSection) so both components react to
the same state updates.



https://github.com/user-attachments/assets/62eb5c98-f15f-4ee8-bdce-1ab4e4752f66
2025-12-24 15:44:55 +01:00
Félix MalfaitandGitHub b46e9d2e64 feat: add AI chat error handling for billing and API key errors (#16797)
## Summary

This PR adds user-friendly error handling for AI chat features,
specifically for **billing credits exhausted** and **API key not
configured** errors.

## Changes

### Backend
- Added `BILLING_CREDITS_EXHAUSTED` exception code with 402 status
- Added `API_KEY_NOT_CONFIGURED` exception code with 503 status
- Added billing check before AI chat streaming in
`agent-chat.controller.ts`
- Added error code to HTTP exception response body for frontend error
type detection
- Created `AgentRestApiExceptionFilter` for agent-specific errors

### Frontend
- Created `AIChatBanner` - reusable banner component for error/warning
messages
- Created `AIChatCreditsExhaustedMessage` - shows upgrade prompts based
on user permissions
- Created `AIChatApiKeyNotConfiguredMessage` - shows configuration
guidance with docs link
- Created `AIChatErrorRenderer` - encapsulates error type switching
logic (fixes nested ternary)
- Created `AIChatStandaloneError` - displays errors when there are no
messages
- Split `aiChatErrorUtils.ts` into separate files (1 export per file):
  - `AIChatErrorCode.ts`
  - `extractErrorCode.ts`
  - `isAIChatErrorOfType.ts`
  - `isBillingCreditsExhaustedError.ts`
  - `isApiKeyNotConfiguredError.ts`
- Added comprehensive test coverage (27 tests)

### Other
- Updated trial period banner messaging

## Testing
- All lint checks pass
- All 27 new tests pass
- TypeScript typecheck passes
2025-12-24 15:30:28 +01:00