Fixes https://github.com/twentyhq/twenty/issues/11864 and
https://github.com/twentyhq/core-team-issues/issues/908
We should not send `createManyXXX` mutations with FE-forged ids in the
payload if we want to do an upsert, because that 1) prevents records
from being merged 2) triggers optimistic rendering while we can't know
before-hand which records will actually be created and which records
will only be updated
Also noticed createdBy was being overriden even for records we are
updating and not creating, which did not seem right, so fixed that too
## Description
When a calendar channel fails, its status is not reset during the
reconnect step.
In some cases, resetting is necessary—especially when we’ve deployed a
fix and users try to reconnect their accounts after the patch.
## Why reseting to initial state
Our processes are idempotent, so we can safely set the status to null to
restart the flow. This approach covers all cases and avoids edge
conditions caused by inconsistent statuses.
Fixes : https://github.com/twentyhq/twenty/issues/12026
closes#11996
- Switched the “Object destination” select in
SettingsDataModelFieldRelationForm to use
activeObjectMetadataItems.filter(...) so workflows, system, and remote
objects are excluded
- Updated useRelationSettingsFormInitialValues to fall back on the same
filtered activeObjectMetadataItems list for its initial value
This ensures workflows (and any unwanted system/remote objects) no
longer show up in the dropdown or as the default.
Fixes https://github.com/twentyhq/twenty/issues/12040
When fields are deleted but still used in workflows we do not update
create record action settings.
It breaks all following workflow execution and the user cannot update
the settings anymore.
This PR fixes the bug by filtering on existing fields.
Next step will be to clean settings on field deletion. Adding it to fast
follows.
Also lowering throttle limit because some infinite loops are not
catched.
Fixes https://github.com/twentyhq/core-team-issues/issues/956
This PR fixes a bug that appeared when switching between two kanban
views multiple times.
Steps to reproduce :
- Go to kanban view A
- Go to kanban view B
- Go back to kanban view A
Video before :
https://github.com/user-attachments/assets/4fa789ae-7187-498e-82b4-ee7896cd95d1
Video after :
https://github.com/user-attachments/assets/2b323a2d-2f76-405d-9abd-38fe72ee2214
The problem was that we allowed a hook to take a nullable parameter that
can be nullable between page switch, and threw when it was undefined.
In order to be more cautious in the future, let's be sure that we don't
throw for undefined props of a hook, when it is expected that those
props can be in an undefined state for several React render loops, while
fetching new data.
Here I identified the parent effect : `<RecordIndexBoardDataLoader />`
that loads all states for a board when we switch between views, for each
column, by calling `<RecordIndexBoardColumnLoaderEffect />` in a
`.map()`.
Each `RecordIndexBoardColumnLoaderEffect` was calling
`useLoadRecordIndexBoardColumn` with a potentially undefined
`boardFieldMetadataId`.
So to fix this, I cut the render flow higher than the throw in
`useLoadRecordIndexBoardColumn`, and by doing that I was able to ensure
that `recordIndexKanbanFieldMetadataItem` in
`RecordIndexBoardDataLoader` was already defined when using it inside
`useLoadRecordIndexBoardColumn`.
`recordIndexKanbanFieldMetadataItem` was unnecessarily fetched two
times, one time in `RecordIndexBoardDataLoader` and another time in its
child `useLoadRecordIndexBoardColumn` hook.
By implementing this flow-cut higher up, I could then remove the `|
null` in TypeScript in children components, and expect a defined value
in all the children of `RecordIndexBoardDataLoader`, thus removing the
need to ask ourselves if we should throw or not in
`useLoadRecordIndexBoardColumn`.
closes#11849
The Logo component’s fallback URL was pointing to
`/icons/android/android-launchericon-192-192.png`, but the asset lives
under `/images/icons/....`. This updates defaultPrimaryLogoUrl to use
the correct `/images/icons/android/android-launchericon-192-192.png`
path, restoring the default logo display when no primaryLogo prop is
provided.
This PR fixes an infinite loop than happens due to a useEffect in a non
deterministic manner.
The fix is to put a `isDeeplyEqual()` to avoid re-rendering the
useEffect if the value is the same.
Fixes : https://github.com/twentyhq/core-team-issues/issues/957
Context
workspaceMemberId is not always present in AuthContext. Solution
implemented here is to fetch workspaceMemberId via userId.
QRQC coming ...
Tested
- FindManyCalendarEvents / FindOneCalendarEvent
- FindManyMessages / FindOneMessage
closes https://github.com/twentyhq/twenty/issues/12027
This PR attemps at improving sentry grouping and filtering by
- Using the exceptionCode as the fingerprint when the error is a
customException. For this to work in this PR we are now throwing
customExceptions instead of internalServerError deprived of their code.
They will still be converted to Internal server errors when sent back as
response
- Filtering 4xx issues where it was missing (for emailVerification
because errors were not handled, for invalid captcha and billing errors
because they are httpErrors and not graphqlErrors)
---------
Co-authored-by: Félix Malfait <felix@twenty.com>
## Changes
- Updated the property name in the upgrade guide to reflect the
permission split in Admin Panel:
- `canImpersonate`: only provides access to impersonate functionality
- `canAccessFullAdminPanel`: provides access to all other admin panel
features
Several users have complained about not being able to read their emails
anymore.
This is because the find-messages post query hook is expecting
ObjectRecord[] as an input but is actually getting a graphql Connection
Typing was wrong. This PR fixes the typing and make sure the post query
hook always get an ObjectRecord[]
Using useEffect triggered at ActivityRichTextEditor unmount, to delete
attachments only when note is closed (and not when file block is deleted
during note update to keep command + z shortcut)
closes : https://github.com/twentyhq/twenty/issues/11229
In this PR:
- Set the default position for the DONE option of the task's status
option to `2` instead of `1`, which was the same as `IN_PROGRESS`
option's position.
- Write a command to prevent position duplicates in the database for the
task's status field.
What I've checked before setting this PR as ready to be reviewed:
- De-duplicating the position solves the issue and it's possible to edit
the field (solves the related issue)
- The upgrade command de-duplicates the position for each workspace.
There are no more DONE options with `position=2`. I ran the upgrade
command on the `database-snapshot-manager` dataset.
- Suspended workspaces aren't fixed
---
To test the script:
```ts
const scannedPositions = new Set();
let biggestPosition = -1;
// Sort options by position for consistent processing
const sortedOptions = [
{ name: 'a', position: 2 },
{ name: 'b', position: 1 },
{ name: 'c', position: 1 },
{ name: 'd', position: 2 },
].sort((a, b) => a.position - b.position);
for (const option of sortedOptions) {
if (scannedPositions.has(option.position)) {
option.position = biggestPosition + 1;
}
biggestPosition = Math.max(biggestPosition, option.position);
scannedPositions.add(option.position);
}
console.log('Sorted options:', sortedOptions);
```
Closes https://github.com/twentyhq/twenty/issues/11790
Revert changes in #12006 as it might still be handy to have the DB
auto-created (e.g. for test or self-hosting users), but if there is a
permission exception we will just ignore it and assume the database
exist in that case
## What
This PR fixes a regression tied to the new relation format refactoring.
I'm also slightly improving the performance by decreasing the number of
queries.
## Considerations
1. I've started adding an integration test to cover relation creation
and deletion but we are still using the r`elation-metadata.service` to
create a relation and the `field-metadata.service` to delete it. As we
plan to fully deprecate the `relation-metadata.service`, I did not want
to invest into writing test tooling to change it in a few weeks so I've
reverted the test
2. We are still maintaining relationMetadata table up-to-date (so
deleting them when we delete the field). relationMetadata full
deprecation is up coming but I'm waiting a bit so we don't have breaking
changes in 0.53
This is a first PR to remove old relation logic
Next steps:
- remove relationMetadata from cache
- remove relationMetadata table content and structure
- refactor relationDefinition to leverage field.settings instead
- In this PR the default value of IS_CONFIG_VARIABLES_IN_DB_ENABLED has
been changed to true,
- This is my first time writing integration tests, so I’d appreciate a
thorough review. :)
I’ve tried to follow the existing test patterns closely, but there might
be some small mistakes I may have missed.
Also let me know if I have missed any important test cases that should
be tested
UPDATE -
### Config Value Converter Refactoring
- Created a centralized type transformers registry with bidirectional
validation
- Refactored ConfigValueConverterService to support validation in both
directions:
- Maintained existing DB-to-app conversion behavior
- Added validation for app-to-DB conversion
- Added integration tests to verify validation works in both directions
---------
Co-authored-by: Félix Malfait <felix@twenty.com>
This PR introduces LINKS and EMAILS sub-field filtering. It's mainly
about the implementation of secondaryLinks and additionalEmails
sub-fields, which are treated like additionalPhones.
There's also a refactor on the computeViewRecordGqlOperationFilter, a
big file that becomes very difficult to read and maintain. This PR
breaks it down into multiple smaller utils. There's still work to be
done to clean it as it is a central part of the record filter module,
this PR lays the foundation.
# Introduction
Encountering a blocking issue due to legacy upgrade history in staging
due to relation refactor
For the moment ( release 0.53 ) swallowing
@charlesBochet
## How to test
```ts
checkout v0.52.11
yarn
database:reset
checkout 0.53
yarn
build server
migrate
upgrade
```
# Keyboard Navigation and Shortcuts Implementation on the board
This PR implements keyboard navigation and shortcuts for the Record
Board component, enabling users to navigate and interact with board
cards using keyboard inputs.
## Key changes
### Navigation Architecture
- Added `useBoardCardNavigation` hook for directional navigation (arrow
keys)
- Implemented scroll behavior to automatically focus visible cards
- Created card focus/active states with component-level management
### State Management
- Added new component states: `focusedBoardCardIndexesComponentState`,
`activeBoardCardIndexesComponentState`,
`isBoardCardActiveComponentFamilyState`
- Extended index tracking with column/row position indicators
- Create hooks to manage these states
### Hotkey Implementation
- Created new `RecordBoardHotkeyEffect` component for hotkey handling
- Added `BoardHotkeyScope`
- Implemented Escape key handling to clear selections
- Replaced table-specific `TableHotkeyScope` with more generic
`RecordIndexHotkeyScope`. This is because, before, the hotkey scope was
always set to Table inside the page change effect, and we used the table
hotkey scope for board shortcuts, which doesn't make a lot of sense.
Since we don't know upon navigation on which type of view we are
navigating, I introduced this generic hotkey scope which can be used on
the table and on the board.
### Page Navigation Integration
- Modified `PageChangeEffect` to handle both table and board view types
- Added cleanup for board state upon navigating away from record pages
### Component Updates
- Updated `RecordBoardColumn` to track indexes for position-based
navigation
- Added `RecordBoardScrollToFocusedCardEffect` for auto-scrolling to
focused cards
- Added `RecordBoardDeactivateBoardCardEffect` for cleanup
This implementation maintains feature parity with table row navigation
while accounting for the 2D navigation needs of the board view.
## New behaviors
### Arrow keys navigation
https://github.com/user-attachments/assets/929ee00d-2f82-43b9-8cde-f7bc8818052f
### Record selection with X
https://github.com/user-attachments/assets/0b534c4d-2865-43ac-8ba3-09cb8c121f06
### Command + Enter opens the record
https://github.com/user-attachments/assets/0df01d1c-0437-4444-beb1-ce74bcfb91a4
### Escape unselect the records and unfocus the card
https://github.com/user-attachments/assets/e2bb176b-b6f7-49ca-9549-803eb31bfc23
# Display "Soft-Deleted Workspace Members" in Actor Field Display
Reminder of the issue :
<img width="154" alt="Screenshot 2025-05-07 at 12 11 59"
src="https://github.com/user-attachments/assets/168f8743-2684-4d9a-b1a4-e86bb335f7a4"
/>
- `ActorFieldDisplay` component : display soft-deleted members
- `UserService` includes soft-deleted records when fetching workspace
members. This is the tricky part : do we want that for all workspace
members or maybe i could create another property dedicated to workspace
members and softdeleted ones. To be discussed
Result looks like this (we loose the source and the context in this
impleentation)
<img width="114" alt="Screenshot 2025-05-07 at 12 05 28"
src="https://github.com/user-attachments/assets/3cdddd91-454f-4e96-8d6d-6fe671658945"
/>
Fixes https://github.com/twentyhq/twenty/issues/11870
Another way we could also get into :
We could also, when a workspace user is softDeleted, change the current
implementation : we could avoid to delete the ActorMetadata like
CreatedByName (and context and source) in the "Person" table.
It would look more like this
<img width="111" alt="Screenshot 2025-05-07 at 12 06 16"
src="https://github.com/user-attachments/assets/daa4ece2-200a-41f0-ba24-177375c72983"
/>
However, this implementation is requires more work, and IMO harder to
maintain since is decouples completely the record from the workspace
member. This could be an issue in case we want tohard delete a user, or
decide another logic to display the Actor name.
Since the usecase should be pretty rare, I chose the first one but
willing to discuss it
---------
Co-authored-by: prastoin <paul@twenty.com>
# TLDR
fix bug due to some event properties coming from the google calendar API
containing weird characters like this
"\u0000�4\u000b\u00042��K\u0001�z,\u001cm�",
it made the Postgres select and insert operator fail
## Details
We can have event properties (like cal UID below) encoded in a strange
way. From my research, the character \u0000 comes from `C` language to
signal end of line. It is wrongly interpreted by Postgres so must be
escaped. I decided to remove all possibility of failure with this regex
`[^\x20-\x7E]` basically "any character that is not a printable ASCII
character"
```
[
"5foijj28qb8smqiafjablo17vd@google.com",
"\u0011�\"�f�\\\u0019G_=��\u0005]x",
"?}|��\f}l��+�弴�",
"%���?t\u0007��n\u001e\u000eY�T<",
".\u0011�\u0016�!�\u000eIǹ� ��\u001f",
"!h\u0004��D�6���h�]E",
"(�CX]�Q�7�^��n\u0006�",
"_040000008200E00074C5B7101A82E0080000000070105B958DEFD801000000000000000010000000EA30DB22E888B943A8EE0AD483F8DB35",
"\t�N�#�D��Ic�h",
"+�)�H���jJ|Ժ�'�",
"_040000008200E00074C5B7101A82E0080000000070A54736C6EED8010000000000000000100000006502334AFE61904595C2831FA4391034",
"_040000008200E00074C5B7101A82E0080000000072C80C3590EFD8010000000000000000100000001BA9FD5B330C1A4D85462AC9D70B9D9D",
"sg�fvUa:St>-<�d\u0006",
"\u0017ڦ��_\u001e\u001fGm-1����",
"_040000008200E00074C5B7101A82E00800000000F0F4F01F4EF0D8010000000000000000100000004C11CE0950C85549B79C456C13987AB8",
"$�����\u0007V\u0007��\u001e�OLN",
"_040000008200E00074C5B7101A82E00800000000341DA81151EDD8010000000000000000100000007453CEFB19AA2D4899B17F0BDB000493",
"_01C756CA-98DC-4799-9F06-883A540A065C",
"_040000008200E00074C5B7101A82E00800000000919548BBF1EDD80100000000000000001000000050AE1E41F3CD314CA9215F193EBE1D39",
"_040000008200E00074C5B7101A82E0080000000039CF64D718EDD801000000000000000010000000B3824EF0711436488CB5459BE83733B1",
"_040000008200E00074C5B7101A82E00800000000C50BDADCB5E4D8010000000000000000100000005B95FE762B2EF84B9C5AC53907B7E5E8",
"�Spx�\u0003ve��ss�X��",
"\b���>\u0013̈�ыh��0�",
"_040000008200E00074C5B7101A82E008000000005BCD492230E8D801000000000000000010000000B243A9CE99E94C4DAD201129A8F2A2F7",
"_040000008200E00074C5B7101A82E008000000009B540B82D1DCD801000000000000000010000000B4AFC9825D94994AA6C528C953BD3D96",
"_040000008200E00074C5B7101A82E008000000000D39EABDB7E4D801000000000000000010000000CD07BA2D05E61B47A597EE538ECE8CA5",
"\u0016���\u0003inv�=O����",
"4?b�-���\u001c\u0013ת�E�p",
">\u0000\u0015-;_�^�W&�p\u001f�",
"_040000008200E00074C5B7101A82E008000000006258818C85D9D80100000000000000001000000003346C625768FE43AF3F8D09917CA3C9",
"+K��ٔ�\u0006�\u0018G\u000b\u0000�s\u000e",
"/\f�\rj�IOD�g脅��",
"_68d820f9-e2c1-4d9a-bf61-83e4957c8261",
"xĠ�W4>���t�\u001d���",
"_040000008200E00074C5B7101A82E008000000003F1F314328E3D8010000000000000000100000002C8DC60F5369F44DA2B066441F882B35",
"_040000008200E00074C5B7101A82E008000000006DFCC204FDDED80100000000000000001000000046ECD444737D2E4992C349B2EA05637F",
"_1FF7C1BB-4E1A-485F-ADD0-5C4768601179",
"_040000008200E00074C5B7101A82E00800000000A0AA1223EFD3D801000000000000000010000000C83B72C2B424944199F3353D1442B27E",
"_040000008200E00074C5B7101A82E0080000000063D101EB06E4D801000000000000000010000000E489F61C89B8914BA6F8C8A2606405FE",
"\u0011��f�\"�b���rB�[�",
";t��\u001d\u001euDY+T\u001d��v",
]
```
Fixes https://github.com/twentyhq/core-team-issues/issues/946
Fixes
https://twenty-v7.sentry.io/issues/6568530279/?environment=prod&project=4507072499810304&query=is%3Aunresolved%20issue.priority%3A%5Bhigh%2C%20medium%5D%20b09d7a84-e6bc-45cf-b3ca-1e6047dddeed&referrer=issue-stream&stream_index=0
### Edit :
Changed the regex to match the chars to remove from
`[^\x20-\x7E]` to `replace('\u0000', '');`
## Context
While deploying the IS_NEW_RELATION_ENABLED (we don't compute relation
based on relationMetadata anymore) to existing workspace, I've tested to
run a sync-metadata post feature flag activation. This has raised two
issues:
- the workspaceMigration generator (which is over-complex and should be
refactored later) for fieldMetadata of type RELATION was not handling
settings update properly ;
- we need to delete existing fieldMetadata corresponding to the UUID
foreignKey as they are not needed anymore. This is handled as a 0.53
upgrade command as 0.53 will also come with the full removal of the old
relation system
---------
Co-authored-by: Etienne <45695613+etiennejouan@users.noreply.github.com>
Co-authored-by: prastoin <paul@twenty.com>