Commit Graph

1636 Commits

Author SHA1 Message Date
Lucas Bordeau ec8773437e Improved table flash on reload (#16419)
This PR fixes https://github.com/twentyhq/core-team-issues/issues/1732

There is still some room for improvement but the main goal is reached :
removing the flash effect each time the table virtualization has to
recompute due to an update after initial loading.

# QA

## Create 


https://github.com/user-attachments/assets/1b4fc307-42ce-4ba6-b557-68ac7fcad40f

## Update with sort


https://github.com/user-attachments/assets/e0700f44-8926-4395-8ab8-b32773f21de8

## Update with filter


https://github.com/user-attachments/assets/d325f85a-1a7b-4366-aac3-250331be7575

## Soft delete


https://github.com/user-attachments/assets/2c980183-c637-4aa7-a0ca-244e61396b20

## Restore and destroy


https://github.com/user-attachments/assets/01af9ec7-b442-4686-a1d7-ea1fc543fe62

## Drag & drop


https://github.com/user-attachments/assets/bba76bdb-d4ec-433d-b44e-37fdb9952b06

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2025-12-11 15:14:20 +01:00
Thomas Trompette 7021cd41ea Use rich text editor in form field (#16474)
Fix https://github.com/twentyhq/twenty/issues/15948

Before
<img width="982" height="505" alt="Capture d’écran 2025-12-10 à 17 26
17"
src="https://github.com/user-attachments/assets/661a8205-cb1f-4b4b-8f0a-813c09ac9d16"
/>

After
<img width="982" height="767" alt="Capture d’écran 2025-12-10 à 17 25
49"
src="https://github.com/user-attachments/assets/58fa83a8-890e-42cb-a0bd-c5f6d7890d37"
/>
2025-12-11 08:43:29 +01:00
Lucas Bordeau 3648fa064c Fixed workflow filter initialization (#16471)
This PR fixes https://github.com/twentyhq/twenty/issues/16165.

The bug was due to a wrong initialization of a record filter, which was
using another object metadata item than the filtered one.

As we can see in the original issue : 

```
...
"fieldMetadataId": "f12697bf-1eba-4061-bdd4-3e8a81172b79"
...
"fieldMetadataId": "658c531c-0c2e-43a1-8f70-4d6266c3841f",
...
```

The fix was to update the hook that returned the default field metadata
item to use for a new filter, and force the caller to tell which object
metadata item to use.
2025-12-10 16:43:20 +01:00
Félix Malfait 5df8fd90c3 feat: simplify AI chat architecture and add record links (#16463)
## Summary

This PR significantly simplifies the AI chat architecture by removing
complex routing/planning mechanisms and introduces clickable record
links in AI responses.

## Changes

### AI Chat Architecture Simplification
- **Removed** the entire `ai-chat-router` module (~850 lines) including:
  - Strategy decider service
  - Plan generator service
  - Complex routing logic
- **Removed** agent execution planning services (~700 lines):
  - `agent-execution.service.ts`
  - `agent-plan-executor.service.ts`
  - `agent-tool-generator.service.ts`
- **Added** centralized `ToolRegistryService` for tool management:
  - Builds searchable tool index (database, action, workflow tools)
  - Provides tool lookup by name
  - Supports agent search for loading expertise
- **Added** `ChatExecutionService` as simple replacement:
  - Includes full tool catalog in system prompt
- Pre-loads common tools (find/create/update for company, person,
opportunity, task, note)
  - Uses `load_tools` mechanism for dynamic tool activation
  - Enables native web search by default

### Record References in AI Responses
- Added `recordReferences` field to tool outputs for create, find, and
update operations
- Implemented `[[record:objectName:recordId:displayName]]` syntax for AI
to reference records
- Created `RecordLink` component that renders clickable chips with
object icons
- Integrated record link parsing into the markdown renderer
- Users can now click directly on created/found records in AI responses

### Workflow Agent Fixes
- Fixed cache invalidation issue when creating agents in workflows
- Added default prompt for workflow-created agents to prevent validation
errors
- Relaxed agent validation to only check properties being updated (not
all required properties)

### Code Quality Improvements
- Extracted `getRecordDisplayName` utility that mirrors frontend's
`getLabelIdentifierFieldValue` logic
- Uses object metadata to determine the correct label identifier field
- Handles `FULL_NAME` composite type for person/workspaceMember objects
- Shared across create, find, and update record services

## Net Impact
- **~1,200 lines deleted** (complex routing/planning code)
- **~500 lines added** (simpler tool registry + record links)
- Significantly reduced code complexity
- Better tool discovery through full catalog in system prompt
- Improved UX with clickable record references

## Testing
- Typecheck passes
- Lint passes
- Manual testing of AI chat with record creation and linking
2025-12-10 15:14:12 +01:00
Etienne 5e44781be1 Fix line break in richTextV2 field workflow editor (#16462)
Api expect markdown format where '\n' is escape (but not '  \n')

fixes https://github.com/twentyhq/twenty/issues/14976
2025-12-10 14:08:08 +00:00
Abhishek Kumar 89cc59d8ab fix(CSV export): update the csv export format for multi-select and arrray fields to match the import template format (#16450)
Closes #16432

Multi-Select and Array fields were exported in an incompatible format:
**Before**: {"0":"VALUE1","1":"VALUE2"} (object with numeric keys)
**After**: ["VALUE1","VALUE2"] (JSON array)

This prevented exported CSV files from being re-imported successfully.

### Changes
Modified useExportProcessRecordsForCSV hook to stringify Multi-Select
and Array fields as JSON arrays before CSV generation

---------

Co-authored-by: Etienne <45695613+etiennejouan@users.noreply.github.com>
2025-12-10 14:07:43 +00:00
Abdul Rahman 1839f8e946 Fix: Persist hide empty groups setting on backend (BREAKING: deploy server first) (#16385)
Closes #13754 and [core team issue
#414](https://github.com/twentyhq/core-team-issues/issues/414)
2025-12-10 19:10:29 +05:30
Marie 790a8d6f93 Fixes on views (#16407)
Fixes

- Fixes https://github.com/twentyhq/twenty/issues/15640 : we have some
viewGroups that were in the past wrongly migrated; eg deleteing an
enum's option did not lead to deleting the associated viewGroup. We have
not cleaned that (we could do a command), but we can identify them and
choose not to display them - otherwise currently they are shown as a
duplicate of "No value" column
- Fixes buggy edge case introduced by
https://github.com/twentyhq/twenty/pull/16382 : after updating a view
from Table/Calendar to Kanban, then visiting another view, when coming
back to the newly updated kanban view the view groups were empty. This
is due to to the view groups being optimistically created with
on-the-fly computed ids when the view is updated, while we call
refreshCoreViewsByObjectMetadataId() after. The view groups we get from
the refresh obviously have different ids. It is not possible to indicate
the ids of the view group through the update of the view as they are a
side effect of the view update.
2025-12-09 10:42:00 +00:00
Lucky Goyal d7dbb87a8f use micros converters in FormCurrencyFieldInput (#16330)
Fixes: #15887

The currency fields were expecting values in micros (multiplied by
10^6), but
this requirement was not indicated anywhere in the workflow UI. Users
had to
manually add a code node to multiply amounts by 10^6 before using the
new
currency value.

This change integrates the micros conversion logic directly into
FormCurrencyFieldInput by using convertCurrencyAmountToCurrencyMicros
and
convertCurrencyMicrosToCurrencyAmount utilities. This allows users to
input
human-readable decimal amounts (e.g., 3.21 for $3.21) in the form, which
are
automatically converted to micros internally for storage and processing.

This eliminates the need for users to add separate code nodes for
conversion
and improves the user experience by making the expected input format
clear.
2025-12-08 17:50:50 +01:00
Thomas Trompette 1c14567bf1 Workflow statuses update on record table - use cache instead of web sockets (#16391)
Updated the 3 hooks - activate, deactivate and discard draft
(deleteVersion) - so those updates the cache.
Removed the update listeners.

Also wrapped a few actions to unsure workflowId is not undefined when
received by useWorkflowWithCurrentVersion hook. Otherwise, useFindRecord
with by performed with skip true, disconnecting tmp from the cache and
making it miss a statuses update.



https://github.com/user-attachments/assets/5fc355e8-cf18-4881-855b-744eb253b79e
2025-12-08 17:17:13 +01:00
Marie 86df188e83 [fix] Fix switch view type from "Layout" switcher (#16382)
In this previous work aiming at eliminating the creation of viewGroups
being separated from the views, I removed the creation of viewGroups
from the FE at view creation, but forgot to do it at view update when
the user chooses "change Layout" option (from Table/Kanban/Calendar to
another).

In this PR
- I removed creation, deletion and destroy of viewGroups from
usePersistViewGroupRecords. I left update because it useful for
visibility and position
- since usePersistViewGroups record was also handling optimistic, I
moved optimistic logic to a new hook useViewsSideEffectsOnViewGroups. I
realized that so far we optimistic is only useful for creation. For the
update though we do need to compute the view groups that will be created
to be able to call loadRecordIndexState, so I created a function for
that, but I did not seek to perform real optimistic, with writing and
deleting groups from the cache as it was a bit heavier and not in use
for now and I want to merge this asap as it fixes the creation of
viewGroups.
2025-12-08 15:05:05 +01:00
Marie 7ce22d5c7e breaking (soft) - Migrate viewGroup.fieldMetadataId -> view.mainGroupByFieldMetadataId (2/3) (#16277)
Should be merged once https://github.com/twentyhq/twenty/pull/16206 has
been released + command run to prod

In this PR
- Remove usage of viewGroup.fieldMetadataId, both in BE and FE states. 
- But we still need to properly populate it until we fully remove
viewGroup.fieldMetadataId from db and ORM entity (upcoming 3rd PR out of
3). fieldMetadataId was removed from CoreViewGroup type and
CreateViewGroupInput and is determined BE-side based on the associated
view's mainGroupByFieldMetadataId. **I expect this means a downtime on
viewGroup creation, until both FE and BE are deployed and cache is
flushed.** This seems acceptable to me as it only regards viewGroup
creation.
    - this information is replaced by view.mainGroupByFieldMetadataID
- Handle view group creation, update and deletion in the BE as a
side-effect of a view creation, update or deletion. Optimistic effects
are still used
- Add validation at view creation or update regarding
mainGroupByFieldMetadata

Left to do in 3rd PR
- Remove viewGroup.fieldMetadataId from db and ORM entity
- Restore feature allowing to update an existing grouped view's group by
field (already OK on BE side but need to rebuild FE optimistic)
2025-12-05 14:00:03 +00:00
nitin f0f648181e add is not operand on numeric fields (#16299)
closes https://github.com/twentyhq/twenty/issues/16162
2025-12-04 18:55:24 +05:30
nitin 2f36c2e82e [Dashboards] Server: Rich Text Widget (#16296)
closes https://github.com/twentyhq/core-team-issues/issues/1893

sync in the transformation layer - 
with just the blocknote format -

<img width="1532" height="1058" alt="CleanShot 2025-12-04 at 16 43 27"
src="https://github.com/user-attachments/assets/081483fb-0bd0-4f14-81fc-8ea2261367a2"
/>

with just the mardown format - 
<img width="1534" height="1056" alt="CleanShot 2025-12-04 at 16 45 03"
src="https://github.com/user-attachments/assets/4eae513b-423d-4597-b79c-97d1f33ab994"
/>

attaching response since in screen shot its getting cut - 
```
{
  "id": "7189a10a-177c-4cc2-8946-950b8c125913",
  "pageLayoutTabId": "82ac56dd-4351-43ad-bf3d-49624c057e17",
  "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419",
  "title": "awdawd awdawdawd",
  "type": "STANDALONE_RICH_TEXT",
  "objectMetadataId": null,
  "gridPosition": {
    "row": 1,
    "column": 1,
    "rowSpan": 1,
    "columnSpan": 1
  },
  "configuration": {
    "body": {
      "markdown": "# Hello World",
      "blocknote": "[{\"id\":\"2e744f21-7c71-414d-b87f-fb48400c593c\",\"type\":\"heading\",\"props\":{\"textColor\":\"default\",\"backgroundColor\":\"default\",\"textAlignment\":\"left\",\"level\":1},\"content\":[{\"type\":\"text\",\"text\":\"Hello World\",\"styles\":{}}],\"children\":[]}]"
    }
  },
  "createdAt": "2025-12-04T11:14:52.212Z",
  "updatedAt": "2025-12-04T11:14:52.212Z",
  "deletedAt": null
}
```
2025-12-04 18:28:33 +05:30
Charles Bochet 38fc14cb3e Fix Data model object setting page not loading (#16308)
Regression introduced by
https://github.com/twentyhq/twenty/pull/16244/files

Why:
- `ChipFieldDisplay` component is using a `recoilComponentState` and
`ContextStoreComponentContext` is not provided on Settings page

This fix
- does not use the componentState in the `ChipFieldDisplay` but in the
RecordIndex area where the `ContextStoreComponentContext` is provided
- this also improve the performance as recoilState access is not free
2025-12-04 08:09:38 +01:00
Lucas Bordeau 05b30554c3 Add back first column shrink on mobile (#16244)
This PR fixes https://github.com/twentyhq/twenty/issues/14829

I created two states because one was needed for the table and the other
for the ChipFieldDisplay, which can appear anywhere.

The states tell if the first column and the ChipFieldDisplay should be
shrinked.

I also removed the usage of `useRecordTableLastColumnWidthToFill` to
avoid unnecessary re-renders of the whole table on scroll.

## Before


https://github.com/user-attachments/assets/8b6886b3-8976-41c2-9937-5d7ea396ec56

## After


https://github.com/user-attachments/assets/dc3b5ff9-59c4-4954-a973-57f6edc2508e
2025-12-02 17:51:06 +00:00
Lucas Bordeau 21c023c6d6 Fixed create new optimistic (#16257)
This PR fixes create new optimistic on boards, which was broken due to a
recent refactor of the query system for boards in : #16063
2025-12-02 16:37:53 +01:00
Lucas Bordeau bf818b7d8d Fixed sample CSV file generation (#16261)
This PR fixes a bug that created a deletedAt column in sample CSV file
generated for import, that when used afterwards for import, would create
soft deleted records, which gives the impression that the CSV import
does not work.
2025-12-02 16:32:51 +01:00
Marie 77409b6eb2 [Requires "warm" cache flush (no immediate downtime before flush)] Migrate viewGroup.fieldMetadataId -> view.mainGroupByFieldMetadataId (1/3) (#16206)
In this PR (1/3)
- introduce view.mainGroupByFieldMetadataId as the new reference
determining which fieldMetadataId is used in a grouped view, in order to
deprecate viewGroup.fieldMetadataId which creates inconsistencies.
view.mainGroupByFieldMetadataId is now filled at every view creation,
though not in use yet.
- Introduce a command to backfill view.mainGroupByFieldMetadataId for
existing views + delete all viewGroup.fieldMetadataId with a
fieldMetadataId that is not view.mainGroupByFieldMetadataId. (It should
concern 37 active workspaces)
- Temporarily disable the option to change a grouped view's
fieldMetadataId as for now it creates inconsistencies. This feature can
be reintroduced when we have done the full migration.

In a next PR
- (2/3) use view.mainGroupByFieldMetadataId instead of
viewGroup.fieldMetadataId. In FE we may keep viewGroup.fieldMetadataId
as a state (TBD). View groups will now be created / deleted as a side
effect of view's mainGroupByFieldMetadataId update.
- (3/3) remove viewGroup.fieldMetadataId

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2025-12-02 16:31:07 +01:00
Lucas Bordeau 2691222d5f Improve board experience 🖼️ (#16063)
This PR improves the general UX and DX of boards, by modifying the query
effect to only use paged group by queries.

In this PR we implement two more things in the backend for group by
queries :
- Fixed ORDER BY in the PARTITION BY sub-query (this wasn't working
because it was applied in the main query, so it sorted randomly picked
records, which was a correct sort on an incorrect dataset returned by
the sub-query)
- Added offset paging in PARTITION BY

Miscellaneous, various bug fixes and improvements along the way : 
- Throttled loading of cards to avoid React freeze
- Handling of drag & drop
- Handling of create / delete / update
- Reworked skeleton (the library slows down a lot with hundreds of
skeleton for a spinning effect that is hardly noticed)
- Fixed refetch of aggregate queries (I included the new group by
aggregates query we use in the existing refetch mechanism)
- Re-trigger queries on filters and sorts changes
- Unselect all record ids when deleting / restoring / detroying
- Fetch only groups that still have records to lighten the group by
query.

# What remains to be done 

This is still a naïve fetch more implementation that will work for a few
fetch more rounds, but if you scroll and load say 200 cards per column
on a board, React will re-render all 200 cards of each column each time.

We would probably need to virtualize the board with paged queries as we
did for the table, this could be done after this PR but seems less
urgent.

What's nice is that this new query pattern is well designed for
virtualization also, drawing from our experience with table
virtualization, and adapted to a multi-column request pattern, like a
2:2 matrix of records, for our boards.

So the remaining work would be to design a UI solution for virtualizing
this matrix of records, which could be quite different from our table
virtualization mechanism.
2025-12-02 10:09:29 +00:00
spiderman3000 af23fddfa2 Move to record page for mobile view (#16195)
Summary

- Move record open behavior to record page for mobile view.


https://github.com/user-attachments/assets/cbf87ec7-8232-4d15-b767-b38097593a5a


Closes #15960
2025-12-01 16:09:29 +01:00
Abdul Rahman b5ec6df62f Improve command menu animation (#16197)
https://github.com/user-attachments/assets/c9ff288d-0e68-4877-af6b-8685a6bbeeaf


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Removes legacy layout and refactors `CommandMenuPageLayout` to use
width-based animation with shared constants and close-animation cleanup.
> 
> - **UI/Command Menu**:
>   - **Refactor `CommandMenuPageLayout`**:
> - Switch to width/margin animation on `StyledSidePanelWrapper`; remove
side panel `x` translate animation.
>     - Use shared `COMMAND_MENU_SIDE_PANEL_WIDTH` constant.
> - Add close-state handling via `isCommandMenuClosingState` and
`useCommandMenuCloseAnimationCompleteCleanup` on animation completion.
> - Simplify props: remove `isSidePanelOpen`; rely on
`isCommandMenuOpenedState` and internal `shouldRenderContent`.
>   - **Cleanup**:
>     - Remove obsolete `CommandMenuLayout.tsx`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
d6cb01114c75b8694fbb746ea4ef31c045d7d16a. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
2025-12-01 15:27:29 +01:00
Thomas des Francs 23a7611aac revert to align center as we add an issue on edit mode. Fixed the inp… (#16179)
# Current Behavior

<img width="441" height="81" alt="image"
src="https://github.com/user-attachments/assets/cc3301b1-c92a-44c3-b452-49264ff5d323"
/>

Revert behavior to align center
fixed input size (24px)

<img width="670" height="202" alt="CleanShot 2025-11-28 at 16 05 30@2x"
src="https://github.com/user-attachments/assets/5c7ca79f-53d7-45c1-a2a6-7c3b1b78524c"
/>
2025-11-28 18:01:06 +01:00
nitin fa87603fd8 [Dashboards] Relation fields groupby (#16093) 2025-11-27 19:28:53 +00:00
Etienne 65480eb492 Currency input field - fix (#16140)
Currency field used to have default value, but default value on field is
not mandatory. Defaulf default value logic has been removed.

Also test all field type input when empty. 
2025-11-27 14:53:42 +00:00
Marie 9c9a01d55a [groupBy][Requires cache flush] Add WEEK date granularity (#16099)
Closes https://github.com/twentyhq/core-team-issues/issues/1921

https://github.com/user-attachments/assets/bf400ec1-ce25-4d9e-b875-774168452514
2025-11-27 10:22:57 +00:00
Baptiste Devessier dc2c2c413c [Workflows] Fix filtering on relative date (#16087)
https://github.com/user-attachments/assets/4079d59e-0550-401f-a29b-b235edd8ed48

Closes https://github.com/twentyhq/twenty/issues/16054
2025-11-26 14:45:05 +01:00
Abdullah. 3c0ae49a23 Clicking outside inline fields on record page saves the value. (#16042)
Closes #15957

The core problem: `handleChange` calls `setDraftValue`, but when blur
fires, `handleClickOutside` runs in the same event turn and uses
the `draftValue` captured in its closure from the last render. React
hasn’t re-rendered yet, so that captured `draftValue` is stale. Recoil
atom writes are synchronous, but the render that would update the
closure happens on the next turn.

I considered deferring `handleClickOutside` to the next tick
(setTimeout/Promise), but that’s a timing hack: it makes focus/blur
ordering unpredictable (inline cells, tables, other listeners), risks
double triggers, and can fire after unmount. Another option was to
duplicate the `handleChange` logic inside `handleClickOutside`
(screenshot), but that defeats having draft state in one place.

<p align="center">
<img width="496" height="332" alt="const nextSecondaryLinks =
updatedLinks slice (1);"
src="https://github.com/user-attachments/assets/638e2bcf-871b-4b53-9124-c8489c5db530"
/>
</p>

The clean solution is to read the current draft from a Recoil snapshot
at call time inside `handleClickOutside`. Snapshot reads pull the latest
atom value (including synchronous `setDraftValue` that just ran) even
before a re-render occurs, so they’re not subject to the stale closure.
That way, blur uses the up-to-date draft without timing hacks or
duplicated logic.

MultiItemFieldInput is used in four places. Each of them contains the
updated code.
2025-11-25 11:37:37 +01:00
Etienne 208c0857ee common api - null equivalence (#15926)
closes https://github.com/twentyhq/core-team-issues/issues/1629

To do before requesting review : 
- filter update

Migration to come in an other PR


Strat : 
1/  Null transformation

- [x] Transform NULL equivalent value to NULL in field validation in
common api - pre-query - with feature flag
- [ ] Same logic in ORM (Not done, complex to handle feature flag here)
- [x] Transform NULL value to equivalent in data formatting in ORM -
post-query

2/ Migration (in other PR) for fieldMetadata not nullable with default
defaultValue (empty string, ...)

- [ ] Remove NOT NULL db constraint
- [ ] Update record value to NULL
- [ ] Update field metadata : isNullable:true
- [ ] Update uniqueIndex whereClause (also for standard uniqueIndex) 
- [ ] Activate feature flag

3/ Update metadata creation

- [x] No more default default value
- [x] Update standard field nullability
- [x] Remove index default whereClause for standard field

4/ Update filter

- [x] When filtering on NULL or empty string, be sure all records are
returned (the one with NULL + the one with "")

5/ Test

- [ ] Strat. to do
2025-11-24 18:57:47 +01:00
Charles Bochet d526b07078 Add ability to discard Information Banner (#16019)
Fixes https://github.com/twentyhq/twenty/issues/14028

<img width="1917" height="965" alt="image"
src="https://github.com/user-attachments/assets/eeb5eab7-2c50-48be-8218-af6052b30777"
/>
2025-11-24 17:34:10 +01:00
nitin 42fef6e09b add is operand on number field (#16022)
Co-authored-by: martmull <martmull@hotmail.fr>
2025-11-24 16:04:41 +00:00
Paul Rastoin 8299488f21 Fix front data model edition + non nullable workspaceCustom application migration (#16016)
# Introduction
Two things:
- Enforcing non nullable workspace custom application Id for any
workspace
- Fixing front non editable data models following
https://github.com/twentyhq/twenty/pull/15911 that associate any custom
entities to an applicationId. The front was putting everything as
readonly when under an app ( we will have to handle the twenty standard
application in the future too )

## Fallback
### Migration
The non nullable migration will fail when released, that's why it's
being swallowed and re-run in an upgrade command post workspace custom
application creation for those that miss one. Allowing the migration to
pass in the end
The typeorm migration still need to exists for any new workspaces

### GetCurrentUser
In order to dynamically display isReadOnly in data model settings we're
fetching the workspaceCustomApplicationId through the `getCurrentUser`
If not fallback this endpoint would throw until we're handling existing
workspaces that do not have a custom workspace application
The fallback should be removed post release
2025-11-24 13:39:04 +00:00
Abdul Rahman 834d354d46 Command menu follow up improvements (#16007)
Co-authored-by: Devessier <baptiste@devessier.fr>
2025-11-24 11:23:08 +01:00
Lucas Bordeau 061cc897af Improve record group aggregate query performance (#15828)
This PR is a first step for improving the performance on boards and
table with groups.

It is related to :
https://github.com/twentyhq/core-team-issues/issues/1870

Here we implement only a groupBy query for aggregate values in the group
section.

This also allows to improve the DX of aggregate computing and group by
query creation and parsing.

## Demo 

Main : 



https://github.com/user-attachments/assets/5d2a8077-5322-4928-a551-f03583bcfb87



This PR : 



https://github.com/user-attachments/assets/d0e82b28-72c3-40f0-b5cb-045f1a736ffb



## Aggregate update bug fix

This PR also solves a bug with aggregate update that was already present
on main.

The bug is linked to core views not being updated properly during a
modification of the aggregate operation on a view.

We should probably improve the view lifecycle and state management
because it is a bit too complex right now.

Main : 


https://github.com/user-attachments/assets/10dbfb8b-dfa0-4f21-8698-d222871a43e7

This PR : 


https://github.com/user-attachments/assets/bac41890-5191-4e4c-b82b-19b1039e9ab5

## Miscellaneous 

- Fixed optimistic rendering of group by queries, when adding a new
record, the aggregate recomputes well.

## TODO 

- We might want to improve the optimistic for group by queries that
don't have records nor more than one dimension.
2025-11-23 20:40:23 +01:00
Abdul Rahman 04b0a65e73 feat: fix Command Menu Side Panel Layout (#15883)
[Figma
Design](https://www.figma.com/design/xt8O9mFeLl46C5InWwoMrN/Twenty?node-id=81380-344641&t=FpjWNOK2gZuDQQfr-0)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Adds a side panel layout for the Command Menu, routes modals into a
local container, updates the top bar and context chips, and standardizes
small button sizes.
> 
> - **Command Menu**:
> - **Side Panel Layout**: Introduces `CommandMenuSidePanelLayout` with
animated width, hosts `CommandMenuRouter`, and provides a modal
container via `ModalContainerContext`.
> - **Top Bar**: Redesign (`CommandMenuTopBar`) with back icon, optional
AI sparkles action, compact height
(`COMMAND_MENU_SEARCH_BAR_HEIGHT=40`), and updated placeholder.
> - **Context Chips**: Adds `CommandMenuLastContextChip` and
`CommandMenuRecordInfo`; extends `CommandMenuContextChip` with `page`
prop; updates `CommandMenuContextChipGroups` to render last chip as
record info when applicable.
> - **Container Simplification**: `CommandMenuContainer` simplified to
just provide contexts and `AgentChatProvider`.
> - **Modal System**:
> - Adds `ModalContainerContext` and updates `Modal` to portal into
provided container; `Modal.Backdrop` supports `isInContainer`.
> - Updates usages (e.g., `UserOrMetadataLoader`, `ActionModal`) to
align with new modal behavior.
> - **Page Integration**:
> - Replaces `PageBody` with `CommandMenuSidePanelLayout` in
`RecordShowPage` and `RecordIndexContainerGater`.
> - Removes global `CommandMenuRouter` from `DefaultLayout` (keeps
keyboard shortcuts).
> - **UI/Styling**:
> - Standardizes several buttons to `size="small"` (e.g., command
actions, open record, options, reply, workflow footer).
> - Adjusts `ShowPageSubContainer` styling when rendered inside command
menu.
>   - Storybook tests updated for new placeholder text.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
81fcaa145618a2fa1c3e11e2dc88fe832c51374c. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
Co-authored-by: Devessier <baptiste@devessier.fr>
Co-authored-by: Aman Raj <92664006+araj00@users.noreply.github.com>
Co-authored-by: Etienne <45695613+etiennejouan@users.noreply.github.com>
Co-authored-by: Paul Rastoin <45004772+prastoin@users.noreply.github.com>
2025-11-21 16:12:41 +01:00
Marie c7aa59491b Fix merge button (#15899)
Fixes https://github.com/twentyhq/private-issues/issues/362

**How to reproduce**
Link a person that has a duplicate to an opportunity. (you can create a
duplicate by giving two people the same linkedin link).
Open the opportunity record from opportunity table. 
Click on the related person (in "Point of contact").
In front of "Duplicates", click on the merge button (two arrows becoming
one).
You should here see an empty "Merge preview" and an error when clicking
"First" tab.

**Issue**
The issue is that CommandMenuMergeRecordPage is getting the referenced
objectMetadataItem from useContextStoreObjectMetadataItemOrThrow without
an instance id. contextStoreObjectMetadataItem is still "opportunity" as
it should be, being on an opportunity view.
So further down it attempts to display the record page according the
label identifier field from opportunity, which is a text field, "name",
and it breaks because the record is actually a person for who the "name"
field is not a text but a full_name type.

**Fix**
I suggested a fix that offers the possibility to find the referenced
objectMetadataItem from the MergeRecords instanceId. But I still gave
flexibility to avoid having to set that state everytime we open the
merge tab, by falling back to the default
contextStoreObjectMetadataItem. (this is used when we merge records from
ticking two records from a view and open the command menu).
Im not sure this is the best option. Open to suggestions !

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2025-11-20 13:58:40 +01:00
Rajdeep Das 4b0d1cd848 Fixed immediate UI update after Enter on single-item fields (#15825)
Previously, single-item fields `maxItemCount: 1` didn’t show updated
values after pressing `Enter` the UI only refreshed on click outside.
This happened because the items list was hidden while
`shouldAutoEditSingleItem` remained true.

This PR updates the render condition to also check `!isInputDisplayed`,
ensuring the items list re-renders immediately after editing.

**Result:** Instant UI updates on Enter with no impact on multi-item
fields.

Fixes #15792

Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
2025-11-19 11:15:17 +01:00
Guillim bcb097256b fix-15838 (#15898)
I know you did this change in order to make the frontend faster and less
resource eating. However it broke this optimistic rendering part
@lucasbordeau.

I suggest this quick fix, but I am open to a sharper one as well

Fixes https://github.com/twentyhq/twenty/issues/15838

---------

Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
2025-11-18 18:49:18 +01:00
Aryan Bhati 8d7ee47ec5 fix: custom-cron-ui (#15786)
Fixes #14723 

### Summary
Fixes a UI while creating a custom CRON

### Changes Made
- updated `WorkflowEditTriggerCronForm.tsx` to use the predefined
`FormSelectFieldInput.tsx` instead of using `Select.tsx`
- added `hint` prop to `FormSelectFieldInput.tsx`
- updated styling for showing `Upcoming execution time`
- added conditional render for `Schedule` and `Upcoming Execution Time` 
- `Schedule`  section is not rendered in Custom Cron

### Steps to Reproduce (Before Fix)
1. Navigate to - /object/workflow/xxxx
2. Try adding a new Trigger
3. Set Trigger Interval to Cron (Custom)


### Before 

![Screenshot 2025-11-13 at 4 00
29 PM](https://github.com/user-attachments/assets/f85ab0fa-cb71-4257-9659-10e1404f17ed)


### After

![Screenshot 2025-11-13 at 4 00
55 PM](https://github.com/user-attachments/assets/db1d54ef-e5d5-42e2-9de5-c1f91f46088e)

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2025-11-17 18:03:41 +01:00
Baptiste Devessier 54f74b2a5a Properly interpret advanced filters boolean values in workflows (#15829) 2025-11-14 19:01:53 +01:00
Lucas Bordeau 9d43058e50 Fixed hovering of kanban cards (#15808)
This PR fixes the record inline cells that disappeared on board card due
to recent refactors.
2025-11-13 17:49:52 +00:00
Lucas Bordeau dd0601ab6f Fix phone not empty filter (#15790)
This PR fixes the filter on not empty phones.

We can end up with phone numbers that only have a country code, but it
makes no sense to consider this special edge case "not empty".

If we have no phone number, then it's empty, so this PR applies this
particular use case for NOT EMPTY filter on phone fields.

Fixes https://github.com/twentyhq/twenty/issues/15638
2025-11-13 13:38:56 +00:00
Aryan Bhati b82d38bb13 fix(ui): layout-shift-on-tasks (#15775)
Fixes #12090 

### Summary
Fixes a UI layout shift issue in table rows in Tasks page, where bottom
borders appeared inconsistently across rows.
The problem occurred because `shouldDisplayBorderBottom` conditionally
applied the bottom border, which caused slight height differences
between rows and visual "jumping" when rendering focused styling.

### Changes Made
- Ensured consistent `border-bottom` rendering
- Removed conditional rendering prop to always display bottom border

### Steps to Reproduce (Before Fix)
1. Navigate to - /objects/tasks?viewId=xxxx
2. Interact with row elements
3. Notice a slight layout shift when first row is active/focused


### Before 

https://github.com/user-attachments/assets/ab95db5d-0922-4460-a086-a03f58375824

### After


https://github.com/user-attachments/assets/a6b4d50c-b6f0-456b-90d4-fc3f0cde42bc

---------

Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
2025-11-13 10:56:18 +00:00
TakuyaKurimoto fcf66bc881 update Notes & Tasks to display the first-letter icon (#15729)
Closes https://github.com/twentyhq/twenty/issues/15630

## Description
I've updated the Notes & Tasks to display the first-letter icon.

I only applied this change to the SummaryCard component to avoid
conflict with the content of
https://github.com/twentyhq/twenty/issues/6486.

## Test
<img width="1155" height="178" alt="スクリーンショット 2025-11-09 19 02 41"
src="https://github.com/user-attachments/assets/3b065f94-7bb8-4ba9-a0f0-3c32fb556e7e"
/>
<img width="1158" height="229" alt="スクリーンショット 2025-11-09 19 02 23"
src="https://github.com/user-attachments/assets/884ff3b6-2c48-4557-8b45-64f94a8fd6a1"
/>

Co-authored-by: Takuya Kurimoto <takuya004869@gmail.com>
2025-11-12 10:38:22 +01:00
Lucas Bordeau 5f3253d5a5 Fix issues with one to many activity targets (#15656)
This PR fixes issues with one to many activity target bugs described
here :
https://github.com/twentyhq/twenty/issues/14280#issuecomment-3490170714

It also improves the request that fetches notes and tasks in index
pages, to only fetch the notes and tasks identifier fields, thus
reducing the amount of network load.

Fixes https://github.com/twentyhq/twenty/issues/14280
2025-11-11 17:19:20 +01:00
Lucas Bordeau 703d9cb08d Improved Kanban performance (#15714)
This PR improves Kanban performance to attain the stock library speed.

There are still some performance issues at load time and drop, but they
are harder to address.

Before, everything is re-rendering at every card move, full re-render at
drop :



https://github.com/user-attachments/assets/7a1cf419-c8d8-4d56-a1a3-4269dce7b5a9


After, only the columns and card outer containers get re-rendered for
d&d, only two columns re-render at drop :



https://github.com/user-attachments/assets/d2dea914-5cc3-4693-9c2d-c7c789ae3452



We can still improve performance and re-render but that would represent
a global effort on D&D on general, table has the same problem currently,
but since we implemented virtualization it is bearable for now.
2025-11-11 17:07:40 +01:00
Charles Bochet 7099b1c174 Fix export CSV not using right columns (#15752)
Fixes https://github.com/twentyhq/twenty/issues/15575
2025-11-10 22:00:39 +01:00
Shantanu Gupta 06b8ea7c36 FIX: export view not exporting all records (#15509)
Fixes #15508 
Addresses the issue where the "Export View" functionality was not
exporting all records from a view. Users reported that only a subset of
records were exported, even when the view contained more. This led to
incomplete data exports.

The core of the problem was found within the `useLazyFetchAllRecords`
hook. The `fetchMoreRecordsLazy` function, which is responsible for
fetching subsequent pages of data during the export process, was
inadvertently using a default page limit (`DEFAULT_SEARCH_REQUEST_LIMIT`
of 60 records) instead of the intended `pageSize` (200 records). This
discrepancy caused the export process to prematurely stop fetching
records.

The PR modifies
`packages/twenty-front/src/modules/object-record/hooks/useLazyFetchAllRecords.ts`
to explicitly pass the `limit` parameter (which correctly reflects the
`pageSize`) to the `fetchMoreRecordsLazy` function. This ensures that
all subsequent data fetches during an export operation adhere to the
configured page size, allowing for the complete retrieval of all
records.
2025-11-10 21:25:39 +01:00
Rounak Joshi 9f594cda1c Slash Command Implementation in Advanced Text Editor (#15488)
Part of Fixing Issue #14976 

### Pull Request Summary: SlashCommand Integration in Advanced Text
Editor

This pull request introduces **SlashCommand functionality** within the
Advanced Text Editor, specifically used in the **Workflow node** of
**Send Email body** components. The implementation leverages the
`@tiptap/suggestion` extension from the TipTap ecosystem, enabling
dynamic styling and command execution via a custom dropdown triggered by
typing `/`.

---

### Implementation Overview

#### 1. **Custom Extension & Dropdown Rendering**
- A new extension was created to handle SlashCommand interactions.
- This extension renders a **Dropdown component** that displays
available commands with relevant styles, icons etc.

#### 2. **Command Configuration**
- Each command includes:
  - Visibility and active state logic
  - Execution behavior upon selection
- All commands are initialized and configured centrally.

#### 3. **Search & Filtering**
- As users type after the `/`, the command list is **filtered based on
the query**.
- For example, typing `/car` filters and displays matching commands in
the dropdown.

#### 4. **Dropdown Lifecycle & Positioning**
- The dropdown is rendered using React lifecycle hooks provided by
`SuggestionTip`:
- `onStart`: Initializes state, sets selected command, and captures
cursor position via `DOMRect`.
- `onUpdate`, `onKeyDown`, `onExit`: Manage dropdown updates and
interactions.
- Positioning is handled via a **`useFloating` hook**, which aligns the
dropdown relative to the cursor and editor bounds.
- The dropdown is rendered in a **react-portal**, wrapped in the current
theme for consistent styling and animation.


#### 6. **State Management**
- A dedicated `SlashCommandState.ts` file manages:
  - Callback functions
  - Current command and selected item
  - Cleanup utilities for event listeners
  - Dropdown navigation (arrow keys, enter key)

#### 7. **Integration Points**
- SlashCommand functionality is now **enabled in Send Email body of the
Workflow**.
- Relevant changes have been applied to support this components in
Storybook as well.

[slash command
test.webm](https://github.com/user-attachments/assets/5c537844-8987-4ce5-9fca-b29ea93d8063)


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Updates Portuguese (Brazil and Portugal) generated locale files,
including a new editor hint string for “Enter text or type '/' for
commands,” plus assorted translation tweaks.
> 
> - **i18n/locales**:
> - **Portuguese (Brazil) `src/locales/generated/pt-BR.ts`**: Add new
editor hint message (`"Enter text or Type '/' for commands"`) and adjust
multiple translations/wording.
> - **Portuguese (Portugal) `src/locales/generated/pt-PT.ts`**: Add the
same editor hint message and refine numerous translations/labels.
> - No functional code changes; translation files regenerated/updated.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
b3d7407525ec08da1fcfafe1309bb4fd61654dac. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Félix Malfait <felix@twenty.com>
2025-11-09 21:18:56 +01:00
Félix Malfait cff17db6cb Enhance role-check system with stricter checks (#15392)
## Overview

This PR strengthens our permission system by introducing more granular
role-based access control across the platform.

## Changes

### New Permissions Added
- **Applications** - Control who can install and manage applications
- **Layouts** - Control who can customize page layouts and UI structure
- **AI** - Control access to AI features and agents
- **Upload File** - Separate permission for file uploads
- **Download File** - Separate permission for file downloads (frontend
visibility)

### Security Enhancements
- Implemented whitelist-based validation for workspace field updates
- Added explicit permission guards to core entity resolvers
- Enhanced ESLint rule to enforce permission checks on all mutations
- Created `CustomPermissionGuard` and `NoPermissionGuard` for better
code documentation

### Affected Components
- Core entity resolvers: webhooks, files, domains, applications,
layouts, postgres credentials
- Workspace update mutations now use whitelist validation
- Settings UI updated with new permission controls

### Developer Experience
- ESLint now catches missing permission guards during development
- Explicit guard markers make permission requirements clear in code
review
- Comprehensive test coverage for new permission logic

## Testing
-  All TypeScript type checks pass
-  ESLint validation passes
-  New permission guards properly enforced
-  Frontend UI displays new permissions correctly

## Migration Notes
Existing workspaces will need to assign the new permissions to roles as
needed. By default, all new permissions are set to `false` for non-admin
roles.
2025-11-07 15:37:17 +01:00