647c32ff3e66d4f27e498418fc471bef82f8dd67
15 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
647c32ff3e |
Deprecate runtime theme objects in favor of CSS variables (#18402)
## Summary
- **Eliminate `ICON_SIZES` / `ICON_STROKES` constants**: all icon
dimensions are now resolved at runtime via
`resolveThemeVariableAsNumber(themeCssVariables.icon.size.X)`, ensuring
values always come from computed CSS variables
- **No more consumer imports from `twenty-ui/theme`**: moved
`ColorSchemeContext`, `ColorSchemeProvider`, `ThemeColor`,
`MAIN_COLOR_NAMES`, `getNextThemeColor`, `AnimationDuration` to
`twenty-ui/theme-constants`
- **Remove `ThemeContext` / `ThemeContextProvider` / `ThemeProvider` /
`ThemeType`**: replaced across ~300 files with `themeCssVariables` (for
CSS contexts) or `resolveThemeVariable` / `resolveThemeVariableAsNumber`
(for JS runtime values)
- **Simplify provider chain**: only `ColorSchemeProvider` remains — it
toggles `light`/`dark` class on `document.documentElement` and provides
`colorScheme` via React context
- **Fix pre-existing test failures**: `useIcons.test.ts`
(non-configurable ES module spy) and
`turnRecordFilterGroupIntoGqlOperationFilter.test.ts`
(`Omit<RecordFilter, 'id'>` type mismatch)
### Theme access pattern (before → after)
| Context | Before | After |
|---------|--------|-------|
| CSS (Linaria) | `${({ theme }) => theme.font.color.primary}` |
`${themeCssVariables.font.color.primary}` |
| JS runtime (icon size, animation) | `theme.icon.size.md` /
`ICON_SIZES.md` |
`resolveThemeVariableAsNumber(themeCssVariables.icon.size.md)` |
| Color scheme check | `theme.name === 'dark'` |
`useContext(ColorSchemeContext).colorScheme === 'dark'` |
|
||
|
|
802a5b0af6 |
chore(twenty-front): migrate auth, activities, AI, pages and small modules from Emotion to Linaria (PR 2-3/10) (#18328)
## Summary - Migrate ~200 files from `@emotion/styled` / `@emotion/react` to `@linaria/react` + `themeCssVariables`, continuing the zero-runtime CSS-in-JS migration (PR 2-3 of the [migration plan](docs/emotion-to-linaria-migration-plan.md)) - Modules covered: **auth** (19), **activities** (53), **ai** (30), **pages** (70), **action-menu** (3), **object-metadata** (4), **onboarding** (2), **workspace** (2), **file** (3), **error-handler** (2), **front-components** (1), **geo-map** (1), **loading** (5), **testing** (5), plus a `style` prop addition to `TableRow` - Handles `styled(FunctionComponent)<Props>` incompatibility with Linaria by using CSS custom properties via `style` + `var()` references ## Test plan - [x] `npx nx lint:diff-with-main twenty-front` passes - [x] `npx nx typecheck twenty-front` passes - [ ] Visual spot-check of auth, onboarding, settings, activities, and AI chat screens - [ ] No remaining `@emotion/styled` or `@emotion/react` imports in migrated files Made with [Cursor](https://cursor.com) |
||
|
|
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 |
||
|
|
b51eb6471f |
Jotai 12 (#18160)
Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
530f74e28c |
Migrate more to Jotai (#18087)
Continue jotai migration |
||
|
|
88424611ec |
Refactor and standardize isSystem field and object (#17992)
# Introduction ## Centralize system field definitions - Extract a single `PARTIAL_SYSTEM_FLAT_FIELD_METADATAS` constant as the source of truth for all 8 system fields (`id`, `createdAt`, `updatedAt`, `deletedAt`, `createdBy`, `updatedBy`, `position`, `searchVector`), eliminating duplication across custom object and standard app field builders - Refactor `buildDefaultFlatFieldMetadatasForCustomObject` to use the shared constant via a new `buildObjectSystemFlatFieldMetadatas` helper ## Mark system fields as `isSystem: true` - Fields `id`, `createdAt`, `updatedAt`, `deletedAt`, `createdBy`, `updatedBy`, `position`, `searchVector` are now properly flagged as system fields across all standard objects and custom object creation - Standard app field builders for all ~30 standard objects updated to set `isSystem: true` on `createdAt`, `updatedAt`, `deletedAt`, `createdBy`, `updatedBy` - System-only standard objects (blocklist, calendar channels, message threads, etc.) now also include `createdBy`, `updatedBy`, `position`, `searchVector` field definitions that were previously missing ## Validate system fields on object creation - New transversal validation (`crossEntityTransversalValidation`) runs after all atomic entity validations in the build orchestrator, ensuring all 8 system fields are present with correct `type` and `isSystem: true` when an object is created - New `buildUniversalFlatObjectFieldByNameAndJoinColumnMaps` utility to resolve field names to universal identifiers for a given object - New exception codes: `MISSING_SYSTEM_FIELD` and `INVALID_SYSTEM_FIELD` on `ObjectMetadataExceptionCode` ## Protect system fields and objects from mutation - Field validators now block update/delete of `isSystem` fields by non-system callers (`FIELD_MUTATION_NOT_ALLOWED`) - Object validators now block update/delete of `isSystem` objects by non-system callers - `POSITION` and `TS_VECTOR` field type validators replaced: instead of rejecting creation outright, they now validate that the field is named correctly (`position` / `searchVector`) and has `isSystem: true` ## Distinguish `isSystemBuild` from `isCallerTwentyStandardApp` - New `isCallerTwentyStandardApp` utility checks whether the caller's `applicationUniversalIdentifier` matches the twenty standard app - Name-sync logic (`isFlatFieldMetadataNameSyncedWithLabel`, `areFlatObjectMetadataNamesSyncedWithLabels`) refactored to use `isCallerTwentyStandardApp` for custom suffix decisions, keeping `isSystemBuild` for mutation permission checks - `WorkspaceMigrationBuilderOptions` type updated to include `applicationUniversalIdentifier` ## Adapt frontend filtering - New `HIDDEN_SYSTEM_FIELD_NAMES` constant (`id`, `position`, `searchVector`) and `isHiddenSystemField` utility to only hide truly internal fields while keeping user-facing system fields (`createdAt`, `updatedAt`, `deletedAt`, `createdBy`, `updatedBy`) visible in the UI - ~20 frontend files updated to replace `!field.isSystem` checks with `!isHiddenSystemField(field)` across record index, settings, data model, charts, workflows, spreadsheet import, aggregations, and role permissions ## Add 1.19 upgrade commands - **`backfill-system-fields-is-system`**: Raw SQL command to set `isSystem = true` on existing workspace fields matching system field names, and fix `position` field type from `NUMBER` to `POSITION` for `favorite`/`favoriteFolder` objects. Includes proper cache invalidation. - **`add-missing-system-fields-to-standard-objects`**: Codegen'd workspace migration to create missing `position`, `searchVector`, `createdBy`, `updatedBy` fields on standard objects that didn't previously have them. Runs via `WorkspaceMigrationRunnerService` in a single transaction with idempotency check. **Known limitation**: assumes all standard objects exist and are valid in the target workspace. ## Add `universalIdentifier` for system fields in standard object constants - `standard-object.constant.ts` updated to include `universalIdentifier` for `createdBy`, `updatedBy`, `position`, and `searchVector` across all standard objects - `fieldManifestType.ts` updated to support the new field manifest shape ## System relation Completely removed and backfilled all `isSystem` relation to be false false As we won't require an object to have any relation system fields ## Add integration tests - New test suite `failing-sync-application-object-system-fields` covering: missing system fields, wrong field types (`id` as TEXT, `createdAt` as TEXT, `position` as TEXT), system field deletion attempts, and system field update attempts - New test utilities: `buildDefaultObjectManifest` (builds an object manifest with all 8 system fields) and `setupApplicationForSync` (centralizes application setup) - Existing successful sync test updated to verify system fields are created with correct properties ## Next step Make the builder scope the compared entity to be the currently built app + nor twenty standard app |
||
|
|
082400f751 |
Add objectRecordCounts query to /metadata endpoint (#18054)
## Summary - Adds an `objectRecordCounts` query on the `/metadata` GraphQL endpoint that returns approximate record counts for all objects in the workspace - Uses PostgreSQL's `pg_class.reltuples` catalog stats — a single instant query instead of N `COUNT(*)` table scans - Replaces the previous `CombinedFindManyRecords` approach which hit the server's 20 root resolver limit and silently showed 0 for all counts on the settings Data Model page ### Server - `ObjectRecordCountDTO` — GraphQL type with `objectNamePlural` and `totalCount` - `ObjectRecordCountService` — reads `pg_class` catalog for the workspace schema - Query added to `ObjectMetadataResolver` with `@MetadataResolver()` + `NoPermissionGuard` ### Frontend - `OBJECT_RECORD_COUNTS` query added to `object-metadata/graphql/queries.ts` - `useCombinedGetTotalCount` simplified to a zero-argument hook using the new query - `SettingsObjectTable` simplified to a single hook call --------- Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
90a30263ac |
[Apps] Content + permission tabs for marketplace and installed apps (#17888)
In this PR - Content tab for marketplace apps and installed apps: complies with [figma](https://www.figma.com/design/xt8O9mFeLl46C5InWwoMrN/Twenty?node-id=34845-126856); addition of field section showing fields added to standard objects; initiative: arrow opens a sub-table of fields rows. (suggested because 1/ for marketplace apps we cannot redirect to the actual object page in settings since the object does not exist yet in the workspace 2/ since we dont have an quick "go back to application page" option, it can be annoying to be redirected to a different setting page when we just want to look at the content of the app objects) - Permission tab for marketplace apps and installed apps - left to do - settings tab (in another PR) There are breaking changes but it's behind a feature flag not exposed (access to marketplace) so not problematic marketplace apps https://github.com/user-attachments/assets/4c660101-50fc-47ce-b90a-8d6f17db5e74 installed apps https://github.com/user-attachments/assets/c9229ee1-e75f-4cad-8766-758b2c5b37b4 |
||
|
|
0001c2e7d0 |
[Apps] Apps marketplace (first draft) (#17562)
https://github.com/user-attachments/assets/c4e63edb-6e98-44bc-841f-ee110ae712d4 How it works - `manifest.json` files are now committed when apps are published to our repo - to display available apps, from the server, we read into our github repo, using a pod-scoped cache - feature flagged - app installation will be behind permission gate MARKETPLACE_APPS Limitations and what is yet to develop - content and settings tabs - installed apps tab - app installation - test and potentially fix reading from .manifest.json once [Reshape manifest structure](https://github.com/twentyhq/core-team-issues/issues/2183) is done. additional work is expected on assets notably. (couldnt properly do it here as manifest.json will only be committed after this pr) - we only read in community/ folder for now - we may want tochange that - the cache is rather artisanal for now and scoped by pod - we may want to change that |
||
|
|
1128331cc1 |
Fix field item type tag (#16860)
# Introduction This has been fixed on main already 1 hour ago, this PR now only passes the field application id instead of the object applicationId that could be different for example when creating a custom field on a standard object For the moment not introducing any logic around application integrity directly and still relying on the isCustom and standardId definition This will have to be refactored once we deprecate the standardId |
||
|
|
ee08060798 |
Improve deactivated objects & fields behaviors. (#16090)
Closes [1918](https://github.com/twentyhq/core-team-issues/issues/1918). - For the first point in the issue, we just show the deactivated entries along with the deactivated text. --- - For the second point, we show a banner and control the enabled/disabled state of save button depending on whether we're allowing the user to create table with the typed name. - For example, we do not want to allow the user to create a table with reserved name, so we disable the save button without showing a banner. - Similarly, we do not want the user to create a table with a name that already exists in the database. In this case, we show a banner and we also disable the save button. - Finally, we do not want to allow the user to create a table where singular and plural name are the same. Therefore, we disable the save button for names like `works`. --- - For the third point, if we add the delete button, it logically means that we allow the user to delete a custom object/field even it has not been deactivated yet, so did that. - Upon deleting the object/field, if we wait for the metadata to refetch before we navigate, this is what we see because the path does not exist any longer after deletion and we're waiting for refetch on the path until we navigate away. https://github.com/user-attachments/assets/dbe0569c-db88-4285-851f-22551b1ca81e - To avoid this page from appearing, I replaced awaiting refetch to not awaiting refetch and redirecting while the refetch happens in the background. - Therefore, when we delete something, there is a slight delay for when it is actually cleared out from the list, but the Not Found view does not appear on the screen. https://github.com/user-attachments/assets/47f49579-ce51-4d6a-b857-72046247bb4b - I tried optimistically removing the object/field from the metadata, but it leads to some issues (crashes the app) and I have not been able to find a solution for it yet. - Therefore, instead of getting stuck at perfection and blocking myself, I stopped getting into the issue further and created this PR by ensuring that the desired functionality works. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Display deactivated objects/fields by default, add delete actions with confirmation, and unify metadata name computation (auto-suffix reserved keywords) across front/back with conflict checks in object creation. > > - **Frontend (Settings/Data Model)**: > - **Visibility/UX**: Show `Deactivated` labels for objects/fields; filters default to include inactive (`showDeactivated`/`showInactive` true); replace field action dropdown with chevron link. > - **Delete flows**: Add delete buttons for custom objects/fields with confirmation modals and background refetch to avoid Not Found flashes. > - **Creation/Edit validation**: Add name conflict detection banner in `SettingsDataModelObjectAboutForm` and disable Save on conflicts; simplify `metadataLabelSchema` to use computed name; form fields validate on change and sync API names. > - **Shared (twenty-shared/metadata)**: > - Add `computeMetadataNameFromLabel` util (slugify+camelCase) and `RESERVED_METADATA_NAME_KEYWORDS`; auto-append `Custom` to reserved names; export constants/utilities. > - **Backend**: > - Migrate to shared `computeMetadataNameFromLabel`; update validators to use shared reserved keywords with new messages; allow deletion of active custom fields/objects (keep standard guards); adjust services/decorators accordingly. > - **Tests/Stories**: > - Update unit/integration snapshots for new reserved-name messages and behaviors; add missing i18n/router decorators in stories. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 5b126155606f6dbc8f7f91e2192cffb7bd2ebd2c. 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: Félix Malfait <felix@twenty.com> |
||
|
|
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 |
||
|
|
0fa2a4524a |
feat: Add filter button to objects table and enable system objects access (#15856)
## Summary This PR replaces the Active/Inactive accordion sections with a modern filter dropdown button and enables full access to system objects in advanced mode. ## Changes ### UI Improvements - ✅ Replaced accordion sections with a filter button dropdown (matching the design pattern from the Group filter) - ✅ Added 'Deactivated' toggle filter (hidden by default, uses IconArchive) - ✅ Added 'System objects' toggle filter (only visible in advanced mode, uses IconSettings) - ✅ Fixed search input width to properly fill available space - ✅ Proper button sizing and alignment ### System Objects Support - ✅ Made system objects visible when 'System objects' filter is toggled on - ✅ System objects are now fully clickable and accessible - ✅ Updated object detail page to support system objects - ✅ Updated field creation/edit pages to support system objects - ✅ System objects can now have custom fields added ### Architecture - ✅ Implemented scalable filter architecture using a single filtered list - ✅ Easy to add more filters in the future (e.g., show remote objects) - ✅ All filters work independently and can be combined ## Testing - [x] Tested deactivated objects toggle - [x] Tested system objects toggle (only shows in advanced mode) - [x] Tested clicking on system objects - [x] Tested adding custom fields to system objects - [x] No linter errors ## Screenshots See attached screenshots in the conversation for the new filter UI. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Adds a filter dropdown to the Settings Objects table (incl. deactivated/system toggles), enables system objects across settings/field flows, seeds core views (workspace members, messages, threads, calendar events), and adds actions for Workspace Members. > > - **Settings UI** > - **Objects Table**: Replaces Active/Inactive sections with a single filterable list and dropdown (`Deactivated`, `System objects` in advanced mode); updates props to `objectMetadataItems` and removes accordion sections. > - **Search/UX**: Search input fills available space; inactive rows show activation/delete menu; active rows remain navigable. > - **Pages Updated**: `SettingsObjects`, `SettingsApplicationDetailContentTab` switch to new table API; object detail and new-field flows use `findObjectMetadataItemByNamePlural` (works with system objects). > - **Action Menu** > - **Workspace Members**: Adds `WORKSPACE_MEMBERS_ACTIONS_CONFIG` with "Manage members in settings" action; wired into `getActionConfig` for `WorkspaceMember`. > - **Server (Core Views Seed)** > - Adds default views: `workspaceMembersAllView`, `messagesAllView`, `messageThreadsAllView`, `calendarEventsAllView`; included in `prefillCoreViews`. > - Marks workflow entities as system (`WorkflowRun`, `WorkflowVersion`). > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 6a2856df85104665bd986cc63f2d54f19bf668d0. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> |
||
|
|
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 |
||
|
|
b16ab1b7c9 |
1518 extensibility front add an application section in settings (#15056)
Protected by IS_APPLICATION_ENABLED featureFlag Add `Application` section in settings <img width="301" height="137" alt="image" src="https://github.com/user-attachments/assets/ee53bdd2-36f6-45c6-8646-17b1e08abf00" /> A `settings/applications` route listing all installed applications <img width="661" height="428" alt="image" src="https://github.com/user-attachments/assets/69d534c4-4e9e-452a-a3d9-ded0223bb457" /> Introduce a new Tag for application managed items <img width="885" height="759" alt="image" src="https://github.com/user-attachments/assets/19767be5-61e5-4bd2-a51d-54ed9bfb1923" /> A `settings/applications/<application_id>` details setting page listing all objects, serverlessFunctions and agents created by the application: <img width="917" height="778" alt="image" src="https://github.com/user-attachments/assets/7fc056a6-1d73-4242-b2eb-6f8955d8597d" /> A `settings/applications/<application_id>/<serverless_function_id>` <img width="905" height="652" alt="image" src="https://github.com/user-attachments/assets/56ca0021-26bf-42cb-9abf-34879f16050a" /> Add trigger tab in serverless function details (readonly for now) <img width="899" height="724" alt="image" src="https://github.com/user-attachments/assets/5eeefa35-f2a4-4fd8-a640-7b5c5891f226" /> Set object, serverless and agent setting detail pages readonly for managed items <img width="1075" height="859" alt="image" src="https://github.com/user-attachments/assets/57c73d69-4980-47a2-b752-8dc5ab494530" /> <img width="648" height="582" alt="image" src="https://github.com/user-attachments/assets/5ad5f3f7-3bc3-4e40-870a-4981c6492524" /> <img width="982" height="692" alt="image" src="https://github.com/user-attachments/assets/7ad756c4-5d33-4a0a-9eb8-416c040362b9" /> <img width="1077" height="647" alt="image" src="https://github.com/user-attachments/assets/e086b9f5-4062-4d10-82a9-4023de3cad3f" /> |