Readonly form fields in Workflow Versions were previously showing a
pointer cursor and hover background
This update introduces a `isReadOnly` prop on the StyledFieldContainer,
which is derived from the field's `readonly` state via
`actionOptions.readonly`.
When `isReadOnly` is true:
- The cursor is set to `default` instead of `pointer`.
This ensures a more accurate and user-friendly UI by visually indicating
that the field is non-interactive.
https://github.com/user-attachments/assets/90e5c109-f2a6-4e79-b72d-e2fa6038bf93#12004
---------
Co-authored-by: Baptiste Devessier <baptiste@devessier.fr>
# Fix cursor-based pagination with lexicographic ordering for composite
fields
## Bug
The existing cursor-based pagination implementation had a bug when
handling composite fields.
When paginating through results sorted by composite fields (like
`fullName` with sub-properties `firstName` and`lastName`), the WHERE
conditions generated for cursor positioning were incorrect, leading to
records being skipped.
The previous implementation was generating wrong WHERE conditions:
For example, when paginating with a cursor like `{ firstName: 'John',
lastName: 'Doe' }`, it would generate:
```sql
WHERE firstName > 'John' AND lastName > 'Doe'
```
This is incorrect because it would miss records like `{ firstName:
'John', lastName: 'Smith' }` which should be included in forward
pagination.
## Fix
Create a new util to use proper lexicographic order when sorting a
composite field.
---------
Co-authored-by: Charles Bochet <charlesBochet@users.noreply.github.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
In this PR
1. Add missing override of insert() method on
WorkspaceSelectQueryBuilder to return our custom
WorkspaceInsertQueryBuilder with permission checks.
2. Replace override implementation of methods on WorkspaceEntityManager
that call createQueryBuilder at a nested internal layer of typeORM (i.e.
not directly in the initial implementation of EntityManager - unlike
findBy for instance -, but in calls done under the hood at a level which
would force us to override entire other classes to pass on our
permissionOptions. It is the case for methods which call typeORM's
EntityPersistExecutor for instance.), to validate permissions and then
allow the subsequent calls to be made without permission checks
3. adapt tests
---------
Co-authored-by: Charles Bochet <charles@twenty.com>
closes https://github.com/twentyhq/core-team-issues/issues/1076
## Problem
When opening a workflow run in the side panel and then navigating to the
full page view, the workflow visualizer tab wouldn't display until the
page was refreshed.
## Root Cause
- In the side panel, tabs are merged into a single "home" tab
- When navigating to full page, the activeTabId state persisted as
"home"
- But the full page view only has a "workflowRun"(flow) tab, not "home"
- TabList was trying to display a non-existent tab, resulting in blank
content
## Solution
Added validation in TabList to check if activeTabId exists in
visibleTabs. If not, it falls back to the first available tab.
# 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>
In this PR
1. adding tests on relations and nested relations to make sure that if
any permission is missing, the query fails
2. adding tests on objectRecord permissions to make sure that
permissions granted or restricted by objectPermissions take precedence
on the role's allObjectRecords permissions
Was looking into the Twenty ORM files and caught a camelCase typo which
is `workspaceEntityOrobjectMetadataName` to
`workspaceEntityOrObjectMetadataName` in two files
1. twenty-orm.manager.ts
2. twenty-orm-global.manager.ts
Co-authored-by: Raphaël Bosi <71827178+bosiraphael@users.noreply.github.com>
This PR improves the sub-field selection UX in advanced filters.
- Now using the icon of the field instead of the field type
- Now using the label of the field instead of the field type
- Removed now useless constant ICON_NAME_BY_ANY_SUB_FIELD
- Now selects a default value (any or default sub-field for type) when
clicking on the field, instead of waiting for the user to select the
sub-field
Fixes https://github.com/twentyhq/core-team-issues/issues/1005
Closes#12361
### Changes Made
- In `ActivityTargetsInlineCell`, we now use different component
instance IDs based on context. This ensures that each instance of the
component (whether in right drawer or main view) has its own isolated
state, preventing state conflicts and duplicate dropdowns.
- The `MultipleRecordPicker` component now properly resets its state
when closed, preventing state leakage between instances.
https://github.com/user-attachments/assets/deb99687-a803-417e-a339-cab061026739
Description:
Resolved a bug where pressing the Escape key did not clear the filter
chips when no filter value was present.
Added a call to onClickOutside inside the useScopedHotkeys hook to
ensure filter chips are removed when Escape is pressed and the dropdown
is open but empty.
https://github.com/user-attachments/assets/42ed35b0-f5a8-4d26-8407-fdd5e2cc4a42fix#12319
We must separate the concept of hydratation which happens at the request
level (take the token and pass auth/user context), from the concept of
authorization which happens at the query/endpoint/mutation level.
Previously, hydratation exemption happened at the operation name level
which is not correct because the operation name is meaningless and
optional. Still this gave an impression of security by enforcing a
blacklist. So in this PR we introduce linting rule that aim to achieve a
similar behavior, now every api method has to have a guard. That way if
and endpoint is not protected by AuthUserGuard or AuthWorspaceGuard,
then it has to be stated explicitly next to its code.
---------
Co-authored-by: Charles Bochet <charles@twenty.com>
BlocknoteJS requires an ESM module where our server is CJS, this forced
us to pin the server-util version, which led us to force the resolution
of several packages, leading to bugs downstream.
From Node 22.12 Node supports requiring ESM modules (available from Node
22.0 with a flag). So I upgrade the module.
I picked Node 22 and not Node 23 or Node 24 because 22 is the LTS and we
don't plan to change node versions frequently.
If you remain on Node 18, things should still mostly work, except if you
edit a Rich Text field.
I also starting changing the default runtime for Serverless Functions
which isn't directly related. This means new serverless functions will
be created on Node 22, but we will still need another PR to migrate
existing serverless functions before September (end of support by AWS).
(In this PR I also remove the upgrade commands from 0.43 since they rely
on Blocknote and I didn't want to have to deal with this)
---------
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
First PR to add filters to send records. Lot of work left, but I want to
split. I mainly want to validate the architecture there.
https://github.com/user-attachments/assets/63375a75-ba88-49df-8c12-5e3e58de5342
TODO in next PRs:
- fix design
- make filters reliable. Some composite fields are not implemented and
some fields like datetime do not work well
- improve typing
ressolve #12205
This PR fixes the issue where the record in the command menu was
reopening when clicking the same field again.
https://github.com/user-attachments/assets/52da7b3f-4704-4a9c-8fc4-29534568b0c0
- Added recordId to cells so it can be accessed when
useListenClickOutside is triggered, and compared the previous recordId
with the new one to prevent closing the command menu for the same
record.
- When the field is clicked, we compare the lastRecordId with the new
recordId inside the openRecordInCommandMenu function to avoid reopening
the menu unnecessarily.
---------
Co-authored-by: Charles Bochet <charles@twenty.com>
# Indexes
### TLDR:
Putting indexes back, except relation ones
### Details:
- Added index synchronization logic back (it was removed previously in
45d4845b26)
in the sync-metadata service.
- for unique inedexes, a command will create unicity again by handling
duplicates that were cretated since the
45d4845b26
was triggered
# Integration test failing
- fix the local run by renaming folder in the jest configuration.
Otherwise "clickhouse" tests were failing
- falsy test introduced 2 days ago in
https://github.com/twentyhq/twenty/pull/12271/files
Fixes an infinite loop introduced by #12371
An infinite loop was triggered when there was an error when fetching the
client config.
Cause of the bug: `isLoadedOnce` wasn't set to true when catching an
error in `useClientConfig`.
This effect then created an infinite loop inside
`ClientConfigProviderEffect` because `fetchClientConfig` updated
`clientConfigApiStatus.isLoading` but not `isLoadedOnce`.
```typescript
useEffect(() => {
if (
!clientConfigApiStatus.isLoadedOnce &&
!clientConfigApiStatus.isLoading
) {
fetchClientConfig();
}
}, [
clientConfigApiStatus.isLoadedOnce,
clientConfigApiStatus.isLoading,
fetchClientConfig,
]);
```