Commit Graph

4310 Commits

Author SHA1 Message Date
Aryan Bhati 8d7ee47ec5 fix: custom-cron-ui (#15786)
Fixes #14723 

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

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

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


### Before 

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


### After

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

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2025-11-17 18:03:41 +01:00
Paul Rastoin a39efeb1ab [BREAKING_CHANGE/GRAPHQL/OBJECT_METADATA_CREATE_ONE] Remove object/fields/view-fields v1 implementation (#15823)
# Introduction
Remove the v2 feature flag for view-field field-metadata and
object-metadata metadata entities

## Some details
- Disabled nestjs-query for object metadata creation and explicitly
calling it
- removed all v1 integration tests files

## Remarks
Not remove v2 referencing in both filenaming right now will handle that
globally later

## Breaking change
Due to object metadata resolver createOne standardization had to rename
the input from `CreateObjectInput` to `CreateOneObjectInput`
2025-11-17 10:55:19 +01:00
Abdullah. 7a68aa7f48 fix: playwright downloads and installs browsers without verifying the authenticity of the SSL certificate (#15843)
Resolves [Dependabot Alert
293](https://github.com/twentyhq/twenty/security/dependabot/293).

Updates the playwright version used to `1.56.1`. The alert could have
also been ignored since the playwright download only happens in CI and
local environments, not the production environment. However, it's an
easy fix instead of just ignoring the alert.
2025-11-17 08:16:56 +01:00
Abdullah. baa1a1e52f fix: babel vulnerable to arbitrary code execution when compiling specifically crafted malicious code (#15840)
Resolves [Dependabot Alert
95](https://github.com/twentyhq/twenty/security/dependabot/95) - babel
vulnerable to arbitrary code execution when compiling specifically
crafted malicious code.

These were the few options we had for a direct drop-in replacement.
- [x-var](https://www.npmjs.com/package/x-var?activeTab=readme)
- [cross-let](https://www.npmjs.com/package/cross-let)
- [cross-var-no-babel](https://www.npmjs.com/package/cross-var-no-babel)

x-var has the most weekly downloads among the three and it is also the
most actively maintained fork of the original cross-var package that
introduced the vulnerability. There is no syntax difference per the
documentation, but I do not have a windows machine to test.

`cross-var-no-babel` offers the most minimal changes, but is also
abandoned without a public-facing repo.
2025-11-16 20:12:25 +01:00
Baptiste Devessier 54f74b2a5a Properly interpret advanced filters boolean values in workflows (#15829) 2025-11-14 19:01:53 +01:00
martmull b3d85623e6 Remove unexisting mock value (#15822)
removes when signup

<img width="975" height="324" alt="image"
src="https://github.com/user-attachments/assets/93184788-81b9-4a7d-b572-d3bce594444f"
/>
2025-11-14 13:56:01 +00:00
Abdul Rahman bff079d3b5 Fix AI chat scroll behavior (#15686) 2025-11-14 01:20:25 +01:00
Lucas Bordeau 9d43058e50 Fixed hovering of kanban cards (#15808)
This PR fixes the record inline cells that disappeared on board card due
to recent refactors.
2025-11-13 17:49:52 +00:00
github-actions[bot] 9bc5486d0d i18n - translations (#15803)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2025-11-13 17:12:39 +01:00
github-actions[bot] 8cadd00d34 i18n - translations (#15799)
Created by Github action

---------

Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
Co-authored-by: github-actions <github-actions@twenty.com>
2025-11-13 16:34:00 +01:00
Félix Malfait cd5d0f9eac Introduce agent hints to reduce context bloat (#15763)
Introducing a new pattern that should reduce token consumption by 90%
for the most common use-cases
2025-11-13 16:15:01 +01:00
Abdullah. 0cab2b49fc (breaking change) Allow users with a single workspace to update their email. (#15736)
- Users with a single workspace are allowed to update their email across
`core.user` and `workspace_xyz.workspaceMember`.
- The latter happens asynchronously (built it like this for non-blocking
with multiple workspaces), but since we restrict the email update
functionality to a single user, we can also update the email in
workspaceMember synchronously - I left asynchronous there to receive
feedback on whether we should move to synchronous or not.
- Merged main and resolved conflicts to ensure we use the
`SettingsPermissionGuard` and the updated `workspace.service.ts` code.

One edge-case that I was trying to communicate on Discord: 

Say that an admin is a member of multiple workspaces. Therefore, they
can allow roles with PROFILE_INFORMATION permission to update their
email.

<p align="center">
<img width="553" height="115" alt="image"
src="https://github.com/user-attachments/assets/80382b1f-a9e3-4dac-b606-c2defeb2c330"
/>
</p>

However, since the admin is part of multiple workspaces, he/she cannot
even update own email - the field stays disabled, leading to some
confusion.

<p align="center">
<img width="545" height="255" alt="image"
src="https://github.com/user-attachments/assets/5e6d27db-c9a8-4d5e-9ab6-65c77beae5b4"
/>
</p>

However, the workspace can have another member with admin role or some
other role that has PROFILE_INFORMATION permission flag. That user will
be and should be allowed to update email, so we cannot hide `email` from
dropdown options.

<p align="center">
<img width="585" height="283" alt="image"
src="https://github.com/user-attachments/assets/a670d3ac-cf48-4865-a425-b909093d8420"
/>
</p>

The behavior is fine imo, just a little confusing for members with more
than one workspace.

I have also tested the flow by signing up to YC workspace with my org
google account (twenty.com), then changing email to my personal address.
- After changing, I need to login using Google with my personal account
to access YC workspace again.
- If I login using Google with org google account (twenty.com), a new
user account is created.

This behavior is consistent with Notion and Linear. 

Finally, as for the verification of email, the user is asked to verify
email while they're logged in, but just in case they logout without
verifying, the next login would force them to verify their email in the
email/password flow.

However, for Social/SSO, they must verify before they logout or else
they'd have to contact support for assistance. I have not looked into
how to show verification screen while logging in via Social/SSO yet, but
if that's something critical for completeness here, I shall revisit it.

---------

Co-authored-by: Félix Malfait <felix@twenty.com>
2025-11-13 15:00:02 +01:00
Lucas Bordeau dd0601ab6f Fix phone not empty filter (#15790)
This PR fixes the filter on not empty phones.

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

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

Fixes https://github.com/twentyhq/twenty/issues/15638
2025-11-13 13:38:56 +00:00
Félix Malfait f9c61833ec Add debug info in AI chat (#15758)
## 🐛 Critical Bug Fix

### Cost Calculation Error (1000x undercharge)
- **Fixed**: Cost conversion utility was calculating credits at 1/1000th
of actual value
- **Before**: `cents * 10` 
- **After**: `(cents / 100) * DOLLAR_TO_CREDIT_MULTIPLIER` 
- **Impact**: Users were being undercharged by 1000x
  - Example: 0.75 cents should = 7,500 credits
  - Bug calculated it as 7.5 credits

---

## 🎯 Code Centralization & DRY

### Unified Cost Calculation
- Centralized all cost conversions to use `convertCentsToBillingCredits`
utility
- Refactored 3 different implementations into 1 single source of truth
- Files updated:
  - `ai-billing.service.ts`
  - `agent-streaming.service.ts` (2 usages)

**Before** (multiple implementations):
```typescript
// Wrong implementation
const credits = cents * 10;

// Verbose implementation  
const costInDollars = costInCents / 100;
const creditsUsed = Math.round(costInDollars * DOLLAR_TO_CREDIT_MULTIPLIER);
```

**After** (unified):
```typescript
const creditsUsed = Math.round(convertCentsToBillingCredits(costInCents));
```

---

##  UI Component Refactoring

### RoutingDebugDisplay.tsx
- **Reduced from 118 lines to 34 lines** (71% reduction)
- Extracted `renderTimingRow` helper to eliminate 15 repetitive JSX
blocks
- Added `formatTokenBreakdown` helper for token display logic
- Much easier to add new debug metrics

**Before**: 15 nearly-identical blocks of repetitive JSX  
**After**: Clean, DRY implementation with reusable helpers

---

## 🧹 Code Quality Improvements

### Removed Debug Code
- Removed `console.log` accidentally left in `RoutingStatusDisplay.tsx`

### Cleaned Up Comments (18+ removed)
Removed redundant comments that stated the obvious:
-  "Calculate routing cost if we have token usage"
-  "Send the updated routing status with execution metrics to the
client"
-  "Count tool calls in the response"
-  "AI SDK's LanguageModelUsage uses inputTokens/outputTokens"
- And 14+ more...

Kept meaningful comments:
-  "Timing is optional, ignore errors" (explains catch block)
-  Type definition grouping comments

---

## 📊 Statistics

**Files Modified**: 10
- `convert-cents-to-billing-credits.util.ts` (fixed formula)
- `ai-billing.service.ts` (use centralized utility)
- `agent-streaming.service.ts` (use utility, remove comments)
- `agent-execution.service.ts` (remove comments)
- `ai-router.service.ts` (remove comments)
- `RoutingStatusDisplay.tsx` (remove debug code)
- `RoutingDebugDisplay.tsx` (major refactor) 
- `isDebugModeState.ts` (new file)
- `DataMessagePart.ts` (type extensions)
- `useClientConfig.ts` (debug mode support)

**Impact**:
- Lines removed: ~130 (redundant code + comments)
- Lines added: ~45 (helper functions)
- **Net reduction**: ~85 lines
- **Bug fixes**: 1 critical (1000x cost error)
- **Centralizations**: 3 locations now using shared utility
- **Major refactors**: 1 UI component (71% reduction)

---

##  Verification

-  All linter checks pass
-  All tests pass (`ai-billing.service.spec.ts` verified)
-  No `any` types in affected code
-  No TODO/FIXME markers

---

## 🎯 Principles Applied

1.  **Fix Root Causes, Not Symptoms** - Fixed utility function, then
used it everywhere
2.  **DRY (Don't Repeat Yourself)** - Centralized cost calculation and
UI rendering
3.  **Single Source of Truth** - One place for cost conversion formula
4.  **Code as Documentation** - Removed comments that repeated what
code says
5.  **Composability** - Created reusable helper functions
6.  **Type Safety** - Maintained strict typing throughout
2025-11-13 13:34:46 +01:00
nitin fddac24e7f connect line chart to backend (#15657)
https://github.com/user-attachments/assets/b797c5a8-32a8-4d3e-9fb1-7541d107a19f

optimizations:
before: 


https://github.com/user-attachments/assets/bf45a3f1-5f89-40c1-9ce4-c2d912b77d63


after:


https://github.com/user-attachments/assets/61bfd603-7b63-4695-8ae8-68fe7d3bfea0
2025-11-13 11:35:08 +00:00
Charles Bochet eee35e5e25 Surface record selection limit in Workflow Manual Trigger and in Search Node (#15785)
fixes https://github.com/twentyhq/twenty/issues/15704

Take over: https://github.com/twentyhq/twenty/pull/15738

based on [KhademOHAli1](https://github.com/KhademOHAli1) work

---------

Co-authored-by: Ali Khadem <ali.kh@pitant.de>
2025-11-13 12:11:48 +01:00
Guillim 0389fcf00d removing feature flag IS_MORPH_RELATION_ENABLED (#15783)
releasing the morph feature for all workspaces
2025-11-13 12:03:25 +01:00
Lucas Bordeau a453d53656 Fix Snackbar crashing the whole app (#15774)
This PR fixes a crash of the app when a Snackbar tries to render an
object.

<img width="3002" height="754" alt="image"
src="https://github.com/user-attachments/assets/988f97eb-5c8a-44f8-ac8e-e2953b872bac"
/>

What happened : the backend sent a MessageDescriptor in
`extensions.userFriendlyMessage` while it should have sent a translated
string.

But it is a problem that the Snackbar can end up rendering objects and
crashing the whole app because it is a the highest level in the tree.

So this PR hardens many points to avoid future bugs : 
- Sanitize what is rendered by the Snackbar to avoid any crash
- Translate any MessageDescriptor object that could end up in the
frontend
- Fix the places in the backend where a MessageDescriptor wasn't
translated and sent directly to the frontend in
`use-graphql-error-handler.hook.ts`

Fixes https://github.com/twentyhq/twenty/issues/15685
Fixes https://github.com/twentyhq/core-team-issues/issues/1869
2025-11-13 12:01:06 +01:00
Aryan Bhati b82d38bb13 fix(ui): layout-shift-on-tasks (#15775)
Fixes #12090 

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

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

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


### Before 

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

### After


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

---------

Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
2025-11-13 10:56:18 +00:00
Balaji Krishnamurthy ec7e49c8bb fix: minor color changes (#15616)
Closes #15597

The `color` of `OnBoardingModalCircularIcon` was set to `gray`. Now it
is set to `inverted` and it is displayed properly. I couldn't figure out
how to reach the onboarding screen, so I created a temporary path and
rendered the element there to verify the changes. Attaching screenshots
of the same.
<img width="398" height="393" alt="Screenshot from 2025-11-05 00-11-05"
src="https://github.com/user-attachments/assets/25efc790-92a3-42b5-8298-5128a3f1a466"
/>

<img width="398" height="418" alt="Screenshot from 2025-11-05 00-10-32"
src="https://github.com/user-attachments/assets/af52c695-4b01-40e9-a873-39d491c633cc"
/>

Additionally, a border has been added to the color picker icons.
<img width="573" height="383" alt="Screenshot from 2025-11-05 00-12-23"
src="https://github.com/user-attachments/assets/03d967aa-8c6f-4dfd-be3d-a2e16fe12b9a"
/>

I noticed that the dropdown after clicking on the icon also renders a
bunch of colors. Do let me know if these need the same border as well.
<img width="571" height="366" alt="Screenshot from 2025-11-05 00-12-37"
src="https://github.com/user-attachments/assets/a13bf253-6765-4d7a-9f0f-17cb7375a515"
/>

---------

Co-authored-by: bosiraphael <raphael.bosi@gmail.com>
2025-11-13 10:00:28 +00:00
BOHEUS 3c58ed233b Add missing color changes in workflow steps with no data (#14967)
Fixes #14888
2025-11-13 10:39:38 +01:00
martmull 1b308a7b74 Fix can't save empty env variables values (#15773) 2025-11-12 15:48:55 +01:00
Raphaël Bosi ea56586766 Fix horizontal bar chart spacing between ticks (#15702)
This PR fixes a bug where the spacing between ticks on the Y axis was
adjusted according to the width of the widget where it should have been
adjusted according to the height. Same for the X axis.

**Before**:
Works for the vertical layout but not for the horizontal layout


https://github.com/user-attachments/assets/f0b94103-1ba6-4dbe-bbc6-c47541c1b5fa


**After**:
Works for both


https://github.com/user-attachments/assets/165faada-2943-4e05-92d6-a31def569500
2025-11-12 10:19:32 +00:00
Harshit Singh 065923d724 feat: Add Workflow duplicate step (#15622)
## Description

- This PR address issue
https://github.com/twentyhq/core-team-issues/issues/1800
- Added workflow duplicate option in workflow sidepanel
- Introduced DuplicateWorkflow.ts mutuation
- Updated graphql generated metadata with new duplicate type




## Visual Appearanc

<img width="1792" height="1031" alt="Screenshot 2025-11-07 at 4 46
22 PM"
src="https://github.com/user-attachments/assets/d75f99df-ae18-4b41-a5f4-21c50010cdbc"
/>


https://github.com/user-attachments/assets/3dbf73cf-f4dd-484c-94a3-29577cfbac25

---------

Co-authored-by: Devessier <baptiste@devessier.fr>
2025-11-12 10:53:25 +01:00
TakuyaKurimoto fcf66bc881 update Notes & Tasks to display the first-letter icon (#15729)
Closes https://github.com/twentyhq/twenty/issues/15630

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

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

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

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

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

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

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

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



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


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



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



We can still improve performance and re-render but that would represent
a global effort on D&D on general, table has the same problem currently,
but since we implemented virtualization it is bearable for now.
2025-11-11 17:07:40 +01:00
nitin 561297436e Anchored tooltip (#15568)
Issue - 
- tooltip gets too long when groupby has too much data points
- we need max height on tooltips
- we need to be able to scroll inside the tooltip
- not possible if the tooltip is following the cursor (which library
enforces)
- its not easy to customize Nivo's own tooltip to make it work how we
want it

what we want - 
- let the tooltip anchor to the bar in such a way -- that the top of the
bar aligns with the vertical middle of the tooltip
- add max height to the tooltip

what I did - 
- use floating portal from floating-ui/react
- get the hover datum (ie hovered bars) dimensions on mouse enter to
render the tooltip
- anchor the tooltip at the calculated position
- floating-ui handles the basic things like flipping/offset/shift
- clear the states as required

---------

Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
2025-11-11 16:47:41 +01:00
Abdul Rahman 2e359f5585 Fix AI table scroll overflow and tool input display (#15753)
- Fixed horizontal scroll overflow when tables appear in AI responses
- Fixed tool call input display to show only user-relevant input instead
of internal metadata (loadingMessage)

### Before

https://github.com/user-attachments/assets/870bf52d-7ffd-464e-9240-bd482ab19077


### After


https://github.com/user-attachments/assets/40a19fc0-6989-437f-b712-8141368179dc
2025-11-11 11:08:26 +01:00
Félix Malfait 11e07f90d2 refactor: Simplify CRUD services to leverage Common API (#15742)
## Summary

This PR refactors all Record CRUD services to use the Common API
(CommonQueryRunners) instead of directly accessing TwentyORM, achieving
**77% code reduction** while maintaining full functionality.

## Changes

### Code Reduction: -547 net lines (77%)
- **Before**: 901 lines across 5 services
- **After**: 354 lines (services + utility)
- **Deleted**: 547 lines of redundant code

### Services Simplified

| Service | Before | After | Reduction |
|---------|--------|-------|-----------|
| CreateRecordService | 142 | 59 | -83 lines |
| UpdateRecordService | 177 | 51 | -126 lines |
| DeleteRecordService | 137 | 51 | -86 lines |
| FindRecordsService | 233 | 68 | -165 lines |
| UpsertRecordService | 212 | 129 | -83 lines |

### Architecture Change

**Before:**
```
CRUD Services → TwentyORM
- Manual query building
- Manual permission checking
- Manual transformations
- Duplicated logic
```

**After:**
```
CRUD Services → CommonQueryRunners → TwentyORM
- Common API handles queries
- Common API handles permissions
- Common API handles transformations
- Single source of truth
```

### Module Dependencies Simplified

**Removed:**
- TwentyORMModule
- RecordPositionModule
- RecordTransformerModule
- WorkflowCommonModule

**Added:**
- CoreCommonApiModule
- WorkspaceMetadataCacheModule

**From 4 heavy dependencies → 2 clean dependencies**

## What Changed

### New Code
- `common-api-context-builder.util.ts` - Single shared utility (68
lines)

### Refactored Services
All services now follow a simple pattern:
1. Build Common API context
2. Call appropriate CommonQueryRunner
3. Return formatted result

Each service is now 50-120 lines instead of 140-230 lines.

### Type Fixes
- Fixed `FindRecordsParams.orderBy` type (was
`Partial<ObjectRecordOrderBy>`, now `ObjectRecordOrderBy`)
- Fixed `FindRecordsInput.gqlOperationOrderBy` type (same fix)

## Benefits

###  Code Quality
- 77% less code to maintain
- No code duplication
- Simpler, clearer logic
- Proper TypeScript types (no hacks)

###  Common API Integration
All services now get Common API benefits:
- Consistent permission checking
- Query hooks (before/after execution)
- Automatic input transformation
- Automatic position handling
- Result processing and enrichment
- Same behavior as REST/GraphQL

###  Safety Preserved
- createdBy actor metadata preserved for workflows
- All field validation maintained
- All transformations maintained
- All error handling maintained

###  No Breaking Changes
- Same external API for all services
- Workflows continue to work
- AI operations continue to work
- MCP operations continue to work

## Testing

-  TypeScript compiles
-  All files pass linting
-  No type casting hacks
-  Proper type safety throughout
- ⚠️ Integration tests recommended

## What Common API Handles For Us

1. **Record Position** - Automatic via `RecordPositionService`
2. **Input Transformation** - Automatic for NUMBER, RICH_TEXT, PHONES,
EMAILS, LINKS
3. **createdBy Actor** - Injected via `CreatedByCreateOnePreQueryHook` +
explicit workflow actor
4. **Field Validation** - Only processes valid fields
5. **Permissions** - Validates permissions before execution
6. **Query Hooks** - Before/after execution hooks work
7. **Error Handling** - Consistent exception handling

## Files Modified (12)

**Services (6):**
- create-record.service.ts
- update-record.service.ts
- delete-record.service.ts
- find-records.service.ts
- upsert-record.service.ts
- record-crud.module.ts

**Types (2):**
- find-records-params.type.ts
- record-crud-input.type.ts

**Workflows (1):**
- find-records.workflow-action.ts

**New Files (3):**
- common-api-context-builder.util.ts
- REFACTORING_COMPLETE.md
- REFACTORING_ANALYSIS.md

## Verification Checklist

- [x] TypeScript compiles
- [x] Linter passes
- [x] No type hacks (`as unknown as` removed)
- [x] createdBy preserved for workflows
- [x] Module dependencies simplified
- [x] Common API integration complete
- [ ] Integration tests pass (recommended)
- [ ] Workflow execution tested (recommended)

## Related Issues

This refactoring establishes the pattern for making CRUD operations
consistent across all presentation layers (REST, GraphQL,
Tools/Workflows/AI/MCP).
2025-11-11 11:07:36 +01:00
Charles Bochet 7099b1c174 Fix export CSV not using right columns (#15752)
Fixes https://github.com/twentyhq/twenty/issues/15575
2025-11-10 22:00:39 +01:00
Shantanu Gupta 06b8ea7c36 FIX: export view not exporting all records (#15509)
Fixes #15508 
Addresses the issue where the "Export View" functionality was not
exporting all records from a view. Users reported that only a subset of
records were exported, even when the view contained more. This led to
incomplete data exports.

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

The PR modifies
`packages/twenty-front/src/modules/object-record/hooks/useLazyFetchAllRecords.ts`
to explicitly pass the `limit` parameter (which correctly reflects the
`pageSize`) to the `fetchMoreRecordsLazy` function. This ensures that
all subsequent data fetches during an export operation adhere to the
configured page size, allowing for the complete retrieval of all
records.
2025-11-10 21:25:39 +01:00
Weiko 02fda92a93 Global workspace datasource poc (#15744)
## Context
This PR introduces a Global Workspace DataSource that consolidates
workspace-specific database access through a single TypeORM DataSource
instance with AsyncLocalStorage-based context management instead of N
workspace datasources.

- Created GlobalWorkspaceDataSource extending TypeORM's DataSource to
manage multiple workspaces with entity metadata caching (1-hour TTL)
- Implemented AsyncLocalStorage for workspace context propagation
(WorkspaceContextForStorage) containing workspace ID, metadata,
permissions, and feature flags
- Modified query execution flow to wrap operations in workspace context
via GlobalWorkspaceOrmManager.executeInWorkspaceContext()
- Added schema name to entity schemas for proper multi-tenant database
separation

Next: 
- use the new global workspace datasource everywhere and deprecate
workspace datasource factory
- improve metadata caching using a short TTL to avoid multiple calls to
redis
- Leverage the new WorkspaceContextALS and put it higher in the request
hierarchy to have access to permission, metadata and featureflag
everywhere --- build it manually for commands --- find a way to
propagate it in jobs?
- Remove PG_POOL patch once we have a unique datasource and increase
global datasource pool size

## Implementation
Why ALS:

1. Automatic Per-Request Isolation

With schema-based multi-tenancy, each workspace has its own PostgreSQL
schema
(e.g. workspace_20202020-1c25-4d02-bf25-6aeccf7ea419).
The critical challenge is ensuring that concurrent requests from
different tenants don't interfere with each other.
```typescript
// Request A (Workspace 1) and Request B (Workspace 2) executing concurrently

// Without ALS: Race condition — they'd share the same global state!
// With ALS: Each request has isolated context ✓
```
ALS automatically isolates context per async execution chain, so:
- Request from Tenant A → ALS stores workspaceId: "tenant-a" → Queries
hit workspace_tenant_a schema
- Request from Tenant B → ALS stores workspaceId: "tenant-b" → Queries
hit workspace_tenant_b schema

 No interference, even when executing simultaneously on the same
Node.js event loop.

2. No Manual Context Passing

Before ALS, you'd need to pass workspaceId through every function call:
```typescript
//  Without ALS - Context threading nightmare
getRepository(workspaceId, entity)
  → createEntityManager(workspaceId)
    → getMetadata(workspaceId, target)
      → findInCache(workspaceId, cacheKey)
```
With ALS:
```typescript
//  With ALS - Clean, implicit context
getRepository(entity)          // Reads workspaceId from ALS
  → createEntityManager()      // Reads workspaceId from ALS
    → getMetadata(target)      // Reads workspaceId from ALS
      → findInCache(cacheKey)  // Reads workspaceId from ALS
```
example
```typescript
override findMetadata(target: EntityTarget<ObjectLiteral>): EntityMetadata | undefined {
  const context = getWorkspaceContext(); // 👈 Automatically gets the right workspace!
  const { workspaceId, metadataVersion } = context;
  const cacheKey = `${workspaceId}-${metadataVersion}`;
  // ... returns metadata for THIS workspace's schema
}
```

3. Async Chain Propagation

Node.js operations are heavily async. ALS automatically propagates
context through:

- async/await chains
- Promise chains
- Callbacks

```typescript
executeInWorkspaceContext(workspaceId, async () => {
  await prepareContext();           // Has context ✓
  const results = await run();      // Has context ✓
  await enrichResults();            // Has context ✓

  // Even nested async operations maintain context!
  await Promise.all([
    saveToCache(),   // Has context ✓
    emitEvent(),     // Has context ✓
    logMetrics(),    // Has context ✓
  ]);
});
```
5. Schema-Specific Metadata Caching

The implementation caches entity metadata per workspace + version:
```typescript
// Cache key format: "workspaceId-metadataVersion"
const cacheKey = `${workspaceId}-${metadataVersion}`;
```
Why this matters with schemas:

- Each workspace has different table structures (custom fields, objects)
- EntitySchema includes schema: "workspace_xxx" property
- Each cached metadata points to the correct schema

ALS ensures getWorkspaceContext() returns the right workspaceId,
so you always get the correct schema's metadata from cache.

6. Single DataSource for All Tenants

The key change here:
```typescript
//  Old approach: One DataSource per tenant
const dataSourceTenantA = new DataSource({ schema: 'workspace_a' });
const dataSourceTenantB = new DataSource({ schema: 'workspace_b' });
// Problem: Hundreds of DB connection pools!
```
```typescript
//  New approach: One shared DataSource + ALS context
const globalDataSource = new GlobalWorkspaceDataSource();

// ALS determines which schema to use at runtime
```
When you call:
```typescript
globalDataSource.getRepository('person');
```
It internally does:
```typescript
const context = getWorkspaceContext();  // Gets current tenant from ALS
const metadata = this.findMetadata('person'); // Finds metadata for THIS tenant's schema
// EntityMetadata includes: schema: "workspace_20202020-1c25..."
// TypeORM automatically queries: SELECT * FROM "workspace_20202020-1c25...".person
```
7. Request Lifecycle Example

```typescript
// 1. GraphQL request arrives: "query people { ... }"
// 2. Middleware extracts authContext.workspace.id = "tenant-a"
// 3. Query runner wraps execution in ALS:
executeInWorkspaceContext("tenant-a", async () => {
  // 4. Everything inside has access to workspace context:
  const repo = getRepository('person');      // ALS → tenant-a
  const metadata = getMetadata('person');    // ALS → tenant-a → cache["tenant-a-v5"]

  // 5. TypeORM builds query with correct schema:
  // SELECT * FROM "workspace_tenant_a"."person" WHERE ...

  // 6. Even nested calls work:
  await saveAuditLog();  // ALS → tenant-a → correct audit schema
  await emitWebhook();   // ALS → tenant-a → correct tenant webhook
});
// 7. Request completes, ALS context automatically cleaned up
```

8. Safety & Error Prevention

```typescript
// If you forget to set context:
const context = getWorkspaceContext();
//  Throws: "Workspace context not set..."
// Fails fast rather than querying wrong schema!

// Can't accidentally query wrong tenant:
// Context is immutable within execution scope
```
2025-11-10 17:32:49 +01:00
Paul Rastoin 7a1e699fc8 Twenty standard and workspace custom applications 1/3 (#15625)
# Introduction
related to https://github.com/twentyhq/core-team-issues/issues/1833
In this PR we're starting the sync-metadata and standardIds deprecation
by introducing `twenty-standard` application that will regroup every
standard object such as company and opportunities. But also the
`custom-workspace-application` which is an app created at the same time
as a workspace and that will regroup everything configure within the
workspace ( custom objects fields etc )

## What's done
On both new workspace and seeded workspace creation:
- Creating a custom workspace app
- Creating a twenty standard app
- Refactored the seed core schema and workspace creation to be run
within a transaction in order to handle circular dependency foreignkey
requirements ( which is deferred for app toward workspace )
- Updated workspace entity to have a custom workspace relation (
nullable for the moment until we implem an upgrade command to handle
retro comp )
- Integration testing on user, workspace creation deletion and expected
default apps creation
- ~~Soft deleted user on `deleteUser`~~ Done by marie and rebased on it

## What's next
- Update seeder to propagate the `twenty-standard` workspace
`applicationId` to every standard synchronized entities ( cheap and fast
iteration through the about to be deprecated sync-metadata as an easy
way to synchronize standards metadata entities ).
- Update seeder to propagate the `custom-workspace-application`
workspace `applicationId` to anything custom ( `pets` and `rockets` )
- Prepend `custom-workspace-application` `applicationId` to every
metadata API operations ( create a specific cache etc )
- Upgrade command on all existing workspace to create a custom app and
associate its applicationId to any existing custom entities
- Make `universalIdentifier` and `applicationId` required for any
syncable entity
2025-11-10 16:13:12 +01:00
github-actions[bot] 2c0df3ca99 i18n - translations (#15734)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2025-11-09 21:32:52 +01:00
Rounak Joshi 9f594cda1c Slash Command Implementation in Advanced Text Editor (#15488)
Part of Fixing Issue #14976 

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

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

---

### Implementation Overview

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

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

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

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


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

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

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


<!-- CURSOR_SUMMARY -->
---

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

---------

Co-authored-by: Félix Malfait <felix@twenty.com>
2025-11-09 21:18:56 +01:00
Abdul Rahman 4a15cbc97c Add token renewal to agent chat transport (#15727) 2025-11-09 13:57:24 +01:00
Abdul Rahman 06d8c8c76a Fix find tool filters by mapping many-to-one relations to fieldId (#15716)
**Root Cause**  
Many-to-one relation filters were being exposed under the relation name
(e.g., `company`) instead of the corresponding foreign-key attribute
(e.g., `companyId`).

**Change**  
- Detect many-to-one relation metadata and remap those filter keys to
`<fieldName>Id`.
- Removed some unused code unrelated to this fix.
2025-11-08 14:32:06 +01:00
github-actions[bot] 136289562e i18n - translations (#15718)
Created by Github action

Co-authored-by: github-actions <github-actions@twenty.com>
2025-11-08 07:48:39 +01:00
github-actions[bot] caecf2d0c2 i18n - translations (#15717)
Created by Github action

---------

Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
Co-authored-by: github-actions <github-actions@twenty.com>
2025-11-08 07:43:59 +01:00
martmull bce1bcf1fa Fix workflow run updates real time (#15701)
as title

## after


https://github.com/user-attachments/assets/34239b6e-16d6-4afd-9a54-cb4767179bea
2025-11-07 15:54:13 +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
Raphaël Bosi 44d6ec2594 Widget: Allow resizing from all corners and sides (#15680)
https://github.com/user-attachments/assets/3e4e1da2-87e6-440e-8371-835ef6eccf59
2025-11-07 15:28:39 +01:00
Abdul Rahman 54815196c1 Improve AI Tool Step Renderer Layout and JSON Tree Scrolling (#15698)
### Before


https://github.com/user-attachments/assets/a222a6ff-550c-453b-bc0b-ee9bdb925956


### After



https://github.com/user-attachments/assets/249b7097-8dc1-4611-8205-2a43cb015a33
2025-11-07 13:31:05 +01:00
github-actions[bot] c9d7361e7c i18n - translations (#15689)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2025-11-06 19:40:28 +01:00
Marie 4ce93aee52 Fix user deletion flows (#15614)
**Before**
- any user with workpace_members permission was able to remove a user
from their workspace. This triggered the deletion of workspaceMember +
of userWorkspace, but did not delete the user (even if they had no
workspace left) nor the roleTarget (acts as junction between role and
userWorkspace) which was left with a userWorkspaceId pointing to
nothing. This is because roleTarget points to userWorkspaceId but the
foreign key constraint was not implemented
- any user could delete their own account. This triggered the deletion
of all their workspaceMembers, but not of their userWorkspace nor their
user nor the roleTarget --> we have orphaned userWorkspace, not
technically but product wise - a userWorkspace without a workspaceMember
does not make sense

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

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

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


Fixes https://github.com/twentyhq/twenty/issues/14608
2025-11-06 18:29:12 +00:00
Baptiste Devessier bfe1f47065 Create old fields design widget (#15645)
In this PR:

- Pass `layoutMode` and `tabId` via PageLayoutContentContext provider
- Getting `pageLayoutType` from the current page layout
- Getting isInPinnedTab through `useIsInPinnedTab` hook

## Before

<img width="3456" height="2160" alt="CleanShot 2025-11-06 at 14 22
44@2x"
src="https://github.com/user-attachments/assets/763bb413-5739-45ef-85ed-82a72415886f"
/>

## After

<img width="3456" height="2162" alt="CleanShot 2025-11-06 at 14 20
38@2x"
src="https://github.com/user-attachments/assets/eee6cccd-9d36-426e-a22f-400e8f7f9413"
/>

---------

Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
2025-11-06 18:16:42 +01:00
Raphaël Bosi 931d12c77b Add animations on widget buttons and on action buttons (#15631)
Animated:
- Grip
- Trash can
- Action buttons


https://github.com/user-attachments/assets/1cac7a5e-2036-4308-9622-3b4809ae90a3
2025-11-06 17:38:05 +01:00
Paul Rastoin 137aba049d Fix tsconfigpaths root (#15683)
# Introduction
We've facing facing intra package build error for a moment such as:
```ts
vite v7.1.12 building for production...
src/components/BaseEmail.tsx:20:19 - error TS2719: Type 'import("/Users/paulrastoin/ws/twenty/node_modules/@lingui/core/dist/index").I18n' is not assignable to type 'import("/Users/paulrastoin/ws/twenty/node_modules/@lingui/core/dist/index").I18n'. Two different types with this name exist, but they are unrelated.
  Types have separate declarations of a private property '_locale'.

20     <I18nProvider i18n={i18nInstance}>
                     ~~~~

  node_modules/@lingui/react/dist/shared/react.b2b749a9.d.ts:42:5
    42     i18n: I18n;
           ~~~~
    The expected type comes from property 'i18n' which is declared here on type 'IntrinsicAttributes & Omit<I18nContext, "_"> & { children?: ReactNode; }'
```

and now since hacktoberfest merge getting even more such as:
```ts
➜  twenty git:(main) ✗ npx nx build twenty-emails

   ✔  2/2 dependent project tasks succeeded [2 read from cache]

   Hint: you can run the command with --verbose to see the full dependent project outputs

——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————

[tsconfig-paths] An error occurred while parsing "/Users/paulrastoin/ws/twenty/packages/twenty-apps/hacktoberfest-2025/linkedin-browser-extension/browser-extension/tsconfig.json". See below for details. To disable this message, set the `ignoreConfigErrors` option to true.
TSConfckParseError: failed to resolve "extends":"./.wxt/tsconfig.json" in /Users/paulrastoin/ws/twenty/packages/twenty-apps/hacktoberfest-2025/linkedin-browser-extension/browser-extension/tsconfig.json
    at resolveExtends (file:///Users/paulrastoin/ws/twenty/node_modules/tsconfck/src/parse.js:261:8)
    at parseExtends (file:///Users/paulrastoin/ws/twenty/node_modules/tsconfck/src/parse.js:196:24)
    ... 5 lines matching cause stack trace ...
    at async createBuilder (file:///Users/paulrastoin/ws/twenty/node_modules/vite/dist/node/chunks/config.js:34104:19)
    at async CAC.<anonymous> (file:///Users/paulrastoin/ws/twenty/node_modules/vite/dist/node/cli.js:629:10) {
  code: 'EXTENDS_RESOLVE',
  cause: Error: Cannot find module './.wxt/tsconfig.json'
  Require stack:
  - /Users/paulrastoin/ws/twenty/packages/twenty-apps/hacktoberfest-2025/linkedin-browser-extension/browser-extension/tsconfig.json
      at Module._resolveFilename (node:internal/modules/cjs/loader:1410:15)
      at require.resolve (node:internal/modules/helpers:163:19)
      at resolveExtends (file:///Users/paulrastoin/ws/twenty/node_modules/tsconfck/src/parse.js:249:14)
      at parseExtends (file:///Users/paulrastoin/ws/twenty/node_modules/tsconfck/src/parse.js:196:24)
      at Module.parse (file:///Users/paulrastoin/ws/twenty/node_modules/tsconfck/src/parse.js:54:23)
      at async Promise.all (index 21)
      at async BasicMinimalPluginContext.configResolved (/Users/paulrastoin/ws/twenty/node_modules/vite-tsconfig-paths/dist/index.js:134:9)
      at async Promise.all (index 0)
      at async resolveConfig (file:///Users/paulrastoin/ws/twenty/node_modules/vite/dist/node/chunks/config.js:35892:2)
      at async createBuilder (file:///Users/paulrastoin/ws/twenty/node_modules/vite/dist/node/chunks/config.js:34104:19) {
    code: 'MODULE_NOT_FOUND',
    requireStack: [
      '/Users/paulrastoin/ws/twenty/packages/twenty-apps/hacktoberfest-2025/linkedin-browser-extension/browser-extension/tsconfig.json'
    ]
  },
  tsconfigFile: '/Users/paulrastoin/ws/twenty/packages/twenty-apps/hacktoberfest-2025/linkedin-browser-extension/browser-extension/tsconfig.json'
}
vite v7.1.12 building for production...
src/components/BaseEmail.tsx:20:19 - error TS2719: Type 'import("/Users/paulrastoin/ws/twenty/node_modules/@lingui/core/dist/index").I18n' is not assignable to type 'import("/Users/paulrastoin/ws/twenty/node_modules/@lingui/core/dist/index").I18n'. Two different types with this name exist, but they are unrelated.
  Types have separate declarations of a private property '_locale'.

20     <I18nProvider i18n={i18nInstance}>
                     ~~~~

  node_modules/@lingui/react/dist/shared/react.b2b749a9.d.ts:42:5
    42     i18n: I18n;
           ~~~~
    The expected type comes from property 'i18n' which is declared here on type 'IntrinsicAttributes & Omit<I18nContext, "_"> & { children?: ReactNode; }'

✓ 492 modules transformed.

[vite:dts] Start generate declaration files...
computing gzip size (31)...[vite:dts] Declaration files built in 981ms.

dist/locales/generated/zh-CN.mjs        4.16 kB │ gzip:   2.02 kB
dist/locales/generated/zh-TW.mjs        4.21 kB │ gzip:   2.05 kB
dist/locales/generated/en.mjs           4.34 kB │ gzip:   1.28 kB
dist/locales/generated/fi-FI.mjs        4.45 kB │ gzip:   1.90 kB
dist/locales/generated/af-ZA.mjs        4.50 kB │ gzip:   1.88 kB
dist/locales/generated/no-NO.mjs        4.52 kB │ gzip:   1.85 kB
dist/locales/generated/da-DK.mjs        4.52 kB │ gzip:   1.84 kB
dist/locales/generated/pt-BR.mjs        4.54 kB │ gzip:   1.89 kB
dist/locales/generated/sv-SE.mjs        4.54 kB │ gzip:   1.88 kB
dist/locales/generated/nl-NL.mjs        4.55 kB │ gzip:   1.87 kB
dist/locales/generated/pt-PT.mjs        4.56 kB │ gzip:   1.88 kB
dist/locales/generated/it-IT.mjs        4.59 kB │ gzip:   1.87 kB
dist/locales/generated/pl-PL.mjs        4.66 kB │ gzip:   2.04 kB
dist/locales/generated/cs-CZ.mjs        4.67 kB │ gzip:   2.05 kB
dist/locales/generated/es-ES.mjs        4.70 kB │ gzip:   1.90 kB
dist/locales/generated/tr-TR.mjs        4.70 kB │ gzip:   2.02 kB
dist/locales/generated/de-DE.mjs        4.71 kB │ gzip:   1.97 kB
dist/locales/generated/ca-ES.mjs        4.73 kB │ gzip:   1.92 kB
dist/locales/generated/ko-KR.mjs        4.73 kB │ gzip:   2.14 kB
dist/locales/generated/ro-RO.mjs        4.73 kB │ gzip:   1.95 kB
dist/locales/generated/fr-FR.mjs        4.74 kB │ gzip:   1.92 kB
dist/locales/generated/hu-HU.mjs        4.82 kB │ gzip:   2.09 kB
dist/locales/generated/he-IL.mjs        4.88 kB │ gzip:   1.99 kB
dist/locales/generated/ja-JP.mjs        4.95 kB │ gzip:   2.19 kB
dist/locales/generated/vi-VN.mjs        5.19 kB │ gzip:   2.14 kB
dist/locales/generated/ar-SA.mjs        5.35 kB │ gzip:   2.21 kB
dist/locales/generated/pseudo-en.mjs    5.68 kB │ gzip:   2.27 kB
dist/locales/generated/sr-Cyrl.mjs      5.82 kB │ gzip:   2.32 kB
dist/locales/generated/uk-UA.mjs        6.11 kB │ gzip:   2.41 kB
dist/locales/generated/el-GR.mjs        6.47 kB │ gzip:   2.53 kB
dist/locales/generated/ru-RU.mjs        6.62 kB │ gzip:   2.55 kB
dist/index.mjs                        822.22 kB │ gzip: 179.78 kB
dist/locales/generated/zh-CN.js        4.23 kB │ gzip:   2.08 kB
dist/locales/generated/zh-TW.js        4.28 kB │ gzip:   2.10 kB
dist/locales/generated/en.js           4.41 kB │ gzip:   1.33 kB
dist/locales/generated/fi-FI.js        4.52 kB │ gzip:   1.95 kB
dist/locales/generated/af-ZA.js        4.56 kB │ gzip:   1.93 kB
dist/locales/generated/no-NO.js        4.58 kB │ gzip:   1.90 kB
dist/locales/generated/da-DK.js        4.59 kB │ gzip:   1.89 kB
dist/locales/generated/pt-BR.js        4.60 kB │ gzip:   1.94 kB
dist/locales/generated/sv-SE.js        4.61 kB │ gzip:   1.93 kB
dist/locales/generated/nl-NL.js        4.62 kB │ gzip:   1.92 kB
dist/locales/generated/pt-PT.js        4.63 kB │ gzip:   1.93 kB
dist/locales/generated/it-IT.js        4.66 kB │ gzip:   1.92 kB
dist/locales/generated/pl-PL.js        4.73 kB │ gzip:   2.09 kB
dist/locales/generated/cs-CZ.js        4.74 kB │ gzip:   2.10 kB
dist/locales/generated/es-ES.js        4.77 kB │ gzip:   1.95 kB
dist/locales/generated/tr-TR.js        4.77 kB │ gzip:   2.07 kB
dist/locales/generated/de-DE.js        4.77 kB │ gzip:   2.02 kB
dist/locales/generated/ca-ES.js        4.80 kB │ gzip:   1.97 kB
dist/locales/generated/ko-KR.js        4.80 kB │ gzip:   2.20 kB
dist/locales/generated/ro-RO.js        4.80 kB │ gzip:   2.00 kB
dist/locales/generated/fr-FR.js        4.81 kB │ gzip:   1.97 kB
dist/locales/generated/hu-HU.js        4.89 kB │ gzip:   2.14 kB
dist/locales/generated/he-IL.js        4.95 kB │ gzip:   2.04 kB
dist/locales/generated/ja-JP.js        5.02 kB │ gzip:   2.24 kB
dist/locales/generated/vi-VN.js        5.26 kB │ gzip:   2.19 kB
dist/locales/generated/ar-SA.js        5.42 kB │ gzip:   2.26 kB
dist/locales/generated/pseudo-en.js    5.75 kB │ gzip:   2.32 kB
dist/locales/generated/sr-Cyrl.js      5.89 kB │ gzip:   2.37 kB
dist/locales/generated/uk-UA.js        6.18 kB │ gzip:   2.47 kB
dist/locales/generated/el-GR.js        6.54 kB │ gzip:   2.58 kB
dist/locales/generated/ru-RU.js        6.69 kB │ gzip:   2.60 kB
dist/index.js                        606.48 kB │ gzip: 160.10 kB
✓ built in 2.45s

——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————

 NX   Successfully ran target build for project twenty-emails and 2 tasks it depends on (5s)

Nx read the output from the cache instead of running the command for 2 out of 3 tasks.
```

Fixing folder to search for tsconfig from
2025-11-06 16:28:01 +00:00
Guillim 373399fadc Settings of morph needs a CSS fix (#15681)
adding margin auto for morph preview card in order to vertically align
the box, as per figma

Before
<img width="467" height="331" alt="Screenshot 2025-11-06 at 16 36 00"
src="https://github.com/user-attachments/assets/23543cdc-d0f3-4bbf-8dc1-4ac5f26f786e"
/>

After
<img width="576" height="362" alt="Screenshot 2025-11-06 at 16 36 16"
src="https://github.com/user-attachments/assets/8530d59f-53a2-4eaa-834a-68b801bba3c8"
/>

Fixes https://github.com/twentyhq/core-team-issues/issues/1846
2025-11-06 17:06:04 +01:00