Commit Graph

4913 Commits

Author SHA1 Message Date
Thomas Trompette f7adf1698e Improve API + set functions in state (#17560)
Prefetch functions and set these in state

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-01-30 09:24:07 +00:00
github-actions[bot] e91457a47e i18n - translations (#17565)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-01-29 18:43:36 +01:00
Baptiste Devessier 7006c53bd9 Remove redundant label (#17563)
## Before

<img width="3456" height="2234" alt="CleanShot 2026-01-29 at 17 59
55@2x"
src="https://github.com/user-attachments/assets/9225b037-2394-44e7-8513-a4edbf889eb6"
/>

## After

<img width="3456" height="2234" alt="CleanShot 2026-01-29 at 17 59
49@2x"
src="https://github.com/user-attachments/assets/9abdded0-5f17-4ed4-925c-fc6a46b81e87"
/>
2026-01-29 17:16:20 +00:00
Copilot b99582c665 Fix React warnings for custom props on styled DOM elements (#17553)
React was warning that custom props like `isExpanded` and `allMatched`
were being passed to DOM elements (SVG icons and divs), which only
accept standard HTML/SVG attributes.

## Changes

Added `shouldForwardProp` configuration to styled components to filter
out custom props before they reach the DOM:

```typescript
import isPropValid from '@emotion/is-prop-valid';

const StyledChevronIcon = styled(IconChevronDown, {
  shouldForwardProp: (prop) =>
    isPropValid(prop) && prop !== 'isExpanded',
})<{ isExpanded: boolean }>`
  transform: ${({ isExpanded }) => isExpanded ? 'rotate(180deg)' : 'rotate(0deg)'};
`;
```

This pattern is already used in other components (e.g.,
`NavigationDrawerItem`, `TableRow`) and ensures custom props are
available for styling logic but don't leak to the underlying DOM
element.

## Files Modified

- `FieldsWidgetSectionContainer.tsx` - `isExpanded` on icon component
- `UnmatchColumnBanner.tsx` - `isExpanded`, `allMatched` on icon, div,
and Banner components

<!-- START COPILOT CODING AGENT TIPS -->
---

💡 You can make Copilot smarter by setting up custom instructions,
customizing its development environment and configuring Model Context
Protocol (MCP) servers. Learn more [Copilot coding agent
tips](https://gh.io/copilot-coding-agent-tips) in the docs.

---------

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-01-29 14:02:16 +00:00
Weiko 7d69000ab7 Update pageLayout* data models for backend recordPageLayout refactor (#17446)
<img width="814" height="356" alt="Screenshot 2026-01-26 at 16 09 27"
src="https://github.com/user-attachments/assets/91d95a1d-cc33-4bf0-a63e-4d1815030983"
/>
2026-01-29 13:39:46 +00:00
Etienne 09de762285 Files v2 - FILES field update/create in common API (#17400)
## FILES Field update interface

```
mutation {
  updateCompany(
    id: "company-uuid"
    data: {
      filesfield: [
          { fileId: "new-file-uuid", label: "new-document.pdf" }
        ]
    }
  ) {
    id
    filesfield {
      fileId
      label
      extension
    }
  }
}
```
2026-01-29 13:33:26 +00:00
github-actions[bot] 3dfb5ffc02 i18n - translations (#17546)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-01-29 12:40:34 +01:00
Baptiste Devessier b15d092abd Record page layout edition frontend (#17519)
Hidden behind a new feature flag:
`IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED`


https://github.com/user-attachments/assets/112f5a8d-0dd0-4b9f-8825-9980db35fcbd
2026-01-29 11:13:09 +00:00
github-actions[bot] 245111dea9 i18n - translations (#17545)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-01-29 12:12:40 +01:00
Marie 06e803d18b [Fix] Various typeError fixes (#17508)
Fixes
[sentry](https://twenty-v7.sentry.io/issues/6539621673/?environment=prod&environment=prod-eu&project=4507072563183616&query=is%3Aunresolved%20issue.priority%3A%5Bhigh%2C%20medium%5D%20timesSeen%3A%3E3%20TypeError&referrer=issue-stream&sort=date):
fieldValue.map on potentially null fieldValue

Fixes
[sentry](https://twenty-v7.sentry.io/issues/6996079360/?environment=prod&environment=prod-eu&project=4507072563183616&query=is%3Aunresolved%20issue.priority%3A%5Bhigh%2C%20medium%5D%20timesSeen%3A%3E3%20TypeError&referrer=issue-stream&sort=date):
note.id on potentially null note due to recent useActivities change

Fixes sentry
([1](https://twenty-v7.sentry.io/issues/6707703562/?environment=prod&environment=prod-eu&project=4507072563183616&query=is%3Aunresolved%20issue.priority%3A%5Bhigh%2C%20medium%5D%20timesSeen%3A%3E3%20TypeError&referrer=issue-stream&sort=date),
[2](https://twenty-v7.sentry.io/issues/6707703563/?environment=prod&environment=prod-eu&project=4507072563183616&query=is%3Aunresolved%20issue.priority%3A%5Bhigh%2C%20medium%5D%20timesSeen%3A%3E3%20TypeError&referrer=issue-stream&sort=date)
- same issue): selectableListHotKey issue

Fixes
[sentry](https://twenty-v7.sentry.io/issues/7087281049/?environment=prod&environment=prod-eu&project=4507072563183616&query=is%3Aunresolved%20issue.priority%3A%5Bhigh%2C%20medium%5D%20timesSeen%3A%3E3%20TypeError&referrer=issue-stream&sort=date):
issue when reordering fields (putting field in last position)
2026-01-29 10:50:28 +00:00
Thomas Trompette 3ad7a9ac94 App logic function as step (#17525)
- Add logic function as step
- Rename previous one as Code

<img width="494" height="573" alt="Capture d’écran 2026-01-28 à 16 15
29"
src="https://github.com/user-attachments/assets/82f7e720-20da-4926-b5bc-94a33cd1f53a"
/>
<img width="494" height="264" alt="Capture d’écran 2026-01-28 à 16 15
39"
src="https://github.com/user-attachments/assets/a0444ae9-8c50-418d-8c5f-68c4da08fce7"
/>
<img width="494" height="264" alt="Capture d’écran 2026-01-28 à 16 15
58"
src="https://github.com/user-attachments/assets/3025db09-4e59-421e-8dc5-f3a7a7326554"
/>

---------

Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-01-29 11:59:24 +01:00
Praise 3188fb5295 fix: standardize billing price display to integers when necessary (#17445)
**Fixes #17420** 

### Problem
The billing/pricing display showed inconsistencies:
- "Get Started" / trial signup flow: simple `$9` (no decimals)
- Pricing page: `$9.00` (with decimals)

For yearly plans (with discount), the effective monthly price might not
always be an integer, leading to messy floats in UI (e.g., 7.5 showing
as 7.499999 or inconsistent formatting).

### Solution
Added a helper function `formatYearlyPriceIfNeccessary` that:
- Only applies to yearly subscriptions (`SubscriptionInterval.Year`)
- Calculates effective monthly price (`price / 12`)
- Returns an integer if the result is whole (`Number.isInteger`)
- Otherwise formats to exactly 2 decimal places (`toFixed(2)` → Number)

This ensures clean, consistent display:
- Whole numbers: no decimals (e.g., $9 → 9)
- Fractional: precise 2 decimals (e.g., $81 yearly → 6.75)

### Changes
- Added `formatYearlyPriceIfNeccessary` function (likely in a
utils/pricing file — specify the file path if you know it, e.g.
`src/utils/pricing.ts`)
- Applied it where yearly effective prices are rendered (e.g., in
BillingPlan component, Pricing page, Signup flow — list the
files/components you changed)

### Before / After
- Before (yearly example with discount): Might show 7.5 or 7.499999
- After: Always 7.5 (or 7 if integer)

### Testing
- Ran locally with `yarn dev` 
- Checked signup flow and pricing page: prices now consistent and clean
- Verified non-yearly plans unchanged

Let me know if there's a preferred formatting style (e.g., always show
.00, or use Intl.NumberFormat) or if this should be applied in more
places!

Thanks for the great project, my first contribution btw

Closes #17420

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: Etienne <45695613+etiennejouan@users.noreply.github.com>
2026-01-29 09:39:14 +00:00
github-actions[bot] 63bf46703d i18n - translations (#17538)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-01-29 10:26:32 +01:00
martmull 3412992e99 2162 Add asset watcher in twenty-sdk dev mode (#17513)
- assets are pushed in .twenty/output
- assets are uploaded in FileFolder.Assets
- not handled yet by the sync-manifest endpoint
2026-01-29 09:08:44 +00:00
Eniola Osabiya 1cc08b84c4 feat: Add bulk input mode for select options #5539 (#17459)
- Implemented bulk input mode in SettingsDataModelFieldSelectForm to
allow users to input multiple options at once.
- Added convertBulkTextToOptions and convertOptionsToBulkText utility
functions for handling bulk text conversion.
- Created tests for both conversion functions to ensure correct
functionality.

Screenshot:
<img width="601" height="752" alt="image"
src="https://github.com/user-attachments/assets/95932860-090e-4743-9bd9-7aa6747ad04f"
/>
<img width="543" height="362" alt="image"
src="https://github.com/user-attachments/assets/84490808-2e0f-4126-951e-167b35f1b0d0"
/>

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: Etienne <45695613+etiennejouan@users.noreply.github.com>
2026-01-29 08:49:38 +00:00
Vasu Singh 59f7582463 Fix: time format issue in datepicker mask (#16922)
Fixes: #16872 

## Summary

Fixes the DateTimePicker to respect user's 12H/24H time format
preference. Previously, the time display at the top of the
DateTimePicker always showed 24-hour format (e.g., "14:30") regardless
of the user's time format setting.

## Screenshots

_After:_ Time respects user preference, showing 12H with AM/PM (e.g.,
"03:28 PM") or 24H format
<img width="357" height="491" alt="image"
src="https://github.com/user-attachments/assets/4a03f195-a52b-4f74-84ba-c5eb2fc6c8c1"
/>


## Implementation Details

### Changes Made:

1. **TimeMask.ts** - Added `getTimeMask()` to return appropriate mask
pattern based on time format
2. **TimeBlocks.ts** - Restored as constant file per linting
requirements
3. **getTimeBlocks.ts** (new) - Dynamic block generator supporting 12H
(1-12 + AM/PM) and 24H (0-23)
4. **DateTimeBlocks.ts** - Simplified to static constant
5. **getDateTimeMask.ts** - Updated to accept and use `timeFormat`
parameter
6. **DateTimePickerInput.tsx** - Dynamically generates mask and blocks
based on user's time format preference, increased input width to
accommodate AM/PM
7. **useParseJSDateToIMaskDateTimeInputString.ts** - Formats dates with
correct time pattern
8. **useParseDateTimeInputStringToJSDate.ts** - Parses dates with
correct time pattern
9. **date-utils.ts** - Added `getTimePattern()` helper (returns 'hh:mm
a' for 12H, 'HH:mm' for 24H)
10. **parseDateTimeToString.ts** - Added optional `timeFormat` parameter
for consistency

### Technical Approach:

- Leverages existing `useDateTimeFormat()` hook to get user's
`timeFormat` preference
- Supports `TimeFormat.SYSTEM`, `TimeFormat.HOUR_12`, and
`TimeFormat.HOUR_24`
- Uses IMask blocks with appropriate ranges: 1-12 for 12H, 0-23 for 24H
- Adds 'aa' (AM/PM) block for 12-hour format with enum validation

---------

Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
2026-01-28 17:43:48 +00:00
Thomas Trompette 9672ca09a2 [Bug] Fix broken variables for database event (#17526)
Fix https://github.com/twentyhq/twenty/issues/17524

Recent update meant to support variable with spaces and dots broken the
database event variables. Inserting a variable `My Name` will be
inserted as `{{trigger.[My Name]}}`

For example, for a database event, we send `trigger.properties.after.id`
instead of `id`.
With the new code, we will consider `properties.after.id` as a variable
to wrap in `[]`, giving `trigger.[properties.after.id]` which cannot be
resolve.

Let's only support variable with spaces. Removing the logic to wrap
variable with dots.
2026-01-28 17:05:59 +00:00
github-actions[bot] 3e9dda6761 i18n - translations (#17528)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-01-28 18:16:49 +01:00
Raphaël Bosi 5c1c998b97 Front component rendering (#17482)
Render front components in a widget.



https://github.com/user-attachments/assets/1ae130a4-070d-498e-88f7-80cee847e2fa

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2026-01-28 16:52:10 +00:00
Félix Malfait 81eaee81a8 Fix AI chat infinite loading shimmer on empty workspace (#17521)
## Summary

Fixes an issue where the AI chat would show loading shimmers
indefinitely when opened on a workspace with no conversation history.

**Root cause:** The `isLoading` state in `useAgentChat` included
`!currentAIChatThread`. On workspaces with no chat threads,
`currentAIChatThread` remained `null`, causing `isLoading` to be
permanently `true`.

**Changes:**
- Remove `!currentAIChatThread` from `isLoading` calculation in
`useAgentChat` - this state should only reflect streaming/file selection
status
- Auto-create a chat thread in `useAgentChatData` when the threads query
returns empty, ensuring a valid thread exists for the `useChat` hook to
initialize properly
- Add primary font color to empty state title for better visibility

## Test plan

1. Create a new workspace or use a workspace with no AI chat history
2. Open the AI chat
3. Verify the empty state shows (not infinite loading shimmer)
4. Send a message and verify it works correctly

Made with [Cursor](https://cursor.com)

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-01-28 17:36:36 +01:00
Copilot 15de09caeb Display Fields widgets title (#17518)
<img width="3456" height="2160" alt="CleanShot 2026-01-28 at 15 40
42@2x"
src="https://github.com/user-attachments/assets/43e39082-b82e-4802-bab6-897016132d44"
/>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Devessier <29370468+Devessier@users.noreply.github.com>
2026-01-28 15:09:19 +00:00
Baptiste Devessier f33b8e12f4 Fix error "No widget found in canvas layout" (#17512)
Fix https://github.com/twentyhq/twenty/issues/17507

The canvas layout mode is expected to render a single widget.
Previously, we threw an error when trying to render a canvas layout with
no widgets at all. This worked fine when we immediately rendered a
widget that used a single-widget canvas layout.

However, the active tab ID is shared across all page layouts with the
same ID, which doesn’t work well with conditional display. The available
tabs may depend on conditions such as the device displaying the page.
For example, when displaying a Note on the show page, the Note widget
appears on a separate tab. On mobile and in the side panel, however, it
is moved to the Home tab.

After that, if the user opens a Note in the side panel, the default
active tab might be the Note tab, which uses a _canvas_ layout mode and
would have no widgets at all when rendered in the side panel. This leads
to the error mentioned above.

The simple workaround is to wait one tick. An `Effect` component then
detects that the active tab doesn’t exist in the list of allowed tabs
and switches to another tab by default.

This feels more like a workaround than a proper solution, but I prefer
to fix it this way for now. We can later revisit this and design a
better separation for the selected tab ID state.

## Before


https://github.com/user-attachments/assets/500e332c-1623-48e5-b69b-5a4fa4e5e28d

## After


https://github.com/user-attachments/assets/b39dcf96-1852-42e4-a8cc-a79bf9036579
2026-01-28 11:03:42 +00:00
github-actions[bot] 2ac8c9e38b i18n - translations (#17501)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-01-28 01:50:22 +01:00
Charles Bochet da6f1bbef3 Rename serverlessFunction to logicFunction (#17494)
## Summary

Rename "Serverless Function" to "Logic Function" across the codebase for
clearer naming.

### Environment Variable Changes

| Old | New |
|-----|-----|
| `SERVERLESS_TYPE` | `LOGIC_FUNCTION_TYPE` |
| `SERVERLESS_LAMBDA_REGION` | `LOGIC_FUNCTION_LAMBDA_REGION` |
| `SERVERLESS_LAMBDA_ROLE` | `LOGIC_FUNCTION_LAMBDA_ROLE` |
| `SERVERLESS_LAMBDA_SUBHOSTING_URL` |
`LOGIC_FUNCTION_LAMBDA_SUBHOSTING_URL` |
| `SERVERLESS_LAMBDA_ACCESS_KEY_ID` |
`LOGIC_FUNCTION_LAMBDA_ACCESS_KEY_ID` |
| `SERVERLESS_LAMBDA_SECRET_ACCESS_KEY` |
`LOGIC_FUNCTION_LAMBDA_SECRET_ACCESS_KEY` |

### Breaking Changes

- Environment variables must be updated in production deployments
- Database migration renames `serverlessFunction` → `logicFunction`
tables
2026-01-28 01:42:19 +01:00
Lucas Bordeau 2ffe2d8aa6 Add delete and restore event handling for table and board (#17489)
This PR adds what is required to handle soft-delete and restore SSE
events in virtualized table and board.

Restore is not handled in board for now as it requires respecting sorts
when inserting record ids.

Since virtualized table is refetching small chunks, we just refetch for
now.

The long term goal is to handle event handling without refetching in all
main components, and also handle SSE events that have the same origin
that the current tab. But for now we implement what is easily doable.

# QA

Delete between table and board (delete only) :


https://github.com/user-attachments/assets/715dd44a-007a-44ab-bf49-5ef039cd57c3

Delete and restore between table and table : 


https://github.com/user-attachments/assets/f2122519-e969-491f-b71c-018d0f85bd86
2026-01-27 21:09:20 +00:00
github-actions[bot] 51c1fa0137 i18n - translations (#17493)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-01-27 21:01:08 +01:00
Charles Bochet a4499d21bb Migrate cron, databaseEventTrigger, httpRoute triggers to serverless functions (#17488)
## Summary

Migrates trigger entities (`CronTriggerEntity`,
`DatabaseEventTriggerEntity`, `RouteTriggerEntity`) into
`ServerlessFunctionEntity` by storing trigger settings as JSONB columns
directly on the serverless function. This simplifies the architecture
since these relationships were effectively one-to-one.

## Changes

### Schema Changes
- Added three new nullable JSONB columns to `ServerlessFunctionEntity`:
  - `cronTriggerSettings` - stores cron pattern
- `databaseEventTriggerSettings` - stores event name and updated fields
filter
- `httpRouteTriggerSettings` - stores path, HTTP method, auth
requirements, and forwarded headers

### Core Logic Updates
- `CronTriggerCronJob` - now queries `ServerlessFunctionEntity` directly
instead of `CronTriggerEntity`
- `CallDatabaseEventTriggerJobsJob` - now queries
`ServerlessFunctionEntity` directly
- `RouteTriggerService` - now queries `ServerlessFunctionEntity`
directly
- `ApplicationSyncService` - extracts trigger settings from manifest and
writes to serverless function
2026-01-27 20:54:09 +01:00
Marie dd98146c99 [Fix] display current object label in morph relation picker after rename 2/2 (#17484)
Following https://github.com/twentyhq/twenty/pull/17209

The goal is to display the updated label. For
SingleRecordPickerMenuItemsWithSearch, we did it in two parts to avoid
the breaking change by calling `objectLabelSingular` after its addition
has been deployed to prod
<img width="410" height="295" alt="image"
src="https://github.com/user-attachments/assets/d6014391-b943-4fdb-a15f-e62717463d74"
/>
2026-01-27 16:26:14 +00:00
github-actions[bot] a913ac7452 i18n - translations (#17485)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-01-27 16:51:07 +01:00
Charles Bochet bc7791871f Introduce webhook v2 (#17456)
Migrate webhook to v2 entity
2026-01-27 15:32:33 +00:00
nitin 27e5b9797b [Dashboards] Fix page layout navigation edit mode sync (#17478)
navigating away - 

before - 


https://github.com/user-attachments/assets/ffd4c592-cf6d-403c-8aa2-9f55692fac65


after - 


https://github.com/user-attachments/assets/fc298e20-21ac-4f2f-b52a-8ecfdfd4eb38

new dashbaord - 

before - 


https://github.com/user-attachments/assets/f9a2d7ab-6b5b-41c3-b993-33745ab61683


after -


https://github.com/user-attachments/assets/cad68c35-6dfa-4fa2-ab9b-890900be3444




empty page layout - 

before - 



https://github.com/user-attachments/assets/27a5b61b-cd0c-4786-a461-e28f1e348822



after - 


https://github.com/user-attachments/assets/213e5242-493b-45de-a622-cf1463bb6380
2026-01-27 15:25:41 +00:00
Baptiste Devessier 856dc8be56 Activate Record Page Layouts flag by default (#17467) 2026-01-27 13:30:38 +00:00
github-actions[bot] 43c9a75402 i18n - translations (#17472)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-01-27 13:15:07 +01:00
Weiko c36d112ab4 Add upgrade to org plan card to RLS (#17455)
## Context

<img width="564" height="270" alt="Screenshot 2026-01-26 at 18 19 39"
src="https://github.com/user-attachments/assets/9a6bdd69-2fa1-449b-9985-bfc7a401780e"
/>
2026-01-27 11:51:08 +00:00
github-actions[bot] d6a7dbb12b i18n - translations (#17469)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-01-27 12:03:13 +01:00
Abdul Rahman 2a8f834377 Integrate NavigationMenuItem with feature flag support (#17268)
## Implement Navigation Menu Items Frontend

Implements the frontend for navigation menu items, the new system
replacing favorites.

### Changes
- Added GraphQL fragments and queries for navigation menu items
- Added hooks for managing navigation menu items (create, update,
delete, sorting, filtering)
- Updated components to use navigation menu items instead of favorites
- Added test coverage for utility functions

### Migration Note
The favorites and navigation menu item modules currently exist in
parallel. The favorites code will be removed once all data has been
migrated to navigation menu items.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Replaces Favorites with feature-flagged `NavigationMenuItem` across
frontend and backend, while keeping Favorites as fallback until
migration completes.
> 
> - UI: new `navigation-menu-item` components (folders, orphan items,
drag provider/droppable, icons, skeleton), dispatcher components to
switch from Favorites, and updated “Add to favorites” action to create
`NavigationMenuItem` when `IS_NAVIGATION_MENU_ITEM_ENABLED`
> - DnD: shared `validateAndExtractFolderId` and droppable id utils
moved to `ui/layout/draggable-list`; favorites DnD updated to use shared
utils
> - GraphQL (client): add fragments, queries, mutations, hooks
(create/update/delete/find), and generated types; added
`RecordIdentifier` and `targetRecordIdentifier` on `NavigationMenuItem`
> - Prefetch: new prefetch state/effect for navigation menu items; skip
favorites prefetch when flag enabled
> - Backend: add DTOs (`NavigationMenuItem`, `RecordIdentifier`),
resolver `targetRecordIdentifier` field, service logic to fetch record
identifiers with permission-aware access and image signing,
`getRecordImageIdentifier` util, entity relation to `view`, and
migration adding FK on `viewId`
> - Feature flags & seeding: add `IS_NAVIGATION_MENU_ITEM_ENABLED` to
enums, dev seeder enables it; standard app seeds workspace navigation
menu items instead of favorites when flag on
> - Tests: add unit tests for sorting/labels/folder id and related utils
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
c99746f08b9f84fc8cec4fcc3a7d7afb8ea92db7. 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: Aman Raj <92664006+araj00@users.noreply.github.com>
Co-authored-by: Félix Malfait <felix@twenty.com>
Co-authored-by: Paul Rastoin <45004772+prastoin@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions <github-actions@twenty.com>
2026-01-27 10:42:27 +00:00
github-actions[bot] c79f633f17 i18n - translations (#17468)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-01-27 11:41:03 +01:00
Thomas des Francs 784b05cf45 fix: update calendar setup CTA to 'Finish Setup' with floppy icon (#17464)
## Today

CTA is confusing

<img width="1442" height="947" alt="image"
src="https://github.com/user-attachments/assets/d5dd6229-e78d-4068-acbc-b5766b725b14"
/>

## Summary
- Replace the "Add account" button text with "Finish Setup" at the end
of the calendar account configuration flow
- Change the button icon from a plus sign (`IconPlus`) to a floppy disk
(`IconDeviceFloppy`) to better reflect saving/completing the setup
2026-01-27 10:15:27 +00:00
Mazen-Saeed 8931f4681a fix isCalendarFieldReadOnly function to check if calender field is re… (#17319)
This PR fixes the inconsistency between Calendar and Table views when
trying to edit createdAt date field.

Previously, calendar cards could be dragged even though the createdAt
field are UI read-only, resulting in the confusing and inconsistent
behavior compared to the Table view where the field is not editable.

The issue was caused by the drag logic checking only user permissions
and not the field’s UI read-only metadata. This change updates the
calendar drag logic to also check for isUIReadOnly, ensuring that
records are not draggable when the selected calendar date field is
read-only.

---------

Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
2026-01-26 16:28:53 +00:00
Richman018 9c9c0a7595 fix: prevent record title reset on focus for notes and tasks (#17439)
Fixes issue where focusing the record title input would reset the title
to empty. This ensures the draft value is properly initialized from the
field value if it's undefined or empty when the input is focused.

Fixes #17437

---------

Co-authored-by: Daniel <daniel@example.com>
Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
2026-01-26 15:35:06 +00:00
Arun 4a5ffcc9d2 [Fix] Bug with one to many update in table #16340 (#17416)
fixes #16340 

we are updating the cache partially to prevent the flow of the corrupted
fields into the cache

the fields get corrupted during the mutation process potentially
overriding the recoil cache as we are passing the `newRecordCache`
directly in `upsertRecordsInStore`, the newRecordCache is thin and hence
the recoil wipes out the fields that are undefined or empty



we prevent this by extracting the partial data ( only the data which is
being updated in the field ) and passing it to `upsertRecordsInStore`,
as it only touched the specific fields and updates the data, leaving the
other fields untouched.


https://github.com/user-attachments/assets/5256bef7-70c3-47b3-b2ce-dd02ee1a2de8

---------

Co-authored-by: Arun kumar <arunkumar@Aruns-MacBook-Air.local>
Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
2026-01-26 13:27:56 +00:00
Raphaël Bosi 7e7a535af0 Add front component widget (#17440)
Modified the data model and introduced a seed to introduce front
components widgets.
2026-01-26 12:45:58 +00:00
github-actions[bot] 23b1b7914a i18n - translations (#17424)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-01-25 13:43:32 +01:00
Félix Malfait 161689be18 feat: fix junction toggle persistence and add type-safe documentation paths (#17421)
## Summary

- **Fix junction relation toggle not being saved**: The form schema
wasn't tracking the `settings` field, so changes to
`junctionTargetFieldId` weren't marked as dirty
- **Add type-safe documentation paths**: Generate TypeScript constants
from `base-structure.json` to prevent broken documentation links
- **Create many-to-many relations documentation**: Step-by-step guide
for building many-to-many relations using junction objects
- **Update `getDocumentationUrl`**: Now uses shared constants from
`twenty-shared` for base URL, default path, and supported languages

## Key Changes

### Junction Toggle Fix
- Added `settings` field to the form schema in
`SettingsDataModelFieldRelationForm.tsx`
- Fixed the toggle to properly merge settings when updating
`junctionTargetFieldId`

### Type-Safe Documentation Paths
- New constants in `twenty-shared/constants`:
- `DOCUMENTATION_PATHS` - All 161 documentation paths as typed constants
  - `DOCUMENTATION_SUPPORTED_LANGUAGES` - 14 supported languages
  - `DOCUMENTATION_BASE_URL` / `DOCUMENTATION_DEFAULT_PATH`
- Generator script: `yarn docs:generate-paths`
- CI integration: Added to `docs-i18n-pull.yaml` workflow

### Documentation
- New article:
`/user-guide/data-model/how-tos/create-many-to-many-relations`
- Updated `/user-guide/data-model/capabilities/relation-fields.mdx` with
Lab warning and link

## Test plan
- [ ] Verify junction toggle saves correctly when enabled/disabled
- [ ] Verify documentation link opens correct localized page
- [ ] Verify `yarn docs:generate-paths` regenerates paths correctly
2026-01-25 13:29:20 +01:00
Aman Raj 62845cac87 Fix the default value of search record if the filter is boolean type (#17297)
This fixes the #15896. For problem statement. Please refer to the shared
video mentioned in the issue.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Aligns filter defaults across UI by centralizing initial value
computation.
> 
> - Add boolean handling in `useGetInitialFilterValue` to return
`value/displayValue` of `'false'` when operand is `IS`
> - Update `WorkflowDropdownStepOutputItems` to use
`getInitialFilterValue` for initial `value` instead of an empty string,
based on field type and default operand
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
3ce05fa31aec1c9e771cb1b3ff20ddea3fab304f. 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>
2026-01-24 22:27:05 +00:00
Abdullah. fa0615d41e Migrate attachments to morph relations + fix morph join column filtering (#17381)
Closes [1744](https://github.com/twentyhq/core-team-issues/issues/1744).

This PR migrates attachments to morph relations behind a feature flag,
following the TimelineActivity pattern. it introduces the
`IS_ATTACHMENT_MIGRATED` flag, updates standard field metadata and
indexes to use morph relations, adds a workspace migration that renames
`attachment.*Id` columns to `target*Id` and converts the corresponding
field metadata to `MORPH_RELATION` with a shared `morphId`. On the
frontend, attachment read/write paths now switch to `target*Id` when the
flag is enabled.

It also fixes optimistic filtering for morph join columns. The metadata
API deduplicates morph fields, so attachments now expose a single target
field of type `MORPH_RELATION` plus a `morphRelations` array listing
each target object. Because only one `settings.joinColumnName` is
returned (e.g. `targetRocketId`), filters like `targetCompanyId` don’t
map to any field and the optimistic cache code throws.
`doesMorphRelationJoinColumnMatch` resolves this by computing all valid
join column names from `morphRelations` using
`computeMorphRelationFieldName` and comparing them to the filter key.
That makes filters like `targetCompanyId` resolvable even with a single
target field, so attachment uploads and list matching no longer crash.

<img width="477" height="474" alt="image"
src="https://github.com/user-attachments/assets/50e19418-3438-4d1e-9f1f-1bc1a03174a9"
/>

<br />
<br />

Today the metadata API returns one morph field called `target` and a
list of possible targets (`morphRelations`), but it does not tell us the
join column for each target. That’s why the Frontend had to compute join
column names.

If we want to fix this at the API level, there are two options:

- Add join column names to each target in `morphRelations` (e.g. company
→ `targetCompanyId`). This is additive and low‑risk.
- Return each target as its own field (`targetCompany`, `targetPerson`,
etc.) instead of a single target. This is a larger change because it
changes the shape of metadata and would require more UI updates.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Introduces morph relations for attachments behind
`IS_ATTACHMENT_MIGRATED`, aligning server schema/metadata and frontend
behavior.
> 
> - Adds `IS_ATTACHMENT_MIGRATED` flag (frontend/server) and
seeds/defaults; updates generated GraphQL enums
> - New workspace upgrade `1.17` command migrates data: renames
`attachment.*Id` → `target*Id` and converts related fields to
`MORPH_RELATION` with shared `morphId`
> - Updates standard field metadata and indexes to `target*` (attachment
+ related objects), dev seeds, snapshots, and workspace entity types
> - Frontend: switches attachment read/write filters via
`getActivityTargetObjectFieldIdName` using the feature flag; updates
hooks/components (`useAttachments`, `useUploadAttachmentFile`, editors);
expands `Attachment` type
> - Fixes optimistic cache filtering to recognize morph join columns in
`isRecordMatchingFilter` by computing valid join-column keys from
`morphRelations`
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
f208fa23b1135af114f484f6d65041a816d6e718. 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>
2026-01-24 21:17:24 +00:00
Arun 84d140025a fix: refresh virtualized table when field metadata is updated ( #16388 ) (#17214)
Fixes #16388 

Now we have used the metadata fetching from network using
resetVirtualizationBecauseDataChanged(), as we navigate back to the
table after updating the field content. As the virtualised table uses
the "cache-first" strategy, it fails to give fresh data from the data
base

Please let me know i we need to add the loading state (and it's UI
requirements) while it fetches the cell content, as currently the cell
is empty until it's populated by fresh data




https://github.com/user-attachments/assets/901085ba-4337-4a5d-86c8-15ac84250e8f

---------

Co-authored-by: Arun kumar <arunkumar@Aruns-MacBook-Air.local>
Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
2026-01-24 18:56:00 +00:00
nitin 8255c51910 [Dashboards] Improve bar chart performance (#17399) 2026-01-23 13:03:36 +00:00
martmull 0091ef5f6c Sync built files (#17379)
as title, upload built files to local storage

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2026-01-23 13:43:53 +01:00
Raphaël Bosi 30620c79fd Add footer to iFrame widget settings (#17397)
Add footer to iFrame widget settings
2026-01-23 11:17:46 +00:00