Pass the dropdownId into every closeDropdown() call so the instance ID
is always defined and the error no longer occurs.
---------
Co-authored-by: prastoin <paul@twenty.com>
Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
resolve#11075
The issue was that when inline cells or table cells are in edit mode, a
click outside event listener is active, and its callback calls
event.stopImmediatePropagation(). This prevents the onClick of LinkChip
from firing, allowing the browser's default behavior to trigger the 'to'
link and cause a full page reload.
To fix this, I added event.preventDefault() inside each click outside
callback to stop the browser from reloading.
Another possible solution: check if currentTableCellInEditModePosition
or isInlineCellInEditMode is true, and if so:
Either convert the StyledLink in LinkChip into a div
Or set forceDisableClick = true, which falls back to AvatarChip.
Before:
https://github.com/user-attachments/assets/7ffd76fd-988e-484b-bad6-10e0147502c2
After:
https://github.com/user-attachments/assets/18cfbc0e-8af6-4ecc-862e-a2b8f02e2535
---------
Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
# Introduction
In this PR we've mainly refactor the typing to be extending existing
entities.
Also handling relations through the field abstraction layer rather than
a dedicated one. We reverted midway
We then still need to:
- Handle indexing
- Uniqueness
- Add strong coverage and avoid static inline snapshoting as right now +
building a coherent testing set
- Deprecate the `standardId` in favor of a `uniqueIdentifier` on each
`objectMetadata` and `fieldMetadata`
- Rename types `input` to `flattened`
- Handle custom or non custom edit edge cases. ( e.g cannot delete a
standard field or object )
## Notes
Right I preferred including too many information ( whole object and
field input ) in the action context, we might wanna evict redundant
information in the future when implementing the runners
This PR fixes a UI bug where the "Quote" item in the slash command menu
was displayed without an icon.
The root cause was that the IconBlockquote component, while available in
the icons library, was not being exported from the internal twenty-ui
package.
## Before / After


