Commit Graph

48 Commits

Author SHA1 Message Date
Raphaël Bosi 29920738dc Fix stale token race forcing re-login on verify pages (#22573)
Landing on /verify often forced users to refresh and log in again. The
culprit is a logout side effect triggered by a stale token: when a
previous session's token pair is still in localStorage, boot queries use
it, fail, and the failed token renewal reacts by logging the user out
(onUnauthenticatedError clears the token pair). That logout fires while
the loginToken exchange is running, so it can wipe the fresh session
that was just stored.

Fix: clear the stale token pair right before exchanging the loginToken
(in useVerifyLogin, so both /verify and /verify-email are covered) —
with no stale token to renew, the logout side effect never fires against
the new session. Also removes the redundant clientConfig gate on the
verify effect, stops that same logout side effect from redirecting users
off /verify-email mid-verification, and always re-enables app redirects
after loading the user.

Note: opening a loginToken link now replaces an existing valid session
instead of keeping it.

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22573?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->
2026-07-06 14:58:32 +02:00
Raphaël Bosi 566c3b6629 Remove v1 onboarding and rely only on v2 (#22398)
https://github.com/user-attachments/assets/a6bfaac3-6c79-4fd5-999a-e6a70cff8ac8


Removes the old (v1) signup and onboarding flow now that v2 is the only
path, and drops the `isOnboardingV2` flag entirely. The surviving
(formerly-v2) pages reclaim the canonical `AppPath` members and clean
URLs (`/welcome`, `/verify`, `/workspace-activation`, `/create/profile`,
`/sync/emails`, `/install-apps`, `/invite-team`, `/plan-required`).

- Deletes the v1 pages, the v1 workspace-creation form, the
`isOnboardingV2State` flag + `onboardingV2` URL-param plumbing, and
`InstallAppsAutoSkipEffect`.
- Collapses the router and page-change navigation matrix to a single set
of paths, and renames the v2 components/stories to drop the `V2` suffix.

Follow-up fixes so the single flow behaves correctly on every
deployment:

- Restore the captcha-token, query-param and pageview effects on the
default (root) domain, and serve `/authorize` there so OAuth login keeps
working.
- Gate the invite-team → `/plan-required` interception on billing so
billing-disabled instances aren't trapped on the upgrade page.
- On a cold boot to an auth/onboarding path, show the onboarding loader
instead of the CRM skeleton, and add `/verify-email` and
`/plan-required/payment-success` to that loader path list.
- Add a retry to PaymentSuccess after the confirmation timeout, fix the
InstallApps icon crossfade, restyle the book-call pages for the
full-page layout, and delete code orphaned by the v1 removal.
- Extract the pageview/captcha/query-param logic out of
`PageChangeEffect` into standalone Effect components shared by the root
and workspace app trees.

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

---------

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
2026-07-03 16:12:34 +00:00
Raphaël Bosi facdbb5ba8 v2 onboarding: dedicated verify step and upgrade-free-trial as the last step (#22303)
https://github.com/user-attachments/assets/b1ee4f77-c6d7-4638-b9f1-dd801d1cc0db

Completes the onboarding-v2 flow: a dedicated verify step, the
reordering that makes the plan step come last, and the
upgrade-free-trial page itself.

## Verify step (`/verify-v2`)
After the cross-domain token exchange, v2 sign-ups land on a clean
`BlankLayout` "Verifying your email" screen (fading Twenty logo) instead
of the v1 `AuthModal` flashing over the background mock. The redirect
target is chosen from `isOnboardingV2` (read from the Jotai store at
redirect time). The pulsing logo is extracted into a shared
`OnboardingPulsingLogo`, reused by the workspace-activation loader.
`/verify-v2` joins the same exempt lists as `/verify` (ongoing-creation
guard, metadata gater, apollo unauthenticated handler, captcha, page
title) — intentionally not `useShowAuthModal`, which is what drops the
modal.

## Plan step is now last
`getOnboardingStatus` checks `PLAN_REQUIRED` after invite-team instead
of first, so onboarding runs workspace activation → email → profile →
invite → plan. This is what lets the upgrade step be reached as the
final step instead of gating right after sign-up. Applies to both v1 and
v2 (same order).

## Upgrade free trial page (`PlanRequiredV2` → `ChooseYourPlanV2` /
`UpgradeFreeTrial`)
The final step, full-screen under `BlankLayout` via
`OnboardingV2Layout`, matching the Figma (billing card with the Stripe
form, the "Basic / without credit card" option, trial + credits pills).
Reuses the v1 `ChooseYourPlanContent` billing logic
(`SubscriptionPaymentForm`, `useHandleCheckoutSession`). The "+N free
credits" reward comes from
`clientConfig.onboarding.upgradeCreditsReward` (sourced from
`BILLING_FREE_WORKFLOW_CREDITS_FOR_TRIAL_PERIOD_WITH_CREDIT_CARD`).

## Also
Fixes a latent staleness in the Apollo `onUnauthenticatedError` handler
— it captured `location` from the memoized client, now read via a ref —
so auth-path exemptions are correct after navigation.

Note: the onboarding step order change affects v1 too (plan becomes its
last step as well).
2026-06-29 16:32:30 +00:00
Félix Malfait b470cb21a1 Upgrade Apollo Client to v4 and refactor error handling (#18584)
## Summary
This PR upgrades Apollo Client from v3.10.0 to v4 and refactors error
handling patterns across the codebase to use a new centralized
`useSnackBarOnQueryError` hook.

## Key Changes

- **Dependency Update**: Upgraded `@apollo/client` from `^3.10.0` to
`^3.11.0` in root package.json
- **New Hook**: Added `useSnackBarOnQueryError` hook for centralized
Apollo query error handling with snack bar notifications
- **Error Handling Refactor**: Updated 100+ files to use the new error
handling pattern:
  - Removed direct `ApolloError` imports where no longer needed
- Replaced manual error handling logic with `useSnackBarOnQueryError`
hook
- Simplified error handling in hooks and components across multiple
modules
- **GraphQL Codegen**: Updated codegen configuration files to work with
Apollo Client v3.11.0
- **Type Definitions**: Added TypeScript declaration file for
`apollo-upload-client` module
- **Test Updates**: Updated test files to reflect new error handling
patterns

## Notable Implementation Details

- The new `useSnackBarOnQueryError` hook provides a consistent way to
handle Apollo query errors with automatic snack bar notifications
- Changes span across multiple feature areas: auth, object records,
settings, workflows, billing, and more
- All changes maintain backward compatibility while improving code
maintainability and reducing duplication
- Jest configuration updated to work with the new Apollo Client version

https://claude.ai/code/session_019WGZ6Rd7sEHuBg9sTrXRqJ

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-13 14:59:46 +01:00
Charles Bochet 9d57bc39e5 Migrate from ESLint to OxLint (#18443)
## Summary

Fully replaces ESLint with OxLint across the entire monorepo:

- **Replaced all ESLint configs** (`eslint.config.mjs`) with OxLint
configs (`.oxlintrc.json`) for every package: `twenty-front`,
`twenty-server`, `twenty-emails`, `twenty-ui`, `twenty-shared`,
`twenty-sdk`, `twenty-zapier`, `twenty-docs`, `twenty-website`,
`twenty-apps/*`, `create-twenty-app`
- **Migrated custom lint rules** from ESLint plugin format to OxLint JS
plugin system (`@oxlint/plugins`), including
`styled-components-prefixed-with-styled`, `no-hardcoded-colors`,
`sort-css-properties-alphabetically`,
`graphql-resolvers-should-be-guarded`,
`rest-api-methods-should-be-guarded`, `max-consts-per-file`, and
Jotai-related rules
- **Migrated custom rule tests** from ESLint `RuleTester` + Jest to
`oxlint/plugins-dev` `RuleTester` + Vitest
- **Removed all ESLint dependencies** from `package.json` files and
regenerated lockfiles
- **Updated Nx targets** (`lint`, `lint:diff-with-main`, `fmt`) in
`nx.json` and per-project `project.json` to use `oxlint` commands with
proper `dependsOn` for plugin builds
- **Updated CI workflows** (`.github/workflows/ci-*.yaml`) — no more
ESLint executor
- **Updated IDE setup**: replaced `dbaeumer.vscode-eslint` with
`oxc.oxc-vscode` extension, configured `source.fixAll.oxc` and
format-on-save with Prettier
- **Replaced all `eslint-disable` comments** with `oxlint-disable`
equivalents across the codebase
- **Updated docs** (`twenty-docs`) to reference OxLint instead of ESLint
- **Renamed** `twenty-eslint-rules` package to `twenty-oxlint-rules`

### Temporarily disabled rules (tracked in `OXLINT_MIGRATION_TODO.md`)

| Rule | Package | Violations | Auto-fixable |
|------|---------|-----------|-------------|
| `twenty/sort-css-properties-alphabetically` | twenty-front | 578 | Yes
|
| `typescript/consistent-type-imports` | twenty-server | 3814 | Yes |
| `twenty/max-consts-per-file` | twenty-server | 94 | No |

### Dropped plugins (no OxLint equivalent)

`eslint-plugin-project-structure`, `lingui/*`, `@stylistic/*`,
`import/order`, `prefer-arrow/prefer-arrow-functions`,
`eslint-plugin-mdx`, `@next/eslint-plugin-next`,
`eslint-plugin-storybook`, `eslint-plugin-react-refresh`. Partial
coverage for `jsx-a11y` and `unused-imports`.

### Additional fixes (pre-existing issues exposed by merge)

- Fixed `EmailThreadPreview.tsx` broken import from main rename
(`useOpenEmailThreadInSidePanel`)
- Restored truthiness guard in `getActivityTargetObjectRecords.ts`
- Fixed `AgentTurnResolver` return types to match entity (virtual
`fileMediaType`/`fileUrl` are resolved via `@ResolveField()`)

## Test plan

- [x] `npx nx lint twenty-front` passes
- [x] `npx nx lint twenty-server` passes
- [x] `npx nx lint twenty-docs` passes
- [x] Custom oxlint rules validated with Vitest: `npx nx test
twenty-oxlint-rules`
- [x] `npx nx typecheck twenty-front` passes
- [x] `npx nx typecheck twenty-server` passes
- [x] CI workflows trigger correctly with `dependsOn:
["twenty-oxlint-rules:build"]`
- [x] IDE linting works with `oxc.oxc-vscode` extension
2026-03-06 01:03:50 +01:00
Félix Malfait 6351c6c1c6 feat: remember original URL and redirect after login (#18308)
## Summary

- Implement a return-to-path mechanism that preserves the user's
intended destination across authentication flows (login, magic link,
cross-domain redirects)
- Uses layered persistence: Jotai atom (in-memory), sessionStorage with
TTL (tab-switch resilience), URL query parameter (cross-domain
propagation)
- Includes path validation to prevent open redirects, automatic cleanup
after successful login, and comprehensive test coverage
- Replaces the unused `previousUrlState` with a robust
`returnToPathState` system

## Test plan

- [ ] Visit a deep link (e.g. `/objects/tasks`) while logged out —
should redirect to login, then back to `/objects/tasks` after logging in
- [ ] Visit an OAuth authorize link while logged out — should redirect
to login, then to the authorize page
- [ ] Test magic link flow: click sign-in link that opens new tab —
should still redirect to original destination
- [ ] Test cross-domain: visit `app.twenty.com/objects/tasks` — should
preserve path through workspace domain redirect
- [ ] Verify auth/onboarding paths are excluded from being saved as
return paths
- [ ] Verify return-to-path is cleared after successful navigation
- [ ] All 215 existing `usePageChangeEffectNavigateLocation` tests pass


Made with [Cursor](https://cursor.com)
2026-03-02 19:00:48 +01:00
Charles Bochet d81f006979 Rename Jotai state hooks and utilities to consistent Atom-based naming (#18209)
## Summary

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

## Naming Convention

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

## Changes

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

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

### Utilities renamed:

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

## Details

- All definition files renamed to match new convention
- All import paths and usages updated across the entire `twenty-front`
package
- Jotai's native `useAtomValue` is aliased as `useJotaiAtomValue` in the
wrapper hook to avoid collision
- Legacy Recoil files in `state/utils/` and `component-state/utils/`
left untouched (separate naming scope)
- Typecheck passes cleanly
2026-02-25 01:55:46 +01:00
Charles Bochet b51eb6471f Jotai 12 (#18160)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-23 12:01:37 +01:00
Charles Bochet d5a8cc2085 Migrate more to Jotai (#17903)
Here we go again
2026-02-12 18:13:31 +01:00
Etienne 2f298307f9 Handle 413 with user friendly message (#17870)
Add friendly message for 413 errors. Currently, 413 errors originate
from the nginx server.
2026-02-11 17:03:22 +00:00
Charles Bochet cfdcc0065c Migrate workflow serverless to logic (#17646)
Migrations commands

---------

Co-authored-by: Charles Bochet <charles@macbook-pro-de-charles-1.home>
2026-02-02 19:39:20 +01:00
Félix Malfait c737028dd6 Move tools/eslint-rules to packages/twenty-eslint-rules (#17203)
## Summary

Moves the custom ESLint rules from `tools/eslint-rules` to
`packages/twenty-eslint-rules` for better organization within the
monorepo packages structure.

## Changes

- Move `eslint-rules` from `tools/` to `packages/twenty-eslint-rules`
- Use `loadWorkspaceRules` from `@nx/eslint-plugin` to load custom rules
- Update all ESLint configs to use the `twenty/` rule prefix instead of
`@nx/workspace-`
- Update `project.json`, `jest.config.mjs` with new paths
- Update `package.json` workspaces and `nx.json` cache inputs
- Update Dockerfile reference

## Technical Details

The custom ESLint rules are now loaded using Nx's `loadWorkspaceRules`
utility which:
- Handles TypeScript transpilation automatically
- Allows loading workspace rules from any directory
- Provides a cleaner approach than the previous `@nx/workspace-`
convention

## Testing

- Verified all 17 custom ESLint rules load correctly from the new
location
- Verified linting works on dependent packages (twenty-front,
twenty-server, etc.)
2026-01-17 07:37:17 +01:00
Félix Malfait b27a97f2c5 feat: enforce @/ alias for imports and fix all relative parent imports (#16787)
## Summary
This PR enforces the use of `@/` alias for imports instead of relative
parent imports (`../`).

## Changes

### ESLint Configuration
- Added `no-restricted-imports` pattern in `eslint.config.react.mjs` to
block `../*` imports with the message "Relative parent imports are not
allowed. Use @/ alias instead."
- Removed the non-working `import/no-relative-parent-imports` rule
(doesn't work properly in ESLint flat config)

### VS Code Settings
- Added `javascript.preferences.importModuleSpecifier: non-relative` to
`.vscode/settings.json` (TypeScript setting was already there)

### Code Fixes
- Fixed **941 relative parent imports** across **706 files** in
`packages/twenty-front`
- All `../` imports converted to use `@/` alias

## Why
- Consistent import style across the codebase
- Easier to move files without breaking imports
- Better IDE support for auto-imports
- Clearer understanding of where imports come from
2025-12-23 22:57:51 +01:00
Charles Bochet b2472b30c4 Add logs to debug user being disconnected randomly (#16037)
As per title, just adding logs to troubleshoot:
https://github.com/twentyhq/twenty/issues/13103
2025-11-24 19:49:02 +01:00
Félix Malfait f7cde28dd6 🔧 Restore PRs #14348 and #14352 that were reverted by PR #14347 (#14359)
## Problem

**CRITICAL:** Two PRs were accidentally reverted when PR #14347 "Prevent
csv export injections" was merged:

1. **PR #14348** "[Page Layout] - Review Refactor" -  **RESTORED**
2. **PR #14352** "Fix wrong path used by backend" -  **RESTORED**

## Root Cause Analysis

During the merge of PR #14347, there was a complex merge conflict with
PR #14352 "Fix wrong path used by backend". The merge commit
`324d7204bb` in the PR #14347 branch brought in changes from PR #14352,
but during the conflict resolution, **BOTH PR #14348 and PR #14352's
changes were accidentally overwritten**.

## What This PR Restores

This PR restores **BOTH** PRs by cherry-picking their commits:

###  PR #14348 Changes Restored:
- `GraphWidgetRenderer.tsx` - was deleted, now restored
- `WidgetRenderer.tsx` - was missing, now restored  
- `SettingsPageLayoutTabsInstanceId.ts` - was deleted, now restored
- `useUpdatePageLayoutWidget.ts` - was renamed back, now restored with
correct name
- Multiple test files that were deleted
- Several hook files that were renamed/reverted
- File renames: `usePageLayoutWidgetUpdate.ts` →
`useUpdatePageLayoutWidget.ts`
- Hook refactoring and test file organization
- Page layout component improvements

###  PR #14352 Changes Restored:
- **Types moved to twenty-shared:**
  - `packages/twenty-shared/src/types/AppBasePath.ts`  RESTORED
  - `packages/twenty-shared/src/types/AppPath.ts`  RESTORED
  - `packages/twenty-shared/src/types/SettingsPath.ts`  RESTORED
- **Navigation utilities moved to twenty-shared:**
- `packages/twenty-shared/src/utils/navigation/getAppPath.ts`  RESTORED
- `packages/twenty-shared/src/utils/navigation/getSettingsPath.ts` 
RESTORED
- **200+ import statements updated** across the codebase to use
twenty-shared
- **Old type files deleted** from twenty-front/src/modules/types/

## Evidence of Complete Restoration

**Before (reverted state):**
-  Types were in `packages/twenty-front/src/modules/types/`
-  Page layout files missing
-  Hook files incorrectly named

**After (this PR):**
-  Types correctly in `packages/twenty-shared/src/types/`
-  All page layout files restored
-  Hook files correctly named
-  All import statements updated

## Verification

**Total changes:**
- PR #14348: 36 files changed, 863 insertions(+), 442 deletions(-)
- PR #14352: 243 files changed, 492 insertions(+), 461 deletions(-)
- **Combined: 279 files changed, 1355 insertions(+), 903 deletions(-)**

## Impact

This completely restores both PRs that were accidentally lost, ensuring:
1. Page layout refactoring work is back
2. Type organization and path utilities are correctly in twenty-shared
3. Backend email paths work correctly again
4. No functionality is lost

Fixes the reversion caused by the merge conflict in PR #14347.

---------

Co-authored-by: nitin <142569587+ehconitin@users.noreply.github.com>
2025-09-08 21:48:13 +02:00
Félix Malfait cebcf4f1f5 Prevent csv export injections (#14347)
**Small Security Issue:** CSV exports were vulnerable to formula
injection attacks when users entered values starting with =, +, -, or @.
(only happens if a logged-in user injects corrupted data)

Solution:
- Added ZWJ (Zero-Width Joiner) protection that prefixes dangerous
values with invisible Unicode character
- This is the best way to preserve original data while preventing Excel
from executing formulas
- Added import cleanup to restore original values when re-importing
 
Changes:
- New sanitizeValueForCSVExport() function for security
- Updated all CSV export paths to use both security + formatting
functions
- Added comprehensive tests covering attack vectors and international
characters
- Also added cursor rules for better code consistency

---------

Co-authored-by: Charles Bochet <charlesBochet@users.noreply.github.com>
2025-09-08 17:57:46 +02:00
Félix Malfait 502bd07db9 Fix wrong path used by backend (#14352)
After moving a section on the frontend, this broke the path that was
sent by email on the backend.
This kind of error comes back every ~2-3 month under different forms so
we need a more robust solution: I moved routes to the shared folder,
that way we will share one common source of truth between the frontend
and the backend.

Fixes #14343
2025-09-08 16:07:13 +02:00
Félix Malfait 464a480043 Continue ESLINT9 Migration (#13795)
Might already fix #13793
2025-08-10 23:25:58 +02:00
Abdul Rahman 30dd457313 App version mismatch handling between frontend and backend (#13368)
https://github.com/user-attachments/assets/d153f177-4d70-4ec6-8693-15413e550938
2025-07-24 01:37:02 +05:30
Antoine Moreaux b1af98f93d refactor(auth): add workspaces selection (#12098) 2025-06-13 16:17:35 +02:00
Antoine Moreaux b7473371b3 fix(client-config): set isLoaded to false on API status update (#12371)
Attempt at #12289 (edit Félix: removed fix keyword since I don't think
it fixes it)

---------

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
Co-authored-by: Félix Malfait <felix@twenty.com>
2025-05-30 14:44:31 +02:00
Raphaël Bosi ffdedf7af3 Fix "PageChangeEffect does not run when changing view on the same object" (#12196)
Fixes https://github.com/twentyhq/core-team-issues/issues/950

This issue was due to the memoization inside `useIsMatchingLocation`,
which was rerendered only if the pathname changed but not the search
params.

After discussion with @lucasbordeau, we decided to remove the hook
`useIsMatchingLocation` and to create an equivalent util function which
takes the location as an argument.

---------

Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
2025-05-22 12:06:07 +02:00
Félix Malfait c66b7afefb Update cache policy (#11732)
I couldn't reproduce
https://github.com/twentyhq/twenty/issues/9299#issuecomment-2576868142
anymore

Closes #4914
2025-04-25 11:18:48 +02:00
Charles Bochet a7e6564017 Make token update synchronous on FE (#11486)
1. Removing tokenPair internal variable of ApolloFactory. We will relay
on cookieStorage
2. setting the cookie explicitely instead of only relaying on recoil
cookieEffect which is too late
2025-04-10 01:39:25 +02:00
Paul Rastoin 9ad8287dbc [REFACTOR] twenty-shared multi barrel and CJS/ESM build with preconstruct (#11083)
# Introduction

In this PR we've migrated `twenty-shared` from a `vite` app
[libary-mode](https://vite.dev/guide/build#library-mode) to a
[preconstruct](https://preconstruct.tools/) "atomic" application ( in
the future would like to introduce preconstruct to handle of all our
atomic dependencies such as `twenty-emails` `twenty-ui` etc it will be
integrated at the monorepo's root directly, would be to invasive in the
first, starting incremental via `twenty-shared`)

For more information regarding the motivations please refer to nor:
- https://github.com/twentyhq/core-team-issues/issues/587
-
https://github.com/twentyhq/core-team-issues/issues/281#issuecomment-2630949682

close https://github.com/twentyhq/core-team-issues/issues/589
close https://github.com/twentyhq/core-team-issues/issues/590

## How to test
In order to ease the review this PR will ship all the codegen at the
very end, the actual meaning full diff is `+2,411 −114`
In order to migrate existing dependent packages to `twenty-shared` multi
barrel new arch you need to run in local:
```sh
yarn tsx packages/twenty-shared/scripts/migrateFromSingleToMultiBarrelImport.ts && \
npx nx run-many -t lint --fix -p twenty-front twenty-ui twenty-server twenty-emails twenty-shared twenty-zapier
```
Note that `migrateFromSingleToMultiBarrelImport` is idempotent, it's atm
included in the PR but should not be merged. ( such as codegen will be
added before merging this script will be removed )

## Misc
- related opened issue preconstruct
https://github.com/preconstruct/preconstruct/issues/617

## Closed related PR
- https://github.com/twentyhq/twenty/pull/11028
- https://github.com/twentyhq/twenty/pull/10993
- https://github.com/twentyhq/twenty/pull/10960

## Upcoming enhancement: ( in others dedicated PRs )
- 1/ refactor generate barrel to export atomic module instead of `*`
- 2/ generate barrel own package with several files and tests
- 3/ Migration twenty-ui the same way
- 4/ Use `preconstruct` at monorepo global level

## Conclusion
As always any suggestions are welcomed !
2025-03-22 19:16:06 +01:00
Weiko 2fca60436b Add settingsPermission gate on the frontend (#10179)
## Context
With the new permissions system, we now need to hide some items from the
settings navigation and gate some routes so they can't be accessed
directly.
To avoid having to set permission gates in all the component pages, I'm
introducing wrapper at the route level and in the Navigation. This is
not required and is mostly for pages that are strictly mapped to a
single permission, for the rest we still need to use the different hooks
manually but it should avoid a bit of boilerplate for most of the cases.

- currentUserWorkspaceState to access settingsPermissions
- SettingsProtectedRouteWrapper in the router that can take a
settingFeature or a featureFlag as a gate logic, if the currentUser does
not have access to the settingFeature or the featureFlag is not enabled
they will be redirected to the profile page.
- SettingsNavigationItemWrapper & SettingsNavigationSectionWrapper. The
former will check the same logic as SettingsProtectedRouteWrapper and
not display the item if needed. The later will check if all
SettingsNavigationItemWrapper are not visible and hide itself if that's
the case.
- useHasSettingsPermission to get a specific permission state for the
current user
- useSettingsPermissionMap to get a map of all permissions with their
values for the current user
- useFeatureFlagsMap same but for featureFlags
2025-02-18 15:50:23 +01:00
Antoine Moreaux a85c4f263a fix(settings routing): handle trailing slashes in base paths (#10055)
Adjusted URL construction to properly handle trailing slashes in base
paths, ensuring consistent matching logic. Added logic for setting the
hotkey scope when navigating to the domain settings path.
2025-02-06 16:07:19 +00:00
Paul Rastoin 7fd89678b7 [CHORE] Avoid isDefined duplicated reference, move it to twenty-shared (#9967)
# Introduction
Avoid having multiple `isDefined` definition across our pacakges
Also avoid importing `isDefined` from `twenty-ui` which exposes a huge
barrel for a such little util function

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

Related PR https://github.com/twentyhq/twenty/pull/9941
2025-02-01 12:10:10 +01:00
Félix Malfait 549c3faf71 Add server translation (#9847)
First proof of concept for server-side translation.

The goal was to translate one metadata item:

<img width="939" alt="Screenshot 2025-01-26 at 08 18 41"
src="https://github.com/user-attachments/assets/e42a3f7f-f5e3-4ee7-9be5-272a2adccb23"
/>
2025-01-27 21:07:49 +01:00
Antoine Moreaux 34afd73923 refacto(invite|signin): remove unused code + fix signin on invite page. (#9745)
- Replace `window.location.replace` by `useRedirect` hook.
- Remove unused code: `switchWorkspace, addUserByInviteHash...`
- Refacto `Invite` component.
- Fix signin on invite modal.
2025-01-21 16:33:31 +01:00
Weiko 8c1b9bf540 Revert "Change Apollo cache policy" (#9480)
Reverts twentyhq/twenty#9296
until we implement a fix for
https://github.com/twentyhq/twenty/issues/9299#issuecomment-2576868142
2025-01-09 14:04:59 +01:00
Félix Malfait 03370b4a1b Change Apollo cache policy (#9296)
Set the default cache policy to 'cache-and-network' to make sure user
get more fresh data without refreshing the browser. Better for workspace
with several users working at the same time.

It will put more load on the server...

Note: I don't think the previous setting was taken into account
<img width="829" alt="Screenshot 2024-12-31 at 10 59 56"
src="https://github.com/user-attachments/assets/30ea74be-0907-422f-8e84-6c352d379337"
/>
2024-12-31 12:12:07 +01:00
gitstart-app[bot] b09ecfbb8c Migrate to twenty-ui - display (#8004)
This PR was created by [GitStart](https://gitstart.com/) to address the
requirements from this ticket:
[TWNTY-6871](https://clients.gitstart.com/twenty/5449/tickets/TWNTY-6871).

 --- 

### Description

Migrate:

- Info display component
- Status display component
- SeparatorLineText display component

### Demo

###### SeparatorLineText In Storybook


![](https://assets-service.gitstart.com/4814/c0a2cd49-e545-469a-b3d3-c02eb462b60d.png)

Info Component on Storybook


![](https://assets-service.gitstart.com/4814/6f3019c5-99e0-4365-a81e-241294887f9e.png)

Status Component on Storybook


![](https://assets-service.gitstart.com/4814/29b5142a-468f-4d7e-88ff-4f3bfdd5abda.png)

###### Fixes twentyhq/private-issues#95

---------

Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
2024-10-24 17:50:14 +02:00
Charles Bochet 17a1760afd Improve performance twenty orm (#6691)
## Context

As we grow, the messaging scripts are experiencing performance issues
forcing us to temporarily disable them on the cloud.
While investigating the performance, I have noticed that generating the
entity schema (for twentyORM) in the repository is taking ~500ms locally
on my Mac M2 so likely more on pods. Caching the entitySchema then!

I'm also clarifying naming around schemaVersion and cacheVersions ==>
both are renamed workspaceMetadataVersion and migrated to the workspace
table (the workspaceCacheVersion table is dropped).
2024-08-20 19:42:02 +02:00
martmull 9080981990 5509 remove flash on intermediate verify step when sign in with sso (#5526)
- remove flash on /verify
- remove flash on signInUp
- remove useless redirections and hooks
- Remove DefaultHomePage component
- Move redirections to /objects/companies in PageChangeEffect
- add useShowAuthModal hooks and tests
- add usePageChangeEffectNaviteLocation hooks and tests
- fix refresh token expired produces blank screen
2024-05-25 10:36:59 +02:00
Marie fe5b558477 [FE] Update remote table schema + refactor Tables list (#5548)
Closes #5062.

Refactoring tables list to avoid rendering all toggles on each sync or
schema update while using fresh data:
- introducing id for RemoteTables in apollo cache
- manually updating the cache for the record that was updated after a
sync or schema update instead of fetching all tables again
2024-05-23 17:00:24 +02:00
Muralidhar ff0db8d716 fix: linked records redirection (#4312)
Closes: #4093 
---------

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
2024-04-04 11:01:33 +02:00
rostaklein 306ef1df9c feat: schema version header check (#4563)
closes https://github.com/twentyhq/twenty/issues/4479

tried to catch the error inside various places including
https://github.com/twentyhq/twenty/blob/main/packages/twenty-server/src/engine/integrations/exception-handler/exception-handler.service.ts
but it seems like the error never reaches the GraphQL module 😮

any idea where we could intercept such an error `Cannot query field`?

---------

Co-authored-by: Jérémy Magrin <jeremy.magrin@gmail.com>
2024-04-04 09:52:45 +02:00
Aditya Pimpalkar 6ed0a5e2d6 feat: Redirect to previous page after login (#4731)
fix: #4721
2024-04-03 08:05:18 +02:00
Jérémy M d1ab063000 feat: use ApolloFactory for metadata client (#4608)
Co-authored-by: Charles Bochet <charles@twenty.com>
2024-03-25 19:15:46 +01:00
karthik 0315f35979 Replace Terms & Conditions with Sign Up Link on Sign In #4502 (#4617)
* Replace Terms & Conditions with Sign Up Link on Sign In #4502

* terms replaced with signup link

* begin fix (incomplete / do not merge)

* Revert

* Introduce welcome page

* Update Twenty website

---------

Co-authored-by: Mamatha Yarramaneni <mamathayarramaneni@Mamathas-Macbook.local>
Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
2024-03-22 22:40:01 +01:00
Charles Bochet cfb0cce9b8 Refactor Views by cleaning the code, relying on apolloCache and improving performances (#4516)
* Wip refactoring view

* Post merge conflicts

* Fix review

* Add create view capability

* Fix create object missing view

* Fix tests
2024-03-20 14:21:58 +01:00
Lucas Bordeau 581dfafe11 Renamed nullable utils into isDefined and isUndefinedOrNull (#4402)
* Renamed nullable utils into isDefined and isUndefinedOrNull
2024-03-11 14:28:57 +01:00
Charles Bochet 86c0f311f5 Introduce ComponentState (#4386)
* Proof of concept ComponentState

* Migrate to createState and createFamilyState

* Refactor

* Fix

* Fix tests

* Fix lint

* Fix tests

* Re-enable coverage
2024-03-09 11:31:00 +01:00
gitstart-app[bot] 17511be0cf TWNTY-3794 - ESLint rule: only take explicit boolean predicates in if statements (#4354)
* ESLint rule: only take explicit boolean predicates in if statements

Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: Toledodev <rafael.toledo@engenharia.ufjf.br>

* Merge main

Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: Toledodev <rafael.toledo@engenharia.ufjf.br>

* Fix frontend linter errors

Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: Toledodev <rafael.toledo@engenharia.ufjf.br>

* Fix jest

Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: Toledodev <rafael.toledo@engenharia.ufjf.br>

* Refactor according to review

Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: Toledodev <rafael.toledo@engenharia.ufjf.br>

* Refactor according to review

Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: Toledodev <rafael.toledo@engenharia.ufjf.br>

* Fix lint on new code

Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: Toledodev <rafael.toledo@engenharia.ufjf.br>

---------

Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com>
Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: Toledodev <rafael.toledo@engenharia.ufjf.br>
2024-03-09 10:48:19 +01:00
Deepak Kumar 46f0eb522f GH-3245 Change password from settings page (#3538)
* GH-3245 add passwordResetToken and passwordResetTokenExpiresAt column on user entity

* Add password reset token expiry delay env variable

* Add generatePasswordResetToken mutation resolver

* Update .env.sample file on server

* Add password reset token and expiry migration script

* Add validate password reset token query and a dummy password update (WIP) resolver

* Fix bug in password reset token generate

* add update password mutation

* Update name and add email password reset link

* Add change password UI on settings page

* Add reset password route on frontend

* Add reset password form UI

* sign in user on password reset

* format code

* make PASSWORD_RESET_TOKEN_EXPIRES_IN optional

* add email template for password reset

* Improve error message

* Rename methods and DTO to improve naming

* fix formatting of backend code

* Update change password component

* Update password reset via token component

* update graphql files

* spelling fix

* Make password-reset route authless on frontend

* show token generation wait time

* remove constant from .env.example

* Add PASSWORD_RESET_TOKEN_EXPIRES_IN in docs

* refactor emails module in reset password

* update Graphql generated file

* update email template of password reset

* add space between date and text

* update method name

* fix lint issues

* remove unused code, fix indentation, and email link color

* update test file for auth and token service

* Fix ci: build twenty-emails when running tests

---------

Co-authored-by: martmull <martmull@hotmail.fr>
2024-01-25 10:28:48 +01:00
Thaïs 8483cf0b4b POC: chore: use Nx workspace lint rules (#3163)
* chore: use Nx workspace lint rules

Closes #3162

* Fix lint

* Fix lint on BE

* Fix tests

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2024-01-03 23:07:25 +01:00
Charles Bochet 5bdca9de6c Migrate to a monorepo structure (#2909) 2023-12-10 18:10:54 +01:00