Commit Graph

53 Commits

Author SHA1 Message Date
Paul Rastoin 987995636f Sync metadata store after view child entity mutations server response (#23150)
## Summary

- View persist hooks
(`usePerformView(Sort|Field|Filter|Group|FieldGroup|FilterGroup|)APIPersist`)
now write successful mutation results back to the metadata store
(`addToDraft` / `updateInDraft` / `removeFromDraft` + `applyChanges`),
following the existing pattern from `usePerformViewAPIUpdate`.
- Previously the store only updated via SSE, so until that landed, save
flows diffed against stale view data and re-sent creates with the same
id — failing server-side with a duplicate key error.

Fixes TWENTY-SERVER-HQM
2026-07-22 19:05:22 +02:00
Weiko 25bd2897a3 Add weekly layout to record calendar (#22819)
## Summary

- Add a week layout to record calendar views and persist the selected
layout.
- Render `DATE` calendars as an all-day week and `DATE_TIME` calendars
as an hourly week.
- Add an optional end date field across calendar configuration,
metadata, persistence, and complete-view upserts.
- Use configured end values for ranged and multi-day events, with a
one-hour fallback when a `DATE_TIME` end is absent or invalid.
- Keep calendar cards consistent with the existing compact view,
including checkbox selection and whole-card record opening.
- Gate the weekly layout and end-date behavior behind the public Labs
`IS_CALENDAR_WEEK_VIEW_ENABLED` workspace feature flag.

## Week interactions

- Show overlapping timed events side by side and cap the visible records
at two per day.
- Display start and end times on timed cards, enforce a readable
30-minute minimum height, and keep today’s text contrast stronger.
- Drag timed events between days and times with 30-minute snapping while
preserving their duration, including zero-duration events.
- Show a create button when hovering a 30-minute slot; keyboard users
can focus a day, move the slot with the arrow keys, and reach the same
contextual action.
- Initialize new records with the selected slot time and a compatible
writable end value one hour later.
- Show the workspace time zone and current-time indicator in timed
weeks; date-only weeks keep the all-day section without an hourly grid.

## Configuration and data loading

- Only allow end fields that match the start field type, and prevent
selecting the same field for both boundaries.
- Load records whose ranges overlap the visible period so month and week
layouts display the same relevant records.
- Resolve and persist calendar end fields when updating existing views
through `upsert_complete_view`.
- Fall back to Month and ignore the configured end field while the flag
is disabled, without overwriting either persisted setting, so
re-enabling restores the previous configuration.
- Expose the flag in Labs and keep it default-off for workspaces without
a stored value; enable it in the development seeder.

<img width="1285" height="808" alt="Screenshot 2026-07-15 at 15 50 17"
src="https://github.com/user-attachments/assets/b7e3f7f1-ca77-492f-8cce-cca186ebca0b"
/>
2026-07-15 16:30:18 +02:00
Félix Malfait 23f5ba9ebf feat: add resizable kanban column width (#21828)
## What & why

Lets users resize the columns of a Kanban (record board) view. Requested
by a user; the design avoids the "ragged board" problem by making the
width a **single shared value**.

## Behaviour

- A drag handle appears on the right edge of every column header.
- Because all columns read **one** width value, dragging any handle
resizes **every** column together — they can never end up mismatched.
- Width is clamped between **150px** and **400px** (default **200px**).
- The width is **persisted per view** and restored on reload.

## Approach

**Backend** — a new nullable `View.kanbanColumnWidth` field, threaded
through the existing view-level setting pattern (the same one
`kanbanAggregateOperation` / `shouldHideEmptyGroups` use), so it gets
create/update/manifest/override support for free:
- entity column + `ViewOverrides` + `@WasIntroducedInUpgrade`
- `CreateViewInput` / `UpdateViewInput` (`Int`, `@Min(150)`/`@Max(400)`)
+ `ViewDTO`
- flat-view editable properties, entity-properties config, compare-type,
standard-view + manifest converters
- a fast instance command adding the `core.view` column

**Frontend** — the value hydrates into a view-scoped atom and drives a
single CSS variable set on the board container, which both column
headers and bodies read. Live dragging only writes that CSS variable (no
per-move React re-render); the final width is committed to the atom and
persisted via `updateView` on pointer-up.

## Nullability / defaults

`kanbanColumnWidth` is nullable — `null` means "never resized" and the
UI falls back to the 200px default, so existing rows need no backfill.

## Validation

- `nx typecheck twenty-server`  and `nx typecheck twenty-front` 
- `nx lint:diff-with-main twenty-server` ; frontend lint fixes applied
(split constants to one-per-file, removed `useRef`-for-state in favour
of `useState`).
- Draft pending a final green CI run (the dev container reclaimed
`node_modules` mid-session; re-running locally).

## Test plan

- [ ] Drag a kanban column edge → all columns resize together, clamped
150–400px
- [ ] Reload → width persists for that view; other views unaffected
- [ ] A view that was never resized still renders at 200px

https://claude.ai/code/session_016Qe6oDBkhVbrq2QkXBJ5nE

---
_Generated by [Claude
Code](https://claude.ai/code/session_016Qe6oDBkhVbrq2QkXBJ5nE)_

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/21828?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-06-19 15:58:13 +02:00
Félix Malfait 291ce5ccdb fix(filters): make filter dispatcher own relation-target resolution (#20670)
## Summary

Two relation-traversal bugs surfaced post-merge of #20533, both rooted
in the same architectural smell: the GraphQL filter dispatcher took a
flat `fields: FieldShared[]` array and silently dropped any filter whose
`relationTargetFieldMetadataId` wasn't in that array. Callers had to
remember to pre-augment the list with relation targets — and 16+ call
sites did not all know this.

This PR fixes both bugs and removes the smell.

### Bug 1 — Save as new view loses the relation target

`useCreateViewFromCurrentView` built the create-filter input without
`relationTargetFieldMetadataId`. The saved view's filter persisted
without the traversal — on reload the chip showed "Company contains
'air'" instead of "Company → Name contains 'air'". Discarded at save
time, not at read time.

Fix: include `relationTargetFieldMetadataId` in the create input.
(Commit 1.)

### Bug 2 — Workflow Search Records drops one-hop traversals

`FindRecordsWorkflowAction` built its fields list from
`flatObjectMetadata.fieldIds` only (source object's fields). The shared
dispatcher then couldn't resolve the relation target field on the
related object and silently dropped the filter — a configured "People
where Company → Name Contains 'Airbnb'" came through as `{ and: [] }`.

This was the same shape as bugs already fixed in 5 other call sites
(chart filters, view filters, record table, etc.). The pattern was:
caller forgets to augment fields → dispatcher silently drops the filter.

Fix (commit 2): change the dispatcher to take a
`findFieldMetadataItemById: (id) => FieldShared | undefined` resolver
callback. Both source-field and relation-target-field lookups go through
the same resolver, so callers no longer need to know about the
augmentation requirement. Frontend callers pass a workspace-wide
resolver built from `flattenedFieldMetadataItemsSelector`; server
callers wrap `findFlatEntityByIdInFlatEntityMaps` on
`flatFieldMetadataMaps`. In both cases relation-target lookups just
work, because the resolver can see fields on related objects.

## Why this matters

Before: "if you call the dispatcher, pre-augment your fields list with
relation targets, or filters get silently dropped." An invariant only
enforceable by code review, broken often enough to ship two user-visible
bugs in one week.

After: the dispatcher resolves field ids itself. There's no list to
forget to augment. The failure mode (filter silently dropped) becomes
structurally impossible at the dispatcher boundary.

Net diff: 240 insertions, 319 deletions. Removed
`augmentFieldsWithRelationTargets` (frontend) and the workflow
whack-a-mole code (server).

## Test plan
- [ ] Save view: create an advanced filter using a one-hop relation
traversal, click "Save as new view", reload, confirm the chip still
reads "Source → Target operator value"
- [ ] Workflow: configure a Search Records action with a
relation-traversal filter, run the workflow, confirm the filter is
actually applied
- [ ] Dashboard chart: configure a chart with a relation-traversal
filter, confirm the chart data respects it
- [ ] Record table, group-by, calendar, total count, footer aggregates:
all continue to work with both plain and relation-traversal filters
2026-05-19 11:55:22 +02:00
Charles Bochet 5c745059ad refactor: remove "core" naming from views and eliminate converter layer (#18667)
## Summary

- **Remove all "core" prefixes** from the views system — the
metadata-based storage migration is complete, so `CoreView`,
`coreViewsSelector`, `getCoreViews`, etc. are now just `View`,
`viewsSelector`, `getViews`
- **Eliminate the entire converter layer** (15 files, ~850 lines
deleted) — `convertCoreViewToView` and all sub-converters were either
no-ops or trivially adding `__typename` / mapping identical enum values.
Local enums now re-export from generated GraphQL types directly (single
source of truth)
- **Unify `View` and `ViewWithRelations`** into one type —
`ViewWithRelations` is now a type alias for `View`, selectors return
data directly without conversion

### Backend
- Rename `@ObjectType('CoreView')` → `@ObjectType('View')` (and all
sub-entities)
- Rename resolver methods: `getCoreViews` → `getViews`, `createCoreView`
→ `createView`, etc.
- Rename `FIND_ALL_CORE_VIEWS_GRAPHQL_OPERATION` →
`FIND_ALL_VIEWS_GRAPHQL_OPERATION`

### Frontend
- Delete 15 converter files (`convertGqlView*ToView*`,
`convertView*ToGql`, `convertViewWithRelationsToView`)
- Re-export `ViewType`, `ViewKey`, `ViewFilterGroupLogicalOperator` from
generated enums (no more duplicate enum definitions with different
casing)
- Replace `ViewOpenRecordInType` with `ViewOpenRecordIn` from generated
- Remove `__typename` from all local view sub-types
- Remove unused `variant` from `ViewFilter`, make `displayValue` and
`definition` optional
- Rename ~45 GraphQL query/mutation files and all selectors to drop
"core" prefix
- Delete unused `viewsWithRelationsSelector`
2026-03-16 09:57:18 +01:00
Charles Bochet ba9aa41bba refactor: metadata store cleanup, SSE unification, mock metadata loading & login redirect fix (#18651)
## Summary
- **SSE unification**: Replaced 11 individual SSE effect components with
a single generic `MetadataStoreSSEEffect`
- **Metadata store cleanup**: Merged `metadataCollectionHashesState`
into `metadataStoreState` (currentCollectionHash / draftCollectionHash
per entity), moved `objectMetadataItemsSelector` to `object-metadata`
domain, converted `navigationMenuItemsState` to a derived selector
- **Naming clarity**: Renamed `isAppMetadataReadyState` →
`isMinimalMetadataReadyState`, `MetadataGater` → `MinimalMetadataGater`,
`useIsLogged` → `useHasAccessTokenPair`,
`patchMetadataStoreFromSSEEvent` now takes named object params
- **Mock metadata loading**: Added `generate-navigation-menu-items.ts`
script, rewrote `useLoadMockedMinimalMetadata` to load full
objects/fields/indexes/views/navItems from generated mock data, enabling
proper sign-in background rendering (table columns, view picker,
navigation)
- **Login/logout transitions**: `MinimalMetadataLoadEffect` manages
mocked↔real metadata transitions based on auth state,
`MainContextStoreProvider` computes context on auth pages for view
picker support
- **Login redirect fix**: `handleLoadWorkspaceAfterAuthentication` now
re-enables `isAppEffectRedirectEnabled` after `loadCurrentUser()`
completes, fixing the blocked post-login navigation
- **Dead code removal**: Deleted `useRefreshPageLayouts`,
`useApplyPageLayouts`, `useStaleMetadataEntities`,
`metadataCollectionHashesState`, and all individual SSE effects

## Test plan
- [x] Login from welcome page redirects to companies page
- [x] Logout transitions cleanly to mocked metadata on welcome page
- [x] Sign-in background shows table columns, view picker, and
navigation items
- [x] SSE events still update metadata store entries correctly
- [x] Navigation menu items persist across page refreshes
- [ ] CI: lint, typecheck, tests pass
2026-03-16 00:38:11 +01:00
BOHEUS c97d872b9f [BREAKING_CHANGE_VIEW_SORT] Refactor view sort to v2 (#17609)
Fixes https://github.com/twentyhq/core-team-issues/issues/2187

---------

Co-authored-by: prastoin <paul@twenty.com>
Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
2026-03-04 12:48:58 +00:00
Charles Bochet d81f006979 Rename Jotai state hooks and utilities to consistent Atom-based naming (#18209)
## Summary

Rename all Jotai-based state management hooks and utilities to a
consistent naming convention that:
1. Removes legacy Recoil naming (`useRecoilXxxV2`, `createXxxV2`)
2. Always includes `Atom` in the name to distinguish from jotai native
hooks
3. Follows a consistent ordering: `Atom` → `Component` → `Family` →
`Type` (`State`/`Selector`)
4. Includes the type qualifier (`State` or `Selector`) in all
value-reading hooks to avoid naming conflicts with jotai's native
`useAtomValue`

## Naming Convention

**Hooks**:
`use[Set]Atom[Component][Family][State|Selector][Value|State|CallbackState]`
**Utils**: `createAtom[Component][Family][State|Selector]`

## Changes

### Hooks renamed (definition files + all usages across ~1,500 files):

| Old Name (Recoil) | Intermediate (Atom) | Final Name |
|---|---|---|
| `useRecoilValueV2` | `useAtomValue` | **`useAtomStateValue`** |
| `useRecoilStateV2` | `useAtomState` | `useAtomState` |
| `useSetRecoilStateV2` | `useSetAtomState` | `useSetAtomState` |
| `useFamilyRecoilValueV2` | `useFamilyAtomValue` |
**`useAtomFamilyStateValue`** |
| `useSetFamilyRecoilStateV2` | `useSetFamilyAtomState` |
**`useSetAtomFamilyState`** |
| `useFamilySelectorValueV2` | `useFamilySelectorValue` |
**`useAtomFamilySelectorValue`** |
| `useFamilySelectorStateV2` | `useFamilySelectorState` |
**`useAtomFamilySelectorState`** |
| `useRecoilComponentValueV2` | `useAtomComponentValue` |
**`useAtomComponentStateValue`** |
| `useRecoilComponentStateV2` | `useAtomComponentState` |
`useAtomComponentState` |
| `useSetRecoilComponentStateV2` | `useSetAtomComponentState` |
`useSetAtomComponentState` |
| `useRecoilComponentFamilyValueV2` | `useAtomComponentFamilyValue` |
**`useAtomComponentFamilyStateValue`** |
| `useRecoilComponentFamilyStateV2` | `useAtomComponentFamilyState` |
`useAtomComponentFamilyState` |
| `useSetRecoilComponentFamilyStateV2` |
`useSetAtomComponentFamilyState` | `useSetAtomComponentFamilyState` |
| `useRecoilComponentSelectorValueV2` | `useAtomComponentSelectorValue`
| `useAtomComponentSelectorValue` |
| `useRecoilComponentFamilySelectorValueV2` |
`useAtomComponentFamilySelectorValue` |
`useAtomComponentFamilySelectorValue` |
| `useRecoilComponentStateCallbackStateV2` |
`useAtomComponentStateCallbackState` |
`useAtomComponentStateCallbackState` |
| `useRecoilComponentSelectorCallbackStateV2` |
`useAtomComponentSelectorCallbackState` |
`useAtomComponentSelectorCallbackState` |
| `useRecoilComponentFamilyStateCallbackStateV2` |
`useAtomComponentFamilyStateCallbackState` |
`useAtomComponentFamilyStateCallbackState` |
| `useRecoilComponentFamilySelectorCallbackStateV2` |
`useAtomComponentFamilySelectorCallbackState` |
`useAtomComponentFamilySelectorCallbackState` |

### Utilities renamed:

| Old Name (Recoil) | Final Name |
|---|---|
| `createStateV2` | **`createAtomState`** |
| `createFamilyStateV2` | **`createAtomFamilyState`** |
| `createSelectorV2` | **`createAtomSelector`** |
| `createFamilySelectorV2` | **`createAtomFamilySelector`** |
| `createWritableSelectorV2` | **`createAtomWritableSelector`** |
| `createWritableFamilySelectorV2` |
**`createAtomWritableFamilySelector`** |
| `createComponentStateV2` | **`createAtomComponentState`** |
| `createComponentFamilyStateV2` | **`createAtomComponentFamilyState`**
|
| `createComponentSelectorV2` | **`createAtomComponentSelector`** |
| `createComponentFamilySelectorV2` |
**`createAtomComponentFamilySelector`** |

## Details

- All definition files renamed to match new convention
- All import paths and usages updated across the entire `twenty-front`
package
- Jotai's native `useAtomValue` is aliased as `useJotaiAtomValue` in the
wrapper hook to avoid collision
- Legacy Recoil files in `state/utils/` and `component-state/utils/`
left untouched (separate naming scope)
- Typecheck passes cleanly
2026-02-25 01:55:46 +01:00
Charles Bochet eaf9fe27b2 Improve Jotai work (#18205) 2026-02-24 20:38:30 +01:00
Charles Bochet 0f2af6a6cb Jotai 13 (#18178)
## Recoil to Jotai Migration — PR 13: Workflow, Page Layout, AI,
Activities, Settings, SSE & Remaining Modules

### Summary

This is the 13th PR in the [14-PR migration
series](packages/twenty-front/src/modules/ui/utilities/state/jotai/MIGRATION_PLAN.md)
to replace Recoil with Jotai as the state management library in
`twenty-front`. This PR migrates the remaining consumer code across all
modules — updating ~1,076 files with ~10k insertions/deletions.

### What changed

**New Jotai infrastructure (13 new files):**
- `createComponentSelectorV2` and `createComponentFamilySelectorV2` —
instance-scoped derived atoms, replacing Recoil's component selectors
- 6 new hooks: `useRecoilComponentSelectorValueV2`,
`useRecoilComponentFamilySelectorValueV2`,
`useRecoilComponentSelectorCallbackStateV2`,
`useRecoilComponentFamilySelectorCallbackStateV2`,
`useRecoilComponentStateCallbackStateV2`,
`useRecoilComponentFamilyStateCallbackStateV2`
- New types: `ComponentSelectorV2`, `ComponentFamilySelectorV2`,
`SelectorCallbacksV2`
- Extended `buildGetHelper` to support the new selector patterns

**State definition migrations:**
- `createState()` → `createStateV2()` (Jotai `atom()`)
- `createFamilyState()` → `createFamilyStateV2()` (Jotai `atom()` with
family cache)
- Recoil `selector`/`selectorFamily` → Jotai derived `atom()` via V2
utilities

**Hook migrations (~2,400 removed, ~1,545 added V2 equivalents):**
- `useRecoilValue` → `useRecoilValueV2`
- `useRecoilState` → `useRecoilStateV2`
- `useSetRecoilState` → `useSetRecoilStateV2`
- `useRecoilCallback` → `useCallback` + `jotaiStore.get/set`
- `useRecoilComponentValue` → `useRecoilComponentValueV2`
- `useSetRecoilComponentState` → `useSetRecoilComponentStateV2`
- `useRecoilComponentFamilyValue` → `useRecoilComponentFamilyValueV2` /
`useFamilySelectorValueV2`
- ~397 direct `import from 'recoil'` removed

**Deleted files (9 files):**
- `dateLocaleState.ts` — consolidated
- `currentAIChatThreadTitleStateV2.ts` — renamed to replace the original
- `isCommandMenuOpenedState.ts` — removed
- `filesFieldUploadState.ts` — replaced by V2
- `recordStoreFamilySelector.ts`, `recordStoreFieldValueSelector.ts`,
`recordStoreRecordsSelector.ts` — replaced by V2 equivalents
- `settingsAllRolesSelector.ts` — replaced by `useSettingsAllRoles` hook
- `settingsRoleIdsStateV2.ts` — consolidated

**Modules migrated:**
- Workflow (diagram, steps, variables, filters)
- Page Layout (widgets, fields, graph, tabs)
- AI (chat, agents, browsing context)
- Activities (rich text editor, targets, timeline)
- Action Menu (single/multiple record actions)
- Command Menu (navigation, history, pages, workflow)
- Context Store
- Record Board, Record Table, Record Calendar, Record Index
- Record Field, Record Filter, Record Sort, Record Group
- Record Drag, Record Picker, Record Store
- Views (view bar, view picker, filters, sorts)
- Settings (roles, permissions, SSO, security, data model, developers,
domains)
- SSE (event streams, subscriptions)
- Spreadsheet Import
- Auth, Favorites, Front Components, Information Banner
2026-02-24 17:37:01 +01:00
Charles Bochet b51eb6471f Jotai 12 (#18160)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-23 12:01:37 +01:00
Lucas Bordeau e9b7ad21d2 Fix view picker small bugs (#16987)
This PR solves small bugs around the view picker.

- Couldn’t obtain optimistic update after a re-order of a view by drag
and drop, we needed to refresh the page
- Picking a new icon wouldn’t trigger optimistic update (same problem)
- Picking a new icon would change the view (difficult to understand
behavior)
- Picking a new icon would trigger left drawer collapse (z-index
problem)

Since core views are not being handled by object metadata items anymore,
and that all view logic is plugged on coreViewsState, this PR
implemented optimistic effect by upserting into this state.

Fixes https://github.com/twentyhq/twenty/issues/15422
Fixes https://github.com/twentyhq/twenty/issues/16986

# Before


https://github.com/user-attachments/assets/64099c21-df9f-4772-ab0d-9ea449aed761

# After


https://github.com/user-attachments/assets/f4e844b3-6530-4178-abdb-b7a10d2327b8

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2026-01-08 12:05:45 +01:00
Marie 86df188e83 [fix] Fix switch view type from "Layout" switcher (#16382)
In this previous work aiming at eliminating the creation of viewGroups
being separated from the views, I removed the creation of viewGroups
from the FE at view creation, but forgot to do it at view update when
the user chooses "change Layout" option (from Table/Kanban/Calendar to
another).

In this PR
- I removed creation, deletion and destroy of viewGroups from
usePersistViewGroupRecords. I left update because it useful for
visibility and position
- since usePersistViewGroups record was also handling optimistic, I
moved optimistic logic to a new hook useViewsSideEffectsOnViewGroups. I
realized that so far we optimistic is only useful for creation. For the
update though we do need to compute the view groups that will be created
to be able to call loadRecordIndexState, so I created a function for
that, but I did not seek to perform real optimistic, with writing and
deleting groups from the cache as it was a bit heavier and not in use
for now and I want to merge this asap as it fixes the creation of
viewGroups.
2025-12-08 15:05:05 +01:00
Marie 7ce22d5c7e breaking (soft) - Migrate viewGroup.fieldMetadataId -> view.mainGroupByFieldMetadataId (2/3) (#16277)
Should be merged once https://github.com/twentyhq/twenty/pull/16206 has
been released + command run to prod

In this PR
- Remove usage of viewGroup.fieldMetadataId, both in BE and FE states. 
- But we still need to properly populate it until we fully remove
viewGroup.fieldMetadataId from db and ORM entity (upcoming 3rd PR out of
3). fieldMetadataId was removed from CoreViewGroup type and
CreateViewGroupInput and is determined BE-side based on the associated
view's mainGroupByFieldMetadataId. **I expect this means a downtime on
viewGroup creation, until both FE and BE are deployed and cache is
flushed.** This seems acceptable to me as it only regards viewGroup
creation.
    - this information is replaced by view.mainGroupByFieldMetadataID
- Handle view group creation, update and deletion in the BE as a
side-effect of a view creation, update or deletion. Optimistic effects
are still used
- Add validation at view creation or update regarding
mainGroupByFieldMetadata

Left to do in 3rd PR
- Remove viewGroup.fieldMetadataId from db and ORM entity
- Restore feature allowing to update an existing grouped view's group by
field (already OK on BE side but need to rebuild FE optimistic)
2025-12-05 14:00:03 +00:00
Marie 77409b6eb2 [Requires "warm" cache flush (no immediate downtime before flush)] Migrate viewGroup.fieldMetadataId -> view.mainGroupByFieldMetadataId (1/3) (#16206)
In this PR (1/3)
- introduce view.mainGroupByFieldMetadataId as the new reference
determining which fieldMetadataId is used in a grouped view, in order to
deprecate viewGroup.fieldMetadataId which creates inconsistencies.
view.mainGroupByFieldMetadataId is now filled at every view creation,
though not in use yet.
- Introduce a command to backfill view.mainGroupByFieldMetadataId for
existing views + delete all viewGroup.fieldMetadataId with a
fieldMetadataId that is not view.mainGroupByFieldMetadataId. (It should
concern 37 active workspaces)
- Temporarily disable the option to change a grouped view's
fieldMetadataId as for now it creates inconsistencies. This feature can
be reintroduced when we have done the full migration.

In a next PR
- (2/3) use view.mainGroupByFieldMetadataId instead of
viewGroup.fieldMetadataId. In FE we may keep viewGroup.fieldMetadataId
as a state (TBD). View groups will now be created / deleted as a side
effect of view's mainGroupByFieldMetadataId update.
- (3/3) remove viewGroup.fieldMetadataId

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2025-12-02 16:31:07 +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
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
Paul Rastoin a3dc6e5c59 View field create many mutation (#15576)
# Introduction
When creating a 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 field here
closing https://github.com/twentyhq/core-team-issues/issues/1836

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

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

## Polish
- use persist view field is quite verbose as contains two data model we
could aim to create an update many view fields in order to standardize
new pattern
2025-11-04 11:36:08 +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
Paul Rastoin 85a570db6b Fix view group operation by not sending __typename (#15092)
Following https://github.com/twentyhq/twenty/pull/15052
2025-10-14 18:16:20 +02:00
Paul Rastoin 7d747c9876 [REQUIRES_CACHE_FLUSH][GQL_VIEW_GROUP_API_BREAKING_CHANGE] ViewGroup in v2 (#15052)
# Introduction
Adding view-group to core engine v2
Following https://github.com/twentyhq/twenty/pull/15010 ( same pattern )

## What's done
- Created flat-view-group
- flat view group runner
- flat view group builder
- create view group service v2 and input transpilers
- refactor the existing view group resolver to fix standard (
BREAKING_CHANGE on graphql api update especially ) REST stays the same
- refactored the front to consume the mutations autogenerated

close https://github.com/twentyhq/core-team-issues/issues/1665
2025-10-14 15:55:50 +02:00
Paul Rastoin 651ab184a7 [GQL_VIEW_FILTER_API_BREAKING_CHANGE][WHEN_RELEASED_REQUIRES_CACHE_FLUSH] ViewFilter migration to workspace migration v2 (#15010)
# Introduction
Migrating `viewFilter` to v2 in order to migrate later the field update
side effect on view to v2 too

## What's done
- Created flat-view-filter
- flat view filter runner
- flat view filter builder
- create view filter service v2 and input transpilers
- refactor the existing view filter resolver to fix standard (
BREAKING_CHANGE on graphql api update especially ) REST stays the same
- refactored the front to consume the mutations autogenerated

## New generic tools
### Compare two flat entity
Introducing a new util to compare two flat entity, it's strictly typed
and will be added to the generic builder in a following PR
This will ease flat entity addition as won't required to create a
specific abstraction for comparison
Generic builder will expect specific constant: properties to compare and
properties to stringify

### Transform flat entity for comparison
Forked and refactor the initial existing method for flat entity business
scope and type safety

## Coverage
Migrated existing integration tests to fit new contract API
This PR does not add strong coverage on validation exceptions
Deadlines are too short

close https://github.com/twentyhq/core-team-issues/issues/1666
2025-10-10 15:02:14 +02:00
Paul Rastoin f13cbad5af View field creation through view creation unique id for migrated view (#14501) 2025-09-15 15:57:46 +02:00
Weiko eada8e2567 Add calendar field metadata id to view table (#14478) 2025-09-15 09:17:17 +02:00
Weiko a81eb854d1 Add calendar view type in picker (#14477) 2025-09-14 17:46:42 +02:00
Charles Bochet 72da21217f Deprecate ViewSort typing (#14476)
Continuing the work to deprecate the old ViewSorts and leverage types
that are available in graphql.tsx codegen as we have migrated views to
codegen
2025-09-14 17:17:35 +02:00
Paul Rastoin c8bfbf00d7 [CoreViewField BREAKING_CHANGES] Refactor view field service v2 and resolver (#14396)
## Introduction

### Twenty-sever

Standardizing resolver input and transpilation models + return type on
destroy and delete
~~Finally~~ Did plug everything under a feature flag and add coverage
Next will do same for the view resolver and service v2

### Twenty-front
Refactored view field service in order to use codegenerated strictly
typed mutations and adapt to new api contract
2025-09-11 15:25:36 +00:00
Charles Bochet 002322c8e3 Rename prefetchViewStates in coreViewStates (#14373)
## Context

View system used to rely on workspaceSchema views and was loaded in what
we called the "prefetch". We have recently migrated views to
core.coreViews and the states should now be named after coreViews

Fixes: https://github.com/twentyhq/twenty/issues/14349
2025-09-09 19:11:17 +02:00
nitin c4f56156d6 Translations - FIX - views not being refreshed on locale change (#14207)
as per title
2025-09-02 14:00:40 +02:00
Charles Bochet 988f6ee1fa Remove old view implementation step 1 (#14189)
Let's move forward and get rid of the past... !

Removing prefetchViewState and the prefetch view query.

Next steps:
- renaming Selectors to remove prefetch keywork
- remove old view type and coreViewToView util
- rework optimistic rendering for coreViews
2025-09-01 10:25:16 +02:00
Raphaël Bosi 0bdd1c4803 Various fixes on core views (#14093)
- Fix fragments
- Add id to create inputs
- Refresh core views
- Fix kanban loading
- Fix core views creation from current view

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2025-08-29 11:20:56 +02:00
Weiko dff00e813c Add coreView state in FE (#14034)
Co-authored-by: bosiraphael <raphael.bosi@gmail.com>
Co-authored-by: Raphaël Bosi <71827178+bosiraphael@users.noreply.github.com>
2025-08-25 15:49:21 +02:00
Raphaël Bosi 30c42345f0 Core views frontend (#13932)
Parallel code path to read and write core views when
IS_CORE_VIEW_ENABLED.

Migrated view key to an enum.

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
2025-08-20 19:04:58 +02:00
Félix Malfait 464a480043 Continue ESLINT9 Migration (#13795)
Might already fix #13793
2025-08-10 23:25:58 +02:00
Lucas Bordeau de802b1447 Removed all v2 in naming of state management logic (#13675)
This PR removes any V2 naming in state management logic and some minor
utils and hooks.

It has a lot of changes but nearly all of them were made by the rename
functionality of vscode which is deterministic, so it shouldn't
introduce any regression.

QA has been made on this PR on the main features of the app without any
noticeable issue.

Also renamed some other v2 naming related items : 
- TextInputV2 => TextInput
- TextInput => SettingsTextInput
- ObjectFilterDropdownFilterSelectMenuItemV2 =>
ObjectFilterDropdownFilterSelectMenuItem
- useInitDraftValueV2 => useInitDraftValue
- useOpenRecordTableCellV2 => useOpenRecordTableCell
2025-08-06 12:09:15 +02: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
Lucas Bordeau d468c3dc84 Add ability to save any field filter to view (#13401)
This PR adds the ability to save an any field filter to a view.

It adds a new `anyFieldFilterValue` on both core view and workspace view
entities.

It also introduces the necessary utils that mimic the logic that manages
the save of record filters and record sorts on views.
2025-07-24 10:08:16 +00:00
Thomas Trompette 2d6d5bf7d6 Prevent workflows to be opened in side panel (#12738)
Workflow views and versions are seed being opened by default into record
page. Issue is that:
- new views are set by default to side panel. Updated by copying the
current opensIn value to the new view
- users can still select side panel into their options. Disabling the
button.

<img width="650" alt="Capture d’écran 2025-06-19 à 16 15 34"
src="https://github.com/user-attachments/assets/0ddc3284-0fed-404f-9c1d-225c65549fd1"
/>
2025-06-19 15:09:56 +00:00
Charles Bochet f3a8b849aa Fix table loading (#12653)
As per title
2025-06-17 15:01:28 +02: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
Lucas Bordeau 911647a279 Fix many bugs on advanced filters for CRUD to work (#10772)
This PR fixes many bugs on advanced filters, the goal here was to have
CRUD working with other simple filters and sorts.

In order to test this PR you'll have to run a sync metadata.

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

## Changed positionInViewFilterGroup field metadata type 

This PR changes the type of positionInViewFilterGroup to NUMERIC instead
of POSITION, there certainly was a confusion during the initial
development, where POSITION type seemed relevant but it is not for this
particular feature because the position in a view filter group is not
the position of a record, which is used for displaying and re-ordering
purpose in table and kanban views.

Here the positionInViewFilterGroup is a specific position concept tied
to a custom feature, and it is handled by the specific logic of this
advanced filter dropdown layout.

## Create new ids when duplicating a view

When we use create view from an existing view, the logic in
useCreateViewFromCurrentView will copy over filters, filter groups and
sorts. The problem is that it copies it with the same ids, and that if
the backend manages somehow to create new ids, the ids that are put in
parentViewFilterGroupId are corresponding to the old filter groups not
the duplicated new ones.

So we had to create a map of old id => new id so that everything that
has to be sent to the backend for creation already has the same mapping
of parent id but with new ids generated by the frontend.

## Bug with creating a simple filter

We couldn't create a simple filter when advanced filters were set, this
was because of findDuplicateRecordFilterInNonAdvancedRecordFilters which
wasn't doing what it's naming tells, it wasn't filtering on simple
filters only before looking for duplicates.

## Clean code

- Use lastChildPosition directly from
useChildRecordFiltersAndRecordFilterGroups instead of drilling it down
- Refactored AdvancedFilterDropdownButton to extract the code lower
where it is really needed in AdvancedFilterChip
- Renamed a few View to Record naming where relevant
2025-03-12 10:23:41 +00:00
Lucas Bordeau aba20dae11 Implemented CRUD for view filter group and removed old states (#10590)
This PR implements CRUD for view filter groups with the new logic as
already done for view filters and view sorts.

It also completely removes the old combined view filter group states and
usage.

This PR is quite big but the impact is limited since it only changes
advanced filters module, which is under feature flag at the moment, and
it is already in a broken state so unusable, even if someone activates
the feature flag.
2025-03-04 13:16:02 +01:00
Lucas Bordeau 2247d3fa91 Clean record filter and record sort (#10466)
This PR removes what's left from record filter and record sort previous
logic to handle CRUD and state management with view.

So everything that is named combinedFilter and combinedSort is removed
here.

We implement currentRecordFilters and currentRecordSorts everywhere.

We also remove the event in a state onSortSelectComponentState. (a
pattern we want to avoid)
2025-02-25 14:03:30 +00:00
Charles Bochet fb42046033 Refacto views (#10272)
In this huge (sorry!) PR:
- introducing objectMetadataItem in contextStore instead of
objectMetadataId which is more convenient
- splitting some big hooks into smaller parts to avoid re-renders
- removing Effects to avoid re-renders (especially onViewChange)
- making the view prefetch separate from favorites to avoid re-renders
- making the view prefetch load a state and add selectors on top of it
to avoir re-renders

As a result, the performance is WAY better (I suspect the favorite
implementation to trigger a lot of re-renders unfortunately).
However, we are still facing a random app freeze on view creation. I
could not investigate the root cause. As this seems to be already there
in the precedent release, we can move forward but this seems a urgent
follow up to me ==> EDIT: I've found the root cause after a few ours of
deep dive... an infinite loop in RecordTableNoRecordGroupBodyEffect...

prastoin edit: close https://github.com/twentyhq/twenty/issues/10253

---------

Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
Co-authored-by: prastoin <paul@twenty.com>
2025-02-18 13:51:07 +01:00
Paul Rastoin c3c800b097 Post #10014 merged nitpicks followup (#10021)
## Only nitpicks
Method signature mutation from several to one record arg
Renamed a variable in map to fit related business logic

#10014 Followup
2025-02-05 14:28:17 +01:00
Paul Rastoin 7fd89678b7 [CHORE] Avoid isDefined duplicated reference, move it to twenty-shared (#9967)
# Introduction
Avoid having multiple `isDefined` definition across our pacakges
Also avoid importing `isDefined` from `twenty-ui` which exposes a huge
barrel for a such little util function

## In a nutshell
Removed own `isDefined.ts` definition from `twenty-ui` `twenty-front`
and `twenty-server` to move it to `twenty-shared`.
Updated imports for each packages, and added explicit dependencies to
`twenty-shared` if not already in place

Related PR https://github.com/twentyhq/twenty/pull/9941
2025-02-01 12:10:10 +01:00
Jérémy M d7da73f0ec feat: record group add new (#8925)
Fix #8757

This PR is adding the Add new button on view groups.
Also this PR fix an issue where the pending record can be draggable, and
is causing error.

<img width="1119" alt="Screenshot 2024-12-10 at 4 24 43 PM"
src="https://github.com/user-attachments/assets/4fd01e99-c85e-4a06-a733-cbf3cc32957d">

It also start to issues with the way we're using Context.
We're initializing pretty much all Context like this:

```typescript
export const RecordTableContext = createContext<RecordTableContextProps>(
   {} as RecordTableContextProps,
 );
```

This is causing issues when by mistake we use the context like this
outside the Provider hierarchy:

```typescript
const context = useContext(RecordTableContext);
```

This is going to fail silently, and all the context variables become
undefined...

To fix this I've introduced an util called `createRequiredContext`, this
one is returning an array containing the provider and the hook to
retrieve the context.
The context is initialized to undefined inside this utility, this way we
can check if the value has been initialized with the provider to check
if we're inside it. It'll throw an error if this one is used outside the
provider.
The return values are properly typed, so `undefined` is not added to the
value of the Context.

I'll create a followup ticket to use this new utility function, if
that's ok and replace it everywhere in the codebase.
We can also consider adding a eslint rule to warn about the use of
`createContext` directly.
2024-12-12 11:50:13 +01:00
Marie 2fc247cb21 Display and update aggregate queries in kanban views (#8833)
Closes #8752, #8753, #8754

Implements usage of aggregate queries in kanban views.

https://github.com/user-attachments/assets/732590ca-2785-4c57-82d5-d999a2279e92

TO DO

1. write tests + storybook
2. Fix values displayed should have the same format as defined in number
fields + Fix display for amountMicros

---------

Co-authored-by: Weiko <corentin@twenty.com>
2024-12-03 22:46:57 +01:00
Jérémy M ffd790c8fd fix: don't use previous view group state when creating a new view (#8370)
When creating a new view we don't want to use view-groups from previous
view.
2024-11-06 16:33:51 +01:00
Lucas Bordeau d46820472c Fix view filter creation on new view (#8199)
Wrong view was used for the creation from another view (source and
target view were inverted)
2024-10-31 12:44:20 +01:00