## Changes:
- Exported IconBlockquote from TablerIcons.ts in the twenty-ui package.
- Updated getSlashMenu.ts in the twenty-front package to import and use
the IconBlockquote for the "Quote" menu item.
This PR is purely technical, it does produces any functional change to
the user
- add Lock mecanism to run steps concurrently
- update `workflow-executor.workspace-service.ts` to handle multi branch
workflow execution
- stop passing `context` through steps, it causes race condition issue
- refactor a little bit
- simplify `workflow-run.workspace-service.ts` to prepare `output` and
`context` removal
- move workflowRun status computing from `run-workflow.job.ts` to
`workflow-executor.workspace-service.ts`
## NOTA BENE
When a code step depends of 2 parents like in this config (see image
below)
If the form is submitted before the "Code - 2s" step succeed, the branch
merge "Form" step is launched twice.
- once because form is submission Succeed resumes the workflow in an
asynchronous job
- the second time is when the asynchronous job is launched when "Code -
2s" is succeeded
- the merge "Form" step makes the workflow waiting for response to
trigger the resume in another job
- during that time, the first resume job is launched, running the merge
"Form" step again
This issue only occurs with branch workflows. It will be solved by
checking if the currentStepToExecute is already in a SUCCESS state or
not
<img width="505" alt="image"
src="https://github.com/user-attachments/assets/b73839a1-16fe-45e1-a0d9-3efa26ab4f8b"
/>
# Introduction
In this PR we've initialized the `workspace-migration-v2` folder.
Focusing on the builder in the first place.
From now it contains:
- Basic temporary types ( `fieldMetadataEntity` and
`ObjectMetadataEntity` )
- Object actions builder ( create, delete, update )
- Fields actions builder ( create, delete ) ( update coming in a
following PR )
We will still have to handle specific conditions such as:
- Index creation
- Uniqueness addition removal
- Relation
We also need to determine when we want to compute and transpile the
object no field `uniqueIdentifier`
We're aiming to merge this first in order to avoid accumulating code in
this PR
---------
Co-authored-by: prastoin <paul@twenty.com>
This PR is raised to close the issue #13044
But there are some doubts that needs to be approved.
If the fields are not custom then we were saving the changes in
**standardOverrides** obj in which only three fields are
overridableFields **label, icon & description** can be updated for a
field.
You can see this in _before-update-one-field.hook.ts_ on line 85
```ts
const overridableFields = ['label', 'icon', 'description'];
```
If the field to be updated are from these three we are putting this in a
**standardOverrides** obj and passing it
However in our _field-metadata.service.ts_ file. We have **updateOne**
function inside it we have wrote a condition if **isCustom** is false
then the purpose was to build the updatableFields from the
**standardOverrides** obj that we got in **fieldMetadataInput** but
there was an error in it. As you can see below
```ts
const updatableFieldInput =
existingFieldMetadata.isCustom === false
? this.buildUpdatableStandardFieldInput(
fieldMetadataInput,
existingFieldMetadata,
)
: fieldMetadataInput;
```
However, the issue was that we were placing the entire
**standardOverrides** object inside **updatableFieldInput** again —
instead of merging its individual fields (label, icon, description)
directly into the update payload.
This PR fixes that by correctly applying the overrides into the
top-level object.
Please refer to the file changes for the full context.
But the thing i don't know.
[ ] - Is this the correct expected flow??
[ ]- Will this change break anything elsewhere?
I still have doubts on these two. Let me know if I missed something.
---------
Co-authored-by: Jagss24 <btwitsjagannat12@gmail.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
In this PR, I'm fixing a bug introduced in recent performance work on
the cache.
Bug context: https://github.com/twentyhq/twenty/issues/12865
Related PR opened by a contributor:
https://github.com/twentyhq/twenty/pull/13003
## Root cause
We cache all objectMetadataItems at graphql level : see
`useCachedMetadata` hook:
- instead of going through the regular resolvers, we direlcty load data
from the cache. However this data must be localized regarding labels and
descriptions
In a precedent refactoring, we introduced the notion of locale in the
cache key. However, the user locale was not properly taken into account
as we did not have the information in this hook.
## Fix
1. **Introduce locale in userWorkspace entity**. The locale is stored on
workspaceMember in each postgres workspaceSchema (workspace_xxx) which
is the alter ego of userWorkspace in postgres core schema. Note that we
can't store it in user as a user can be part of multiple workspaces (the
locale already there must be seen as a default for this user), and we
cannot rely on workspaceMember as we would need to query the
workspaceSchema in the authentication layer which we want to avoid for
performance reasons.
2. During request hydration from token (containing the userWorkspaceId),
we fetch the userWorkspace and store it in the Request (this impact both
AuthContext and Request interface)
3. Leverage userWorkspace.locale in the useCachedMetadata hook
## Additional notes
There is no need to change the way we store and retrieve the
object-metadata-maps object itself which is different from the graphql
layer cache. object-metadadata-maps are not localized
Context :
- Phones import is a bit complex if not all subfields are provided.
- Phones subfield validation are absent or different from BE validation.
Solution :
- Normalize callingCode and countryCode validation (BE/FE)
- Ease phone import if only phoneNumber is provided
## Summary
- Fixes#12893 - Workspace switcher button now aligns properly with
record index headers when navigation drawer is collapsed
- Maintains consistent button height in both expanded and collapsed
states
- Simple CSS fix that improves visual consistency
## Fix Details
The issue was caused by the workspace switcher button changing height
from 20px (expanded) to 16px (collapsed). This created misalignment with
the page headers.
Changed in `MultiWorkspacesDropdownStyles.tsx`:
```tsx
// Before - height changed based on drawer state
height: ${({ theme, isNavigationDrawerExpanded }) =>
isNavigationDrawerExpanded ? theme.spacing(5) : theme.spacing(4)};
// After - consistent height
height: ${({ theme }) => theme.spacing(5)};
```
## Visual Alignment
- Workspace switcher button: 20px height (theme.spacing(5))
- Maintains alignment with record index headers in collapsed state
- Consistent with Figma design requirements
## Test Plan
- [x] Collapsed navigation drawer - workspace switcher aligns with
headers
- [x] Expanded navigation drawer - no visual regression
- [x] Button functionality remains unchanged
---
🤖 This fix was implemented using [Claude Code](https://claude.ai/code)
by Jez (Jeremy Dawes) and Claude working together\!
Thanks to the Twenty team for the great project\! 🚀
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: ehconitin <nitinkoche03@gmail.com>
Co-authored-by: nitin <142569587+ehconitin@users.noreply.github.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
resolve#12662
This PR enables exporting deleted records by detecting when deleted view
mode is active and adding deletedAt: { is: 'NOT_NULL' } to
graphqlFilter.
---------
Co-authored-by: Charles Bochet <charles@twenty.com>
This PR fixes a bug that forced all title cell to behave as if they were
in a show page, but we have workflow page breadcrumb that is not a show
page title.
Fixes https://github.com/twentyhq/twenty/issues/13041
This PR fixes a mismatch between the filter operation we have on NUMBER
and RATING field types, and the labels we use for those filters in the
application.
What is actually used is :
- Greater than or equal
- Less than or equal
But unfortunately, until now we display "less than" and "greater than"
everywhere.
This PR fixes that.
We would still have to change the value that is saved in viewFilter
table from `greaterThan` to `greaterThanOrEqual` and likewise for less
than, but it would require a careful migration, and for now just
changing the display labels is enough.
See follow-up issue for migration of the DB values :
https://github.com/twentyhq/core-team-issues/issues/1196
Fixes https://github.com/twentyhq/twenty/issues/13000
This PR fixes a bug with phone input clearing its value when we press
space right after a country calling code.
As the problem comes from the library `react-phone-input-number` this PR
implements a yarn patch.
Fixes https://github.com/twentyhq/twenty/issues/12903
Currently, when a server query or mutation from the front-end fails, the
error message defined server-side is displayed in a snackbar in the
front-end.
These error messages usually contain technical details that don't belong
to the user interface, such as "ObjectMetadataCollection not found" or
"invalid ENUM value for ...".
**BE**
In addition to the original error message that is still needed (for the
request response, debugging, sentry monitoring etc.), we add a
`displayedErrorMessage` that will be used in the snackbars. It's only
relevant to add it for the messages that will reach the FE (ie. not in
jobs or in rest api for instance) and if it can help the user sort out /
fix things (ie. we do add displayedErrorMessage for "Cannot create
multiple draft versions for the same workflow" or "Cannot delete
[field], please update the label identifier field first", but not
"Object metadata does not exist"), even if in practice in the FE users
should not be able to perform an action that will not work (ie should
not be able to save creation of multiple draft versions of the same
workflows).
**FE**
To ease the usage we replaced enqueueSnackBar with enqueueErrorSnackBar
and enqueueSuccessSnackBar with an api that only requires to pass on the
error.
If no displayedErrorMessage is specified then the default error message
is `An error occured.`
Fixes https://github.com/twentyhq/twenty/issues/12885
This PR fixes a hotkey scope race condition happening on note/task
creation.
The problem is that `ActivityRichTextEditor` catches the click event
before the title cell.
So here we prevent this from happening by checking if the record title
cell is.
This is only temporary and should be improved after the persist logic
refactor : https://github.com/twentyhq/core-team-issues/issues/192
When we use a record field in a form, record relations are displayed as
available variables in following step.
But those are actually empty at execution.
When choosing the record in the form and submitting, we enrich the
record id with the full record before starting the workflow again. But
we were not adding the relations to that enrichment.
This PR does not produce any functional change
First step of the workflow branch feature
- add gather `workflowRun.output` and `workflowRun.context` into one
column `workflowRun.runContext`
- add a command to fill `runContext` from `output` and `context` in
existing records
- maintain `runContext` up to date during workflow runs
This PR fixes the database name check to ignore query params.
This is useful for situations where you need to force sslmode, like
?sslmode=require. Yarn seems to handle this, but this db creation check
fails.
My environment enforces ssl for all PG connections, so I need twenty to
handle this check for me to test it locally.
Modifying the data-model can sometimes fail in the middle of your
operation, due to the way we handle both metadata update and schema
migration separately, a field can be created while the associated column
creation failed (same for object/table and such). This is also an issue
because WorkspaceMigrations are then stored as FAILED can never really
recovered by themselves so the schema is broken and we can't update the
models anymore.
This PR adds a executeMigrationFromPendingMigrationsWithinTransaction
method where we can (and must) pass a queryRunner executing a
transaction, which should come from the metadata services so that if
anything during metadata update OR schema update fails, it rolls back
everything (this also mean a workspaceMigration should never stay in a
failed state now).
This also fixes some issues with migration not running in the correct
order due to having the same timestamp and having to do some weird logic
to fix that.
This is a first step and fix before working on a much more reliable
solution in the upcoming weeks where we will refactor the way we
interact with the data model.
---------
Co-authored-by: Charles Bochet <charlesBochet@users.noreply.github.com>
# Context
We had an error saying "Unknown error importing calendar events for
[...]: Access token is undefined or empty. Please provide a valid token.
For more help -
https://github.com/microsoftgraph/msgraph-sdk-javascript/blob/dev/docs/CustomAuthenticationProvider.md
"
Reason is that the access token method for microsoft is a bit different
than the one from google. And in microsoft case, we want to check the
access token in the authProvider in case it fails. Currently it was not
catched, so it broke services above that counted on the accesstoken to
be valid.
That ended in UNKNOWN failure for our calendar event fetch service.
# Solution
This PR should solve the issue since :
1. forcing the method to break if accesstoken renewal fails
2. logs will help to know what kind of errors will be sent in case we
need to tackle this issue again
3. we now throw TEMPORARY error instead of unknown, allowing 3
getClientConfig failure before it is definitive
Why so many changes while it should have been simple :
The root cause is the `authProvider` from
`'@microsoft/microsoft-graph-client'` npm package. It does not throw a
custom error, and we cannot catch it on calling `Client.init`. Errors
only occurs when the client from
```
const client = this.microsoftOAuth2ClientManagerService.getOAuth2Client(refreshtoken)
```
is used, as in `client.api('/messages').get().catch(err => [...])`
So we need to go in every call using the client and catch errors, and
rethrow whenver we need as a newly created message type
`MessageImportDriverExceptionCode.CLIENT_NOT_AVAILABLE`
We discussed 1. and 2. with @bosiraphael already
I added 3. to make our system more robust without waiting for more
failures
# Related
Fixes : https://github.com/twentyhq/twenty/issues/12880
---------
Co-authored-by: Charles Bochet <charles@twenty.com>
## Summary
- Updates "Customize fields" button navigation to go directly to the
specific object's detail page
- Changes navigation from `SettingsPath.Objects` to
`SettingsPath.ObjectDetail`
- Aligns with existing behavior of "Edit Fields" functionality
## Problem
When clicking "Customize fields" in the record table header plus button
dropdown, users were taken to the general objects list page instead of
the specific object's fields page, making it harder to find and
customize the relevant object.
## Solution
Changed the navigation path from `SettingsPath.Objects` to
`SettingsPath.ObjectDetail` in `RecordTableHeaderPlusButtonContent.tsx`,
which takes users directly to the object-specific fields page where they
can see and manage all fields for that object.
## Screenshots
### Before: Customize Fields Dropdown
When clicking the "+" button in the table header, the dropdown shows
"Customize fields" option:
\
### After: Direct Navigation to Object Fields
Clicking "Customize fields" now navigates directly to the specific
object's fields page:
\
## Test plan
- [x] Navigate to any record table view (e.g., People, Companies)
- [x] Click the "+" button in the table header
- [x] Click "Customize fields"
- [x] Verify navigation goes directly to that object's fields page
instead of the general objects list
- [x] Confirmed the URL is `/settings/objects/{objectNamePlural}` (e.g.,
`/settings/objects/companies`)
Fixes#12835🤖 Generated with [Claude Code](https://claude.ai/code)
Co-authored-by: Jez (Jeremy Dawes)
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
This PR replaces the many calls of useDropdown by the new standalone
hooks : useCloseDropdown, useOpenDropdown and useToggleDropdown.
This will allow to remove useDropdown and then the dropdown recoil
component state v1.
A big round of QA has been made, with some bugs caught along the way.
Closes https://github.com/twentyhq/core-team-issues/issues/1155
Closes https://github.com/twentyhq/core-team-issues/issues/618
## QA
Component|Status|Comment
|---|---|---|
CurrentWorkspaceMemberFavorites|Ok|
FavoriteFolderPickerFooter|Ok|
AdvancedFilterAddFilterRuleSelect|Ok|
AdvancedFilterRecordFilterGroupOptionsDropdown|Ok|
AdvancedFilterRecordFilterOperandSelectContent|Ok|
AdvancedFilterRecordFilterOptionsDropdown|Ok|
useAdvancedFilterFieldSelectDropdown|Ok|
ObjectFilterDropdownBooleanSelect|Ok|
ObjectFilterDropdownOptionSelect|Ok|
ObjectOptionsDropdown|Ok|
ObjectOptionsDropdownLayoutContent|Ok|
ObjectSortDropdownButton|Ok|
useCloseSortDropdown|Ok|
FormDateTimeFieldInput|Ok|Bug detected, cannot select a month or a year,
see issue https://github.com/twentyhq/twenty/issues/12922
FormSingleRecordPicker|Ok|
MultiItemFieldMenuItem|Ok|
RecordDetailRelationRecordsListItem|Ok|
RecordDetailRelationSection|Ok|
RecordDetailRelationSectionDropdownToMany|Ok|
RecordDetailRelationSectionDropdownToOne|Ok|
RecordTableColumnAggregateFooterDropdownSubmenuContent|Ok|
RecordTableColumnAggregateFooterAggregateOperationMenuItems|Ok|
RecordTableColumnAggregateFooterMenuContent|Ok|
RecordTableColumnAggregateFooterValueCell|Ok|
RecordTableColumnHeadDropdownMenu|Ok|
RecordTableHeaderPlusButtonContent|Ok|
useTriggerActionMenuDropdown|Ok|
MultipleSelectDropdown|Ok|
RecordBoardColumnHeaderAggregateDropdownButton|Ok|
SettingsDataModelFieldSelectFormOptionRow|Ok|
SettingsDataModelNewFieldBreadcrumbDropDown|Ok|
SettingsObjectFieldActiveActionDropdown|Ok|
SettingsObjectFieldInactiveActionDropdown|Ok|
SettingsObjectInactiveMenuDropDown|Ok|
SettingsSecurityApprovedAccessDomainRowDropdownMenu|Couldn’t test|
SettingsSecuritySSORowDropdownMenu|Couldn’t test|
SettingsAccountsRowDropdownMenu|Ok|
SettingsRoleAssignment|Ok|
SettingsServerlessFunctionTabEnvironmentVariableTableRow|Couldn’t test|
MatchColumnToFieldSelect|Ok|
SubMatchingSelectDropdownButton|Ok|Removed conflicting duplicate open
dropdown
SubMatchingSelectRowRightDropdown|Ok|
CurrencyPickerDropdownButton|Ok|
IconPicker|Ok|
DateTimePicker|Ok|
PhoneCountryPickerDropdownButton|OK|
Select|Ok|
Dropdown|Ok|Not QAing all dropdowns in the app because the ones of this
QA are enough to show up that Dropdown is behaving correctly on a lot of
use cases
DropdownMenuInnerSelect|Ok|
TabList|Ok|Removed onClickOutside called in dropdown clickable
component, validated with Raph who recently worked on this
DateInput|Ok|
MultiWorkspaceDropdownDefaultComponents|Ok|
AdvancedFilterChip|Ok|
EditableFilterDropdownButton|Ok|
UpdateViewButtonGroup|Ok|
ViewBarDetailsAddFilterButton|Ok|
ViewBarFilterButton|Ok|
ViewBarFilterDropdown|Ok|
ViewBarFilterDropdownAdvancedFilterButton|Ok|
ViewPickerDropdown|Ok|
ViewPickerListContent|Ok|
ViewPickerOptionDropdown|Ok|
WorkflowEditTriggerDatabaseEventForm|Ok|
WorkflowVariablesDropdownWorkflowStepItems|Ok|
AttachmentDropdown|Ok|
SupportDropdown|Ok|
Co-authored-by: Charles Bochet <charlesBochet@users.noreply.github.com>
Co-authored-by: Charles Bochet <charles@twenty.com>