Commit Graph

1607 Commits

Author SHA1 Message Date
Charles Bochet d526b07078 Add ability to discard Information Banner (#16019)
Fixes https://github.com/twentyhq/twenty/issues/14028

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

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

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

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

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

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

## Demo 

Main : 



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



This PR : 



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



## Aggregate update bug fix

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

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

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

Main : 


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

This PR : 


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

## Miscellaneous 

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

## TODO 

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

<!-- CURSOR_SUMMARY -->
---

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

---------

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

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

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

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

---------

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

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

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

Fixes #15792

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

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

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

---------

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

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

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

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


### Before 

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


### After

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

---------

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

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

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

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

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

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

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


### Before 

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

### After


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

---------

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

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

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

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

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

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

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

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

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



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


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



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



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

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

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

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

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

---

### Implementation Overview

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

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

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

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


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

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

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


<!-- CURSOR_SUMMARY -->
---

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

---------

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

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

## Changes

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

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

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

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

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

## Migration Notes
Existing workspaces will need to assign the new permissions to roles as
needed. By default, all new permissions are set to `false` for non-admin
roles.
2025-11-07 15:37:17 +01:00
Marie 4ce93aee52 Fix user deletion flows (#15614)
**Before**
- any user with workpace_members permission was able to remove a user
from their workspace. This triggered the deletion of workspaceMember +
of userWorkspace, but did not delete the user (even if they had no
workspace left) nor the roleTarget (acts as junction between role and
userWorkspace) which was left with a userWorkspaceId pointing to
nothing. This is because roleTarget points to userWorkspaceId but the
foreign key constraint was not implemented
- any user could delete their own account. This triggered the deletion
of all their workspaceMembers, but not of their userWorkspace nor their
user nor the roleTarget --> we have orphaned userWorkspace, not
technically but product wise - a userWorkspace without a workspaceMember
does not make sense

So the problems are
- we have some roleTargets pointing to non-existing userWorkspaceId
(which caused https://github.com/twentyhq/twenty/issues/14608 )
- we have userWorkspaces that should not exist and that have no
workspaceMember counterpart
- it is not possible for a user to leave a workspace by themselves, they
can only leave all workspaces at once, except if they are being removed
from the workspace by another user

**Now**
- if a user has multiple workspaces, they are given the possibility to
leave one workspace while remaining in the others (we show two buttons:
Leave workspace and Delete account buttons). if a user has just one
workspace, they only see Delete account
- when a user leaves a workspace, we delete their workspaceMember,
userWorkspace and roleTarget. If they don't belong to any other
workspace we also soft-delete their user
- soft-deleted users get hard deleted after 30 days thanks to a cron
- we have two commands to clean the orphans roleTarget and userWorkspace
(TODO: query db to see how many must be run)

**Next**
- once the commands have been run, we can implement and introduce the
foreign key constraint on roleTarget


Fixes https://github.com/twentyhq/twenty/issues/14608
2025-11-06 18:29:12 +00:00
Weiko 051a226b6f Fix display currency amount if currency code is empty string (#15654)
## Before
<img width="1306" height="841" alt="Screenshot 2025-11-05 at 18 40 05"
src="https://github.com/user-attachments/assets/964f5771-bd91-4cb2-9684-52073b845580"
/>


## After
<img width="1297" height="795" alt="Screenshot 2025-11-05 at 18 39 55"
src="https://github.com/user-attachments/assets/4ae99265-7459-4579-9f65-e2d8225e8306"
/>
2025-11-05 23:55:57 +01:00
Marie 982964efbf Fix scroll to start when resize or move around columns (#15655)
Fixes https://github.com/twentyhq/private-issues/issues/361

There's room for more improvement here -
triggerInitialRecordTableDataLoad does a lot of things, should not be
triggered so much. actually even
RecordTableVirtualizedInitialDataLoadEffect should not be triggered when
there's just a metadata field change (if we trust the name
initialDataLoad)
2025-11-05 18:58:35 +01:00
martmull abde3c04ac 1630 extensibility twenty cli ability to create edit and delete fields (#15501)
As title

- adds decorators in twenty-sdk
- update twenty-cli load-manifest to it gets @FieldMetadata infos +
testing
- update twenty-server so it CRUD fields properly, using
universalIdentifier
- Fix UI so we can update managed objects records
- move FieldMetadata items from twenty-server to twenty-shared
2025-11-05 17:50:06 +01:00
Harshit Singh 003b04e9ae fix: removeuseMergeRecordRelatationship and simplify dry run response (#15486)
## Description

- This PR addresses issue
https://github.com/twentyhq/twenty/issues/15201
- Removed
[useMergeRecordRelationships.ts](https://github.com/twentyhq/twenty/compare/main...harshit078:fix-merge-frontend?expand=1#diff-5d0366f814ff0c0e8961f40120690206a7acd3f7b66135cfb8c4ad8d3f6bc681)
- now backend returns populated result and frontend just shows it
without refetching relations.
- to be merged after PR- https://github.com/twentyhq/twenty/pull/15484


## Visual Appearance

 


https://github.com/user-attachments/assets/09d7548a-74a9-4742-af49-e98b4174f68c

---------

Co-authored-by: Etienne <45695613+etiennejouan@users.noreply.github.com>
2025-11-05 10:33:24 +01:00
Paul Rastoin 8dd43be9a2 Create many view groups (#15591)
# Introduction
Same as https://github.com/twentyhq/twenty/pull/15576 but for view
groups creation

When creating a kanban view with v2 flag activated in production result
in race condition due to request being slow and //.
That's why we're introducing a batch create on view group here
closing https://github.com/twentyhq/core-team-issues/issues/1847

## In v2
- batch create view group endpoint is available
- frontend will target the new endpoint

## In v1
- batch create view group endpoint is not available
- frontend will stick to old fake batch view group creation loop


## Gallery
### v2
<img width="1796" height="486" alt="image"
src="https://github.com/user-attachments/assets/932cfe9f-85f1-41cc-a1c4-72a4b5d5a256"
/>

### v1
<img width="1852" height="966" alt="image"
src="https://github.com/user-attachments/assets/8aa9df11-cdea-4b12-ae60-118cdf5e257b"
/>
2025-11-04 15:17:55 +01:00
nitin 106c33abec fix inconsistent widget placeholder placement (#15580)
fixes -
https://github.com/twentyhq/twenty/pull/15496#issuecomment-3481636780

and https://discord.com/channels/1130383047699738754/1434971632539009055

- make the pending placeholder to be non-static -- so that it behaves
similarly to compact behavior like other widgets do
- make sure users can't set dashboards to be opened in the side panel --
similar to workflows

before- 


https://github.com/user-attachments/assets/d991db56-1388-4e4b-b743-a63f56b6187a

after- 


https://github.com/user-attachments/assets/9031f2c6-1e3b-4604-a5a0-3124d14484ce
2025-11-04 11:07:57 +01:00
Lucas Bordeau b33b38cb02 Follow-up high fixes on date refactor (#15553)
This PR fixes important bugs on date filter handling following-up date
refactor.

Fixes : https://github.com/twentyhq/core-team-issues/issues/1814
2025-11-03 17:51:42 +01:00
Weiko 464f80ed9b fix front lint 2025-11-03 16:38:55 +01:00
Weiko a5e53d74dc fix calendar view when switched from other layout type bis (#15569) 2025-11-03 16:35:30 +01:00
Weiko 0b21ac7dd8 Add permission check on calendar view drag and add new (#15556)
## Context
If selected date field of the calendar view has readonly, we should not
allow users to drag/drop cards nor allow them to add a new record
(resulting in a permission error on the BE due to the FE updating the
said field)
2025-11-03 16:33:59 +01:00
Charles Bochet 20576f2ee7 Add Dashboard in Lab, make Calendar available out of lab (#15560)
As per title!
2025-11-03 15:40:26 +01:00
Weiko 82ac642d73 Fix calendar view when switched from other layout type not updating state (#15562)
## Context
Switching from kanban layout to calendar was not displaying records
properly. Adding the missing state update (similar to kanban case a few
lines above)
2025-11-03 15:32:23 +01:00
Raphaël Bosi 1739ee0595 Add date granularity and timezone and first day of the week to graphs (#15543)
- Allow users to choose the date granularity of the x axis and the group
by of the y axis on a bar chart
- Display those options conditionally
- Store timezones in graphs: each graph has its own timezone, defaults
to the user timezone. There will be a picker in the v2 to choose the
timezone. For now the timezone is not used by the backend, but it will
be used in filters and in group by queries.
- Store first day of the week



https://github.com/user-attachments/assets/66a5d156-dd93-4ebe-8c8f-d172f93e25be
2025-11-03 15:27:47 +01:00
Lucas Bordeau afeb505eed [Breaking Change] Implement reliable date picker utils to handle all timezone combinations (#15377)
This PR implements the necessary tools to have `react-datepicker`
calendar and our date picker components work reliably no matter the
timezone difference between the user execution environment and the user
application timezone.

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

This PR won't cover everything needed to have Twenty handle timezone
properly, here is the follow-up issue :
https://github.com/twentyhq/core-team-issues/issues/1807

# Features in this PR

This PR brings a lot of features that have to be merged together.

- DATE field type is now handled as string only, because it shouldn't
involve timezone nor the JS Date object at all, since it is a day like a
birthday date, and not an absolute point in time.
- DATE_TIME field wasn't properly handled when the user settings
timezone was different from the system one
- A timezone abbreviation suffix has been added to most DATE_TIME
display component, only when the timezone is different from the system
one in the settings.
- A lot of bugs, small features and improvements have been made here :
https://github.com/twentyhq/core-team-issues/issues/1781

# Handling of timezones

## Essential concepts

This topic is so complex and easy to misunderstand that it is necessary
to define the precise terms and concepts first. It resembles character
encoding and should be treated with the same care.

- Wall-clock time : the time expressed in the timezone of a user, it is
distinct from the absolute point in time it points to, much like a
pointer being a different value than the value that it points to.
- Absolute time : a point in time, regardless of the timezone, it is an
objective point in time, of course it has to be expressed in a given
timezone, because we have to talk about when it is located in time
between humans, but it is in fact distinct from any wall clock time, it
exists in itself without any clock running on earth. However, by
convention the low-level way to store an absolute point in time is in
UTC, which is a timezone, because there is no way to store an absolute
point in time without a referential, much like a point in space cannot
be stored without a referential.
- DST : Daylight Save Time, makes the timezone shift in a specific
period every year in a given timezone, to make better use of longer days
for various reasons, not all timezones have DST. DST can be 1 hour or 30
min, 45 min, which makes computation difficult.
- UTC : It is NOT an “absolute timezone”, it is the wall-clock time at
0° longitude without DST, which is an arbitrary and shared human
convention. UTC is often used as the standard reference wall-clock time
for talking about absolute point in time without having to do timezone
and DST arithmetic. PostgreSQL stores everything in UTC by convention,
but outputs everything in the server’s SESSION TIMEZONE.

## How should an absolute point in time be stored ?

Since an absolute point in time is essentially distinct from its
timezone it could be stored in an absolute way, but in practice it is
impossible to store an absolute point in time without a referential. We
have to say that a rocket launched at X given time, in UTC, EST, CET,
etc. And of course, someone in China will say that it launched at 10:30,
while in San Francisco it will have launched at 19:30, but it is THE
SAME absolute point in time.

Let’s take a related example in computer science with character
encoding. If a text is stored without the associated encoding table, the
correct meaning associated to the bits stored in memory can be lost
forever. It can become impossible for a program to guess what encoding
table should be used for a given text stored as bits, thus the glitches
that appeared a lot back in the early days of internet and document
processing.

The same can happen with date time storing, if we don’t have the
timezone associated with the absolute point in time, the information of
when it absolutely happened is lost.

It is NOT necessary to store an absolute point in time in UTC, it is
more of a standard and practical wall-clock time to be associated with
an absolute point in time. But an absolute point in time MUST be store
with a timezone, with its time referential, otherwise the information of
when it absolutely happened is lost.

For example, it is easier to pass around a date as a string in UTC, like
`2024-01-02T00:00:00Z` because it allows front-end and back-end code to
“talk” in the same standard and DST-free wall-clock time, BUT it is not
necessary. Because we have date libraries that operate on the standard
ISO timezone tables, we can talk in different timezone and let the
libraries handle the conversion internally.

It is false to say that UTC is an absolute timezone or an absolute point
in time, it is just the standard, conventional time referential, because
one can perfectly store every absolute points in time in UTC+10 with a
complex DST table and have the exactly correct absolute points in time,
without any loss of information, without having any UTC+0 dates
involved.

Thus storing an absolute point in time without a timezone associated,
for example with `timestamp` PostgreSQL data type, is equivalent to
storing a wall-clock time and then throwing away voluntarily the
information that allows to know when it absolutely happened, which is a
voluntary data-loss if the code that stores and retrieves those
wall-clock points in time don’t store the associated timezone somewhere.

This is why we use `timestamptz` type in PostgreSQL, so that we make
sure that the correct absolute point in time is stored at the exact time
we send it to PostgreSQL server, no matter the front-end, back-end and
SQL server's timezone differences.

## The JavaScript Date object

The native JavaScript Date object is now officially considered legacy
([source](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date)),
the Date object stores an absolute point in time BUT it forces the
storage to use its execution environment timezone, and one CANNOT modify
this timezone, this is a legacy behavior.

To obtain the desired result and store an absolute point in time with an
arbitrary timezone there are several options :

- The new Temporal API that is the successor of the legacy Date object.
- Moment / Luxon / @date-fns/tz that expose objects that allow to use
any timezone to store an absolute point in time.

## How PostgreSQL stores absolute point in times

PostgreSQL stores absolute points in time internally in UTC
([source](https://www.postgresql.org/docs/current/datatype-datetime.html#DATATYPE-DATETIME-INPUT-TIME-STAMPS)),
but the output date is expressed in the server’s session timezone
([source](https://www.postgresql.org/docs/current/sql-set.html)) which
can be different from UTC.

Example with the object companies in Twenty seed database, on a local
instance, with a new “datetime” custom column :

<img width="374" height="554" alt="image"
src="https://github.com/user-attachments/assets/4394cb43-d97e-4479-801d-ca068f800e39"
/>

<img width="516" height="524" alt="image"
src="https://github.com/user-attachments/assets/b652f36a-d2e2-47a4-8950-647ca688cbbd"
/>

## Why can’t I just use the JavaScript native Date object with some
manual logic ?

Because the JavaScript Date object does not allow to change its internal
timezone, the libraries that are based on it will behave on the
execution environment timezone, thus leading to bugs that appear only on
the computers of users in a timezone but not for other in another
timezone.

In our case the `react-datepicker` library forces to use the `Date`
object, thus forcing the calendar to behave in the execution environment
system timezone, which causes a lot of problems when we decide to
display the Twenty application DATE_TIME values in another timezone than
the user system one, the bugs that appear will be of the off-by-one date
class, for example clicking on 23 will select 24, thus creating an
unreliable feature for some system / application timezone combinations.

A solution could be to manually compute the difference of minutes
between the application user and the system timezones, but that’s not
reliable because of DST which makes this computation unreliable when DST
are applied at different period of the year for the two timezones.

## Why can’t I compute the timezone difference manually ?

Because of DST, the work to compute the timezone difference reliably,
not just for the usual happy path, is equivalent to developing the
internal mechanism of a date timezone library, which is equivalent to
use a library that handles timezones.

## Using `@date-fns/tz` to solve this problem

We could have used `luxon` but it has a heavy bundle size, so instead we
rely here on `@date-fns/tz` (~1kB) which gives us a `TZDate` object that
allows to use any given timezone to store an absolute point-in-time.

The solution here is to trick `react-datepicker` by shifting a Date
object by the difference of timezone between the user application
timezone and the system timezone.

Let’s take a concerte example.

System timezone : Midway,  ⇒ UTC-11:00, has no DST.

User application timezone : Auckland, NZ ⇒ UTC+13:00, has a DST.

We’ll take the NZ daylight time, so that will make a timezone difference
of 24 hours !

Let’s take an error-prone date : `2025-01-01T00:00:00` . This date is
usually a good test-case because it can generate three classes of bugs :
off-by-one day bugs, off-by-one month bugs and off-by-one year bugs, at
the same time.

Here is the absolute point in time we take expressed in the different
wall-clock time points we manipulate


Case | In system timezone ⇒ UTC-11 | In UTC | In user application
timezone ⇒ UTC+13
-- | -- | -- | --
Original date | `2024-12-31T00:00:00-11:00` | `2024-12-31T11:00:00Z` |
`2025-01-01T00:00:00+13:00`
Date shifted for react-datepicker | `2025-01-01T00:00:00-11:00` |
`2025-01-01T11:00:00Z` | `2025-01-02T00:00:00+13:00`

We can see with this table that we have the number part of the date that
is the same (`2025-01-01T00:00:00`) but with a different timezone to
“trick” `react-datepicker` and have it display the correct day in its
calendar.

You can find the code in the hooks
`useTurnPointInTimeIntoReactDatePickerShiftedDate` and
`useTurnReactDatePickerShiftedDateBackIntoPointInTime` that contain the
logic that produces the above table internally.

## Miscellaneous

Removed FormDateFieldInput and FormDateTimeFieldInput stories as they do
not behave the same depending of the execution environment and it would
be easier to put them back after having refactored FormDateFieldInput
and FormDateTimeFieldInput

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2025-11-01 18:31:24 +01:00
Baptiste Devessier 5f0d24798a Support workflows in record page layouts (#15471)
https://github.com/user-attachments/assets/275a02a3-7054-45d1-9423-75bb5223a8ba
2025-10-31 18:45:58 +01:00
Weiko 09c704c8bd Add useGroupBy hook + update calendar view to use groupBy (#15439)
## Context
Took inspiration from findMany + kanban => Implemented a hook for the
new groupBy API endpoints
Fixed an issue when DnD to an empty day
2025-10-31 18:39:22 +01:00
Thomas Trompette 5f13e6fcf4 Put delete button on step footer + add unique fields on upsert action (#15497)
<img width="491" height="823" alt="Capture d’écran 2025-10-31 à 14 54
38"
src="https://github.com/user-attachments/assets/8058a6a3-8a6c-4cdd-93d9-2af71208dc5a"
/>
2025-10-31 16:39:45 +00:00
Ranjeet Baraik 6ed1fd841d fix: composite field label retrieval in spreadsheet import utility (#15489)
Fixes - https://github.com/twentyhq/twenty/issues/15368

Seems like the sub field was not being used for the actual label lookup
part

<img width="1302" height="354" alt="image"
src="https://github.com/user-attachments/assets/444f76be-117b-4b8b-91fe-dedd293e09af"
/>
2025-10-31 11:39:39 +01:00
Charles Bochet eba3b0ca88 Simplify Code on FetchMore (#15465)
Simplifying a bit more fetchMore / lazyQuery api
2025-10-30 13:36:30 +01:00
Weiko 736fac021d Add contextMenu actions to calendar view (#15451)
<img width="432" height="307" alt="Screenshot 2025-10-29 at 19 31 38"
src="https://github.com/user-attachments/assets/61965305-3a20-46de-b47f-7ac78cb1228c"
/>
2025-10-30 10:59:11 +01:00
Raphaël Bosi 198bf5a333 Complete color refactoring (#15414)
# Complete color refactoring

Closes https://github.com/twentyhq/core-team-issues/issues/1779

- Updated all colors to use Radix colors with P3 color space allowing
for brighter colors
- Created our own gray scale interpolated on Radix's scale to have the
same values for grays as the old ones in the app
- Introduced dark and light colors as well as there transparent versions
- Added many new colors from radix that can be used in the tags or in
the graphs
- Updated multiple color utilities to match new behaviors
- Changed the computation of Avatar colors to return only colors from
the theme (before it was random hsl)

These changes allow the user to use new colors in tags or charts, the
colors are brighter and with better contrast. We have a full range of
color variations from 1 to 12 where before we only had 4 adaptative
colors.
All these changes will allow us to develop custom themes for the user
soon, where users can choose their accent colors, background colors and
there contrast.
2025-10-29 18:08:51 +00:00
Weiko 33545a072c Fix creating kanban view when no select field (#15441)
Adding an early return when no select field exists and you are
redirected to the setting page otherwise it tries to call
setAndPersistViewType with kanban and fails with "No fields for kanban -
should not happen"
2025-10-29 19:04:18 +01:00
Charles Bochet 7b70a1bff6 Fix infinite loop on FE (#15415)
Fixes https://github.com/twentyhq/twenty/issues/15369

It's the first time we are hitting this weird behavior on apollo
onCompleted / onError. Theoretically if the reference of the onCompleted
(resp onError) callback is changing, this will trigger a re-run of
onCompleted. But also theretically the reference here is a
recoilCallback so should never change.

As this is synchronous I have move this logic to a sync way
2025-10-29 12:25:23 +01:00
Balaji Krishnamurthy 98b4e8431b Reset limit to 1 when object is changed (#15354)
Closes #15345 

The issue was that when the `onChange` was called on the Select
component in `WorkflowEditActionFindRecords.tsx`, the limit was being
reset to 1, but it wasn't rendering immediately. The sidebar had to be
closed and reopened.

I have added a `useEffect` as a hack to re-render the
`FormNumberFieldInput` when it's `defaultValue` is changed. I understand
that using `useEffect` is not a good choice. Please suggest a better fix
if any and I will implement it.

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2025-10-28 15:06:15 +01:00
Baptiste Devessier 2f3912aa98 Always use page layout renderer for dashboards (#15403)
🙈
2025-10-28 14:26:17 +01:00
Paul Rastoin 503a5029da Refactor twenty-front metadata api services for v2 (#15360)
# Introduction
Please first review this PR initial base
https://github.com/twentyhq/twenty/pull/15358
In a nutshell refactored the frontend fetchers to display v2 errors
format smoothly
Please note that the v2 now finished the whole validation and does fail
fast anymore ( summary is hardcoded for the moment )
```json
[
  {
    "extensions": {
      "code": "BAD_USER_INPUT",
      "errors": {
        "cronTrigger": [],
        "databaseEventTrigger": [],
        "fieldMetadata": [
          {
            "errors": [
              {
                "code": "INVALID_FIELD_INPUT",
                "message": "Default value should be as quoted string",
                "value": "",
              },
              {
                "code": "INVALID_FIELD_INPUT",
                "message": "Default value "" must be one of the option values",
                "value": "",
              },
            ],
            "flatEntityMinimalInformation": {
              "id": Any<String>,
              "name": "testField",
              "objectMetadataId": Any<String>,
            },
            "status": "fail",
            "type": "create_field",
          },
        ],
        "index": [],
        "objectMetadata": [],
        "routeTrigger": [],
        "serverlessFunction": [],
        "view": [],
        "viewField": [],
        "viewFilter": [],
        "viewGroup": [],
      },
      "message": "Validation failed for 0 object(s) and 0 field(s)",
      "summary": {
        "invalidCronTrigger": 0,
        "invalidDatabaseEventTrigger": 0,
        "invalidFieldMetadata": 0,
        "invalidIndex": 0,
        "invalidObjectMetadata": 0,
        "invalidRouteTrigger": 0,
        "invalidServerlessFunction": 0,
        "invalidView": 0,
        "invalidViewField": 0,
        "invalidViewFilter": 0,
        "invalidViewGroup": 0,
        "totalErrors": 0,
      },
      "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)",
    },
    "message": "Multiple validation errors occurred while creating fields",
    "name": "GraphQLError",
  },
]
```

## What's done
- `usePersistView` tool ( CRUD )
- renamed `usePersistViewX` tools accordingly ( no more records or core
)
- Now catching a lot of before unhandled exceptions
- refactored each services to handle their own exception handlers and
return either the response or the error within a discriminated union
record

## Result
### Primary entity error 
When performing an metadata operation on a given metadata, if validation
errors occurs we will display each of them in a toast
Here while creating an object metadata.
<img width="700" height="327" alt="image"
src="https://github.com/user-attachments/assets/0c33d13c-c66c-4749-af36-b253abd3449b"
/>

### Related entity error
Still while creating an object
<img width="700" height="327" alt="image"
src="https://github.com/user-attachments/assets/52607788-c4e9-470c-ac8c-23437345ee5c"
/>

### Translated
<img width="700" height="327" alt="image"
src="https://github.com/user-attachments/assets/a7198c20-ae82-47a6-910c-761de9594672"
/>


## Conclusion
This PR is an extract of https://github.com/twentyhq/twenty/pull/15331
close https://github.com/twentyhq/core-team-issues/issues/1776
## Notes
- Not refactor around triggers services as they're not consumed directly
by any frontend services
2025-10-28 10:50:41 +01:00
Guillim 7e1c046e58 morph bug fix (#15370)
Two bug fixes here: 

# MorphRelationOneToManyFieldDisplay
we expect an empty array, not undefined (run time error otherwise)


Fixes `Cannot read properties of undefined (reading 'length'): Cannot
read properties of undefined (reading 'length')` in
**MorphRelationOneToManyFieldDisplay**

```js
morphValuesWithObjectNameSingular.every(
      (morphValueWithObjectNameSingular) =>
        morphValueWithObjectNameSingular.value.length === 0,
    );
```

# create record in table mode
if the record has a relation there is currenlty a bug in production when
it is created. A cache issue.

`Missing field 'companyFoundedId' while writing result `
2025-10-27 17:34:59 +01:00
Baptiste Devessier 24349cb729 Enable records layouts for all records except workflows (#15378)
https://github.com/user-attachments/assets/3cb30486-3409-459e-9d60-7f6f31ebe00c
2025-10-27 17:34:21 +01:00