Commit Graph
10099 Commits
Author SHA1 Message Date
MarieandGitHub 6a5974e06c [fix] Some fixes (#17674)
- fixes
[sentry](https://twenty-v7.sentry.io/issues/7239112455/?environment=prod&environment=prod-eu&project=4507072563183616&query=anything%20else&referrer=issue-stream&sort=date)
- adapt useClearField logic to morph relations
- adapt useClearField logic to one-to-many relations (early return)
- fix creation of objects without "name" field from specific parts of
the product (which involved a "name" field)
2026-02-04 14:51:33 +00:00
MarieandGitHub d4303469ff Improve qualification of rest errors (#17629)
Will help close
[sentry](https://twenty-v7.sentry.io/issues/6827612895/?environment=prod&environment=prod-eu&project=4507072499810304&query=is%3Aunresolved%20%21issue.type%3A%5Bperformance_consecutive_db_queries%2Cperformance_consecutive_http%2Cperformance_file_io_main_thread%2Cperformance_db_main_thread%2Cperformance_n_plus_one_db_queries%2Cperformance_n_plus_one_api_calls%2Cperformance_p95_endpoint_regression%2Cperformance_slow_db_query%2Cperformance_render_blocking_asset_span%2Cperformance_uncompressed_assets%2Cperformance_http_overhead%2Cperformance_large_http_payload%5D%20timesSeen%3A%3E10&referrer=issue-stream&sort=date):
a 400 error (attempt to filter on a `null` id) qualified as a 500 error
from rest api.

I don't know what was our long term plan on validation for rest api, I
suppose it's not a priority, making it acceptable to interceipt some
postgres errors based on their messages. Ideally we would have a
validation earlier, at args parsing level.

before
<img width="1286" height="460" alt="Capture d’écran 2026-02-02 à 14 08
53"
src="https://github.com/user-attachments/assets/bf3d34f9-1436-4739-8f8e-95b18f59045b"
/>

after
<img width="1222" height="438" alt="Capture d’écran 2026-02-02 à 14 09
01"
src="https://github.com/user-attachments/assets/e817eaff-1ab9-49fb-869d-ddfd00671fbf"
/>
2026-02-04 14:33:30 +00:00
4629fb90be i18n - translations (#17712)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-02-04 15:24:23 +01:00
Paul RastoinandGitHub 48c8fa6809 Refactor workspace migration update action (#17701)
# Introduction
Removing:
- `from` property from actions definition, as it's a legitimate source
of truth. The stored comparison might have been compromised since action
generation. If from is needed it should be computed from the optimistic
cache at runner lvl
- Removed the `FlatEntityPropertyUpdates` Array complexity in favor of

From
```ts
export type PropertyUpdate<T, P extends keyof T> = {
  property: P;
} & FromTo<T[P]>;
```

To
```ts
export type FlatEntityUpdate<T extends AllMetadataName> = Partial<
  Pick<
    MetadataFlatEntity<T>,
    Extract<FlatEntityPropertiesToCompare<T>, keyof MetadataFlatEntity<T>>
  >
>;
```

## New interactions
From
```ts
    const positionUpdate = findFlatEntityPropertyUpdate({
      flatEntityUpdates,
      property: 'position',
    });

    if (
      isDefined(positionUpdate) &&
      (!Number.isInteger(positionUpdate.to) || positionUpdate.to < 0)
    ) {


   const toFlatNavigationMenuItem = {
      ...fromFlatNavigationMenuItem,
      ...fromFlatEntityPropertiesUpdatesToPartialFlatEntity({
        updates: flatEntityUpdates,
      }),
    };
```

To
```ts
    const positionUpdate = flatEntityUpdate.position;
    if (
      isDefined(positionUpdate) &&
      (!Number.isInteger(positionUpdate) || positionUpdate < 0)
    ) {

    const toFlatNavigationMenuItem = {
      ...fromFlatNavigationMenuItem,
      ...flatEntityUpdate,
    };
```

## `SanitizeFlatEntityUpdate`
Enforcing the `flatEntityUpdate` to only contains comparable properties
per flat entity by striping out all unexpected keys
In the future we will also move the whole validation at runner lvl at
some point

```ts
export const sanitizeFlatEntityUpdate = <T extends AllMetadataName>({
  flatEntityUpdate,
  metadataName,
}: {
  flatEntityUpdate: FlatEntityUpdate<T>;
  metadataName: T;
}): FlatEntityUpdate<T> => {
  const { propertiesToCompare } =
    ALL_FLAT_ENTITY_PROPERTIES_TO_COMPARE_AND_STRINGIFY[metadataName];

  const initialAccumulator: FlatEntityUpdate<T> = {};

  return propertiesToCompare.reduce((accumulator, property) => {
    const updatedValue =
      flatEntityUpdate[property as MetadataFlatEntityComparableProperties<T>];

    if (updatedValue === undefined) {
      return accumulator;
    }

    return {
      ...accumulator,
      [property]: updatedValue,
    };
  }, initialAccumulator);
};
```
2026-02-04 13:50:46 +00:00
Thomas TrompetteandGitHub b03e3772e6 Add real time image (#17710)
As title
2026-02-04 14:43:42 +01:00
nitinandGitHub 660a15b721 [FRONT COMPONENT] Stories in twenty-sdk for front component generation and upon render interactivity (#17675)
closes https://github.com/twentyhq/core-team-issues/issues/2179
2026-02-04 12:39:54 +00:00
Thomas TrompetteandGitHub 59c36736d4 Put SSE in lab (#17709)
as title
v1.16.14
2026-02-04 13:57:25 +01:00
92359603c1 i18n - translations (#17708)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-02-04 13:44:21 +01:00
Félix MalfaitandGitHub 177cae8c53 feat: audit Logs (#17660) 2026-02-04 13:30:55 +01:00
martmullandGitHub 6407474461 Fix build without nx build (#17700)
as title
2026-02-04 11:14:28 +00:00
bcfacdead9 i18n - translations (#17706)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-02-04 12:23:29 +01:00
EtienneandGitHub 4fcc424e24 Files field - add files field display and input + filtering (#17637)
This PR introduces a new FILES field type for Twenty CRM, allowing users
to attach multiple files to any record.

- Files field display
- Files field preview
- Files field input
- Files field filtering

To test : 
1/ need to activate feature flag `IS_FILES_FIELD_ENABLED` + create a new
FILES field

- display in read only, edit, inline, table
- edit
- filter
- export


closes https://github.com/twentyhq/core-team-issues/issues/2154


<img width="354" height="134" alt="Screenshot 2026-02-02 at 19 11 01"
src="https://github.com/user-attachments/assets/3c3de89e-f6b6-4526-b710-e4c7ee1a6d30"
/>
<img width="1081" height="933" alt="Screenshot 2026-02-02 at 19 10 41"
src="https://github.com/user-attachments/assets/7c9a7278-edb7-4d4a-882c-f7404689d011"
/>
<img width="1073" height="719" alt="Screenshot 2026-02-02 at 19 10 33"
src="https://github.com/user-attachments/assets/79cc372b-56a2-4cbf-b4fe-023adc4753a8"
/>
2026-02-04 10:55:48 +00:00
Raphaël BosiandGitHub 9b8eacb7f7 [FRONT COMPONENTS] Expose twenty UI in twenty sdk (#17645)
- An app will declare its `twenty-sdk` version in the manifest.
- `twenty-sdk` will be served by a CDN to be imported in front component
host.
- When we render the host we will load twenty-ui through the correct
version of the sdk

We will proceed this way because twenty-ui is not mature enough yet to
be deployed as its own package. So instead, since the sdk is already
deployed as its own package, we will serve the ui with it. It allows us
to have versioning to handle breaking changes in twenty-ui.
2026-02-04 10:43:08 +00:00
EtienneandGitHub f6b210dd0d Files v2 - File table migration + data migration command (#17661)
To add also in 1.16 patch
2026-02-04 10:28:55 +00:00
EtienneandGitHub 50ef231704 Billing - Fix inactivity (#17703)
- Add suspendedAt column on workspace table
- Update suspendedAt field when workspace suspended or re-activated
- Compute inactivity on suspendedAt



Tested : 
- Cancel subscription
- Cancel subscription + Subscribe again
- Cleaning command
2026-02-04 10:17:27 +00:00
aa06dab920 i18n - translations (#17704)
Created by Github action

Co-authored-by: github-actions <github-actions@twenty.com>
2026-02-04 11:11:10 +01:00
Félix MalfaitGitHubclaude[bot] <41898282+claude[bot]@users.noreply.github.com>
414f68fb63 fix(workspace-cache): memory leak in deleteFromLocalCache (#17686)
## Problem

The `deleteFromLocalCache` method was only setting `lastHashCheckedAt=0`
instead of actually deleting the cache entry. This caused old versions
to accumulate in the local cache when `invalidateAndRecompute` was
called.

### Flow that causes the leak:

1. `invalidateAndRecompute()` is called
2. `flush()` → `deleteFromLocalCache()` — **only sets
`lastHashCheckedAt=0`, keeps old data**
3. `recomputeDataFromProvider()` → `setInLocalCache()` — **adds new
version with new hash**
4. `cleanupStaleVersions()` — **never called** (only triggered from
`getFromLocalCache` path)

Result: Each `invalidateAndRecompute` call adds a new version to
`entry.versions` without removing the old one.

### Impact

For migration commands (like
`1-17-migrate-attachment-to-morph-relations`) that process thousands of
workspaces, this caused significant memory growth:
- Each workspace calls `getOrRecompute` (version 1)
- Then calls `invalidateAndRecompute` (version 2 added, version 1 stays)
- Memory accumulates as the command processes more workspaces

## Solution

Actually delete the local cache entry in `deleteFromLocalCache`, so
`recomputeDataFromProvider` starts fresh.

```typescript
// Before (memory leak)
if (isDefined(entry)) {
  entry.lastHashCheckedAt = 0;
}

// After (proper cleanup)
this.localCache.delete(localKey);
```

---------

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
2026-02-04 09:47:45 +00:00
Félix MalfaitGitHubclaude[bot] <41898282+claude[bot]@users.noreply.github.com>
0edc3a385c fix: prevent anonymous users from bypassing workspace creation restriction (#17635)
When `IS_WORKSPACE_CREATION_LIMITED_TO_SERVER_ADMINS` is true, anonymous
users could still create workspaces because
`checkWorkspaceCreationIsAllowedOrThrow` checked per-user workspace
count (always 0 for new users) instead of system-wide workspace count.

The bootstrap bypass now only applies when no workspaces exist in the
entire system. Also adds the same check in `signUpOnNewWorkspace` to
guard the `signInUp` code path.

Fixes #17631

Generated with [Claude Code](https://claude.ai/claude-code)

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
2026-02-04 09:47:24 +00:00
Baptiste DevessierandGitHub 29093fdbf1 Fetch soft-deleted records in Record Page Layouts (#17698)
## Before


https://github.com/user-attachments/assets/35a69015-8d3a-498f-8cb3-07bbf3f4d307

## After


https://github.com/user-attachments/assets/1232b41f-50a1-4f7d-afbe-f1fe57bd7de0
2026-02-04 09:07:00 +00:00
Charles BochetandGitHub 402d149ee1 Remove logic function layer (#17697)
## Remove logic function layer

Package.json and yarn.lock are now on the application entity, so the
logic function layer is no longer used except as a legacy source for the
1.17 backfill. This PR removes all layer usage outside of that migration
and keeps only the entity for backfill.

### Summary

- **Kept:** `LogicFunctionLayerEntity` and its table, only used by the
1.17 backfill command to read legacy layer data and backfill application
package files.
- **Removed:** All other layer logic: CRUD, cache, resolvers, services,
DTOs, and frontend types. Logic functions now depend only on the
application for package/dependency context.


### Why Dependencies instead of Source for package files

Package.json and yarn.lock are the application’s dependency set and are
stored under the application in **FileFolder.Dependencies**. The build
service and drivers now read them only from Dependencies; nothing is
written to Source for these files.
2026-02-04 10:17:27 +01:00
martmullandGitHub e10e0b337e Fix twenty sdk build (#17696)
- add twenty-ui in dist/vendor folder
- fix ts issue due to react version mismatch
2026-02-04 08:46:13 +00:00
Abdullah.andGitHub 7867617385 Migrate noteTarget and taskTarget to Morph. (#17476)
This PR migrates `noteTarget` and `taskTarget` to morph relations behind
separate feature flags, following the Attachment/TimelineActivity
pattern.

It introduces the `IS_NOTE_TARGET_MIGRATED` and
`IS_TASK_TARGET_MIGRATED` flags, updates standard field metadata and
indexes to use morph relations, and adds two **1.17 workspace
migrations** that:
- rename `noteTarget.*Id` / `taskTarget.*Id` columns to `target*Id`
- convert the corresponding field metadata to `MORPH_RELATION` with a
shared `morphId`

On the frontend, note/task target read and write paths switch to
`target*Id` when the respective flag is enabled. Deleted targets are
filtered on reload to prevent reappearing relations.
2026-02-04 02:53:06 +00:00
9aba2f62e1 i18n - docs translations (#17692)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
v1.16.13
2026-02-04 00:22:17 +01:00
neo773andGitHub 4ae5732483 Migrate gmail fetch by batch to library (#17514)
Replace manual HTTP batch implementation with
`@jrmdayn/googleapis-batcher` library (we already use this for fetching
message list)

Initial real testing works fine but do not merge yet needs more
extensive real test runs
2026-02-04 00:21:56 +01:00
Charles BochetandGitHub 867b03393b Backfill package json for custom and standard app (#17681)
# Backfill application package files for custom and standard apps

- Backfill `package.json` / `yarn.lock` (and related fields) for
existing workspaces; new standard/custom apps get default dependency
files.
- Default package files under
`application/constants/default-package-files/`; util with hardcoded
checksums (comment on how to regenerate).
- New **FileFolder.Dependencies** for app dependency files;
**writeFile_v2** accepts optional `queryRunner` for transactional
writes.

Usages:
- **Upgrade command** `upgrade:1-17:backfill-application-package-files`:
standard/custom apps → default files; other apps → from logic function
layer.
- **Workspace creation**: create workspace with
`workspaceCustomApplicationId` first, then create application (enables
same-transaction insert). Migration makes workspace/application/file FKs
deferrable.
-  dev seeder
2026-02-03 21:23:29 +01:00
60b48339b9 i18n - docs translations (#17689)
Created by Github action

Co-authored-by: github-actions <github-actions@twenty.com>
2026-02-03 20:14:58 +01:00
Thomas TrompetteandGitHub c18f574aee Trigger refetch workflow on version creation (#17685)
https://github.com/user-attachments/assets/ec156aba-3a67-4eef-addf-86158c3f1837
2026-02-03 17:52:30 +00:00
fdd3e6d245 i18n - translations (#17688)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-02-03 19:01:52 +01:00
neo773andGitHub 29a2635164 Fix message/calendar channels stuck with null syncStageStartedAt (#17684)
PR #17492 fixed `markAsMessagesListFetchOngoing` to set
`syncStageStartedAt`, but also changed `isSyncStale` to return `false`
for null values. This prevented the stale recovery job from recovering
channels that were already stuck before the fix was deployed.

Changing `isSyncStale` to return `true` for null/undefined allows the
stale job to properly reset stuck channels back to PENDING state.
2026-02-03 17:24:00 +00:00
martmullandGitHub b53dfa0533 Publish twenty packages (#17676)
- removes code editor in settings
- update readmes and docs
2026-02-03 17:16:54 +00:00
Baptiste DevessierandGitHub ccd40e7633 feat: make feature flag image optional (#17679)
Prevent layout shift when no image is provided for a feature flag

## Before


https://github.com/user-attachments/assets/b1a98da9-1208-46f7-9fc6-9c34a9012c02

## After 


https://github.com/user-attachments/assets/ed12df0c-1651-4fc9-a0e7-60f5fb1533a4
2026-02-03 17:03:37 +00:00
3db961c038 i18n - translations (#17682)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-02-03 18:04:07 +01:00
Paul RastoinandGitHub 476bdf764c Refactor flat entity maps to be universal oriented (#17665)
# Introduction
In preparation of the workspace agnostic builder, we're migrating
`FlatEntityMaps` to be universal identifier oriented and based
As in the builder context there're won't be any ids at all
Please also note that the FlatEntity is a UniversalFlatEntity superset

From
```ts
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-from.type';

export type FlatEntityMaps<T extends SyncableFlatEntity> = {
  byId: Partial<Record<string, T>>;
  idByUniversalIdentifier: Partial<Record<string, string>>;
  universalIdentifiersByApplicationId: Partial<Record<string, string[]>>;
};
```

To
```ts
export type FlatEntityMaps<
  T extends SyncableFlatEntity | UniversalSyncableFlatEntity,
> = {
  byUniversalIdentifier: Partial<Record<string, T>>;
  universalIdentifierById: Partial<Record<string, string>>;
  universalIdentifiersByApplicationId: Partial<Record<string, string[]>>; // this might make more sense to be migrated to universalIdentifiersByApplicationUniversalIdentifier but it's the main topic of this PR
};
```

## Low level maps tools
Had to refactor find | create | delete | replace | find-many | get-sub
tools ( through mutations and or throw equivalent )
2026-02-03 16:16:02 +00:00
CopilotGitHubcopilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>DevessierDevessier
43042d55b2 Scaffold Fields widget edition (#17548)
https://github.com/user-attachments/assets/960b8b0d-10e8-42a1-bf61-e875359ea302

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Devessier <29370468+Devessier@users.noreply.github.com>
Co-authored-by: Devessier <baptiste@devessier.fr>
2026-02-03 15:56:41 +00:00
Raphaël BosiandGitHub 66d7182d02 Remote dom twenty UI POC (#17652)
Create a proof of concept which allows us to use twenty-ui in the
remote-dom.
For now only the button is allowed.


https://github.com/user-attachments/assets/e5441d2c-eb63-4b99-931b-86ee14621393

Known limitation: The icons are not yet available
2026-02-03 15:54:18 +00:00
WeikoandGitHub 5c91a96e84 Add position to page layout widgets (#17643)
## Context
Introducing a new position column in PageLayoutWidget. This is because
we already have gridPosition but all widgets are not supposed to fit in
a grid (see pageLayoutTab layoutMode (GRID, VERTICAL_LIST, CANVAS...),
position will now support the different layoutMode

## Implementation
- Adding the new column (not renaming to avoid breaking changes in the
dashboards)
- Add proper validation for each layout mode
- Update standard page layout to not always use GRID but rely on the tab
layout mode

<details>

<summary>Graphql Query</summary>

```graphql
{
  "data": {
    "getPageLayouts": [
      {
        "tabs": [
          {
            "title": "Tab 1",
            "layoutMode": "GRID",
            "widgets": [
              {
                "title": "Untitled Rich Text",
                "position": {
                  "column": 0,
                  "columnSpan": 6,
                  "layoutMode": "GRID",
                  "row": 0,
                  "rowSpan": 6
                }
              },
              {
                "title": "Deals by Company",
                "position": {
                  "column": 6,
                  "columnSpan": 6,
                  "layoutMode": "GRID",
                  "row": 0,
                  "rowSpan": 6
                }
              },
              {
                "title": "Pipeline Value by Stage",
                "position": {
                  "column": 0,
                  "columnSpan": 6,
                  "layoutMode": "GRID",
                  "row": 6,
                  "rowSpan": 6
                }
              },
              {
                "title": "Revenue Timeline",
                "position": {
                  "column": 6,
                  "columnSpan": 6,
                  "layoutMode": "GRID",
                  "row": 6,
                  "rowSpan": 6
                }
              },
              {
                "title": "Opportunities by Owner",
                "position": {
                  "column": 0,
                  "columnSpan": 6,
                  "layoutMode": "GRID",
                  "row": 12,
                  "rowSpan": 6
                }
              },
              {
                "title": "Stock market (Iframe)",
                "position": {
                  "column": 6,
                  "columnSpan": 6,
                  "layoutMode": "GRID",
                  "row": 12,
                  "rowSpan": 8
                }
              },
              {
                "title": "Deals created this month",
                "position": {
                  "column": 0,
                  "columnSpan": 3,
                  "layoutMode": "GRID",
                  "row": 18,
                  "rowSpan": 2
                }
              },
              {
                "title": "Deal value created this month",
                "position": {
                  "column": 3,
                  "columnSpan": 3,
                  "layoutMode": "GRID",
                  "row": 18,
                  "rowSpan": 2
                }
              }
            ]
          }
        ]
      },
      {
        "tabs": [
          {
            "title": "Home",
            "layoutMode": "VERTICAL_LIST",
            "widgets": [
              {
                "title": "Fields",
                "position": {
                  "layoutMode": "VERTICAL_LIST",
                  "index": 0
                }
              }
            ]
          },
          {
            "title": "Timeline",
            "layoutMode": "CANVAS",
            "widgets": [
              {
                "title": "Timeline",
                "position": {
                  "layoutMode": "CANVAS"
                }
              }
            ]
          },
          {
            "title": "Tasks",
            "layoutMode": "CANVAS",
            "widgets": [
              {
                "title": "Tasks",
                "position": {
                  "layoutMode": "CANVAS"
                }
              }
            ]
          },
          {
            "title": "Notes",
            "layoutMode": "CANVAS",
            "widgets": [
              {
                "title": "Notes",
                "position": {
                  "layoutMode": "CANVAS"
                }
              }
            ]
          },
          {
            "title": "Files",
            "layoutMode": "CANVAS",
            "widgets": [
              {
                "title": "Files",
                "position": {
                  "layoutMode": "CANVAS"
                }
              }
            ]
          },
          {
            "title": "Emails",
            "layoutMode": "CANVAS",
            "widgets": [
              {
                "title": "Emails",
                "position": {
                  "layoutMode": "CANVAS"
                }
              }
            ]
          },
          {
            "title": "Calendar",
            "layoutMode": "CANVAS",
            "widgets": [
              {
                "title": "Calendar",
                "position": {
                  "layoutMode": "CANVAS"
                }
              }
            ]
          }
        ]
      },
      {
        "tabs": [
          {
            "title": "Home",
            "layoutMode": "VERTICAL_LIST",
            "widgets": [
              {
                "title": "Fields",
                "position": {
                  "layoutMode": "VERTICAL_LIST",
                  "index": 0
                }
              }
            ]
          },
          {
            "title": "Timeline",
            "layoutMode": "CANVAS",
            "widgets": [
              {
                "title": "Timeline",
                "position": {
                  "layoutMode": "CANVAS"
                }
              }
            ]
          },
          {
            "title": "Tasks",
            "layoutMode": "CANVAS",
            "widgets": [
              {
                "title": "Tasks",
                "position": {
                  "layoutMode": "CANVAS"
                }
              }
            ]
          },
          {
            "title": "Notes",
            "layoutMode": "CANVAS",
            "widgets": [
              {
                "title": "Notes",
                "position": {
                  "layoutMode": "CANVAS"
                }
              }
            ]
          },
          {
            "title": "Files",
            "layoutMode": "CANVAS",
            "widgets": [
              {
                "title": "Files",
                "position": {
                  "layoutMode": "CANVAS"
                }
              }
            ]
          },
          {
            "title": "Emails",
            "layoutMode": "CANVAS",
            "widgets": [
              {
                "title": "Emails",
                "position": {
                  "layoutMode": "CANVAS"
                }
              }
            ]
          },
          {
            "title": "Calendar",
            "layoutMode": "CANVAS",
            "widgets": [
              {
                "title": "Calendar",
                "position": {
                  "layoutMode": "CANVAS"
                }
              }
            ]
          }
        ]
      },
      {
        "tabs": [
          {
            "title": "Home",
            "layoutMode": "VERTICAL_LIST",
            "widgets": [
              {
                "title": "Fields",
                "position": {
                  "layoutMode": "VERTICAL_LIST",
                  "index": 0
                }
              }
            ]
          },
          {
            "title": "Timeline",
            "layoutMode": "CANVAS",
            "widgets": [
              {
                "title": "Timeline",
                "position": {
                  "layoutMode": "CANVAS"
                }
              }
            ]
          },
          {
            "title": "Tasks",
            "layoutMode": "CANVAS",
            "widgets": [
              {
                "title": "Tasks",
                "position": {
                  "layoutMode": "CANVAS"
                }
              }
            ]
          },
          {
            "title": "Notes",
            "layoutMode": "CANVAS",
            "widgets": [
              {
                "title": "Notes",
                "position": {
                  "layoutMode": "CANVAS"
                }
              }
            ]
          },
          {
            "title": "Files",
            "layoutMode": "CANVAS",
            "widgets": [
              {
                "title": "Files",
                "position": {
                  "layoutMode": "CANVAS"
                }
              }
            ]
          },
          {
            "title": "Emails",
            "layoutMode": "CANVAS",
            "widgets": [
              {
                "title": "Emails",
                "position": {
                  "layoutMode": "CANVAS"
                }
              }
            ]
          },
          {
            "title": "Calendar",
            "layoutMode": "CANVAS",
            "widgets": [
              {
                "title": "Calendar",
                "position": {
                  "layoutMode": "CANVAS"
                }
              }
            ]
          }
        ]
      },
      {
        "tabs": [
          {
            "title": "Home",
            "layoutMode": "VERTICAL_LIST",
            "widgets": [
              {
                "title": "Fields",
                "position": {
                  "layoutMode": "VERTICAL_LIST",
                  "index": 0
                }
              },
              {
                "title": "Note",
                "position": {
                  "layoutMode": "VERTICAL_LIST",
                  "index": 1
                }
              }
            ]
          },
          {
            "title": "Note",
            "layoutMode": "CANVAS",
            "widgets": [
              {
                "title": "Note",
                "position": {
                  "layoutMode": "CANVAS"
                }
              }
            ]
          },
          {
            "title": "Timeline",
            "layoutMode": "CANVAS",
            "widgets": [
              {
                "title": "Timeline",
                "position": {
                  "layoutMode": "CANVAS"
                }
              }
            ]
          },
          {
            "title": "Files",
            "layoutMode": "CANVAS",
            "widgets": [
              {
                "title": "Files",
                "position": {
                  "layoutMode": "CANVAS"
                }
              }
            ]
          }
        ]
      },
      {
        "tabs": [
          {
            "title": "Home",
            "layoutMode": "VERTICAL_LIST",
            "widgets": [
              {
                "title": "Fields",
                "position": {
                  "layoutMode": "VERTICAL_LIST",
                  "index": 0
                }
              },
              {
                "title": "Note",
                "position": {
                  "layoutMode": "VERTICAL_LIST",
                  "index": 1
                }
              }
            ]
          },
          {
            "title": "Note",
            "layoutMode": "CANVAS",
            "widgets": [
              {
                "title": "Note",
                "position": {
                  "layoutMode": "CANVAS"
                }
              }
            ]
          },
          {
            "title": "Timeline",
            "layoutMode": "CANVAS",
            "widgets": [
              {
                "title": "Timeline",
                "position": {
                  "layoutMode": "CANVAS"
                }
              }
            ]
          },
          {
            "title": "Files",
            "layoutMode": "CANVAS",
            "widgets": [
              {
                "title": "Files",
                "position": {
                  "layoutMode": "CANVAS"
                }
              }
            ]
          }
        ]
      },
      {
        "tabs": [
          {
            "title": "Flow",
            "layoutMode": "CANVAS",
            "widgets": [
              {
                "title": "Flow",
                "position": {
                  "layoutMode": "CANVAS"
                }
              }
            ]
          }
        ]
      },
      {
        "tabs": [
          {
            "title": "Home",
            "layoutMode": "VERTICAL_LIST",
            "widgets": [
              {
                "title": "Fields",
                "position": {
                  "layoutMode": "VERTICAL_LIST",
                  "index": 0
                }
              }
            ]
          },
          {
            "title": "Flow",
            "layoutMode": "CANVAS",
            "widgets": [
              {
                "title": "Flow",
                "position": {
                  "layoutMode": "CANVAS"
                }
              }
            ]
          }
        ]
      },
      {
        "tabs": [
          {
            "title": "Home",
            "layoutMode": "VERTICAL_LIST",
            "widgets": [
              {
                "title": "Fields",
                "position": {
                  "layoutMode": "VERTICAL_LIST",
                  "index": 0
                }
              }
            ]
          },
          {
            "title": "Flow",
            "layoutMode": "CANVAS",
            "widgets": [
              {
                "title": "Flow",
                "position": {
                  "layoutMode": "CANVAS"
                }
              }
            ]
          }
        ]
      }
    ]
  }
}
```

</details>
2026-02-03 15:54:01 +00:00
f009913cbe i18n - translations (#17678)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-02-03 17:01:31 +01:00
Charles BochetandGitHub 97867c11e6 Upgrade application model (#17673) 2026-02-03 16:44:00 +01:00
CopilotGitHubcopilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>DevessierBaptiste Devessier
1a39cd6019 Disable initial animation in Toggle component (#17648)
## Before


https://github.com/user-attachments/assets/1d915d04-9917-4999-83ea-5fd2e97867e6

## After



https://github.com/user-attachments/assets/091c7e59-f545-43d7-b077-c502b9509799

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Devessier <29370468+Devessier@users.noreply.github.com>
Co-authored-by: Baptiste Devessier <baptiste@devessier.fr>
2026-02-03 15:15:11 +00:00
nitinandGitHub c31ffef510 [Dashboard] fix rich text widget bugs + text selection in non edit mode (#17624)
closes -
https://discord.com/channels/1130383047699738754/1467809736715141211 and
https://discord.com/channels/1130383047699738754/1467810112453345333
 
before - 

text selection -- didn't work - 


https://github.com/user-attachments/assets/a12c5301-5eb1-4641-8386-87e534675c67

tripple click color picker bug - 


https://github.com/user-attachments/assets/8f2ebdd9-53c1-4635-8b28-6c82110b88a0


immediate cancel (before 300ms) - draft persist -- have to refresh to
get correct oncancel data



https://github.com/user-attachments/assets/d56e5738-d42f-4ba8-a9d3-b83acb8546ca



after - 
text selection - 


https://github.com/user-attachments/assets/e358035a-1424-45c5-a062-bb2ae6b6ca47

tripple click color picker bug - 


https://github.com/user-attachments/assets/d70947b0-b68b-4a85-93d4-8bed50e308fd



immediate cancel (before 300ms) - 


https://github.com/user-attachments/assets/f3cfb013-1d48-4f2d-b535-4b8bc5bb1c50



immediate save (before 300ms) - 



https://github.com/user-attachments/assets/3b017755-8523-429e-a511-f65732edec34
2026-02-03 15:10:34 +00:00
nitinandGitHub 19b56c5d3a [FRONT COMPONENTS] Frontend component widget creation (#17653)
closes https://github.com/twentyhq/core-team-issues/issues/2182



https://github.com/user-attachments/assets/babf154c-9cda-40ff-b2e8-5053e447c35f
2026-02-03 15:09:52 +00:00
Félix MalfaitandGitHub a1f26cda0d fix: increase findByText timeout for lazy-loaded DateTimePicker tests (#17672)
## Root Cause

The `DateTimePicker` component lazy-loads `react-datepicker` using
React's `lazy()` with a `Suspense` fallback that shows skeleton loaders:

```typescript
const ReactDatePicker = lazy<ComponentType<DatePickerPropsType>>(() =>
  import('react-datepicker').then(...)
);

// In render:
<Suspense fallback={<SkeletonLoader />}>
  <ReactDatePicker ... />
</Suspense>
```

On slower CI runners (GitHub Actions vs depot.dev), the lazy load takes
longer, causing tests to timeout while still showing skeletons instead
of the actual date picker content.

## Fix

Increased `findByText` timeout from the default 1000ms to 10000ms for
tests that wait for the date picker to load:

- `DateTimeFieldInput.stories.tsx` - 4 stories fixed
- `InternalDatePicker.stories.tsx` - 2 stories fixed

## Why This Wasn't Flaky Before

depot.dev runners have faster I/O and more consistent performance, so
the lazy load completed quickly. GitHub Actions runners have more
variable performance, causing the load to sometimes exceed the 1000ms
default timeout.
2026-02-03 15:44:58 +01:00
Thomas TrompetteandGitHub f2284579f0 Fix code container display (#17666)
Display is broken on code step
2026-02-03 14:12:37 +00:00
Charles BochetandGitHub 10ba8b9a97 Improve cache-clear behavior (#17662)
## Cache flush: scope and options

**Scope**
- `cache:flush` only flushes the **cache** Redis (REDIS_URL). It no
longer touches the queue Redis.

**Options**
- **`--namespace`** (optional): Flush one namespace or omit to flush
all. Valid: `module:messaging`, `module:calendar`, `module:workflow`,
`engine:workspace`, `engine:lock`, `engine:health`,
`engine:subscriptions`.
- **`--pattern`** (optional, default `*`): Key pattern inside the chosen
namespace(s).

**Troubleshooting**
- **`cache:flush:verify`**: Inserts keys inside and outside
`engine:workspace`, flushes, and checks only namespace keys are removed
(confirms flush scope).

**Usage**
- `yarn command:prod cache:flush` — flush all **KNOWN** namespaces
- `yarn command:prod cache:flush -n engine:workspace` — flush one
namespace
- `yarn command:prod cache:flush -n engine:workspace -p
"feature-flag:*"` — flush keys matching pattern in given namespace

FYI, existing namespaces:
```
export enum CacheStorageNamespace {
  ModuleMessaging = 'module:messaging',
  ModuleCalendar = 'module:calendar',
  ModuleWorkflow = 'module:workflow',
  EngineWorkspace = 'engine:workspace',
  EngineLock = 'engine:lock',
  EngineHealth = 'engine:health',
  EngineSubscriptions = 'engine:subscriptions',
}
```
2026-02-03 15:13:23 +01:00
Félix MalfaitandGitHub 9b063af7ab fix: increase RelationToOneFieldDisplay perf threshold to 0.4ms (#17671)
## Summary

Follow-up to #17656 - the `RelationToOneFieldDisplay` performance test
is still failing on GitHub Actions runners.

**Failure:** 0.313ms actual vs 0.3ms threshold

**Fix:** Increased threshold from 0.3ms → 0.4ms to provide more headroom
for runner variability.
2026-02-03 15:06:33 +01:00
Thomas TrompetteandGitHub 99aab9f40d Fix spaces in code step + suggestion overflow (#17664)
- fixedOverflowWidgets fixes the suggestions being overflow outside the
editor
- on focus, stop event propagation to avoid catching spaces as document
level events
2026-02-03 13:36:51 +01:00
martmullandGitHub 65678ed99f Upload files instead ofsources (#17608) 2026-02-03 12:11:10 +01:00
MarieandGitHub cdaa8f1d9d Allow twenty standard app to access messaging items (#17659) 2026-02-03 11:40:21 +01:00
Thomas des FrancsGitHubclaude[bot] <41898282+claude[bot]@users.noreply.github.com>Thomas des Francs
963066c7e3 fix: use red3 for dark mode danger background color (#17658)
## Summary

Fixes the dark mode error chip background color issue by changing
`background.danger` from `red12` to `red3` in the dark theme constants.

Fixes #17657

Generated with [Claude Code](https://claude.ai/code)

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Thomas des Francs <Bonapara@users.noreply.github.com>
2026-02-03 11:00:28 +01:00
Félix MalfaitandGitHub 2826540bb1 fix: increase performance test thresholds for GitHub Actions runners (#17656)
## Summary

After migrating from depot.dev runners to GitHub Actions runners, three
performance tests are failing due to slower single-threaded performance
on the new infrastructure (even with 16 cores).

## Problem

The performance tests use React's `<Profiler>` API to measure component
render times. depot.dev runners have better single-core performance and
lower memory latency compared to GitHub Actions runners, even larger
ones.

Failed tests:
| Test | Threshold | Actual | Overage |
|------|-----------|--------|---------|
| `DateTimeFieldDisplay` | 0.2ms | 0.281ms | +41% |
| `ChipFieldDisplay` | 0.2ms | 0.222ms | +11% |
| `RelationToOneFieldDisplay` | 0.22ms | 0.237ms | +8% |

## Solution

Increased thresholds to account for GitHub Actions runner performance:

- `DateTimeFieldDisplay`: 0.2ms → 0.35ms
- `ChipFieldDisplay`: 0.2ms → 0.3ms  
- `RelationToOneFieldDisplay`: 0.22ms → 0.3ms

## Future Considerations

For a more robust long-term solution, we could implement baseline
comparison that:
1. Saves performance results on main branch builds
2. Compares PR results against baseline with tolerance (±25%)
3. Self-calibrates to actual runner performance

This would catch real regressions without being sensitive to
infrastructure differences.
2026-02-03 10:03:38 +01:00