Commit Graph

6965 Commits

Author SHA1 Message Date
dc0401edb5 Fixed kanban filter on kanban field metadata item (#12367)
This PR fixes an edge case where we couldn't apply a filter on the field
metadata item that is used by a kanban.

As this has already been fixed for tables with groups, this PR just uses
the same technique.

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

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
2025-05-29 14:40:02 +02:00
4485e8e3db Update enums to be all caps (#12372)
- Make custom domain public (remove from lab)
- Use ALL_CAPS definition for enums
2025-05-29 14:08:36 +02:00
76d0be7f81 Fix members table column alignment (#12298)
Fixes: #12287 


![image](https://github.com/user-attachments/assets/4f8e8c9e-cf0a-4fa8-b129-087c29a8fd94)

---------

Co-authored-by: Divyanshu Lohani <DivyanshuLohani@users.noreply.github.com>
Co-authored-by: etiennejouan <jouan.etienne@gmail.com>
2025-05-28 17:29:07 +00:00
081376f594 Onboarding - add nextPath logic after email verification (#12342)
Context :
Plan choice [on pricing page on website](https://twenty.com/pricing)
should redirect you the right plan on app /plan-required page (after
sign in), thanks to query parameters and BillingCheckoutSessionState
sync.
With email verification, an other session starts at CTA click in
verification email. Initial BillingCheckoutSessionState is lost and user
can't submit to the plan he choose.

Solution : 
Pass a nextPath query parameter in email verification link

To test : 
- Modify .env to add IS_BILLING_ENABLED (+ reset db + sync billing) +
IS_EMAIL_VERIFICATION_REQUIRED
- Start test from this page
http://app.localhost:3001/welcome?billingCheckoutSession={%22plan%22:%22ENTERPRISE%22,%22interval%22:%22Year%22,%22requirePaymentMethod%22:true}
- After verification, check you arrive on /plan-required page with
Enterprise plan on a yearly interval (default is Pro/monthly).

closes https://github.com/twentyhq/twenty/issues/12288
2025-05-28 17:20:31 +00:00
9eeb50cb14 Add relations in workflow action fields (#12359) 2025-05-28 18:32:24 +02:00
1115f6fc57 Automatically open pending form nodes in the side panel (#12332)
- Keep the side panel open when submitting a pending form node if the
history isn't empty
- Prevent the same pending Form step from being automatically opened
several times
- Prevent duplicated views of the same pending form in the side panel

> [!WARNING]
Switching from the side panel view to the full-screen view isn't robust,
and I used a hack to make one use case work here. We'll have to improve
that part later.

## Before


https://github.com/user-attachments/assets/0f830e87-7681-49e9-acc8-a08178f631a2

## After


https://github.com/user-attachments/assets/bfd742d6-e38e-4981-a93b-8e895d3aa38a
2025-05-28 18:17:22 +02:00
b90cb3e1f9 Add filter fields on update record trigger (#12354)
Fixes https://github.com/twentyhq/core-team-issues/issues/928

<img width="503" alt="Capture d’écran 2025-05-28 à 15 04 08"
src="https://github.com/user-attachments/assets/b83ceced-4b3a-454c-83c1-1176f6836d96"
/>
2025-05-28 14:56:29 +00:00
630e4780b8 Fixed IconPicker infinite loop (#12356)
This PR fixes an infinite loop that was appearing on IconPicker, since
it was about setting and unsetting the hotkey scope, it wasn't really
noticeable.

The direct cause was using the mouse enter and mouse leave events to set
and unset the hotkey scope, without using a local state to prevent race
condition, so this PR just adds this local state.

Fixes https://github.com/twentyhq/twenty/issues/12344
2025-05-28 16:05:57 +02:00
1144e210c5 Add fields to database event settings (#12331)
Backend part of https://github.com/twentyhq/core-team-issues/issues/928

- Add fields to database event settings
- If not set, match all automated triggers with the right event name
- If set, event needs at least one updated field listened to be treated
2025-05-28 14:58:35 +02:00
ee00e2319e Fix missing objectRecordsPermissions from the API when permissions v2 is enabled (#12353) 2025-05-28 14:33:03 +02:00
689e4ccfee Reverting broken filter from (#12352)
# Introdution
Reverting introduced bug by
https://github.com/twentyhq/twenty/pull/12082

We need to address the bug that was "fixed" by this in order to refresh
the recordFilters state, will have a look with @lucasbordeau 🙏
2025-05-28 12:20:51 +00:00
0a0fb976bf fixing : "message" : "Mail service not enabled" (#12349)
Fix Gmail API error handling for "Mail service not enabled" scenarios
Add proper await

Improves Gmail API error handling by properly detecting "Mail service
not enabled" errors and classifying them as INSUFFICIENT_PERMISSIONS
instead of TEMPORARY_ERROR


Fixes https://github.com/twentyhq/twenty/issues/12260
### Refernce :


https://stackoverflow.com/questions/31692720/gmail-api-returning-status-code-400-error-mail-service-not-enabled
2025-05-28 13:49:19 +02:00
a4f190b913 Fix datasource race condition on migrate (#12350) 2025-05-28 13:31:02 +02:00
69831b17ff Signed file follow up (#12347) 2025-05-28 13:02:27 +02:00
d4fac6793a Left menu and chip links (#12294)
Small optimization for faster loading (gaining ~80ms - average time of a
click)

It might seem a little over-engineered but there are a lot of edge cases
and I couldn't find a simpler solution

I also tried to tackle Link Chips but it's more complex so this will be
for another PR
2025-05-28 12:32:49 +02:00
97d4ec96af Fix view filter update and deletion propagation (#12082)
# Introduction

Diff description: ~500 tests and +500 additions

close https://github.com/twentyhq/core-team-issues/issues/731

## What has been done here
In a nutshell on a field metadata type ( `SELECT MULTI_SELECT` ) update,
we will be browsing all `ViewFilters` in a post hook searching for some
referencing related updated `fieldMetadata` select. In order to update
or delete the `viewFilter` depending on the associated mutations.

## How to test:
- Add FieldMetadata `SELECT | MULTI_SELECT` to an existing or a new
`objectMetadata`
- Create a filtered view on created `fieldMetadata` with any options you
would like
- Remove some options ( in the best of the world some that are selected
by the filter ) from the `fieldMetadata` settings page
- Go back to the filtered view, removed or updated options should have
been hydrated in the `displayValue` and the filtered data should make
sense

## All filtered options are deleted edge case
If an update implies that a viewFilter does not have any existing
related options anymore, then we remove the viewFilter

## Testing
```sh 
PASS  test/integration/metadata/suites/field-metadata/update-one-field-metadata-related-record.integration-spec.ts (27 s)
  update-one-field-metadata-related-record
    SELECT
      ✓ should delete related view filter if all select field options got deleted (2799 ms)
      ✓ should update related multi selected options view filter (1244 ms)
      ✓ should update related solo selected option view filter (1235 ms)
      ✓ should handle partial deletion of selected options in view filter (1210 ms)
      ✓ should handle reordering of options while maintaining view filter values (1487 ms)
      ✓ should handle no changes update of options while maintaining existing view filter values (1174 ms)
      ✓ should handle adding new options while maintaining existing view filter (1174 ms)
      ✓ should update display value with options label if less than 3 options are selected (1249 ms)
      ✓ should throw error if view filter value is not a stringified JSON array (1300 ms)
    MULTI_SELECT
      ✓ should delete related view filter if all select field options got deleted (1127 ms)
      ✓ should update related multi selected options view filter (1215 ms)
      ✓ should update related solo selected option view filter (1404 ms)
      ✓ should handle partial deletion of selected options in view filter (1936 ms)
      ✓ should handle reordering of options while maintaining view filter values (1261 ms)
      ✓ should handle no changes update of options while maintaining existing view filter values (1831 ms)
      ✓ should handle adding new options while maintaining existing view filter (1610 ms)
      ✓ should update display value with options label if less than 3 options are selected (1889 ms)
      ✓ should throw error if view filter value is not a stringified JSON array (1365 ms)

Test Suites: 1 passed, 1 total
Tests:       18 passed, 18 total
Snapshots:   18 passed, 18 total
Time:        27.039 s
```
## Out of scope
- We should handle ViewFilter validation when extracting its definition
from the metadata
https://github.com/twentyhq/core-team-issues/issues/1009

## Concerns
- Are we able through the api to update an RATING fieldMetadata ? ( if
yes than that's an issue and we should handle RATING the same way than
for SELECT and MULTI_SELECT )
- It's not possible to group a view from a MULTI_SELECT field

The above points create a double nor a triple "lecture" to the post hook
effect:
- ViewGroup -> only SELECT
- VIewFilter -> only SELECT || MULTI_SELECT
- Rating nothing
I think we should determine the scope of all of that

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2025-05-28 10:22:28 +00:00
e63cd39a5b i18n - translations (#12341)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2025-05-28 10:50:02 +02:00
1c64b7b072 feat: implement dynamic driver configuration + fix integration test log pollution (#12104)
### Primary Changes: Dynamic Driver Configuration
Refactors FileStorageService and EmailSenderService to support dynamic
driver configuration changes at runtime without requiring application
restarts.

**Key Architectural Change**: Instead of conditionally registering
drivers at build time based on configuration, we now **register all
possible drivers eagerly** and select the appropriate one at runtime.

### What Changed:
- **Before**: Modules conditionally registered only the configured
driver (e.g., only S3Driver if STORAGE_TYPE=S3)
- **After**: All drivers (LocalDriver, S3Driver, SmtpDriver,
LoggerDriver) are registered at startup
- **Runtime Selection**: Services dynamically choose and instantiate the
correct driver based on current configuration

### Secondary Fix: Integration Test Log Cleanup
Addresses ConfigStorageService error logs appearing in integration test
output by using injected LoggerService for consistent log handling.
2025-05-28 14:19:20 +05:30
d133055609 Fix Client Config async loading (#12308)
Fix ClientConfig async loading

---------

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
Co-authored-by: Félix Malfait <felix@twenty.com>
2025-05-28 10:40:20 +02:00
196d8c97a4 Add relations in database event trigger output data (#11820)
## Done
- add relations in dropdown variables
- add relations in worklfow run inputs
- use objectMetadataMaps in workflow folder

## To do
- does not work with rest api calls, will be fixed after
https://github.com/twentyhq/twenty/pull/11349 is merged
- waiting for crud action relation fields
https://github.com/twentyhq/core-team-issues/issues/509
2025-05-27 20:46:15 +02:00
01b40e173b Refactored dropdown content and fixed all dropdown width bugs (#12334)
This PR refactors all the dropdown content wrapping mechanism across the
entire app.

It refactors the internals of the `Dropdown` component and introduces a
new generic `DropdownContent` component that is a generic wrapper used
for each dropdown.

## Why this PR ?

Because we’ve been experiencing continuous regressions for months on the
dropdown content width, with weird scrolling behaviors in some and not
in others, and every time a solution was found for a particular set of
dropdowns, it broke another set of dropdowns, which wasn’t noticed
because doing the QA of all dropdowns of the app is very difficult for
fixing an apparently small bug.

## Don’t we already have a `DropdownMenu` component ?

Indeed, this new `DropdownContent` is almost like `DropdownMenu` and
took inspiration from it but `DropdownContent` acts as a generic content
container that sets the width of the whole dropdown, whether we have a
menu or not.

## Why don’t we put it directly in Dropdown internals ?

Because the Dropdown component is using a complex logic with floating-ui
middleware to compute its position and size, and for this logic to work
correctly, it cannot be responsible for the “wanted” width of its
content, because the children components, which the dropdown is not
aware of, can request different widths after the dropdown has been
mounted.

A good example with multiple use cases inside the same dropdown can be
found in `AdvancedFilterDropdownFilterInput`

Thus, it is the responsibility of the content of the dropdown to
determine the width it wants to have.

## What is the difference with DropdownMenuItemsContainer ?

We can have multiple `DropdownMenuItemsContainer` in a dropdown,
alongside other components like `DropdownMenuSeparator` or
`DropdownMenuHeader`, and each of those components behaves differently
regarding to its width, paddings, etc. Therefore it is logical that the
`DropdownMenuItemsContainer` cannot be responsible for the whole
dropdown content width, and trying to do so has been the cause of many
regressions for months.

Now `DropdownMenuItemsContainer` is taking a width of `auto` by default,
which is the best to adapt to a parent which has a defined width.

## How do I set the width of my dropdown now ?

By passing a pixel width to the props `widthInPixels` of
`DropdownContent`, which only accepts numbers to avoid any confusion
with `auto` , `100%` or `160px` and other specific width variables.

The `dropdownWidth` props has been removed from `<Dropdown>` to avoid
any confusion.

Also the `DropdownMenuItemsContainer` is now using `auto` as its default
width to fill the available space inside `DropdownContent` .

It is highly recommended to use the enum `GenericDropdownContentWidt` to
define your width.

## Where to use this new `DropdownContent` component ?

There are two main use cases.

If the dropdown content is defined directly inline in the Dropdown
props, then it is recommended to use it here too.

On the other hand if the dropdown content is abstracted in another
component, it’s recommended to use this new component alongside the
others components like `DropdownMenuItemsContainer`.

A good rule of thumb is to place `DropdownContent` where
`DropdownMenuItemsContainer`, `DropdownMenuSearchInput`, etc. are
placed.

## What if I have a custom width ?

Just define a constant like `ICON_PICKER_DROPDOWN_CONTENT_WIDTH` and use
it with the props `widthInPixels` .

Otherwise there’s a `GenericDropdownContentWidth` enum. The default
value being `GenericDropdownContentWidth.Medium` (or 200px), which most
dropdowns use.

## QA 


Component | Comment
-- | --
AttachmentDropdown | Fixed overflowing (thanks to DropdownContent)
RecordIndexActionMenuDropdown |  
CommandMenuActionMenuDropdown |  
SupportDropdown | Fixed overflowing (thanks to DropdownContent)
MessageThreadSubscribersDropdownButton | Removed because unused
FavoriteFolderNavigationDrawerItemDropdown | Set width at Narrow
FavoriteFolderPicker |  
ViewPickerOptionDropdown |  
PageFavoriteFolderDropdown | Removed because unused
AdvancedFilterAddFilterRuleSelect |  
AdvancedFilterAddFilterRuleSelect |  
AdvancedFilterFieldSelectMenu |  
AdvancedFilterRecordFilterGroupOptionsDropdown |  
AdvancedFilterRecordFilterOperanceSelect | Set width at Narrow
AdvancedFilterLogicalOperatorDropdown | Set width at Narrow
AdvancedFilterRecordFilterOptionsDropdown |  
AdvancedFilterRootRecordFilterGroup | Fixed broken horizontal scrolling
behavior
AdvancedFilterSubFieldSelectMenu |  
AdvancedFilterDropdownFilterInput |  
ObjectFilterDropdownBooleanSelect |  
ObjectFilterDropdownCountrySelect | Fixed broken menu items container
ObjectFilterDropdownCurrencySelect | Set width to Large
ObjectFilterDropdownFilterInput |  
ObjectFilterDropdownOperandDropdown | Fixed width that was not fixed
ObjectFilterDropdownFilterInput | Fixed width that wasn’t the same for
EditableFilterChip
ObjectFilterDropdownOperandSelect | Refactored
ObjectOptionsDropdownRecordGroupFieldsContent | Added missing separator
ObjectOptionDropdownFieldsContent |  
ObjectOptionsDropdownHiddenFieldsContent |  
ObjectOptionsDropdownLayoutContent |  
ObjectOptionsDropdownLayoutOpenInContent |  
ObjectOptionsDropdownMenuContent |  
ObjectOptionsDropdownRecordGroupFieldsContent |  
ObjectOptionsDropdownRecordGroupsContent |  
ObjectOptionsDropdownRecordGroupSortContent |  
ObjectOptionsDropdownHiddenRecordGroupsContent | Removed unnecessary
DropdownMenuItemsContainer
RecordBoardColumnHeaderAggregateDropdown | Fixed overflowing (thanks to
DropdownContent)
RecordBoardColumnHeaderAggregateDropdownFieldsContent | Fixed
overflowing (thanks to DropdownContent)
RecordBoardColumnHeaderAggregateDropdownMenuContent | Fixed overflowing
(thanks to DropdownContent)
RecordBoardColumnHeaderAggregateDropdownOptionsContent | Fixed
overflowing (thanks to DropdownContent)
MultiItemFieldInput | Fixed overflowing (thanks to DropdownContent)
MultiItemFieldMenuItem |  
MultipleRecordPicker | Fixed overflowing (thanks to DropdownContent)
SingleRecordPicker |  
RecordTableColumnAggregateDropdownSubmenuContent |  
RecordTableColumnAggregateFooterMenuContent |  
RecordTableColumnHeadDropdownMenu | Fixed overflowing (thanks to
DropdownContent)
RecordTableHeaderPlusButtonContent |  
MultipleSelectDropdown | Broken width fixed
ObjectSortDropdownButton |  
RecordDetailRelationRecordsListItem |  
ConfigVariableDatabaseInput |  
ConfigVariableOptionsDropdownContent |  
SettingsObjectFieldActiveActionDropdown | Fixed overflowing (thanks to
DropdownContent)
SettingsObjectFieldDisabledActionDropdown | Set width at Narrow
SettingsObjectSummaryCard | Removed because unused
SettingsDataModelFieldSelectFormOptionRow |  
SettingsDataModelNewFieldBreadcrumbDropdown |  
SettingsObjectInactiveMenuDropDown |  
SettingsRoleAssignementWorkspaceMemberPickerDropdown |  
SettingsRolePermissionObjectLevelObjectPickerDropdownContent |  
SettingsSecurityApprovedAccessDomainRowDropdownMenu | Couldn’t test
SettingsSecuritySSORowDropdownMenu | Couldn’t test
SettingsAccountsRowDropdownMenu | Fixed overflowing (thanks to
DropdownContent)
SettingsIntegrationDatabaseConnectionSummaryCard | Couldn’t test
SettingsServerlessFunctionTablEnvironmentVariableTableRow | Deactivated
scope
MatchColumnSelectFieldSelectDropdownContent | Removed now unnecessary
width on DropdownMenuItemsContainer
MatchColumnSelectSubFieldSelectDropdownContent |  
SubMatchingSelectInput |  
CurrencyPickerDropdownSelect |  
IconPicker | Fixed overflowing (thanks to DropdownContent)
PhoneCountryPickerDropdownSelect |  
Select | Refactored to drilldown wanted width of content, in this case
it’s intended
ExpandedListDropdown |  
ShowPageAddButton | Removed because unused
MultiWorkspaceDropdownDefaultComponent |  
MultiWorkspaceDropdownThemesComponent |  
MultiWorkspaceDropdownWorkspacesListComponent |  
AdvancedFilterDropdownButton |  
EditableFilterChip |  
EditableFilterDropdownButton |  
UpdateViewButtonGroup |  
ViewBarFilterDropdown |  
ViewBarFilterDropdownFieldSelectMenu |  
ViewPickerContentCreateMode |  
ViewPickerContentEditMode |  
ViewPickerListContent |  
WorkflowEditTriggerDatabaseEventForm |  
WorkflowVariablesDropdownFieldItems |  
WorkflowVariablesDropdownObjectItems |  
WorkflowVariablesDropdownWorkflowStepItems |  
CommandMenuContextChipGroups |  
RecordBoardColumnDropdownMenu |  
MultiSelectInput |  
SelectInput |  
CustomSlashMenu |  
DropdownMenu | Removed and replaced by DropdownContent
OverlayContainer and around |  


<!-- notionvc: 1e23bdb8-2dda-4f8d-a64d-ecc829a768a2 -->

## Miscellaneous 

Side notes : 

- The `Select` component is now wrapping the `DropdownContent` because
it computes a dynamic width.
- The advanced filter dropdown has been fixed, it was broken when
resizing the window horizontally, we couldn’t scroll. This specific edge
case was taken into account when refactoring the whole dropdown content
system
- As discussed with Nitin, data-select-disable will probably be removed
entirely, so I let it as is, because right now it is not used by the
refactored d&d selection.
- Duplicate separators under DropdownMenuHeader have been removed.

Fixes : https://github.com/twentyhq/twenty/issues/12327
Fixes : https://github.com/twentyhq/core-team-issues/issues/951
2025-05-27 19:44:13 +02:00
5ce462b17e i18n - translations (#12330)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2025-05-27 18:12:10 +02:00
017940b2cb better logging in order to investigate later one on this kind of error (#12326)
# extracting domain emails

Added new test cases covering weird but valid email formats (plus
addressing, subdomains, international domains, etc.) to identify
potential failures in the current implementation.

Two tests with quoted local parts containing @ symbols or quotes are
marked as skipped since they're expected to fail with the current simple
string splitting approach. They are too exotic IMO, we should throw
errors.

## Next
We will monitor errors related to this and update accordingly later on.


### Note 
technically, quotes are possible in RFC see
[here](https://stackoverflow.com/questions/4816424/are-single-quotes-legal-in-the-name-part-of-an-email-address)

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2025-05-27 18:10:48 +02:00
f210d274bf Role page various fixes (#12324)
Various fixes from fast follows

- Sort roles by alphabetical order
- Change some tooltips
- During role creation, role should have all permissions enabled by
default
- Changed Permission icons design and refactored duplicating logic in a
dedicated component
- Changed "Revoked by" design
- Display role icon in default role picker
- Workspace member avatar was missing in role list and member picker
- Set "seeded" member role as editable for new workspaces
- Various css fixes
2025-05-27 17:58:55 +02:00
8051646567 Handle restricted objects #1 refactor permissions map + return object permissions from gql (#12313)
## Context
- Introduced objectPermissions in currentUserWorkspace which uses role
permissions from cache so we can fetch granular permissions from the API
- Refactored cached role permissions to map permissions with object
metadata id instead of object metadata name singular to be more flexible

New Cache
<img width="574" alt="Screenshot 2025-05-27 at 11 59 06"
src="https://github.com/user-attachments/assets/1a090134-1b8a-4681-a630-29f1472178bd"
/>

GQL
<img width="977" alt="Screenshot 2025-05-27 at 11 58 53"
src="https://github.com/user-attachments/assets/3b9a82b0-6019-4a25-a6e2-a9e0fb4bb8a0"
/>


Next steps: Use the updated API in the FE to fetch granular permissions
and update useHasObjectReadOnlyPermission hook
2025-05-27 17:42:26 +02:00
651ad38e79 feat: trim empty space (#12293)
Trim trailing spaces of the input, instead of manually trimming, thus
improving the user experience.
Fixes #12279

### Screencast
[Screencast from 2025-05-26
21-03-54.webm](https://github.com/user-attachments/assets/cc40be5a-d260-4a20-bbc8-c0b21ddbbd9b)

---------

Co-authored-by: Devessier <baptiste@devessier.fr>
2025-05-27 17:31:54 +02:00
13d13144b7 [permissions] Override repository and manager methods #2 (#11929)
Closes https://github.com/twentyhq/core-team-issues/issues/747
2025-05-27 15:12:30 +00:00
97cc1b3cbb [permissions V2] Throw when objectPermissions not found in datasource (#12325)
I encountered a bug where I was missing permissions while calling
searchResolver because the repository from
`twentyORMManager.getRepository` was missing permissions itself.
The repository was returned from the cached repositories map using a
repository key feature the roleId, the rolesVersion and
featureFlagMapVersion.
I was not able to reproduce but this error should not go unnoticed: we
always expect to find objectPermissions for every roleId in the
datasource now.
I was not able to understand what happened for now but I think throwing
the error will help keeping an eye on it
2025-05-27 15:01:11 +00:00
7cacccf0b8 UNAUTHORIZED gmail error (#12262)
# Gmail OAuth authentication flow issues

### TLDR
This error is not an error and therefore should be treated as a simple
redirect with a snackbar.

### More details
Fixing incomplete OAuth token exchange processes and improving error
handling for empty Gmail inboxes.
The changes include modifications to OAuth guards, to ensure that if a
user clicks "cancel" instead of completing the authentication workflow
if fails

## Before:
Redirection from `/settings/accounts` to `app.twenty.com` with an
`UNAUTHORIZED` error

## After :
<img width="948" alt="Screenshot 2025-05-26 at 18 04 37"
src="https://github.com/user-attachments/assets/62c8721e-c2b3-4e3d-ad0b-e4059dfb7a98"
/>


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

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2025-05-27 16:45:42 +02:00
4b25aabfa2 Update schema and add tests (#12314)
For database event triggers, we remove the before / after logic. We go
directly with the properties
<img width="211" alt="Capture d’écran 2025-05-27 à 11 40 36"
src="https://github.com/user-attachments/assets/a05bd3c1-104b-477b-be52-d56846ce7e63"
/>

To achieve this without changing the shape of events, we need to handle
keys using dots, such:
```
'properties.after.name': {
    icon: 'IconBuildingSkyscraper',
    type: FieldMetadataType.TEXT,
    label: 'Name',
    value: 'My text',
    isLeaf: true,
},
```

This PR:
- adds logic to handle the case where the key has dot included
- adds tests
2025-05-27 15:57:28 +02:00
78f8562457 fix: prevent drag selection from blocking input focus (#12322)
closes #12309
Fixes input elements becoming unusable due to drag selection preventing
default browser behavior.

**Problem:**
- Input elements couldn't receive focus because `event.preventDefault()`
was called unconditionally
- Removing `preventDefault()` broke click-outside-to-deselect
functionality

**Solution:**
- Only call `preventDefault()` when actually starting drag selection
- Preserves input focus while maintaining drag selection and deselection
behavior

**Changes:**
- Move `event.preventDefault()` inside the `shouldStartSelecting`
condition
- Update test to reflect correct behavior for disabled elements
2025-05-27 14:51:48 +02:00
feeb032602 Add mcp.json to gitignore (#12321)
# Introduction
In order to avoid pushing secrets within an project scoped mcp.json
configuration
[Related
docs](https://docs.cursor.com/context/model-context-protocol#configuration-locations)
2025-05-27 14:06:21 +02:00
0275fad5f7 billing - remove deprecated endpoint (#12315)
staging and main env config in stripe updated (prod already updated)
2025-05-27 14:03:37 +02:00
d85c45a4cf Fix last row disappearing when dragging a row in the table (#12297)
# Fix last row disappearing when dragging a row in the table

Fixes https://github.com/twentyhq/core-team-issues/issues/836

The issue came from the fact that the provided placeholder was not
mounted at the right place (after the footer when it should be mounted
before it).

I created a context to which we can pass the placeholder. We can use
this placeholder anywhere inside the table by using
`RecordTableBodyDroppablePlaceholder`.

## Before


https://github.com/user-attachments/assets/39a2e45b-6d97-4450-bfee-12135a873a1d


## After


https://github.com/user-attachments/assets/ca126819-67f2-4358-b644-85172fef3b8f
2025-05-27 12:02:24 +02:00
c7b3ebc743 i18n - translations (#12312)
Created by Github action

Co-authored-by: github-actions <github-actions@twenty.com>
2025-05-27 11:46:00 +02:00
42d493d31d Commit index.ts twenty-ui (#12310)
Related to https://github.com/twentyhq/twenty/pull/12282
2025-05-27 09:37:19 +00:00
7b5d6a2ffc Open the executed workflow run in the side panel (#12284)
> [!WARNING]
> This PR introduces a new way to interact with workflow runs. It comes
with a few known flaws that will be solved in a second time.

## Launching a Test


https://github.com/user-attachments/assets/89b0eb63-d276-4ac5-a5d8-665d0084e0c5

## Triggering a workflow with a manual trigger


https://github.com/user-attachments/assets/047975d4-a24d-4cf0-b617-525965e3bfd8

Closes https://github.com/twentyhq/core-team-issues/issues/812
2025-05-27 11:34:02 +02:00
a83279ddce fix(dropdown): separator width + DropdownHeader height (#12285)
## Before

![CleanShot 2025-05-26 at 15 26
35@2x](https://github.com/user-attachments/assets/d6247af2-6008-4234-b777-13597c697b12)

## After

![CleanShot 2025-05-26 at 15 26
42@2x](https://github.com/user-attachments/assets/65447c84-4313-4f9a-831d-efc1eccd3d26)
2025-05-27 11:17:03 +02:00
8cf3b83bb9 fix/replace-set-primary-with-bookmark-12268 (#12276)
## 🛠️ What this PR fixes

Fixes #12268

This PR fixes the UI behavior where the "Set as Primary" button was
incorrectly shown for emails or phones that are already marked as
primary. Instead, users now see a bookmark icon indicating the entry as
primary.

## 🎥 Demo

The attached video demonstrates the updated UI where the "Set as
Primary" button is hidden for primary contacts or emails and replaced by
a bookmark icon.



https://github.com/user-attachments/assets/9afcc818-fbb4-4e7c-8fa2-093fdc7d8a26

---------

Co-authored-by: Davinder Kumar <davinder.kumar@intverse.io>
Co-authored-by: Devessier <baptiste@devessier.fr>
2025-05-27 11:10:12 +02:00
92aa6a8e1a filter out 500 errors from sentry-captured errors in FE (#12307)
Since https://github.com/twentyhq/twenty/pull/12286 we are now capturing
in sentry graphql queries errors in the FE.
We want to exclude InternalServerErrors because they are already
captured in sentry from the BE.
2025-05-27 10:43:26 +02:00
9cdd0fdac0 Revert "Client config not render blocking (#12300)" (#12302)
This reverts commit 4ce7fc6987, to take
more time to address PR comments
2025-05-27 09:04:47 +02:00
e8532faaaa Fix find duplicates typing (id -> uuid) (#12301)
Minor fix of a bug I saw while testing in staging
2025-05-27 08:02:47 +02:00
4ce7fc6987 Client config not render blocking (#12300)
Changes for performance improvement.
The primary improvements include replacing GraphQL queries with
REST-based client configuration fetching and making the client config
non render-blocking
2025-05-27 00:06:48 +02:00
aa58259019 11744 emails broken image in emails (#12265)
- refactor file tokens
- update file token management
  - generate one token per file per workspaceId
  - move token from query params to url path
2025-05-26 22:05:21 +02:00
69badf2a66 Capture FE GraphQL exceptions in sentry (#12286)
We should capture graphQL exceptions thrown in the FE in Sentry.

All the more so as we have just cleaned back-end errors in sentry,
preventing 4xx errors from being wrongfully sent to sentry.
Those 4xx errors should, except for `Unauthenticated` and `Forbidden`
errors (for now - this list can evolve), trigger a sentry FE error, as
we are not suppose to let users of the product interface trigger queries
that will fail with 4xx errors (for instance a malformed input).

We still miss an efficient way to group those errors together in sentry.
It could be the message but the message may be different for each user
if it contains user-specific data, and we don't always have control on
the message.
This can be done later as we iterate on improving sentry
2025-05-26 17:23:19 +00:00
a15451dab2 Fix close command menu button (#12282)
Fixes #12280 

The `dataClickOutsideId` and `dataGloballyPreventClickOutside` props
weren't passed to the button components.

This PR fixes this and introduces the type `ClickOutsideAttributes`.



https://github.com/user-attachments/assets/38b1a6f9-8f3a-43d2-aa7b-aaa259ac6737
2025-05-26 15:37:46 +02:00
ec4e4740d2 Make workflow statuses more resilient (#12263)
Workflow statuses are often broken. I did not figured out why yet. But I
see two causes that can be fixed:
- statuses calculation are really complicated today, just to spare a
call to the database
- job is not indempotent, it is using the combination of the previous
statuses + the update to calculate the new statuses. Which means that
once broken, next updates will be broken as well

Instead, we now:
- fetch workflow versions
- get the statuses from these.
It simplifies the code and make the job indempotent.
2025-05-26 13:05:18 +00:00
742af7884a Update Makefile in local setup to clean postgres instead of pg-spile (#12273)
In Makefile used for Local dev setup spilo container is still in the use
despite deprecating it in 0.43.0

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2025-05-26 12:20:19 +02:00
524a1d78d2 Refactor drag selection: Replace external library with custom implementation and add auto-scroll (#12134)
Closes #12076
Closes #11764

Replaced the `@air/react-drag-to-select` library with a custom
implementation to get better control over the selection behavior and add
auto-scroll functionality.

**What changed:**
- Removed external drag selection dependency 
- Built custom drag selection from scratch using pointer events --
@charlesBochet
- Added auto-scroll when dragging near container edges
- Fixed boundary detection so selection stays within intended areas
- Added proper `data-select-disable` support for checkboxes and other
non-selectable elements

The new implementation gives us full control over the selection logic
and eliminates the external dependency while adding the auto-scroll
feature that was **not** requested 😂

**Auto Scroll**



https://github.com/user-attachments/assets/3509966d-5b6e-4f6c-a77a-f9a2bf26049f



related to #12076 


https://github.com/user-attachments/assets/2837f80e-728c-4739-a0e2-b8d7bc83a21a

**Also fixed:**
- Record board column height not extending to the bottom (styling issue
I found while working on this)

before:

<img width="1512" alt="Screenshot 2025-05-19 at 23 58 54"
src="https://github.com/user-attachments/assets/602b310f-7ef6-44f6-99e9-da5ff59b31d3"
/>

after:

<img width="1512" alt="Screenshot 2025-05-19 at 23 56 40"
src="https://github.com/user-attachments/assets/1d0ecb5c-49e0-4f03-be3b-154a6f16a7a4"
/>

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2025-05-26 11:58:22 +02:00
621a779526 Prevent setting primary link as primary link (#12266)
## Before

It was possible to set the primary link as the... primary link.


https://github.com/user-attachments/assets/a6ffefab-50c5-403e-9aa1-5acc08593168

## After


https://github.com/user-attachments/assets/494e45c4-de15-4b52-b71b-032a2ca77c35

- We display the bookmark icon for the first link if there is more than
one link to show. (`index === 0 && links.length > 1`)
- It's never possible to "Set as Primary" the first link (`index > 0`)
- I introduced abstractions to make it easy to solve a similar issue for
phones and emails fields (see
https://github.com/twentyhq/twenty/issues/12268)
- Wrote stories to document the current improper behavior of phones and
emails fields
2025-05-23 18:55:26 +02:00