Commit Graph

210 Commits

Author SHA1 Message Date
Marie ee19ee5119 [permissions] QA fixes (#13698)
In this PR

- Introduction of readableFields and updatableFields in
objectMetadataItem selector to ease filtering from a developer
experience perspective ( + to help developers think to do it). In
discussion @lucasbordeau @charlesBochet
- Remove non-updatable field from CSV import process (@etiennejouan)
- QA fix / Non-readable fields should not show on show page
- QA fix / It should not be offered to create a kanban view on a
non-readable field
- QA fix / It should not be offered to create view groups on a
non-readable field
- QA fix / Rating field should have a readonly mode

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2025-08-07 18:21:59 +02:00
Etienne 010c9b6250 fix typo (#13634) 2025-08-05 14:34:10 +02:00
Charles Bochet 42045667a4 Fix id typing in metadata generated schema (#13596)
In our Graphql schema, ids are typed as UUID.

Our FE codegen is typing it as 'any', unless we say otherwise. Fixing it
and fixing the impacts in the codebase
2025-08-04 18:40:26 +02:00
neo773 a5cb3168c1 feat: merge records button in RecordDetailDuplicatesSection (#13537)
Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
2025-08-01 16:37:20 +02:00
neo773 06e0814ce8 feat: merge records (#13436)
Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
2025-07-31 10:06:36 +00:00
Lucas Bordeau d61eb1a951 Remove all legacy state management (#13476)
This PR removes every legacy state management logic left in the code
base, we only keep our last component state management logic.

Removed : 
- Scoped states logic
- Dropdown scope logic
- Scope id naming
- Component state v1
- Component state v2_alpha


# QA

| Component | Comments |
| --- | --- |
| AttachementDropdown | Ok |
| ObjectTasks | Ok |
| ActivityRichTextEditor | Ok |
| App | Ok dialogs work |
| AppRouterProviders | Ok dialogs work |
| RecordBoardScrollToFocusedCardEffect | Ok |
| RecordBoard | Ok |
| RecordBoardCard | OK |
| useSelectAllCards | Ok |
| RecordInlineCell | Ok |
| useInlineCell | Ok |
| RecordDetailRelationRecordsListItem | Ok |
| RecordDetailRelationSectionDropdownToMany | Ok |
| RecordDetailRelationSectionDropdownToOne | Ok |
| useHandleContainerMouseEnter | Ok |
| useResetTableRowSelection | Ok |
| useSelectAllRows | Ok |
| useSetRecordTableData | Ok |
| useRecordTable | Ok |
| useRecordTableMoveFocusedCell | Ok |
| useRecordTableMoveFocusedRow | Ok |
| useMoveHoverToCurrentCell | OK |
| useTriggerActionMenuDropdown | Ok |
| RecordTableBodyDragDropContextProvider | Ok |
| RecordTableHeaderCell | Ok |
| useSetCurrentRowSelected | Ok |
| useRecordTitleCell | Ok |
| SettingsObjectFieldActiveActionDropdown | Ok |
| SettingsObjectFieldInactiveActionDropdown | Ok |
| SettingsObjectFieldItemTableRow | Ok |
| SettingsObjectInactiveMenuDropDown | Ok |
| SettingsRoleEditEffect | Ok |
| SettingsRolesQueryEffect | Ok |
| Dropdown | Ok |
| useSelectableList | Ok |
| useSelectableListHotKeys | Ok |
| useSelectableListListenToEnterHotkeyOnItem | Ok |
| useNavigationSection | Ok |
| useCreateViewFromCurrentState | Ok |
| useDeleteViewFromCurrentState | Ok |
| useUpdateViewFromCurrentState | Ok |
| ViewPickerFavoriteFoldersDropdown | Ok |
| useCreateViewFromCurrentView | Ok |
| ViewBarDetails | Ok |
| WorkflowRunVisualizer | Ok |
| useHandleWorkflowRunDiagramCanvasInit | Ok |
| WorkflowDiagramCanvasBase | Ok |
| WorkflowRunVisualizerEffect | Ok |
| useRemoveStepFilter | Ok |
| useRemoveStepFilterGroup | Ok |
| useUpsertStepFilterSettings | Ok |
| WorkflowFindRecordsFilters | Ok |
| SettingsObjects | Ok |
2025-07-29 09:52:24 +00:00
Marie 16ba72edab [permissions] Adapt FE to non-readable fields (#13440)
Fixes https://github.com/twentyhq/core-team-issues/issues/1261 and
https://github.com/twentyhq/core-team-issues/issues/1153

In this PR we
- remove fields user do not have read access on from queries (findMany,
findDuplicates, returned fields from create or update etc.)
- remove fields user do not have read access on from views 

This is behind a feature flag
2025-07-28 16:24:08 +00:00
Charles Bochet fdc6705a75 Remove old body on note and tasks (#13290)
Fixes: https://github.com/twentyhq/twenty/issues/13110

I'm deprecating note.body and task.body to remove confusion between body
and bodyV2

What will be left but should be done later to avoid breaking changes:
- re-add a body field in the graphql API only that points to the same
bodyV2 field in SQL (need to be handled in fields and filter for note
and task)
- (wait some time)
- remove bodyV2 field
2025-07-19 11:25:49 +02:00
Félix Malfait 6ba6860e1c Frontend tests improvements (#13115)
Fix warnings and lower coverage by 0.1%
2025-07-09 09:23:26 +02:00
Abdul Rahman 51d02c13bf Feat - Agent chat tab (#13061)
Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
Co-authored-by: Marie <51697796+ijreilly@users.noreply.github.com>
Co-authored-by: Antoine Moreaux <moreaux.antoine@gmail.com>
Co-authored-by: Raphaël Bosi <71827178+bosiraphael@users.noreply.github.com>
2025-07-07 22:47:41 +02:00
Jagannath Samantra ee8e223aed fix: fixed the update of field metadata label, icon & object (#13064)
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>
2025-07-06 12:47:33 +02:00
nitin 1729970836 Fix circular structure error in useFetchMoreRecordsWithPagination (#13042)
Fixes:  
TypeError: Converting circular structure to JSON crashing opportunities
pagination.

Issue: 
useFetchMoreRecordsWithPagination was putting an Apollo client object in
React's dependency array. React tried to serialize it for memoization,
hit circular refs in InMemoryCache, and was throwing the error.

Fix: 
Removed unnecessary Apollo client import. The fetchMore from the
original useQuery is already bound to the correct client.

before: 


https://github.com/user-attachments/assets/0422c57b-5cd2-4c0f-9828-fb7bbd7f94c1

after:



https://github.com/user-attachments/assets/20112fb7-3990-4c34-bf39-8c53b7b48e45
2025-07-04 21:53:18 +02:00
Marie 288f0919db Define server error messages to display in FE from the server (#12973)
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.`
2025-07-03 12:42:10 +00:00
nitin d2ddd6f473 Separate system operations from core objects in GraphQL endpoints (#12977)
Moves system-level operations (auth, billing, admin) to use the
/metadata endpoint instead of /graphql.

This cleans up the endpoint separation so /graphql is purely for core
objects (Company, People, etc.) and /metadata handles all system
operations.

Part of prep work for webhook/API key core migration.
2025-07-01 18:29:32 +02:00
Marie 2d5312276c Improve FE error handling (#12864)
This PR aims at improving readability in sentry and user experience with
runtime errors.

**GraphQL errors (and ApolloError)**
1. In sentry we have a lot of "Object captured as exception with keys:
extensions, message" errors (2k over the last 90d), on which we have
zero information. This is because in apollo-factory we were passing on
GraphQL errors to sentry directly why sentry expects the structure of a
JS Error. We are now changing that, rebuilding an Error object and
attempting to help grouping by creating a fingerPrint based on error
code and truncated operationName (same as we do in the back for 500
graphql errors).
2. In sentry we have a lot of ApolloError, who actually correspond to
errors that should not be logged in sentry (Forbidden errors such as
"Email is not verified"), or errors that are already tracked by back-end
(Postgres errors such as "column xxx does not exist"). This is because
ApolloErrors become unhandled rejections errors if they are not caught
and automatically sent to sentry through the basic config. To change
that we are now filtering out ApolloErrors created from GraphQL Errors
before sending error to sentry:
<img width="524" alt="image"
src="https://github.com/user-attachments/assets/02974829-26d9-4a9e-8c4c-cfe70155e4ab"
/>

**Runtime errors**
4. Runtime errors were all caught by sentry with the name "Error",
making them not easy to differentiate on sentry (they were not grouped
together but all appeared in the list as "Error"). We are replacing the
"Error" name with the error message, or the error code if present. We
are introducing a CustomError class that allows errors whose message
contain dynamic text (an id for instance) to be identified on sentry
with a common code. _(TODO: if this approach is validated then I have
yet to replace Error with dynamic error messages with CustomError)_
5. Runtime error messages contain technical details that do not mean
anything to users (for instance, "Invalid folder ID: ${droppableId}",
"ObjectMetadataItem not found", etc.). Let's replace them with "Please
refresh the page." to users and keep the message error for sentry and
our dev experience (they will still show in the console as uncaught
errors).
2025-06-26 15:54:12 +00:00
Weiko 85c50f149d [Permissions][FE] Design followup 5 (#12793)
## Context
- We now display workspace member full name and email in role assignment
picker
- Replaced Forbidden by "Not shared" with lock icon
- Fix Disabled for Danger accent
- Fix avatar URL

<img width="575" alt="Screenshot 2025-06-23 at 16 38 56"
src="https://github.com/user-attachments/assets/08430bfe-29c4-4ac4-821c-9062dfad7150"
/>
<img width="756" alt="Screenshot 2025-06-23 at 16 21 36"
src="https://github.com/user-attachments/assets/c19f31bd-fe9d-415d-aa55-62fa3e228c49"
/>
<img width="373" alt="Screenshot 2025-06-23 at 17 13 08"
src="https://github.com/user-attachments/assets/e2f7878c-7c5a-40b4-a482-8e99292257c3"
/>
<img width="342" alt="Screenshot 2025-06-23 at 17 37 49"
src="https://github.com/user-attachments/assets/04169e85-14dd-4aed-bd71-7aefd601a894"
/>
<img width="434" alt="Screenshot 2025-06-23 at 17 37 35"
src="https://github.com/user-attachments/assets/7caf0967-c4dd-4d0f-90c8-259a85182b19"
/>
2025-06-23 19:15:58 +02:00
Paul Rastoin 4da0152c33 FixuseLazyFetchAllRecords any wrong infer (#12728)
# Introduction
closes https://github.com/twentyhq/twenty/issues/12721
Regression seems to be introduced by
https://github.com/twentyhq/twenty/pull/12653

## Post mortem
### Previously
No mapping on `namePlural` dynamic response data key
```ts
      const rawResult = await fetchMore({
        variables: {
          lastCursor: lastCursor,
          limit,
        },
      });
```

### Now
Mapping is done by the tool we're consuming already
```ts
      const rawResult = await fetchMoreRecordsLazy();

// 
const fetchMoreRecordsLazy = useRecoilCallback(
    ({ snapshot, set }) =>
      async () => {

          //...
           return {
              data: fetchMoreDataResult?.[objectMetadataItem.namePlural],
              totalCount:
                fetchMoreDataResult?.[objectMetadataItem.namePlural]
                  ?.totalCount,
              records: getRecordsFromRecordConnection({
                recordConnection: {
                  edges:
                    fetchMoreDataResult?.[objectMetadataItem.namePlural]?.edges,
                  pageInfo:
                    fetchMoreDataResult?.[objectMetadataItem.namePlural]
                      ?.pageInfo,
                },
              }) as T[],
```

## Concerns
TypeScript did not throw any errors because `RecordConnectionGql` is
typed as any, we should consider adding a generic type defaulted to
unknown
```ts
import { RecordGqlEdge } from '@/object-record/graphql/types/RecordGqlEdge';
import { Nullable } from 'twenty-ui/utilities';

export type RecordGqlConnection = {
  __typename?: string;
  edges: RecordGqlEdge[];
  pageInfo: {
    __typename?: string;
    hasNextPage?: boolean;
    hasPreviousPage?: boolean;
    startCursor?: Nullable<string>;
    endCursor?: Nullable<string>;
    totalCount?: number;
  };
  totalCount?: number;
  [aggregateFieldName: string]: any; // Any is problematic here should be unknown
};
```

Example:
```ts
export type RecordGqlConnection<
  T extends Record<string, unknown> = Record<string, unknown>,
> = {
  __typename?: string;
  edges: RecordGqlEdge[];
  pageInfo: {
    __typename?: string;
    hasNextPage?: boolean;
    hasPreviousPage?: boolean;
    startCursor?: Nullable<string>;
    endCursor?: Nullable<string>;
    totalCount?: number;
  };
  totalCount?: number;
} & T;
```
2025-06-19 14:22:05 +02:00
Charles Bochet 82876bb7d1 Fix table fetchMore flakyness (#12702)
Remove useless debounce + using cacheFirst for fetchMore as fetchingMore
will trigger initial fetch if not already performed
2025-06-18 15:37:22 +02:00
Etienne 78d39294ef Import - Increase record import limit (#12627)
<img width="700" alt="Screenshot 2025-06-16 at 15 05 09"
src="https://github.com/user-attachments/assets/a09c3fae-c0ae-4a63-8bda-9d29c97a6a66"
/>


closes https://github.com/twentyhq/twenty/issues/11980
2025-06-18 10:13:24 +00:00
Charles Bochet f3a8b849aa Fix table loading (#12653)
As per title
2025-06-17 15:01:28 +02:00
Charles Bochet a68895189c Deprecate old relations completely (#12482)
# What

Fully deprecate old relations because we have one bug tied to it and it
make the codebase complex

# How I've made this PR:
1. remove metadata datasource (we only keep 'core') => this was causing
extra complexity in the refactor + flaky reset
2. merge dev and demo datasets => as I needed to update the tests which
is very painful, I don't want to do it twice
3. remove all code tied to RELATION_METADATA /
relation-metadata.resolver, or anything tied to the old relation system
4. Remove ONE_TO_ONE and MANY_TO_MANY that are not supported
5. fix impacts on the different areas : see functional testing below 

# Functional testing

## Functional testing from the front-end:
1. Database Reset 
2. Sign In 
3. Workspace sign-up 
5. Browsing table / kanban / show 
6. Assigning a record in a one to many / in a many to one 
7. Deleting a record involved in a relation  => broken but not tied to
this PR
8. "Add new" from relation picker  => broken but not tied to this PR
9. Creating a Task / Note, Updating a Task / Note relations, Deleting a
Task / Note (from table, show page, right drawer)  => broken but not
tied to this PR
10. creating a relation from settings (custom / standard x oneToMany /
manyToOne) 
11. updating a relation from settings should not be possible 
12. deleting a relation from settings (custom / standard x oneToMany /
manyToOne) 
13. Make sure timeline activity still work (relation were involved
there), espacially with Task / Note => to be double checked  => Cannot
convert undefined or null to object
14. Workspace deletion / User deletion  
15. CSV Import should keep working  
16. Permissions: I have tested without permissions V2 as it's still hard
to test v2 work and it's not in prod yet 
17. Workflows global test  

## From the API:
1. Review open-api documentation (REST)  
2. Make sure REST Api are still able to fetch relations ==> won't do, we
have a coupling Get/Update/Create there, this requires refactoring
3. Make sure REST Api is still able to update / remove relation => won't
do same

## Automated tests
1. lint + typescript 
2. front unit tests: 
3. server unit tests 2 
4. front stories: 
5. server integration: 
6. chromatic check : expected 0
7. e2e check : expected no more that current failures

## Remove // Todos
1. All are captured by functional tests above, nothing additional to do

## (Un)related regressions
1. Table loading state is not working anymore, we see the empty state
before table content
2. Filtering by Creator Tim Ap return empty results
3. Not possible to add Tasks / Notes / Files from show page

# Result

## New seeds that can be easily extended
<img width="1920" alt="image"
src="https://github.com/user-attachments/assets/d290d130-2a5f-44e6-b419-7e42a89eec4b"
/>

## -5k lines of code
## No more 'metadata' dataSource (we only have 'core)
## No more relationMetadata (I haven't drop the table yet it's not
referenced in the code anymore)
## We are ready to fix the 6 months lag between current API results and
our mocked tests
## No more bug on relation creation / deletion

---------

Co-authored-by: Weiko <corentin@twenty.com>
Co-authored-by: Félix Malfait <felix@twenty.com>
2025-06-10 16:45:27 +02:00
Charles Bochet 9598a4dda2 Fix infinite loop on table load (#12474)
This was a tough one:
- we should avoid updating lazy findManyRecords function with
onCompleted callback, this is prone to infinite loops
2025-06-05 19:37:23 +02:00
Weiko 3f30964523 [FE] handle restricted objects 2 (#12437)
Co-authored-by: Charles Bochet <charles@twenty.com>
2025-06-05 15:49:22 +02:00
Thomas des Francs e13d83b660 Seed update - Replaced Qonto by Anthropic (#12340)
Co-authored-by: Charles Bochet <charles@twenty.com>
2025-06-02 16:42:53 +02:00
Félix Malfait 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
Abdul Rahman af5762c8ba Infinite scrolling in relation picker menu (#12051)
https://github.com/user-attachments/assets/4be785e0-ea8a-4c8e-840e-6fa0a663d7ba

Closes #11938

---------

Co-authored-by: martmull <martmull@hotmail.fr>
2025-05-23 17:23:09 +02:00
Marie 362d540aac Misc. of sentry improvements (#12233)
This PR mixes various initiatives to improve visibility on sentry 

**1. Catch errors on workflow jobs**
commit [catch workflowTriggerExceptions in job
handle](https://github.com/twentyhq/twenty/commit/1dbba8c9e27fed8fe01c5ac91d492720c45ba7a5)
@thomtrp 

**2. Fix type in messagingImportExceptionHandler** 
commit [fix type issue on
messagingImportExceptionHandler](https://github.com/twentyhq/twenty/commit/919bb3844c2e11f929a01dff0539e0a2ec7e4b00)
@guillim 

**3. Catch invalid uuid errors thrown by Postgres by rightfully typing
expected id as uuid**
commits [use UUIDFilter instead of IDFilter to get graphqlError in case
of malformed
id](https://github.com/twentyhq/twenty/commit/57cc315efeb0365b1cd589f7487dbfc886338d26),
[use UUIDFilter
(2)](https://github.com/twentyhq/twenty/commit/304553d770426362ee8bfcd3c2e1f0066abe2c04),
[fix ids typed as UUID instead of
ID](https://github.com/twentyhq/twenty/commit/f95d6319cf9290a5ae1d59eb634617a511411633)
@Weiko 
⚠️⚠️⚠️ when we deploy this PR we need to flush the schema types from
redis as this PR changes them ⚠️⚠️⚠️


**4. Do not group UNKNOWN errors together**
commit [do not group unknown errors
together](https://github.com/twentyhq/twenty/commit/c299b39c8fdcc4d6656dc5ce58437e4365cd60b0)
Some CustomException classes have introduced UNKNOWN error codes as a
default fallback error code. We use CustomException codes to group
issues together, but we don't want to do it with UNKNOWN error as they
may not have anything in common. For exemple [this sentry for UNKNOWN
code](https://twenty-v7.sentry.io/issues/6605750776/events/a72272d8941b4fa2add9b1f39c196d3f/?environment=prod&environment=prod-eu&project=4507072499810304&query=Unknown&referrer=next-event&stream_index=0)
groups together "Unknown error importing calendar events for calendar
channel...", "Insufficent permissions...", to name a few.

**5. Improve postgres error grouping**
commit [group together postgres
errors](https://github.com/twentyhq/twenty/commit/567c25495e37cdccfc9010f346145f7d5cc46a54)
Postgres error are thrown by typeORM as QueryFailedError. we have a lot
of them on sentry where they are badly grouped They are currently
grouped on sentry according to the stack trace, which leads them to
sometimes be grouped even if they don't have anything in common : for
exemple [this sentry for
QueryFailedError](https://twenty-v7.sentry.io/issues/6563624590/events/2d636821e27a448595b647b4b5a7d6a8/?environment=prod&environment=prod-eu&project=4507072499810304&query=is%3Aunresolved%20%21issue.type%3A%5Bperformance_consecutive_db_queries%2Cperformance_consecutive_http%2Cperformance_file_io_main_thread%2Cperformance_db_main_thread%2Cperformance_n_plus_one_db_queries%2Cperformance_n_plus_one_api_calls%2Cperformance_p95_endpoint_regression%2Cperformance_slow_db_query%2Cperformance_render_blocking_asset_span%2Cperformance_uncompressed_assets%2Cperformance_http_overhead%2Cperformance_large_http_payload%5D%20timesSeen%3A%3E10&referrer=previous-event&sort=date&stream_index=0)
groups together "user mapping not found for "postgres" and "invalide
type for uuid: 'fallback-id'" to name a few. I attempted to improve the
grouping by grouping them with a new custom fingerPrint composed of the
[code returned by
Postgres](https://www.postgresql.org/docs/current/errcodes-appendix.html)
+ the truncated operation name (Find, Aggregate, Check...). This is
still not ideal as postgres code are quite broad - we could have the
same error code for two Find operations with different causes. let's
give this a try !
2025-05-23 13:36:02 +00:00
Gaurav 98e199c01d Support Full Name as Record Text Identifier (#11610)
closes #11296 


[recording.webm](https://github.com/user-attachments/assets/da0f2587-a435-4bee-a802-81eb9ca92733)

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2025-05-20 00:03:30 +02:00
Marie f782f4dcd8 Fix CSV import upsert (#12048)
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
2025-05-15 14:44:31 +02:00
Jérémy M cc29c25176 feat: new relation sync-metadata, twenty-orm, create/update (#10217)
Fix
https://github.com/twentyhq/core-team-issues/issues/330#issue-2827026606
and
https://github.com/twentyhq/core-team-issues/issues/327#issue-2827001814

What this PR does when `isNewRelationEnabled` is set to `true`:
- [x] Drop the creation of the  foreign key as a `FieldMetadata`
- [x] Stop creating `RelationMetadata`
- [x] Properly fill `FieldMetadata` of type `RELATION` during the sync
command
- [x] Use new relation settings in TwentyORM
- [x] Properly create `FieldMetadata` relations when we create a new
object
- [x] Handle `database:reset` with new relations

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
Co-authored-by: Charles Bochet <charlesBochet@users.noreply.github.com>
2025-04-22 19:01:39 +02:00
Baptiste Devessier efab98a8f8 Get all first depth fields in the table and the board (#11650)
After discussing it with the team, we now want to query all fields in
the table and the board by default. Feeding the cache with exhaustive
data will make the side panel's life easier, as it needs all the record
fields to determine the actions to enable.
2025-04-22 16:45:36 +02:00
Raphaël Bosi 446919bc72 Remove onboarding flashes + close all dropdowns on CommandMenu close (#11483)
## Remove onboarding flashes

Tested:
- sign in with credentials
- sign in with social oAuth
- sign up with credentials
- multidomain
- single domain
- reset password

No more flashes, and code logic simplified!

## Close all dropdowns on CommandMenu close

Before:


https://github.com/user-attachments/assets/244ff935-3d40-47d5-a097-12d4cc3810dd


After:


https://github.com/user-attachments/assets/1de692f8-5032-404a-be74-025ebca67138

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2025-04-11 14:15:14 +02:00
Charles Bochet b6e344e7be Various fixes (#11448)
# Scrollbar fix

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

<img width="1512" alt="image"
src="https://github.com/user-attachments/assets/b13fe0f2-8c61-4ea8-9ea1-e61e571a90da"
/>

---------

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
2025-04-09 01:03:43 +02:00
Charles Bochet 59ae978ee3 Fix safari broken table (#11417)
In this PR:
- deprecate usage of useInView (react-intersection-observer) for record
table
- fixes #11254
2025-04-07 16:33:02 +02:00
Charles Bochet 2308091b13 Remove overlay-scroll-bar (#11258)
## What

- Deprecate overlayscrollbars as we decided to follow the native
behavior
- rework on performances (avoid calling recoil states too much at field
level which is quite expensive)
- Also implements:
https://github.com/twentyhq/core-team-issues/issues/569

---------

Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
2025-04-04 16:13:48 +02:00
Marie 0df07a766a Handle no value options in filters (#11351)
Fixes #11323 - see description to reproduce

The issue was that the filter was malformed for no value options: 
<img width="649" alt="Capture d’écran 2025-04-02 à 14 56 25"
src="https://github.com/user-attachments/assets/5287c4f8-7eaf-4488-b692-4d7634236d3d"
/>
causing
<img width="333" alt="Capture d’écran 2025-04-02 à 14 56 43"
src="https://github.com/user-attachments/assets/aa1b7333-50da-4b7d-979b-70dab9a1ab41"
/>


after fix: 
<img width="653" alt="Capture d’écran 2025-04-02 à 14 39 56"
src="https://github.com/user-attachments/assets/1777c068-7231-4e14-bc41-84ef7909cf10"
/>
2025-04-03 10:41:50 +02:00
Charles Bochet 6898a40ac3 Fix relation from many notes (#11120)
Fixes https://github.com/twentyhq/twenty/issues/3415
2025-03-24 15:19:05 +01:00
Etienne 1c5f3ef5fa clean searchResolvers in server (#11114)
Introduces break in change

- remove search... resolvers
- rename globalSearch to search
- rename searchRecord.objectSingularName > objectNameSingular
closes https://github.com/twentyhq/core-team-issues/issues/643
2025-03-24 13:42:51 +01:00
Charles Bochet 6e7d2db58f Fix From Many relation for deleted notes crashing (#11117)
In this PR, I'm: 
- fixing the root cause (we should not try to render a RecordChip if the
record is not defined in RelationFromMany Display)
- fixing related typing issues
- we won't be able to catch the issue from TS perspective as
ObjectRecord is a Record of string, any
2025-03-24 13:29:44 +01:00
Paul Rastoin 9ad8287dbc [REFACTOR] twenty-shared multi barrel and CJS/ESM build with preconstruct (#11083)
# Introduction

In this PR we've migrated `twenty-shared` from a `vite` app
[libary-mode](https://vite.dev/guide/build#library-mode) to a
[preconstruct](https://preconstruct.tools/) "atomic" application ( in
the future would like to introduce preconstruct to handle of all our
atomic dependencies such as `twenty-emails` `twenty-ui` etc it will be
integrated at the monorepo's root directly, would be to invasive in the
first, starting incremental via `twenty-shared`)

For more information regarding the motivations please refer to nor:
- https://github.com/twentyhq/core-team-issues/issues/587
-
https://github.com/twentyhq/core-team-issues/issues/281#issuecomment-2630949682

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

## How to test
In order to ease the review this PR will ship all the codegen at the
very end, the actual meaning full diff is `+2,411 −114`
In order to migrate existing dependent packages to `twenty-shared` multi
barrel new arch you need to run in local:
```sh
yarn tsx packages/twenty-shared/scripts/migrateFromSingleToMultiBarrelImport.ts && \
npx nx run-many -t lint --fix -p twenty-front twenty-ui twenty-server twenty-emails twenty-shared twenty-zapier
```
Note that `migrateFromSingleToMultiBarrelImport` is idempotent, it's atm
included in the PR but should not be merged. ( such as codegen will be
added before merging this script will be removed )

## Misc
- related opened issue preconstruct
https://github.com/preconstruct/preconstruct/issues/617

## Closed related PR
- https://github.com/twentyhq/twenty/pull/11028
- https://github.com/twentyhq/twenty/pull/10993
- https://github.com/twentyhq/twenty/pull/10960

## Upcoming enhancement: ( in others dedicated PRs )
- 1/ refactor generate barrel to export atomic module instead of `*`
- 2/ generate barrel own package with several files and tests
- 3/ Migration twenty-ui the same way
- 4/ Use `preconstruct` at monorepo global level

## Conclusion
As always any suggestions are welcomed !
2025-03-22 19:16:06 +01:00
Charles Bochet ccf60284cf Various fixes (#11108)
Fixes many bug regarding TableCell and InlineCells
2025-03-22 14:19:10 +01:00
Etienne e624e8deee replace search resolvers by global search in front (#11086)
Done
- Replace global search in multi record picker and single record picker

To do
- refactor SingleRecordPicker to match MultipleRecordPicker - next 1:1
- items in this issue
https://github.com/twentyhq/core-team-issues/issues/643



closes https://github.com/twentyhq/core-team-issues/issues/535
2025-03-21 17:25:00 +01:00
Paul Rastoin 872c0e97f6 [BUGFIX] GenerateDefaultRecordChipData returns RecordChipData (#11071)
# Introduction
closes https://github.com/twentyhq/twenty/issues/11030, might not fix
the issue as it seems to be related to the passed record to
`identifierChipGeneratorPerObject` about to dig deeper in this generator
code => found nothing revelant doubled check each `RecordChip`
invocation that could provide undefined record
Fixed wrong default generated `RecordChipData` signature

## Reproducibility
I've only been able to reproduce the bug in production using the very
same opportunity than within the issue, but not all the time

https://crm.twenty-internal.com/objects/opportunities?viewId=b709d3d1-2dd2-455d-ba73-784f3ab00883
```json
// Removed timelineActivities to prevent linking ids
{
  "data": {
    "opportunity": {
      "__typename": "Opportunity",
      "closeDate": null,
      "company": null,
      "companyId": null,
      "createdAt": "2024-06-17T09:45:22.357Z",
      "deletedAt": null,
      "id": "006a22dd-6bd6-4247-a24b-42fb164cd48c",
      "name": "test",
      "pointOfContact": null,
      "pointOfContactId": null,
      "position": 0,
      "probability": "0",
      "stage": "NEW_STAGE",
      "updatedAt": "2025-03-20T16:27:51.927Z",
      "amount": {
        "__typename": "Currency",
        "amountMicros": null,
        "currencyCode": "USD"
      },
      "attachments": {
        "__typename": "AttachmentConnection",
        "edges": []
      },
      "createdBy": {
        "__typename": "Actor",
        "source": "MANUAL",
        "workspaceMemberId": null,
        "name": "",
        "context": {}
      },
      "favorites": {
        "__typename": "FavoriteConnection",
        "edges": []
      },
      "taskTargets": {
        "__typename": "TaskTargetConnection",
        "edges": []
      },
      "noteTargets": {
        "__typename": "NoteTargetConnection",
        "edges": [
          {
            "__typename": "NoteTargetEdge",
            "node": {
              "__typename": "NoteTarget",
              "appEventId": null,
              "companyId": null,
              "createdAt": "2025-01-22T17:11:07.801Z",
              "deletedAt": null,
              "feedbackId": null,
              "id": "2e8eca1c-e2c2-425a-93fc-ef2aeb65f410",
              "issueId": null,
              "listingId": null,
              "noteId": "ab586b51-6931-4a4a-9c24-0d16226211b2",
              "opportunityId": "006a22dd-6bd6-4247-a24b-42fb164cd48c",
              "personId": null,
              "somethingId": null,
              "testId": null,
              "updatedAt": "2025-01-22T17:11:07.801Z"
            }
          }
        ]
      },
    }
  }
}
```
2025-03-20 18:38:19 +01:00
Raphaël Bosi 7dac60cfee Fix useFindManyRecords withSoftDeleterFilter (#11056)
Fixes #11038

# Fix useFindManyRecords withSoftDeleterFilter

The error came from a faulty implementation of the `withSoftDeleted`
parameter inside `useFindManyRecords` and from the fact that
`withSoftDeleted: true` was added to access deleted records actions.
However, this parameter was always set in
`useFindManyRecordsSelectedInContextStore` instead of considering
whether the filter was active or not.

```
const withSoftDeleterFilter = {
  or: [{ deletedAt: { is: 'NULL' } }, { deletedAt: { is: 'NOT_NULL' } }],
};
```

The final filter was incorrectly doing an `or` operation between the
base filter and `withSoftDeleterFilter` when it should have been an
`and`:

```
filter: {
  ...filter,
  ...(withSoftDeleted ? withSoftDeleterFilter : {}),
}
```

The correct implementation should be:

```
filter:
  filter || withSoftDeleted
    ? {
        and: [
          ...(filter ? [filter] : []),
          ...(withSoftDeleted ? [withSoftDeleterFilter] : []),
        ],
      }
    : undefined,
```

# Fix useFindManyRecordsSelectedInContextStore

- Check if the soft deleted filter is active before using the
`withSoftDeleterFilter` parameter
2025-03-20 16:27:55 +01:00
Weiko d34ec4da2d Fix kanban view picker total count (#10898)
Fixes https://github.com/twentyhq/twenty/issues/9790

Before


https://github.com/user-attachments/assets/332ec338-ce87-4d4d-ac47-a4e76dceb5b0



After


https://github.com/user-attachments/assets/93a03842-386a-4e75-a709-85a91bbc7679

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2025-03-14 17:27:25 +01:00
Paul Rastoin 2e4c596644 [TEST] Covering useDeleteOne relations optimistic cache behavior (#10238)
## Introduction
Added coverage on the `useDeleteOneRecord` hooks, especially its
optimistic behavior feature.
Introduced a new testing tool `InMemoryTestingCacheInstance` that has
builtin very basic expectors in order to avoid future duplication when
covering others record hooks `update, create, destroy` etc etc

## Notes
Added few comments in this PR regarding some builtin functions I've
created around companies and people mocked object model and that I think
could be cool to spread and centralize within a dedicated "class
template"

Also put in light that unless I'm mistaken some tests are running on
`RecordNode` and not `RecordObject`

Took few directions on my own that as I always I would suggestion nor
remarks on them !

Let me know

## Misc
- Should we refactor `useDeleteOneRecord` tests to follow `eachTesting`
pattern ? => I feel like this is inappropriate as this hooks is already
high level, the only plus value would be less tests code despite
readability IMO
2025-03-03 10:22:26 +01:00
Etienne 39543872e6 add new @WorkspaceIsSearchable decorator + updates services + add migration command (#10507)
closes https://github.com/twentyhq/core-team-issues/issues/345
2025-02-27 13:57:07 +01:00
Weiko 431da37cdf add stories to roles components (#10503)
## Context
Adding stories for roles components. Also moving modules components to
the proper "modules" folder, "pages" folder being only for entry points.

## Test
Run storybook

<img width="1145" alt="Screenshot 2025-02-26 at 13 40 40"
src="https://github.com/user-attachments/assets/bc184ab0-c590-4362-8c5a-1bf5ef176e6c"
/>
<img width="1149" alt="Screenshot 2025-02-26 at 13 40 32"
src="https://github.com/user-attachments/assets/699cd205-31db-45e9-b9c1-caff1832bd47"
/>
<img width="1153" alt="Screenshot 2025-02-26 at 13 40 11"
src="https://github.com/user-attachments/assets/72e45a67-ea89-4999-8b16-6f7d027d07f6"
/>
<img width="471" alt="Screenshot 2025-02-26 at 13 38 16"
src="https://github.com/user-attachments/assets/62676943-9935-42b5-b769-5544f7eed85f"
/>
<img width="472" alt="Screenshot 2025-02-26 at 13 38 12"
src="https://github.com/user-attachments/assets/946baab9-1be4-439e-bf99-0ebeab0995f7"
/>
2025-02-26 18:16:05 +01:00
Paul Rastoin ea0d3c605f [FIX] Optimistically compute position only for objectMetadataItem that has the field (#10510)
# Introduction
In this PR https://github.com/twentyhq/twenty/pull/10493 introduced a
regression on optimistic cache for record creation, by expecting a
`position` `fieldMetadataItem` on every `ObjectMetadataItem` which is a
wrong assertion
Some `Tasks` and `ApiKeys` do not have one

## Fix
Dynamically compute optimistic record input position depending on
current `ObjectMetadataItem`

## Refactor
Refactored a failing test following [jest
each](https://jestjs.io/docs/api#describeeachtablename-fn-timeout)
pattern to avoid error prone duplicated env tests. Created a "standard'
and applied it to an other test also using `it.each`.
2025-02-26 17:04:52 +01:00
Paul Rastoin ec87218b9c [Refactor] generateDepthOneRecordGqlFieldsFromRecord (#10499)
## Introduction
This refactor results from this
https://github.com/twentyhq/twenty/pull/10493 review
Introduced a new abstraction to the extinsting
`generateDepthOneRecordGqlFields` that was accepting an optional record
in arg in order to map generated `recordGqlFields` to the keys in the
record

1/ Created a dedicated util method
`generateDepthOneRecordGqlFieldsFromRecord` to do so
2/ Updated each previous `generateDepthOneRecordGqlFields` passing a
record to call new `generateDepthOneRecordGqlFieldsFromRecord`
2025-02-26 11:11:45 +00:00