Commit Graph

4671 Commits

Author SHA1 Message Date
Lucas Bordeau d51c988a9e Implemented SSE update across main front components (#17205)
This PR implements SSE update events across the main components of the
application : tables, boards, calendars, show pages.

There is still work to do on other event type and on making sure
everything works fine, but this first implementation should be robust
enough to start with.

Some problems encountered along the way : 
- Events are returning raw Postgres output, because they are not
normalized by the GraphQL layer, so we ended up with amountMicros as
string values, which the frontend does not like, so I implemented a
small util in our `formatResult` generic pipeline to turn amountMicros
to a number if it's a string value. We could implement other formatters
for composite fields if we see problems with events.
-`action` property was missing in SSE events, which is required by the
frontend to know what kind of event it is.

# QA


https://github.com/user-attachments/assets/393b45ac-59d2-48b0-855b-2ce9c4b8ae57


https://github.com/user-attachments/assets/cb214e7a-1595-4b85-bdb6-87630993d2e2
2026-01-18 16:14:36 +00:00
Abdullah. 92eff62523 Replace test-runner with vitest for storybook (#17187) 2026-01-18 03:25:45 +00:00
Félix Malfait c737028dd6 Move tools/eslint-rules to packages/twenty-eslint-rules (#17203)
## Summary

Moves the custom ESLint rules from `tools/eslint-rules` to
`packages/twenty-eslint-rules` for better organization within the
monorepo packages structure.

## Changes

- Move `eslint-rules` from `tools/` to `packages/twenty-eslint-rules`
- Use `loadWorkspaceRules` from `@nx/eslint-plugin` to load custom rules
- Update all ESLint configs to use the `twenty/` rule prefix instead of
`@nx/workspace-`
- Update `project.json`, `jest.config.mjs` with new paths
- Update `package.json` workspaces and `nx.json` cache inputs
- Update Dockerfile reference

## Technical Details

The custom ESLint rules are now loaded using Nx's `loadWorkspaceRules`
utility which:
- Handles TypeScript transpilation automatically
- Allows loading workspace rules from any directory
- Provides a cleaner approach than the previous `@nx/workspace-`
convention

## Testing

- Verified all 17 custom ESLint rules load correctly from the new
location
- Verified linting works on dependent packages (twenty-front,
twenty-server, etc.)
2026-01-17 07:37:17 +01:00
github-actions[bot] 1b9dc414c7 i18n - translations (#17206)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-01-16 20:20:38 +01:00
Abdul Rahman 5a617e4718 Add command menu item entity (#17181) 2026-01-16 19:02:07 +00:00
Baptiste Devessier 5bcbe43596 Various layout fixes so that RPL v1 look the same as production version (#17195)
> [!WARNING]
> Most of the quick fixes will be dropped once we release the feature
and deprecate the old show pages code.

This PR fixes padding and alignment issues so that the new Record Page
Layout feature looks like the old show pages.

## This PR

<img width="3456" height="2160" alt="CleanShot 2026-01-16 at 17 24
40@2x"
src="https://github.com/user-attachments/assets/f3640553-2316-498c-8dd0-14b09ed913f1"
/>

<img width="3456" height="2160" alt="CleanShot 2026-01-16 at 17 27
14@2x"
src="https://github.com/user-attachments/assets/c4ccb28f-5629-4e68-83ad-863f21066962"
/>


## The production

<img width="3456" height="2160" alt="CleanShot 2026-01-16 at 17 25
11@2x"
src="https://github.com/user-attachments/assets/a91f7216-0b57-404b-9f9d-f6f45d4858d6"
/>

<img width="3456" height="2234" alt="CleanShot 2026-01-16 at 17 27
19@2x"
src="https://github.com/user-attachments/assets/aaf1ee6b-b323-4844-9f1a-a59807cdbe40"
/>
2026-01-16 17:06:34 +00:00
github-actions[bot] 8a27c4987d i18n - translations (#17200)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-01-16 17:40:58 +01:00
Charles Bochet 5fc4e810f7 Front Extensibility: Introduce Front Component Entity (#17175)
As part of the extensibility effort, we are introducing a new engine
entity called "Front Component". This represents a dynamic react
component that will be rendered in CommandMenu actions or in PageLayout
widgets

This PR introduce the entity and all the necessary boilerplate to make
it syncable and cachable in the engine
2026-01-16 17:23:46 +01:00
Etienne 76cbe59929 File v2 - update core.file table (#17172)
For the following, I'll create the issues first
2026-01-16 15:59:39 +00:00
martmull 1917c1c9b9 Add forwardedRequestHeaders in routeTriggers (#17151)
- add `forwardedRequestHeaders` `string[]` column in `core.routeTrigger`
- filter request headers and forward filtered headers to function
payload (avoid spreading unexpectedly token or cookie)
- add `forwardedRequestHeaders` option in twenty-sdk `defineFunction`
util

BREAKING for actual routeTrigger payload but only 16 to migrate in
production
2026-01-16 09:19:28 +00:00
Weiko 8413c6f3dd Fix insert new record with RLS (#17164)
## Context
Now that RLS predicates are applied, creating a record through the FE
(which is empty by default) is failing if your role has predicates and
your input does not respect them (which will always be true since, as
said above, input will be pretty much empty)

## Implementation
- Moved isMatching* filters to twenty-shared
- Implemented isMatchingRlsPredicates utils in the backend (ORM) to
check before insertion/update if the record is matching the current user
role Rls predicates, reusing the isMatching* filters utils moved to
twenty-shared
- Frontend now applies RLS predicates before creating a new record
(similarly to what we do with view filters)

Note:
It seems composite were not properly handled with view-filter insertion
logic, since I'm reusing the util for now, the issue remains for RLS and
will need to be addressed
2026-01-15 16:40:47 +00:00
Lucas Bordeau 2cff75d772 Refactored object operation dispatch for SSE (#17174)
This PR refactors object record operation dispatch through a browser
event instead of a state that was registering all operations.

This is a cleaner pattern as it is a synchronous event code path instead
of relying on a useEffect to watch state change, which is not ideal.

We introduce this change first to then rely on this new pattern to
dispatch SSE events in a following PR.
2026-01-15 16:38:21 +00:00
nitin 3f28fde03a [Dashboards] fix widget type switching when navigating back in command menu (#17166)
before - 



https://github.com/user-attachments/assets/ab1e1719-f636-4d49-8c3f-cbc6b5e1f61f





after - 


https://github.com/user-attachments/assets/4bebe9c5-d8eb-49ca-9265-70e571408465
2026-01-15 13:47:02 +00:00
Félix Malfait 161e8670d0 fix: show save button when creating a new role (#17163)
## Summary
Fixes a regression where the save button was not visible when creating a
new role.

## Root Cause
PR #17062 (RLS FE implementation) introduced a change to the `isDirty`
logic that added `isDefined(settingsPersistedRole)` as a condition:

```typescript
const isDirty =
  isDefined(settingsPersistedRole) &&
  !isDeeplyEqual(settingsDraftRole, settingsPersistedRole);
```

However, in create mode, `settingsPersistedRole` is intentionally set to
`undefined` (in `SettingsRoleCreateEffect.tsx`), causing `isDirty` to
always evaluate to `false` and hiding the save button.

## Fix
Added `isCreateMode` to the `isDirty` condition so the save button shows
when creating a new role:

```typescript
const isDirty =
  isCreateMode ||
  (isDefined(settingsPersistedRole) &&
    !isDeeplyEqual(settingsDraftRole, settingsPersistedRole));
```

cc @Weiko

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Restores save button visibility when creating a role.
> 
> - Simplifies `isDirty` to `!isDeeplyEqual(settingsDraftRole,
settingsPersistedRole)`, removing the `isDefined(settingsPersistedRole)`
check so create-mode is considered dirty.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
21593d54c373b15b09406502f8d931cb5e203e46. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Weiko <corentin@twenty.com>
2026-01-15 13:42:23 +00:00
nitin abdccf2940 [Dashboards] restrict dashboard actions based on object permissions (#17169) 2026-01-15 13:37:08 +00:00
nitin 975401e18f fix widget skeleton loader not being centered (#17157) 2026-01-15 13:04:12 +00:00
nitin 55b4ac4314 [Dashboards] [Performance] Bar chart re renders fix (#17162)
before - 


https://github.com/user-attachments/assets/c9b4a60a-d4bd-43d5-8621-54777a326171


after - 




https://github.com/user-attachments/assets/74358810-067e-44f7-82f1-f4dcd7956956
2026-01-15 12:40:28 +00:00
Marie 8379e19587 [Apps] Small improvements (#17129)
- Fix undefined in breadcrumbs
<img width="783" height="220" alt="breadcrumbs_bad"
src="https://github.com/user-attachments/assets/557648da-f825-4bf6-b66f-2ac3992eeab1"
/>
- Make role required in app definition
2026-01-14 17:28:51 +00:00
Thomas Trompette 93aef30046 Add feature flag for sse (#17152)
As title
2026-01-14 14:20:45 +00:00
nitin a9e07d4f97 [Dashboards] disable chart drill-down and pointer cursor for relation group-by fields (#17150) 2026-01-14 14:15:33 +00:00
Lucas Bordeau 6b14cfaa89 Fixes two critical bugs for DATE type (#17143)
This PR fixes two critical bugs with the DATE type, following up the
recent refactor around dates and time zones :
https://github.com/twentyhq/twenty/pull/16544

There are a lot of related bugs in Sentry, this PR should fix all bugs
that are of the form :

`Cannot parse: 2026-02-04T00:00:00.000Z`

# `node-postgres` date type

The package `node-postgres`, used by TypeORM, returns by default a Date
object for the date OID type.

But we can change this behavior without patching anything.

See the documentation for `pg-types` :
https://github.com/brianc/node-pg-types

Our fix is to call `setTypeParser` from `pg` to have the postgres "date"
type returned as a string always.

```ts
export const setPgDateTypeParser = () => {
  types.setTypeParser(PG_DATE_TYPE_OID, (val: string) => val);
};
```

Then in server's main.ts : 

```ts
const bootstrap = async () => {
  setPgDateTypeParser();
```

## Are we safe with this very low-level fix ?

Since TypeORM bypasses a string value returned by `pg` we are safe with
this modification at a very low-level.

```ts
else if (columnMetadata.type === "date") {
  value = DateUtils.mixedDateToDateString(value)
}
```


https://github.com/typeorm/typeorm/blob/0ec4079cd3760dc49247a02c54415f16a2a51766/src/driver/postgres/PostgresDriver.ts#L838

```ts
/**
* Converts given value into date string in a "YYYY-MM-DD" format.
*/
static mixedDateToDateString(value: string | Date): string {
  if (value instanceof Date) {
      return (
          this.formatZerolessValue(value.getFullYear(), 4) +
          "-" +
          this.formatZerolessValue(value.getMonth() + 1) +
          "-" +
          this.formatZerolessValue(value.getDate())
      )
  }

  return value
}
```


https://github.com/typeorm/typeorm/blob/6f3788b83730463e3b787b2a98bb41695e13caf8/src/util/DateUtils.ts#L28

For reference the original type parser seems to be configured in
node-pg-types, on the 1182 OID, which is an array of date / 1082 OID,
this type parser calls another small library `postgres-date` which
creates a JS Date. I couldn't find a type parser explicitly on 1082 in
the stack TypeORM -> node-postgres -> node-pg-types -> postgres-date

```ts
register(1182, parseStringArray) // date[]
``` 


https://github.com/brianc/node-pg-types/blob/26bfe645a8ddc0c73830b1b8c63f2c4f8265b24f/lib/textParsers.js#L168C19-L168C45

```ts
 static parse (dateString) {
  return new PGDateParser(dateString).getJSDate()
}
```


https://github.com/bendrucker/postgres-date/blob/b3060560ed62c250f7800d29e4b68a9d5a0622bd/index.js#L285


# Calendar view mixing DATE and DATE_TIME

At the time of the refactor, DATE type wasn't properly tested with
calendar view, thus the drag and drop of a card with a calendar view on
a DATE field and not a DATE_TIME field, was not working, this is now
fixed.
2026-01-14 13:38:24 +00:00
Thomas Trompette ef8d7c18c1 Set back amount micros (#17124)
The amount to amount micros in UI breaks variable. Setting back amount
micros in UI with a hint

<img width="399" height="178" alt="Capture d’écran 2026-01-13 à 15 54
04"
src="https://github.com/user-attachments/assets/52f53a78-05a8-421d-80fe-f5cd0e8aad19"
/>
2026-01-14 14:18:28 +01:00
Thomas Trompette ec87b29286 Move query matching before publication (#17121)
- new channel EVENT_STREAM_CHANNEL based on event stream id
- on event, perform the matching and publish only to the right streams
- store a list of active streams per workspace
- store the user id along with the queries for each stream

Bonus:
- remove onSubscriptionMatch
2026-01-14 12:29:12 +00:00
github-actions[bot] 2845f7e666 i18n - translations (#17132)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-01-14 00:01:01 +01:00
Manikanth Martha 55cc7f809e feat(auth): Show Last used label on SSO sign-in method (#17093)
Fixes #17006 

## Changes
Added `lastAuthenticateWorkspaceSsoMethodState` Recoil atom to track the
last used SSO method, persisted in localStorage
Updated `SignInUpWithGoogle` component to display a "Last" pill badge
when Google was the last auth method
Updated `SignInUpWithMicrosoft` component to display a "Last" pill badge
when Microsoft was the last auth method
Updated `SignInUpWithSSO` component to display a "Last" pill badge when
SSO was the last auth method.


The state is saved after successful authentication redirect, ensuring it
persists across sessions

## Implementation Details
Uses existing `localStorageEffect` for persistence across browser
sessions
Leverages the existing Pill component from twenty-ui with blue accent
color
The label is positioned on the right border of the button using absolute
positioning
State is saved in the `useAuth` hook during Google/Microsoft sign-in and
in the SSO login component

<img width="684" height="608" alt="image"
src="https://github.com/user-attachments/assets/629a1599-aab0-44e4-b684-ae91a8e725fd"
/>

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Highlights the most recently used authentication method and preserves
it across sessions.
> 
> - Introduces `AuthenticatedMethod` enum and
`lastAuthenticatedMethodState` (persisted via `localStorageEffect`) and
preserves it through `useAuth.clearSession`
> - Displays a "Last" pill via `LastUsedPill` on `SignInUpWithGoogle`,
`SignInUpWithMicrosoft`, `SignInUpWithSSO`, and
`SignInUpWithCredentials` when appropriate; adds
`StyledSSOButtonContainer` for badge positioning
> - Adds `useHasMultipleAuthMethods` to detect when to show the badge;
threads `isGlobalScope` to relevant components
> - Sets last-used method on click/submit in SSO and credentials flows
(`useSignInUp`, SSO button handlers)
> - Refactors `SignInUpGlobalScopeForm` to use `SignInUpWithCredentials`
and updates `SignInUp` title logic for global scope (e.g., "Welcome to
Twenty")
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
70d552760916e7d5a8c83a33437585ca376253fc. 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-13 23:50:38 +01:00
Raphaël Bosi 869a0a7cf4 Hardcode workflow objects and dashboards to be last in the navigation drawer (#17123)
Closes https://github.com/twentyhq/core-team-issues/issues/2058

We settled on a simpler solution by just hardcoding the objects order
for now. We will change this once it's possible to reorder the workspace
favorites with drag and drop.
2026-01-13 16:24:14 +00:00
nitin e73aa80e73 [Dashboards] add primary axis select gap fill for bar and line charts (#17098)
closes https://github.com/twentyhq/core-team-issues/issues/2056


https://github.com/user-attachments/assets/44eb2704-9ea9-4f2b-8941-6dd5c12d6276
2026-01-13 10:25:58 +00:00
nitin 110cef2ccf fix rich text widget's side menu handle (#17113)
before - 



https://github.com/user-attachments/assets/283a1ed6-19e9-4a4d-ba4f-5bac7d4a23ef


after - 


https://github.com/user-attachments/assets/778a45af-fb59-4e21-aa53-290461c4d159
2026-01-13 10:00:38 +00:00
Abdullah. 2c8d3f02e1 feat: upgrade to Storybook version 10 (#17110)
Upgraded to Storybook 10. We still use `@storybook/test-runner` for
testing since it appears it'd require more work to move from Jest to
Vitest than I initially anticipated, but I completed this PR to fix
`storybook:serve:dev` - it takes time to load, but it works the way it
used to with Storybook 8.


https://github.com/user-attachments/assets/7afc32c6-4bcf-4b37-b83b-8d00d28dda15
2026-01-13 08:18:07 +00:00
github-actions[bot] 5b25ddd5b4 i18n - translations (#17108)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-01-12 19:22:48 +01:00
Lucas Bordeau 04a370e043 Implemented SSE subscription mechanism on the frontend (#17017)
This PR is a follow-up of https://github.com/twentyhq/twenty/pull/16966
and implements a new mechanism to handle SSE events.

It creates only one event stream per browser tab, then use mutations to
tell the backend which query to listen to, without re-mounting the event
stream connexion.

Then each event that comes from this unique subscription is then
dispatched in a new JavaScript CustomEvent, per queryId, on which
specific hooks add an event listener.

This PR introduces the generic tooling as well as the handling of update
events on table.
2026-01-12 18:58:46 +01:00
Thomas des Francs d7638a9075 Fix settings data model tables to take full width and align columns (#17104)
## Summary
- Updated Relations and Fields tables in the object detail settings page
to use flexible width (`1fr`) for the Name column instead of fixed
pixels
- Aligned column widths between both tables (`1fr 148px 148px 36px`) so
the App and Type/Data type columns line up

## Test plan
- [ ] Navigate to Settings > Data model > select any object (e.g.,
Companies)
- [ ] Verify the Relations table rows take the full available width
- [ ] Verify the Fields table rows take the full available width
- [ ] Verify the App and Type/Data type columns are aligned between both
tables
2026-01-12 18:58:29 +01:00
martmull bcc6b3cd21 Fix agent app setting section (#17105)
## Before

<img width="2616" height="2012" alt="image"
src="https://github.com/user-attachments/assets/40c8c12d-aa06-42d1-9cc8-4644dbf64318"
/>


## After

<img width="640" height="702" alt="image"
src="https://github.com/user-attachments/assets/25d924fb-82d1-4c95-9285-2b0bac68e250"
/>
2026-01-12 18:58:18 +01:00
github-actions[bot] 1c2fda30bd i18n - translations (#17106)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-01-12 18:58:01 +01:00
Thomas des Francs b951757220 fix: use theme-aware background color for billing credits progress bar (#17103)
## Summary
- Fixed the billing credits progress bar background color in dark mode
- The background was hardcoded to `BACKGROUND_LIGHT.tertiary`, causing
it to always display a light color regardless of the current theme
- Changed to use `theme.background.tertiary` to properly respect
dark/light mode

## Test plan
- [x] Navigate to Settings > Billing in dark mode
- [x] Verify the credits progress bar background matches the tertiary
background color (dark in dark mode)
- [x] Verify it still looks correct in light mode

Figma reference:
https://www.figma.com/design/xt8O9mFeLl46C5InWwoMrN/Twenty?node-id=64812-242606&m=dev
2026-01-12 18:53:44 +01:00
Weiko c795b8c52a RLS FE implementation (#17062)
## Summary
This PR introduces row-level security (RLS) permissions for roles in the
frontend, allowing fine-grained access control at the record level.
Users can now define permission rules that determine which specific
records a role can access based on dynamic conditions and filters.
## What's Changed
Implemented UI for configuring record-level permissions on object
permissions screens
Added support for defining permission predicates using filter conditions
(similar to advanced filters)
Introduced variable picker for dynamic permission rules (e.g., "me"
context for user-specific access)
Built predicate conversion layer to sync UI state with backend
permission structure
Extended GraphQL schema with mutations for upserting row-level
permission predicates
Fixed handling of orphaned RLS groups to prevent data inconsistencies
Added enterprise key validation for RLS features
The implementation enables scenarios like "users can only see their own
records" or "users can access records associated with their team."

<img width="687" height="702" alt="Screenshot 2026-01-09 at 23 07 02"
src="https://github.com/user-attachments/assets/33fe736e-6cbf-40bd-b2eb-c8a90c8d21bc"
/>

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2026-01-12 17:39:17 +00:00
github-actions[bot] 493f0575ea i18n - translations (#17097)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-01-12 14:29:26 +01:00
Raphaël Bosi 655f1eef5f [DASHBOARDS] Allow dashboards to be restored (#17042)
This PR introduces a few changes:
- Add three actions: see deleted dashboards, destroy dashboard and
restore dashboard
- Remove the soft delete and restore on all the page layout entities
- Cascade the destruction of a dashboard to a page layout

Video QA:


https://github.com/user-attachments/assets/ab993b11-dd9c-4e88-880c-92691a521cc2
2026-01-12 12:59:17 +00:00
github-actions[bot] 94fe385731 i18n - translations (#17094)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-01-12 13:23:13 +01:00
nitin 342ae995d9 Add error boundary on widget renderer and minor widget seed fix (#17058)
closes https://github.com/twentyhq/twenty/issues/16896 and
https://github.com/twentyhq/core-team-issues/issues/2050

should error be Invalid Configuration or something else?
2026-01-12 12:02:58 +00:00
Lucas Bordeau 9b95d28cb3 Refactored table virtualization real index state (#17074)
This PR refactors the table virtualization real index main state that
was creating performance problems.

The problem was that we kept track of all the real rows even if we only
print 200 at a time in the application.

This caused a crash when some users with 10k+ rows on a table tried to
iterate over this state 10.000 times or more.

The trade-off is that now we keep all real indices in a Map, and each
virtual row uses a selector to go to this Map.

This way if we want to reset the full Map, we just have to overwrite the
base state that contains the map, and the 200 selectors will recompute.
This happens for example when we delete a row. This now has a limited
and negligible performance impact.
2026-01-12 11:41:59 +00:00
Baptiste Devessier 7735a0fc7d Add missing RPL configuration for note tabs (#17092)
## Before

<img width="3456" height="2160" alt="CleanShot 2026-01-12 at 12 03
52@2x"
src="https://github.com/user-attachments/assets/3c7c28f7-b38a-40e2-b8d6-ba6385f823ee"
/>

## After


https://github.com/user-attachments/assets/16db3823-8b7d-4403-9901-75ee109680af
2026-01-12 11:26:58 +00:00
salmonumbrella 94e5d93e60 Enable editing for calendar event custom fields (#17063)
## Summary
- Enable editing for custom calendar event fields while keeping standard
fields read-only
- Load calendar event fields dynamically so custom field values are
editable everywhere they appear
- Preserve calendar event participants rendering

## Testing
- npx nx run twenty-front:lint:diff-with-main --skip-nx-cache
--output-style=stream
- npx jest --config packages/twenty-front/jest.config.mjs
--runTestsByPath
packages/twenty-front/src/modules/activities/calendar/hooks/__tests__/useCalendarEvents.test.tsx

## Notes
- Full nx lint/test are very slow locally after barrel generation; CI
should run the full suite

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2026-01-12 10:21:42 +00:00
Arun d5acc24bb7 fix: removed scrollbar, elipsified overflow text supporting tooltip (#17078)
fixes #15152 

Added CSS to ellipsify overflowing text with tooltip support, consistent
with existing dropdown implementations such as the address dropdown for
long country names.
This approach resolves the issue locally without modifying global
components, avoiding the limitations of previous attempts.

<img width="655" height="508" alt="Screenshot 2026-01-11 at 4 09 45 PM"
src="https://github.com/user-attachments/assets/3e11f6c2-3f13-4c1a-91da-59fc1a34e9dd"
/>


Before :

<img width="547" height="496" alt="Screenshot 2026-01-11 at 4 09 11 PM"
src="https://github.com/user-attachments/assets/43181d93-0603-4338-bb6e-688cffac91c9"
/>

After :

<img width="578" height="527" alt="Screenshot 2026-01-11 at 4 08 28 PM"
src="https://github.com/user-attachments/assets/0f277f3b-eeff-4866-99d9-6b31309c02af"
/>

---------

Co-authored-by: Arun kumar <arunkumar@Aruns-MacBook-Air.local>
Co-authored-by: Charles Bochet <charles@twenty.com>
2026-01-12 10:09:48 +00:00
nitin 46e5420d20 dashboard workspace standard seeds (#16962)
# Introduction

In this pull request we're introducing new standard page layout, tabs
and widget ( 1 page layout, 1 tab and 8 widgets ) and also a new
opportunity field

Also now prefilling new records, 6 opportunities and a dashboard.

## Standard declaration
### New workspace creation
Relies on existing standard declaration builder

### Backfill command
We've been hacking through the standard builder in order to extract only
the standard page layout entities, updated their entity dependencies to
match the workspace ids so the validation passes


## Remark
- Refactored the `PageLayoutWidget` configuration type to be dynamically
typed through a generic discriminated union

---------

Co-authored-by: prastoin <paul@twenty.com>
2026-01-12 09:34:15 +00:00
Ayesha Waseem 89af749b94 fix: hide "Add new" button for workspace member relations (#17080)
**Description**

Fixes the "Add new" button appearing in relation picker dropdowns for
workspace member relations (e.g., Account Owner on companies). Workspace
members cannot be created from relation pickers, so this button should
not appear.

**Changes Made**

- Modified RelationManyToOneFieldInput.tsx to conditionally pass the
onCreate prop to SingleRecordPicker only when
createNewRecordAndOpenRightDrawer is defined.
- Moved the conditional check to the JSX level for clarity.

**Technical Details**

The useAddNewRecordAndOpenRightDrawer hook already returns undefined for
workspace member relations, but the component was still passing a
handler function to SingleRecordPicker, causing the "Add new" button to
appear. The fix ensures that when createNewRecordAndOpenRightDrawer is
undefined, onCreate is also undefined, which prevents
SingleRecordPickerMenuItemsWithSearch from rendering the button.

Testing

- Verified that the "Add new" button no longer appears in the Account
Owner dropdown for companies.
- Confirmed that the "Add new" button still appears for other relation
fields where it's appropriate (e.g., People, Opportunities).
- Tested that existing functionality for selecting workspace members
from the dropdown still works correctly.

Fixes #17060
2026-01-12 09:08:45 +00:00
Abdullah. 5240a1818f feat: upgrade Storybook to version 9 (#17077)
Upgraded from 8.6.15 to 9.1.17 in two steps: 
- 8.6.15 -> 9.0.0 
- 9.0.0  -> 9.1.17

I had to disable `storybook-addon-cookie` since it is not supported for
Storybook 9. However, I do intend to upgrade to Storybook 10 when this
is merged, so we can replace the aforementioned add-on with this fork
specifically created to support Storybook 10 and above:
https://www.npmjs.com/package/@storybook-community/storybook-addon-cookie.

Additionally, once we upgrade to Version 10 successfully, I will start
looking into integrating the official Vitest add-on.
2026-01-11 13:54:41 +00:00
martmull 936ec06fe8 Improve application ast 3 (#17061)
- fix should generate
- fix errors not displayed properly
2026-01-10 14:52:28 +00:00
Thomas Trompette 3acc87a620 [SSE] Add backend for SSE subscriptions (#17022)
- moved a few gql types to twenty shared to re-use in server
- added a new endpoint, onEventSubscription that expect a streamId to
create a connection
- two new endpoints to store queries in Redis
- updated the existing batch channel to directly use object record type
2026-01-10 14:44:02 +00:00
Match 9e22c74b2d Fix sort direction toggle when clicking on existing sort (#17046)
Closes #17032

  Summary

When a sort is already applied to a column, clicking "Sort" from the
column header dropdown now toggles the sort direction (ASC → DESC or
DESC → ASC) instead of doing nothing.

  Problem

Previously, clicking "Sort" on a column that already had a sort applied
would always try to create a new sort with ASC direction. Since the
upsertRecordSort function updates an existing sort with the same field,
this effectively did nothing when the sort was already ASC—which felt
unintuitive.

  Solution

  Modified useHandleToggleColumnSort to:
  - Check if a sort already exists for the clicked field
  - If it exists, toggle the direction
- If it doesn't exist, create a new sort with ASC direction (existing
behavior)

---

Contribution by Gittensor, see my contribution statistics at
https://gittensor.io/miners/details?githubId=132382032
2026-01-10 14:04:26 +00:00