Commit Graph

16 Commits

Author SHA1 Message Date
Raphaël Bosi d0bc8b9ffe [DASHBOARDS] Move all the graph computing logic to the backend (#17189)
- Create resolvers for each type of charts which needs data
transformation after the group by operation: Bar Chart, Line Chart and
Pie Chart
- Move all the utils to the backend and refactored some into services

This allows all the computation to be done in the backend, improving
performances in the frontend.
2026-01-19 17:25:45 +00:00
Paul Rastoin fae6d0e262 Improve cleaning job (#17208)
# Introduction

Refactored the workspace deletion to dynamically iterate over all known
v2 syncable entities repos and delete all of them from child to parent
Exception for field metadata that we chunk delete in order to avoid
locking the core schema too long, it does not have an impact on perfs at
all ( neither plus or less ) Chunking by constraint within a transaction
is not necessary both does not cost more

## From 
30s for a workspace complete deletion
```ts
[Nest] 93244  - 01/16/2026, 10:24:52 PM     LOG [WorkspaceService] workspace WS_ID cache flushed
[Runner] Total execution: 26.290s // ( deleteAllObjectMetadatas v2 )
[Nest] 93244  - 01/16/2026, 10:25:22 PM     LOG [WorkspaceService] workspace WS_ID hard deleted
```

## To
3s !

```ts
[Nest] 65112  - 01/18/2026, 4:37:38 PM     LOG [DatabaseConfigDriver] [INIT] Config variables loaded: 0 values found in DB, 69 falling to env vars/defaults
[Nest] 65112  - 01/18/2026, 4:37:38 PM     LOG [CleanSuspendedWorkspacesCommand] IGNORING GRACE PERIOD - Cleaning 1 suspended workspaces
[Nest] 65112  - 01/18/2026, 4:37:38 PM     LOG [CleanerWorkspaceService] batchWarnOrCleanSuspendedWorkspaces running...
[Nest] 65112  - 01/18/2026, 4:37:38 PM     LOG [CleanerWorkspaceService] Processing workspace - 1/1
[Nest] 65112  - 01/18/2026, 4:37:38 PM     LOG [CleanerWorkspaceService] Destroying workspace Twenty Eng
[Nest] 65112  - 01/18/2026, 4:37:38 PM     LOG [WorkspaceService] workspace user workspaces deleted
[Nest] 65112  - 01/18/2026, 4:37:38 PM     LOG [WorkspaceService] workspace cache flushed
[Nest] 65112  - 01/18/2026, 4:37:38 PM     LOG [WorkspaceService] workspace: deleted 80 viewFilter record(s)
[Nest] 65112  - 01/18/2026, 4:37:38 PM     LOG [WorkspaceService] workspace: deleted 21 pageLayoutWidget record(s)
[Nest] 65112  - 01/18/2026, 4:37:38 PM     LOG [WorkspaceService] workspace: deleted 1515 viewField record(s)
[Nest] 65112  - 01/18/2026, 4:37:38 PM     LOG [WorkspaceService] workspace: deleted 91 index record(s)
[Nest] 65112  - 01/18/2026, 4:37:38 PM     LOG [WorkspaceService] workspace: deleted 66 roleTarget record(s)
[Nest] 65112  - 01/18/2026, 4:37:38 PM     LOG [WorkspaceService] workspace: deleted 174 viewGroup record(s)
[Nest] 65112  - 01/18/2026, 4:37:38 PM     LOG [WorkspaceService] workspace: deleted 1 agent record(s)
[Nest] 65112  - 01/18/2026, 4:37:38 PM     LOG [WorkspaceService] workspace: deleted 7 pageLayout record(s)
[Nest] 65112  - 01/18/2026, 4:37:38 PM     LOG [WorkspaceService] workspace: deleted 111 view record(s)
[Nest] 65112  - 01/18/2026, 4:37:38 PM     LOG [WorkspaceService] workspace: fieldMetadata chunk 1/15 - deleted 50 record(s)
[Nest] 65112  - 01/18/2026, 4:37:38 PM     LOG [WorkspaceService] workspace: fieldMetadata chunk 2/15 - deleted 50 record(s)
[Nest] 65112  - 01/18/2026, 4:37:38 PM     LOG [WorkspaceService] workspace: fieldMetadata chunk 3/15 - deleted 50 record(s)
[Nest] 65112  - 01/18/2026, 4:37:38 PM     LOG [WorkspaceService] workspace: fieldMetadata chunk 4/15 - deleted 50 record(s)
[Nest] 65112  - 01/18/2026, 4:37:38 PM     LOG [WorkspaceService] workspace: fieldMetadata chunk 5/15 - deleted 50 record(s)
[Nest] 65112  - 01/18/2026, 4:37:38 PM     LOG [WorkspaceService] workspace: fieldMetadata chunk 6/15 - deleted 50 record(s)
[Nest] 65112  - 01/18/2026, 4:37:38 PM     LOG [WorkspaceService] workspace: fieldMetadata chunk 7/15 - deleted 50 record(s)
[Nest] 65112  - 01/18/2026, 4:37:38 PM     LOG [WorkspaceService] workspace: fieldMetadata chunk 8/15 - deleted 50 record(s)
[Nest] 65112  - 01/18/2026, 4:37:38 PM     LOG [WorkspaceService] workspace: fieldMetadata chunk 9/15 - deleted 50 record(s)
[Nest] 65112  - 01/18/2026, 4:37:38 PM     LOG [WorkspaceService] workspace: fieldMetadata chunk 10/15 - deleted 50 record(s)
[Nest] 65112  - 01/18/2026, 4:37:38 PM     LOG [WorkspaceService] workspace: fieldMetadata chunk 11/15 - deleted 50 record(s)
[Nest] 65112  - 01/18/2026, 4:37:38 PM     LOG [WorkspaceService] workspace: fieldMetadata chunk 12/15 - deleted 51 record(s)
[Nest] 65112  - 01/18/2026, 4:37:38 PM     LOG [WorkspaceService] workspace: fieldMetadata chunk 13/15 - deleted 50 record(s)
[Nest] 65112  - 01/18/2026, 4:37:38 PM     LOG [WorkspaceService] workspace: fieldMetadata chunk 14/15 - deleted 50 record(s)
[Nest] 65112  - 01/18/2026, 4:37:38 PM     LOG [WorkspaceService] workspace: fieldMetadata chunk 15/15 - deleted 36 record(s)
[Nest] 65112  - 01/18/2026, 4:37:38 PM     LOG [WorkspaceService] workspace: deleted 737 fieldMetadata record(s)
[Nest] 65112  - 01/18/2026, 4:37:38 PM     LOG [WorkspaceService] workspace: deleted 6 role record(s)
[Nest] 65112  - 01/18/2026, 4:37:38 PM     LOG [WorkspaceService] workspace: deleted 78 serverlessFunction record(s)
[Nest] 65112  - 01/18/2026, 4:37:39 PM     LOG [WorkspaceService] workspace: deleted 43 objectMetadata record(s)
[Nest] 65112  - 01/18/2026, 4:37:41 PM     LOG [WorkspaceService] workspace hard deleted
[Nest] 65112  - 01/18/2026, 4:37:41 PM     LOG [CleanerWorkspaceService] Destroyed 1 workspaces on 5 limit durings this execution
[Nest] 65112  - 01/18/2026, 4:37:41 PM     LOG [CleanerWorkspaceService] batchWarnOrCleanSuspendedWorkspaces done!
[Nest] 65112  - 01/18/2026, 4:37:41 PM     LOG [CleanSuspendedWorkspacesCommand] Command completed!
```


## Update
Discussed with @charlesBochet ended debugging and analyzing sql query
operations
He discovered that we were not indexing foreignKey effectively
We've ended up fixing all the FK indeces coverage leading to 

## Cleaning
Removed the
```sh
npx nx run twenty-server:command workspace:clean-soft-deleted-suspended-workspaces --ignore-grace-period
```
In favor of
```sh
npx nx run twenty-server:command workspace:clean --only-operation destroy --ignore-destroy-grace-period
```

## Conclusion
Not that crazy but still worth it and could demultiply in production
2026-01-18 16:22:26 +00:00
Raphaël Bosi f793faae2b 17042 followups (#17122)
Followups after @Weiko review on
https://github.com/twentyhq/twenty/pull/17042
2026-01-13 16:25:30 +00:00
Raphaël Bosi 655f1eef5f [DASHBOARDS] Allow dashboards to be restored (#17042)
This PR introduces a few changes:
- Add three actions: see deleted dashboards, destroy dashboard and
restore dashboard
- Remove the soft delete and restore on all the page layout entities
- Cascade the destruction of a dashboard to a page layout

Video QA:


https://github.com/user-attachments/assets/ab993b11-dd9c-4e88-880c-92691a521cc2
2026-01-12 12:59:17 +00:00
nitin 46e5420d20 dashboard workspace standard seeds (#16962)
# Introduction

In this pull request we're introducing new standard page layout, tabs
and widget ( 1 page layout, 1 tab and 8 widgets ) and also a new
opportunity field

Also now prefilling new records, 6 opportunities and a dashboard.

## Standard declaration
### New workspace creation
Relies on existing standard declaration builder

### Backfill command
We've been hacking through the standard builder in order to extract only
the standard page layout entities, updated their entity dependencies to
match the workspace ids so the validation passes


## Remark
- Refactored the `PageLayoutWidget` configuration type to be dynamically
typed through a generic discriminated union

---------

Co-authored-by: prastoin <paul@twenty.com>
2026-01-12 09:34:15 +00:00
Paul Rastoin 942d2fef83 Remove sync-metadata and IS_WORKSPACE_CREATION_V2_ENABLED feature flag (#16997)
# Introduction
Followup of
https://github.com/twentyhq/twenty/pull/17001#pullrequestreview-3638508738
close https://github.com/twentyhq/core-team-issues/issues/1910

We've completely decom the `sync-metadata` in production. We're now then
removing its implementation in favor of the v2.

## TODO:
- [x] Remove sync-metadata implem and commands
- [x] Remove workspace decorators 
- [x] Type each deprecated field to deprecated on their workspaceEntity
- [x] Remove the `workspace-sync-metadata` folder entirely
- [x] remove workspace migration
- [x] workspace migration removal migration
- [x] remove the `v2` references from workspace manager file names
- [x] remove the `v2` references from workspace manager modules
- [ ] Double check impact on translation file path updates


## Note
- Removed the gate logic
- Remains some service v2 naming, serverless needs to be migrated on v2
fully
- Removed workspaceMigration service app health consumption, making it
always returning up ( no more down ) cc @FelixMalfait ( quite obsolete
health check now, will require complete refactor once we introduce inter
app dependency etc )
2026-01-08 15:45:12 +00:00
Raphaël Bosi 2e0eeda52e [DASHBOARDS] Fix dashboard duplication createdBy (#16999)
Fixes https://github.com/twentyhq/core-team-issues/issues/2032

## Before


https://github.com/user-attachments/assets/5804d3e7-1c03-4eb9-9203-64656438f5d1


## After


https://github.com/user-attachments/assets/9f96458c-d2a5-481a-b6b2-4d88f0daa98a
2026-01-08 09:13:43 +00:00
Raphaël Bosi 7af98a9c15 Update updatedat field on dashboards after edition (#16964)
Closes https://github.com/twentyhq/core-team-issues/issues/1896
2026-01-07 17:14:24 +00:00
Raphaël Bosi 4faed25624 [PAGE LAYOUTS] Add widgets validation (#16635)
- Add widget validation
- Remove 'None' option for primary axis group by
- Fix error message parsing by passing the operation type in
`useMetadataErrorHandler`
2026-01-07 15:00:13 +00:00
Raphaël Bosi c531cfe0a4 [DASHBOARDS] Manual and position-based sorting for chart widgets (#16794)
## Description

SELECT fields have a defined option order that users expect to see
reflected in charts.
This PR allows sorting by that position and also enables custom manual
ordering.

## Video QA

### Reordering on primary axis


https://github.com/user-attachments/assets/994f515e-19cb-4a5e-b745-e8c77e92ae0b


### Reordering on secondary axis


https://github.com/user-attachments/assets/444c16f2-1920-4dc4-8b42-312d520ab43b

Note: The colors in the graph will match the colors of the select
options, but this will be done in another PR

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Introduces new sort modes and UI for chart groupings, with full FE/BE
support and updated GraphQL schema.
> 
> - Extend `GraphOrderBy` with `FIELD_POSITION_ASC/DESC` and `MANUAL`;
add corresponding fields in configs: `primaryAxisManualSortOrder`,
`secondaryAxisManualSortOrder`, and `manualSortOrder` (pie)
> - New UI: dropdown options filtered by field type, icons, and a
draggable submenu (`ChartManualSortSubMenuContent`) to reorder select
options; integrates with widget edit flow
> - Sorting logic added/refactored: `sortChartData`,
`sortByManualOrder`, `sortBySelectOptionPosition`,
`sortLineChartSeries`, plus updates to bar/line/pie transformers to
honor new modes and manual orders
> - Default behaviors: select fields default to `FIELD_POSITION_ASC`;
query variable builders skip `orderBy` when using manual/position sorts
> - Update GraphQL generated types/fragments/queries and backend
DTOs/schemas to persist new fields; add tests for sorting utilities and
snapshots; add sorting icons in `twenty-ui`
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
78c9b56c0f1f2d45f7f8b270bb59ca599a005abe. 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>
2026-01-06 11:52:54 +01:00
Félix Malfait f8fa709abf refactor: Migrate CRUD services to use Common API (#16869)
This PR migrates the workflow CRUD services to use the Common API
(CommonQueryRunners) instead of directly accessing TwentyORM.

## Changes

- Created CommonApiContextBuilderService to build context for Common API
- Migrated CreateRecordService to use CommonCreateOneQueryRunnerService
- Migrated UpdateRecordService to use CommonUpdateOneQueryRunnerService
- Migrated DeleteRecordService to use CommonDeleteOneQueryRunnerService
- Migrated FindRecordsService to use CommonFindManyQueryRunnerService
- Migrated UpsertRecordService to use Common API with upsert flag
- Removed unused get-selected-columns-from-restricted-fields.util.ts
- Updated module dependencies

## Benefits

- Consistent permission checking via Common API
- Query hooks (before/after execution)
- Automatic input transformation
- Same behavior as REST/GraphQL APIs
- Reduced code duplication
2025-12-31 10:24:50 +01:00
Paul Rastoin e3ffdb0c2b [BREAKING_CHANGE_NESTED_WORKSPACE]Refactor FlatEntity typing in aim of introducing UniversalFlatEntity (#16701)
# Introduction
Added a `WorkspaceRelated` and `AllNonWorkspaceRelatedEntity` to
simplify the `FlatEntityFrom` that now do not expect a string literal to
omit and itself builds the related many to one entities foreign key
aggregators

We now have the type grain over relation to syncable or just workspace
related entities

Added a migrations that sets the fk on missing entities

## Next
In upcoming PR we will be able to introduce such below type
```ts
import { type CastRecordTypeOrmDatePropertiesToString } from 'src/engine/metadata-modules/flat-entity/types/cast-record-typeorm-date-properties-to-string.type';
import { type ExtractEntityManyToOneEntityRelationProperties } from 'src/engine/metadata-modules/flat-entity/types/extract-entity-many-to-one-entity-relation-properties.type';
import { type ExtractEntityOneToManyEntityRelationProperties } from 'src/engine/metadata-modules/flat-entity/types/extract-entity-one-to-many-entity-relation-properties.type';
import { type ExtractEntityRelatedEntityProperties } from 'src/engine/metadata-modules/flat-entity/types/extract-entity-related-entity-properties.type';
import { type RemoveSuffix } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/remove-suffix.type';
import { type SyncableEntity } from 'src/engine/workspace-manager/workspace-sync/types/syncable-entity.interface';

export type UniversalFlatEntityFrom<TEntity extends SyncableEntity> = Omit<
  TEntity,
  | `${ExtractEntityManyToOneEntityRelationProperties<TEntity> & string}Id`
  | ExtractEntityRelatedEntityProperties<TEntity>
  | 'application'
  | 'workspaceId'
  | 'applicationId'
  | keyof CastRecordTypeOrmDatePropertiesToString<TEntity>
> &
  CastRecordTypeOrmDatePropertiesToString<TEntity> & {
    [P in ExtractEntityManyToOneEntityRelationProperties<TEntity> &
      string as `${RemoveSuffix<P, 's'>}UniversalIdentifier`]: string;
  } & {
    [P in ExtractEntityOneToManyEntityRelationProperties<
      TEntity,
      SyncableEntity
    > &
      string as `${RemoveSuffix<P, 's'>}UniversalIdentifiers`]: string[];
  };

```
2025-12-30 13:47:02 +00:00
Marie 19c9f957b1 Improve userFriendlyMessage devX (#16815)
Two challenges with error messages
- always provide a useful/meaningful error message for the end user
instead of the generic one. eg: show "Wrong password" and not "An error
occured"
- avoid technical details unless error regards a technical feature. eg:
show "An error occured" and not "Invalid post-hook payload."; but do
show "Invalid issuer URL." as it occurs while configuring SSO

What this PR does
- Make userFriendlyMessage mandatory for widely used
GraphqlQueryRunnerException and CommonQueryRunnerException, so that
developers are forced to ask themselves what the error message should
be, and as it contains very wide error codes (eg: "Bad request") which
should not be mapped to just one default message
- Keep userFriendlyMessage optional for service-specific exceptions (eg:
workflowStepExecutorException), but convert the error code to
userFriendlyMessage mapper to a switch case function with a typecheck
ensuring that all codes are mapped to a message. These default messages
are still overridable where they are thrown.
2025-12-30 09:08:43 +00:00
Paul Rastoin 4135a6473a [BREAKING_CHANGE_DASHBOARDS][DASHBOARD_CACHE_FLUSH_REQUIRED] Refactor page layout widget configuration type (#16671)
# Introduction
In this pull-request we're refactoring the page layout widget
configuration entity to be containing its discriminated key simplifying
underlying code and maintainability
- Made the configuration and title non nullable
- Introduced a generic predicate for the `widgetConfigurationType`
- Upgraded command to remove `graphType` and insert new
`configurationType` to existing entries
- Migrated frontend to new type system

---------

Co-authored-by: bosiraphael <raphael.bosi@gmail.com>
Co-authored-by: Raphaël Bosi <71827178+bosiraphael@users.noreply.github.com>
2025-12-29 15:46:59 +01:00
Baptiste Devessier b5ebc44fee Add field widget (#16609)
- Ability to display the details of a field
- The field can be edited (relations edition will be supported later)
- For now, the widget configuration stores the name of the field instead
of its fieldMetadataId. A hook resolves the fieldMetadataId from the
list of fields and the provided name. This will be replaced once we
migrate the configuration to the backend.

## Demo


https://github.com/user-attachments/assets/ab7efbda-66b2-46c1-b641-c350977c31dd

## Remaining to do

- Edition of relations
2025-12-18 17:25:51 +00:00
Paul Rastoin 47a8a15598 Metadata modules for PageLayoutTab PageLayoutWidget (#16662)
# Introduction
Creating dedicated folders and module for both `page-layout-tab` and
`page-layout-widget`

The addition diff with deletion is due to the module being added
2025-12-18 11:15:29 +00:00