This PR is a follow-up of https://github.com/twentyhq/twenty/pull/10612
where the method of computation of total count was only taking records
fetched on the front end.
In this PR we use `totalCount` returned by `useFindManyRecords` instead,
which returns the total count in DB for the given filters.
We also set `shouldMatchRootQueryFilter` on board card create mutation
to avoid optimistic rendering issues.
Fixes https://github.com/twentyhq/twenty/issues/10598
### Context
For calendar and message sync job health monitoring, we used to
increment a counter in redis cache which could lead to concurrency
issue.
### Solution
- Update to a set structure in place of counter + use sAdd redis method
which is atomic
- Each minute another counter was incremented on a new cache key ->
Update to a 15s window
- Remove ONGOING status not needed. We only need status at job end (or
fail).
### Potential improvements
- Check for cache key existence before fetching data to avoid useless
call to redis ?
closes https://github.com/twentyhq/twenty/issues/10070
Solves: https://github.com/twentyhq/core-team-issues/issues/527
**TLDR:**
Basically the title. Fetches the product and prices from the database
instead of the environment variables.
**What this means:**
- new subscriptions in twenty will be hybrid (per seat subscription plus
an usage base product)
- right now the price for the usage base product is 0$ per unit
- The existing subscription will work normally, however we will need to
update their subscription items in order to contain the usage base
product (remember that the pricing intervals like monthly or yearly
should match in all the subscription items)
- The previous point can be done using Stripe Postman
**In order to test:**
- Have the environment variable IS_BILLING_ENABLED set to true and add
the other required environment variables for Billing to work
- Do a database reset (to ensure that the new feature flag is deleted
and that the billing tables are created)
- Run the command: npx nx run twenty-server:command
billing:sync-plans-data (if you don't do that the products and prices
will not be present in the database)
- Run the server , the frontend, the worker, and the stripe listen
command (stripe listen --forward-to
http://localhost:3000/billing/webhooks)
- Buy a subscription for acme workspace
- Update the quantity of members in a workspace (add or delete)
- Change the subscription interval
---------
Co-authored-by: Etienne <45695613+etiennejouan@users.noreply.github.com>
# Introduction
This PR contains around ~+300 tests + snapshot additions
Please check both object model creation and edition
Closes https://github.com/twentyhq/core-team-issues/issues/355
Refactored into two agnostic forms the Object Model settings page for
instance `/settings/objects/notes#settings`.
## `SettingsDataModelObjectAboutForm`
Added a new abstraction `SettingsUpdateDataModelObjectAboutForm` to wrap
`SettingsDataModelObjectAboutForm` in an `update` context

Schema:
```ts
const requiredFormFields = objectMetadataItemSchema.pick({
description: true,
icon: true,
labelPlural: true,
labelSingular: true,
});
const optionalFormFields = objectMetadataItemSchema
.pick({
nameSingular: true,
namePlural: true,
isLabelSyncedWithName: true,
})
.partial();
export const settingsDataModelObjectAboutFormSchema =
requiredFormFields.merge(optionalFormFields);
```
## `SettingsDataModelObjectSettingsFormCard`
Update on change

Schema:
```ts
export const settingsDataModelObjectIdentifiersFormSchema =
objectMetadataItemSchema.pick({
labelIdentifierFieldMetadataId: true,
imageIdentifierFieldMetadataId: true,
});
```
## Error management and validation schema
Improved the frontend validation form in order to attest that:
- Names are in camelCase
- Names are differents
- Names are not empty string ***SHOULD BE DONE SERVER SIDE TOO*** ( will
in a next PR, atm it literally breaks any workspace )
- Labels are differents
- Labels aren't empty strings
Hide the error messages as we need to decide what kind of styling we
want for our errors with forms
( Example with error labels )

This PR improves advanced filter code and fixes the bug that prevented
the creation of a filter group.
On the debugging side :
- Adding an advanced filter rule to create a group now works
On the refactoring side :
- We now use AdvancedFilterRecordFilterGroupChildOptionsDropdown to
clarify the code that show the option dropdown of a group.
- Refacatored useCurrentViewViewFilterGroup to
useChildRecordFiltersAndRecordFilterGroups. It is now using only
RecordFilter and RecordFilterGroup type instead of view types. It also
exports recordFilters and recordFilterGroups alone, when they are
children of a group, so we don't have to extract them from the merged
array that is typed RecordFilter | RecordFilterGroup, which is necessary
for displaying a group.
- Two typeguards have been introduced to help discern RecordFilter from
RecordFilterGroup : isRecordFilterGroupChildARecordFilterGroup and
isRecordFilterGroupChildARecordFilter, this allows to remove any typing
on child processing.
- Renaming from view to record (but there are still some left)
Closes https://github.com/twentyhq/core-team-issues/issues/491
This PR:
- Duplicates the right drawer pages for the command menu and replace all
the states used in these pages by component states (The right drawer
pages will be deleted when we deprecate the command menu v1)
- Wraps those pages into a component instance provider
- We store the component instance id upon navigation to restore the
states when we navigate back to a page
The only pages which are not updated for now are the pages related to
the workflow objects, this will be done in another PR.
In another PR, to improve the navigation experience I will replace the
icons and titles of the chips by the label identifier and the avatar if
the page is a record page.
https://github.com/user-attachments/assets/a76d3345-01f3-4db9-8a55-331cca8b87e0
---------
Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
- Create a workflow version component family state for each workflow
version : `stepId` => `StepOutputSchema`
- Populate this state when reaching the workflow visualizer of the
workflow version
- Wrap the right drawer when in edit mode with the context. It is the
only one who needs this schema
Next step:
- read this state from the variables
### Context
In order to deprecate search[Object] resolvers, we need to update
globalSearch resolver to bring it to the same level of functionality
### Solution
- Add includedObject args to search in pre-selected tables
- Add record filtering
### Tested on gql api ✅
- Simple search with search term
- Search with excluded objects, with included objects, with both and
both with search term
- Search with id filtering and all args combined
- Search with deletedAt filtering and all args combined
- from front, search in command menu
back end part of https://github.com/twentyhq/core-team-issues/issues/495
This PR removes the legacy useGetCurrentView hook that still returned
view with combined filters and sorts, which we don't use anymore.
This allows to remove a bug where we couldn't select the "open in"
settings of a view.
**TLDR:**
Deprecate getProductPrices in the frontEnd and replace it with
BillingBaseProductPrices.
**In order to test:**
- Have the environment variable IS_BILLING_ENABLED set to true and add
the other required environment variables for Billing to work
- Do a database reset (to ensure that the new feature flag is properly
added and that the billing tables are created)
- Run the command: npx nx run twenty-server:command
billing:sync-plans-data (if you don't do that the products and prices
will not be present in the database)
- Run the server , the frontend, the worker, and the stripe listen
command (stripe listen --forward-to
http://localhost:3000/billing/webhooks)
- Buy a subscription for acme workspace the choose your plan should be
using the new front end endpoint
This PR partially fixes advanced filters that were not working even with
feature flag activated.
Bugs fixed here :
- Advanced filters are not applied
- Root advanced filters cannot be created
- Cannot close advanced filters dropdown
- Can create multiple times the same non-advanced filter (reserved for
advanced filters)
upsertRecordFilter and removeRecordFilter have been refactored to take
record filter id instead of field metadata id, because the user should
be allowed to apply multiple filters for the same field.
We now base view filter CRUD directly on id, otherwise it could lead to
inconsistencies between advanced filters and simple filters.
This PR also refactors an important hook :
computeRecordGqlOperationFilter, so that it takes an object instead of
multiple params.
There are still bugs left, they will be taken in other PRs.
## Context
ActivityTargetsInlineCell was not using the useIsFieldValueReadOnly hook
but a dedicated prop instead. To align with the rest of the
implementation I've updated that part of the code however we still want
the table/kanban views to always be in read-only mode regardless of the
hook logic so I've updated the hook to take the ContextStoreViewType
into account.
# Introduction
close#9965
When landing on twenty you should be able to see a white screen
flickering if you had setup dark mode.
This is because before the SPA has been loaded we're not displaying
anything, which in a white screen from the browser.
During this period we should display a background color following the
user's device theme.
## Reproduction
In order to reproduce this behavior define a fast 4G connection from
your network console.
## Cons
Device mode might not the one chosen afterwards when the user has been
authenticated
=> We should store appearance settings in the local storage in order to
optimistically render the default "loading" background ( wouldn't be
100% bullet proof for instance if the user is now unauth for some reason
)
Body background will be override by theme after app bootstrap
This PR implements CRUD for view filter groups with the new logic as
already done for view filters and view sorts.
It also completely removes the old combined view filter group states and
usage.
This PR is quite big but the impact is limited since it only changes
advanced filters module, which is under feature flag at the moment, and
it is already in a broken state so unusable, even if someone activates
the feature flag.