Compare commits

..
468 Commits
Author SHA1 Message Date
Weiko e8dcb393e0 Upgrade 0.33.0
update upgrade-guide
2024-11-21 18:28:53 +01:00
WeikoandGitHub 1c04b2b0b7 [Flexible-schema] Refactor gql query runner to emit api event before processing to gql types (#8596)
Fixes https://github.com/twentyhq/twenty/issues/8300

## Context
API events were created too late and were already formatted as Gql
responses (including nesting with edges/node/type + formatting that
should not exist in an event payload). This PR moves the emit logic to
the resolver where we actually do the DB query
Note: Also added RESTORED events
2024-11-21 18:11:28 +01:00
Raphaël BosiandGitHub 8f5515cab3 8414 add records selection context inside the command menu (#8610)
Closes #8414



https://github.com/user-attachments/assets/a6aeb50a-b57d-43db-a839-4627c49b4155
2024-11-21 17:56:53 +01:00
WeikoandGitHub 52df5301a8 Enforce unique constraints for 0.33 (#8645)
## Context
- Fixing folder structure where 0.33 was inside 0.32.
- Updating the command so it runs enforce uniqueness on all tables
- Updating workspaces entities so the sync metadata adds the index
2024-11-21 17:39:26 +01:00
martmullandGitHub 39373b4a28 8643 fix sentry error (#8644)
- fixes missing data in event payload when adding a new workspaceMember
- add strong typing to database event emitters
2024-11-21 16:09:36 +00:00
Thomas des FrancsandGitHub 395da91071 wrote changelog for 0.33 (#8651)
![0
33-multiselect-filter](https://github.com/user-attachments/assets/e14b75af-f954-42a0-93fa-81d77e659cd2)
![0
33-percentage-number](https://github.com/user-attachments/assets/0899fffe-960f-43c5-a744-4e743520edef)

0.33 Changelog
2024-11-21 16:50:08 +01:00
Raphaël BosiandGitHub b8c01bcf5a Fix empty state not being centered (#8650)
Fix empty state not being centered

Before:
<img width="1512" alt="Capture d’écran 2024-11-21 à 15 50 56"
src="https://github.com/user-attachments/assets/8ea843b6-dce3-46d9-b2e3-db3be39e0cc1">

After:
<img width="1512" alt="Capture d’écran 2024-11-21 à 15 50 41"
src="https://github.com/user-attachments/assets/b18d306a-ccea-489f-941f-086d816d3a79">
2024-11-21 16:28:07 +01:00
Raphaël BosiandGitHub aae18a94c5 Fix action menu padding (#8652)
Before:
<img width="211" alt="Capture d’écran 2024-11-21 à 16 10 29"
src="https://github.com/user-attachments/assets/f13be007-e043-4b65-8fb1-b7264f7b37fd">

After:
<img width="218" alt="Capture d’écran 2024-11-21 à 16 10 10"
src="https://github.com/user-attachments/assets/3fdf02b1-f932-4e72-8994-7596f6e22164">
2024-11-21 16:27:50 +01:00
670c8a0b98 Refactor standard relations update at custom object renaming (#8638)
Refactoring update of standard relations when a custom object is
renamed, after observing occasional issues.

---------

Co-authored-by: Weiko <corentin@twenty.com>
2024-11-21 15:54:12 +01:00
MarieandGitHub cf73e32969 Fix isLabelSyncedWithName toggle at object creation (#8646)
+ remove useless disableNameEdit prop (always has same value as disabled
prop)
2024-11-21 15:15:25 +01:00
3f98c2ddbe feat(vite): add HTTPS support with configurable SSL (#8585)
The Pull Request adds support for local HTTPS configuration and
introduces a new environment variable for the app's base URL.
- Added new environment variable REACT_APP_BASE_URL in .env.example.
- Introduced logic to utilize SSL certificates for local HTTPS in
vite.config.ts.
- Added validation to ensure SSL key and certificate paths are defined
for HTTPS.
- Included support for dynamic base URL setting based on the environment
configuration.
- Enhanced server configuration in vite.config.ts to handle HTTPS and
local development.

---------

Co-authored-by: Félix Malfait <felix@twenty.com>
2024-11-21 14:22:00 +01:00
ae4fb7d113 fix: soft deleted records are read only (#8198)
TODO:
- [ ] It should not be possible to add tasks, notes, files, etc.

Fix for https://github.com/twentyhq/twenty/issues/7172

Note for reviewer:
- With these changes, `deletedAt` is now always included in
`recordGqlFields`.

--- Edit from Charles --
In this PR:
1) As mentionned by @pau-not-paul, we are adding deletedAt to our
recordGqlFields for board and table
2) I'm removing cellReadOnly logic, it is now fully computed using
useIsFieldValueReadonly like it's done in other places, there is no need
to maintain two read only systems
3) refactoring useIsFieldValueReadonly to take all the business logics
into one place together. It's now a function of the 5 factors (isRemote,
isDeleted, objectName, fieldName, etc...). Later it's likely to get back
to a function of Pick<FieldMetadata>, Pick<ObjectMetadata>,
record.isDeleted but we are not there yet

Note: as all cells are listening to the record (for isDeleted), updating
a field will trigger a re-rendering of the row which is not an issue
right now. It will be if we introduce bulk edition. In this case we
would need to use a selector on fields on top of record store

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2024-11-21 14:02:09 +01:00
Sebastian VaisovandGitHub 3c5eb539bb Add missing example URLs (#8640) 2024-11-21 13:48:33 +01:00
Félix MalfaitandGitHub 4c225a918e Temporarily restore install.sh (#8639)
Git.new link can't be change. Let's remove this file tomorrow
2024-11-21 12:07:38 +01:00
Félix MalfaitandGitHub 9cb076d9e1 Improve docker compose (#8637)
Add a proxy script to use the right install.sh branch/version matching
the docker-compose

Also stop exposing redis publicly as it's not necessary
2024-11-21 11:51:42 +01:00
WeikoandGitHub 24dbabcad7 Improve object metadata maps size (#8635)
## Context
The object metadata map is becoming quite large and its structure could
be simplified.
We are removing byNameSingular/byNamePlural keys, the former can be
retrieved through a new helper and the latter is not used in the code
base currently.
2024-11-21 11:49:19 +01:00
8772f8aac7 Hide the "Expand to Full Page" button on Email and Calendar pages (#8615)
### Overview
This pull request addresses issue #8612 by ensuring the "Expand to Full
Page" button does not appear on the Email and Calendar pages in the
right drawer.

### Changes Made
- Added conditions in the `RightDrawerTopBar` component to prevent the
`RightDrawerTopBarExpandButton` from rendering on:
  - Email pages (`RightDrawerPages.ViewEmailThread`)
  - Calendar pages (`RightDrawerPages.ViewCalendarEvent`)
- Verified that the button still renders correctly on other pages, such
as Record pages.

### Testing
Since I couldn't run the project locally, I was unable to confirm the
changes in a running environment. However, the logic has been carefully
updated to ensure the button is conditionally hidden based on the
current `rightDrawerPage` state.

### Additional Notes
Please let me know if further adjustments are needed or if there are any
issues during testing. Thank you for reviewing this PR!

---------

Co-authored-by: Weiko <corentin@twenty.com>
2024-11-20 20:33:54 +01:00
Thomas TrompetteandGitHub 39076df922 Fix version status colored tag + fix trash icon hover (#8618)
As title

Closes 
- https://discord.com/channels/1130383047699738754/1306250586668404736
- https://discord.com/channels/1130383047699738754/1305934421529985055
2024-11-20 18:42:57 +01:00
martmullandGitHub eb66c019f5 Set initial step if only one root step (#8617) 2024-11-20 17:38:35 +00:00
WeikoandGitHub ffbc9ca59c Set infinite ttl to all workspace cache keys (#8616)
## Context
We recently added an infinite ttl to metadata version however other keys
such as the object metadata map are also linked to the version so
keeping the version in cache without the rest breaks the app. I'm
editing all engine related keys with infinite ttl
2024-11-20 18:29:29 +01:00
2968085e73 Feat: revamp group by settings (#8503)
This PR fix #8202 that is revamping the `Options` settings for board and
table.

<img width="221" alt="Screenshot 2024-11-15 at 11 47 52 AM"
src="https://github.com/user-attachments/assets/0b143c95-810d-408b-b19e-c2678cd5653a">
<img width="214" alt="Screenshot 2024-11-15 at 11 47 59 AM"
src="https://github.com/user-attachments/assets/3468734a-8174-4e36-a8ee-08dad6c56227">
<img width="210" alt="Screenshot 2024-11-15 at 11 48 10 AM"
src="https://github.com/user-attachments/assets/300628f5-6645-4f1c-af8a-befce2714716">
<img width="212" alt="Screenshot 2024-11-15 at 11 48 37 AM"
src="https://github.com/user-attachments/assets/37a3db40-2146-45eb-bea4-44e1041f5bcf">
<img width="214" alt="Screenshot 2024-11-15 at 11 48 44 AM"
src="https://github.com/user-attachments/assets/42d2adcc-8f03-4f28-928b-d3c3d54d388a">
<img width="213" alt="Screenshot 2024-11-15 at 11 48 51 AM"
src="https://github.com/user-attachments/assets/90824568-b979-46a7-9841-ab8b9978e138">
<img width="211" alt="Screenshot 2024-11-15 at 11 49 00 AM"
src="https://github.com/user-attachments/assets/fa22446a-b1db-4d97-9a45-0778bf09ae3c">

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2024-11-20 17:03:18 +01:00
martmullandGitHub 0f7ebd3026 Fix wrong getAll keyValue method (#8603)
Fixes
https://github.com/twentyhq/twenty/issues/8520#issuecomment-2485913500

- Fix the getAll key-value pairs method, as it returns incorrect
results. The keyVar values were being affected by keyValues from other
workspaces.
- Fix missing Sync Email step for existing users joining existing
workspace
  
Before, this method returned keyValues that verifies:
- workspaceId = user.defaultWorkspaceId
- userId = user.id

This method now returns:
- userId = null && workspaceId = user.defaultWorkspaceId
- userId = user.id && workspaceId = null
- userId = user.id && workspaceId = user.defaultWorkspaceId

## Result


https://github.com/user-attachments/assets/b7563db6-a6a8-4e09-a0c6-c372d7e2b712
2024-11-20 15:41:42 +00:00
96c8673278 fix: empty composite field input (#8451)
Fixes: #7225

---------

Co-authored-by: bosiraphael <raphael.bosi@gmail.com>
2024-11-20 15:39:55 +01:00
Raphaël BosiandGitHub 24c0b0f873 Remove "When no records are selected" actions on record page ⌘O (#8575)
Closes #8566 
- Introduce the concept of scope for an ActionMenuEntry, scope is either
`global` or `record-selection`
2024-11-20 14:33:16 +01:00
Baptiste DevessierandGitHub c133129eb0 Fix state mutation serverless action (#8580)
In this PR:

- Ensure the `setNestedValue` does a deep copy of the provided object
and doesn't mutate it directly.
- Store the form's state in a `useState` instead of relying entirely on
the backend's state. This makes the form more resilient to slow network
connections.
- Ensure the input settings are reset when selecting another function.
- The Inner component now expects the serverless functions data to be
resolved before being mounted, so I split it.

Closes https://github.com/twentyhq/twenty/issues/8523
2024-11-20 09:15:55 +00:00
martmullandGitHub a744515303 Fix composite subfields format in OpenAPI schema (#8592)
Fixes https://github.com/twentyhq/twenty/issues/7262
## Before

![image](https://github.com/user-attachments/assets/54d188d3-5e72-4b8f-8ebe-b074f43c2685)


## After

![image](https://github.com/user-attachments/assets/316c69db-0e0b-43d9-a745-66d753682c4e)

![image](https://github.com/user-attachments/assets/22e39d16-e2f3-4aae-a491-f7f0765f557d)
2024-11-20 10:06:05 +01:00
MarieandGitHub 271af37327 Fix relations in search queries (#8595)
We were not handling relations in the search resolver, which started
being an issue as we query those relations in the combinedSearch queries
(introduced here https://github.com/twentyhq/twenty/pull/8564); they
were nullified in the response payload. The response was overwriting
findManyRecords results in the cache as it contained the exact same
fields.

So we now
1. Handle relations in the search resolver
2. Stop querying relations in search queries (no use)
2024-11-19 19:07:57 +01:00
Sasank ChilamkurthyandGitHub d90c3110cf Fail entrypoint if migration fails (#8590)
If migration fails for some reason, the script runs anyway and creates
the file which indicates that migration is complete. This is obviously
not cool. If database is not available for some reason and migrations
fail, the container should exit, not continue.

Relevant stack overflow: https://stackoverflow.com/a/2871034
2024-11-19 18:57:15 +01:00
4f2019edae favorite folders followup (#8570)
Something changed, which affected the Favorite folder picker checkbox
styles -- fixed it!
Cleaned up code in `CurrentWorkspaceMemberFavoritesFolders` - removed
redundant filtering since favorites are already filtered in
`usePrefetchedFavoritesData`.
Regarding issue #8569 - I am not sure what to do in this case. Since
Folders data is gated by a feature flag, we can't use it in
`CurrentWorkspaceMemberFavoritesFolders` to ensure the favorite section
renders with empty folders. Currently, the section only appears when at
least one favorite exists - may be leave this section open at all times
or fix this bug after removal of the feature flag?

---------

Co-authored-by: Nitin Koche <nitinkoche@Nitins-MacBook-Pro.local>
Co-authored-by: Charles Bochet <charles@twenty.com>
2024-11-19 18:55:25 +01:00
Thomas TrompetteandGitHub 2773974459 Add disable state to variable tag component (#8586)
- add hover on variables
- add disable state with readonly props

Disabled
<img width="284" alt="Capture d’écran 2024-11-19 à 16 12 10"
src="https://github.com/user-attachments/assets/19b21429-8500-4cdc-9914-22a7968beb64">


Normal
<img width="284" alt="Capture d’écran 2024-11-19 à 16 12 30"
src="https://github.com/user-attachments/assets/bc3be00f-944d-488c-bf05-a9f7b9f134c4">
2024-11-19 17:15:32 +00:00
Thomas TrompetteandGitHub ba1c094775 Fix select filter eq (#8594)
Fix
https://discord.com/channels/1130383047699738754/1308384008043757640/1308384008043757640
2024-11-19 18:12:08 +01:00
KhudditeandGitHub eeb4f2d329 Set white-space nowrap for table cells (#8568)
Fixes: #8552 

1. Summary
It seems table cell content is missing `white-space: nowrap`, so it
breaks the content into multiple lines when there are spaces or such.

2. Solution
Set `white-space: nowrap` for the table cell container so it always
takes a single line regardless of the length of the content.

3. Recording


https://github.com/user-attachments/assets/a42a2e80-d1fc-43b1-bf87-d52bf0367a88
2024-11-19 17:44:37 +01:00
Raphaël BosiandGitHub ac72f8a271 Fix workflow actions not being selectable with arrow keys (#8576)
https://github.com/user-attachments/assets/c108b60b-030e-4eef-a30f-fab472ea60a9
2024-11-19 16:01:28 +01:00
martmullandGitHub 1e55010e26 8563 workflow workflow node does not open on step click (#8582)
- fix multiple node selection
- fix console error
- fix close right drawer no unselect nodes
- fix edges not selectable
- fix sometime node not selected when clicking

## After


https://github.com/user-attachments/assets/ceec847f-5b7d-4452-9685-81a845bbf21e
2024-11-19 14:51:52 +01:00
86c2e9f0e4 fix: uncontrolled input to controlled in SigninUpForm (#8536)
Fixes: #8535

---------

Co-authored-by: Devessier <baptiste@devessier.fr>
2024-11-19 13:13:35 +00:00
MarieandGitHub 0d0f7e67a6 Add custom objects to command menu search + use ilike for notes search (#8564)
In this PR

- Re-introduce previously used search based on "ILIKE" queries for
search on notes since the tsvector search with json text is not working
correctly (@charlesBochet)
- Add search on custom objects in Command Menu bar (closes
https://github.com/twentyhq/twenty/issues/8522)


https://github.com/user-attachments/assets/0cc064cf-889d-4f2c-8747-6d8670f35a39
2024-11-19 14:11:38 +01:00
4a8234d18c Feature 7552 patch (#8574)
Related to #7552

<img width="556" alt="Screenshot 2024-11-18 at 17 57 30"
src="https://github.com/user-attachments/assets/e89e575b-9adb-4910-ab0d-b60079727f70">

---------

Co-authored-by: guillim <guillaume@twenty.com>
2024-11-19 12:47:33 +01:00
9073bdf21a Background Blur added across multiple Input Fields in Edit Popups (#8277)
Fix #5644 

**Apply background blur to input fields across UI for improved
consistency and appearance with Theme compatibility :**

1. Updated **TextAreaInput.tsx** to apply background blur to text input
fields (e.g., City name).

2. Enhanced **PhonesFieldInput.tsx** to apply background blur for
seamless styling in phone number input sections.

3. Modified **TextInputV2.tsx** to add background blur in address
inputs, workspace fields (e.g., Blocklist, Name fields), invitation
inputs, profile name/email fields, and other input areas.

4. Updated **DateTimeInput.tsx** and **DateInput.tsx** to improve the
appearance of date, time, and calendar popup fields with background
blur.

5. Refined **DropdownMenuInput.tsx** and **DropdownMenuSearchInput.tsx**
to add background blur to inputs for Emails, Domain name, and search
fields across the web (e.g., Time Zone dropdowns, phone number country
search).

Some images are attached for reference.

<img width="235" alt="1_b"
src="https://github.com/user-attachments/assets/bd72e69a-712e-4226-8fda-0cb737d4cbd1">
<img width="229" alt="1_w"
src="https://github.com/user-attachments/assets/bb8eb60b-31fb-44c6-ac2a-ca28638b5e07">
<img width="234" alt="2_b"
src="https://github.com/user-attachments/assets/a4f0a9de-dea1-4ef8-926b-99de984c081b">
<img width="239" alt="2_w"
src="https://github.com/user-attachments/assets/4d2c7331-4bbf-4ea2-adad-76c7cde4072c">
<img width="225" alt="3_b"
src="https://github.com/user-attachments/assets/458f4759-8428-43ae-a6b6-aa38ab6fb0f8">
<img width="219" alt="3_w"
src="https://github.com/user-attachments/assets/5ddb67c5-e59d-47cc-b2e7-44b3a7b794e6">
<img width="646" alt="4_b"
src="https://github.com/user-attachments/assets/01252bce-a34a-4dda-a801-654ccc5e7841">
<img width="637" alt="4_w"
src="https://github.com/user-attachments/assets/ea60deab-7594-4aef-ac63-0cedc9168951">
<img width="648" alt="5_b"
src="https://github.com/user-attachments/assets/465789ec-55b3-4750-a2bc-a9e156b1101e">
<img width="642" alt="5_w"
src="https://github.com/user-attachments/assets/8b58977a-f543-4018-a4ee-b1ff5b9180a3">
<img width="647" alt="6_b"
src="https://github.com/user-attachments/assets/88030efe-bd16-43e4-9744-ee223aa04298">
<img width="642" alt="6_w"
src="https://github.com/user-attachments/assets/4ca2c365-ab1e-47e9-ba4a-bdb738500f56">
<img width="647" alt="7_b"
src="https://github.com/user-attachments/assets/224c3da5-cf57-4652-bd29-681c2098917e">
<img width="655" alt="7_w"
src="https://github.com/user-attachments/assets/eecc2d51-ce1f-47c9-845c-c6fe15a40fa5">
<img width="317" alt="8_b"
src="https://github.com/user-attachments/assets/e899b4a2-4849-4d1c-805b-5a950a53d6cc">
<img width="335" alt="8_w"
src="https://github.com/user-attachments/assets/73fef887-0a46-4557-aca4-d07c9dc298d1">
<img width="246" alt="9_b"
src="https://github.com/user-attachments/assets/99c5627a-e7ba-4453-9666-8d73b0d676ee">
<img width="238" alt="9_w"
src="https://github.com/user-attachments/assets/bb36e4ea-3b78-48f5-822f-cc5012e5d434">
<img width="218" alt="10_b"
src="https://github.com/user-attachments/assets/450fa833-12ad-40b7-80f5-17de6af582bd">
<img width="225" alt="10_w"
src="https://github.com/user-attachments/assets/3fe6d128-4146-4316-821e-2ebd65fd12d5">
<img width="647" alt="11_b"
src="https://github.com/user-attachments/assets/ec39f88f-0beb-4cf0-b35f-b4f78b4e75ff">
<img width="663" alt="11_w"
src="https://github.com/user-attachments/assets/6eb19fe7-604c-4cb9-9623-208e541df751">
<img width="235" alt="12_b"
src="https://github.com/user-attachments/assets/98e68530-f5c5-43d1-839e-a8c14582b72a">
<img width="245" alt="12_w"
src="https://github.com/user-attachments/assets/e3f0aec9-6a32-4784-a36c-d187303d3310">

---------

Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
2024-11-19 12:21:01 +01:00
Thomas TrompetteandGitHub cdf0240ccb Fix active navigation tab + quick workflows fixes (#8567)
- Active navigation tab hovered in show page
- remove timeline tab + rename workflow tab
- remove {{variable}} placeholder
- fix margin
- Workflow Runs and Versions show page title

<img width="807" alt="Capture d’écran 2024-11-18 à 18 23 12"
src="https://github.com/user-attachments/assets/688dfc67-362e-4f04-b436-3ff94d7e3e4a">
2024-11-19 10:55:25 +00:00
Baptiste DevessierandGitHub c17e18b1e9 Add Record Create action in the frontend (#8514)
In this PR:

- Updated the front-end types for workflows to include CRUD actions and
global naming changes
- Allow users to create a Record Create action
- Scaffold the edit for Record Create action; for now, I render a
`<VariableTagInput />` component for every editable field; it's likely
we'll change it soon

Closes https://github.com/twentyhq/private-issues/issues/142

Demo:


https://github.com/user-attachments/assets/6f0b207a-b7d2-46d9-b5ab-9e32bde55d76
2024-11-18 18:23:46 +01:00
316537a68a FIx minor issue related to gap between checkbox & menu item label (#8220)
## Summary
This pull request addresses a minor issue reported in the #8171 , which
was causing misalignment in the content and overall theme spacing.

Fixes #8171

## Fix

> Removed the 5px padding based on the check if its non hoverable, the
current gap between the checkbox and the icon is 8px as expected.

> For the small variant the total size of the non hoverable component is
14x14 as mentioned in the design, for hoverable its 24x24

> For the Large variant the total size of the non hoverable component is
20x20 as mentioned in the design, for hoverable
its 32x32 

> checked for the hoverable checkbox component as well working as
expected



## Screenshot for the fixes

<img width="345" alt="Screenshot 2024-10-30 at 10 49 39 PM"
src="https://github.com/user-attachments/assets/2b5cadb7-67d2-4c61-bd40-0d5a12ae48d0">


#### Thank you for considering this contribution! I look forward to your
feedback.

---------

Co-authored-by: Karan Parmar <karan.parmar@PE-HO-MAC-185.local>
Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
2024-11-18 16:50:34 +00:00
Raphaël BosiandGitHub 9810c5b6f2 Update ShowPageMoreButton to open the command menu when clicked (#8565)
https://github.com/user-attachments/assets/6e269391-8ea2-4146-8e86-7e75c84982f4
2024-11-18 17:44:23 +01:00
nitinandGitHub e1a730a8fc Stories and SSL Configuration docs update (#8551) 2024-11-18 17:38:02 +01:00
2f3c41620c Wrap Long text fields (textarea) (#8557)
Here we add the option for Text inputs to be wrapped, and to select on
how many lines text should be displayed.

Fix #7552

---------

Co-authored-by: guillim <guillaume@twenty.com>
2024-11-18 17:36:19 +01:00
Antoine MoreauxandGitHub 83b5eb69b0 feat(env-vars): Add warning validation decorator (#8555)
Introduced a custom decorator 'WarningIf' to log warnings for specific
environment variable conditions. Implemented this for
SESSION_STORE_SECRET to ensure users change it from the default value.
2024-11-18 17:04:10 +01:00
martmullandGitHub e3b327de8e Add missing Icons (#8562)
## Before

![image](https://github.com/user-attachments/assets/54fdddd6-4a48-4e7c-a654-30a6599f22ea)


## After

![image](https://github.com/user-attachments/assets/c4e0318d-f0b0-4fc5-84b7-14cc72447ac3)
2024-11-18 16:22:17 +01:00
Jérémy MandGitHub fb0221b4c1 feat: default record group table (#8397)
This PR is preparing states to we'll be able to handle view groups
correctly with table data.
RowIds are now stores in 2 component states, one storing ids by view
group and another storing all the rowIds.
We're doing that because some other state like focus, or select must not
be scoped by view group id.
2024-11-18 15:36:40 +01:00
0125d58ba8 Favorite folders (#7998)
closes - #5755

---------

Co-authored-by: martmull <martmull@hotmail.fr>
Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
2024-11-18 15:22:19 +01:00
5115022355 fix: Dropdown Overlapping Sidebar on Column Header Click in Horizontal Table When Scrolling (#8287)
fixes : #8272

---------

Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
2024-11-18 15:19:04 +01:00
8b8b9fe55b Add "type" to reserved keywords in object metadata validation (#8548)
This PR adds "type" to the reserved keywords list in
validate-object-metadata-input.util.ts. This prevents users from
creating objects with "type" as a key, which has caused issues in the
past .
issue solved #8543 

1.Updated the RESERVED_KEYWORDS array to include "type"

---------

Co-authored-by: Weiko <corentin@twenty.com>
2024-11-18 15:10:49 +01:00
d8626b1304 Fix 'Error in devtools while checking fields of object' (#8554)
Fixes https://github.com/twentyhq/twenty/issues/8298

---------

Co-authored-by: Devessier <baptiste@devessier.fr>
2024-11-18 14:59:50 +01:00
Antoine MoreauxandGitHub ba847292b6 refactor: add default fallback for session store secret (#8553)
**Description:**
- Add default fallback for session store secret.
- Updated SESSION_STORE_SECRET validation to be optional and of type
string.
2024-11-18 14:29:19 +01:00
6a977ad529 Created a temporary background transparent blue color for checkboxes (#8363)
Created a temporary background transparent blue color for checkboxes

Co-authored-by: Weiko <corentin@twenty.com>
2024-11-18 12:14:55 +01:00
Thomas TrompetteandGitHub a0200e6d91 Fix workspace favorites in storybook (#8519)
- create mock page when user not logged in
- add mocks when user logged in

Reset password story
<img width="1073" alt="Capture d’écran 2024-11-15 à 16 49 31"
src="https://github.com/user-attachments/assets/5d70d587-8094-47ad-8029-d8c729bd298d">

Record Index page story
<img width="1073" alt="Capture d’écran 2024-11-15 à 16 49 58"
src="https://github.com/user-attachments/assets/421772a9-62ee-4563-b492-5158db31fb9b">

Reset password page
<img width="1031" alt="Capture d’écran 2024-11-15 à 16 50 18"
src="https://github.com/user-attachments/assets/2d1cb119-5e34-49d0-9cfa-2b856a96f39c">
2024-11-18 12:08:05 +01:00
WeikoandGitHub 0f1cf0e4e9 Add composite fields to aggregation (#8518)
## Context
This PR introduces a first aggregation for a composite field

## Test
<img width="1074" alt="Screenshot 2024-11-15 at 15 37 05"
src="https://github.com/user-attachments/assets/db2563f9-26b7-421f-9431-48fc13bce49e">
2024-11-18 12:02:57 +01:00
2f5dc26545 Settings Option Card component (#8456)
fixes - #8195

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2024-11-18 09:22:33 +00:00
KhudditeandGitHub ade1c57ff4 Fix remove redundant onClick event in favor of Link component (#8540)
Fixes: #8531 

1. Summary
There is `onClick` event handler defined for `NavigationDrawerItem`
component, and inside the handler, if `to` is not empty, we trigger
another navigation when it's already handled by `Link` component from
`react-router-dom`

2. Solution
Removed extra navigation logic from `NavigationDrawerItem`'s `onClick`
handler

3. Screen Recording


https://github.com/user-attachments/assets/cfefdd51-1663-4d96-acd2-57783ae9877f
2024-11-18 09:41:14 +01:00
ad-eliasandGitHub ef5cc80440 Enable array filtering (#8538)
- Set array filtering always enabled
- Rename `IS_ARRAY_AND_JSON_FILTER_ENABLED ` TO
`IS_JSON_FILTER_ENABLED`.
2024-11-18 09:38:46 +01:00
Harsh SinghandGitHub 9134ed8ce4 fix: prevent non-boolean 'active' prop from being forwarded to DOM (#8534)
Fixes: #8533
2024-11-17 20:11:13 +01:00
badebc513f Fix multi select filtering (#5358) (#8452)
Allow filtering by multi-select fields.

<img width="1053" alt="Screenshot 2024-11-11 at 11 54 45"
src="https://github.com/user-attachments/assets/a79b2251-94e3-48f8-abda-e808103a6c39">

---------

Co-authored-by: Félix Malfait <felix@twenty.com>
2024-11-17 15:27:38 +01:00
ad-eliasandGitHub ac1197afe1 Fix secondary links default value and types (#8532)
Fixes broken companies view
2024-11-17 15:18:02 +01:00
8c33e4cdae fix: Checkbox column width should be fixed (#8489)
## Description

- This PR adds the functionality of fixed column width across all boards
- This PR fixes the issue 
#8463 
#8331

<img width="1167" alt="Screenshot 2024-11-14 at 12 19 02 PM"
src="https://github.com/user-attachments/assets/7c2b1016-2a59-4d08-8d29-9558648bcd67">

---------

Co-authored-by: Félix Malfait <felix@twenty.com>
2024-11-16 16:47:36 +01:00
AbstergoandGitHub 859ce89e87 Fixed_Auth_Documentation (#8526)
Fixes #8525 

Fixed a small documentation API change:

AUTH_GOOGLE_APIS_CALLBACK_URL changed to
AUTH_MICROSOFT_APIS_CALLBACK_URL
2024-11-16 09:04:53 +01:00
Félix MalfaitandGitHub 4feb59a369 Fix Vite File does not exist (#8527)
This should fix #8491 

https://vite.dev/config/dep-optimization-options
2024-11-16 09:04:19 +01:00
Thomas des FrancsandGitHub b733a2f3ec changed multiItem Field Menu Item button to tertiary (#8517)
Think a simpler fix can fix
https://github.com/twentyhq/twenty/pull/8504/files#diff-13c19c3083bfe3172351cddbdd325960072496e9d50b73919fb35aa661bcdd52

https://github.com/twentyhq/twenty/issues/8492
2024-11-16 07:02:41 +01:00
dc42315f12 fix(SingleEntitySelectMenuItems): extract Add New button from entitiesToSelect (#8474)
# Description
Closes #8169

Extract Add New button from entitiesToSelect and add it as a separate
element .
There doesn't seem to be a point in having Add New as part of a list, it
seems better off in its own component, apart from list items

## Rationale
There already is #8353 addressing the same issue, but it seems it
doesn't really remove the duplicate "Add New" in the list, leaving a
duplicate "Add New" in `SingleEntitySelect`

---------

Co-authored-by: Félix Malfait <felix@twenty.com>
2024-11-16 06:49:55 +01:00
martmullandGitHub 9b2853bb01 Fix variable dropdown (#8521)
- fixed dropdown width
- add icons
- handle composite fields
## After

![image](https://github.com/user-attachments/assets/b9ac585e-2a39-4ab2-8620-739f83272b9b)

![image](https://github.com/user-attachments/assets/d9f7eabb-5693-4c1c-b81c-45a901479042)

![image](https://github.com/user-attachments/assets/9edced28-8a04-4951-913d-3e5561d4fcbe)
2024-11-15 18:08:03 +00:00
Thomas TrompetteandGitHub 54b28ff7ed Enable workflow testing + fix header (#8512)
- clean execution header
- enable test on workflows + add snack bar
- display snack bar error if workflow cannot be tested

Behaviour still need to be validated by @Bonapara 
<img width="880" alt="Capture d’écran 2024-11-15 à 12 16 36"
src="https://github.com/user-attachments/assets/1dab0c3b-157c-449f-aee7-4c8cf2e369a6">
<img width="880" alt="Capture d’écran 2024-11-15 à 12 16 48"
src="https://github.com/user-attachments/assets/16279611-0a58-4fe6-b117-0192714a6d5c">
2024-11-15 18:38:39 +01:00
KhudditeandGitHub ac93d35538 Fix remove no result menu from relation picker (#8485)
Fixes: #8455 

1. Summary
Removed redundant `No result` menu from relation picker

2. Screenshot


https://github.com/user-attachments/assets/0bf457dc-57d6-4b38-8ef9-e985edd92396
2024-11-15 17:51:18 +01:00
9e7b90a551 fix: Added keyboard functionality for esc and Ctrl + a (#8282)
## Description

- This PR fixes 
#8247 
#8206 
- Adds keyboard functionality for esc (deselect all records) and Ctrl +
a (select records)

## Changes

https://github.com/user-attachments/assets/7b2718d6-dbe5-4cd8-8ead-b6baed1fc357

Merged during stream 🎉 

---------

Co-authored-by: Devessier <baptiste@devessier.fr>
2024-11-15 17:15:39 +01:00
77165a280e Refactored query result getter handlers to support recursivity (#8497)
The `QueryResultGettersFactory` that is called on every query return to
was called only on the first level of relations because recursivity
wasn't implemented.

In this PR I implement recursivity and add some typing for the possible
forms a GraphQL query field can take.

This PR will fix any issue we have with pictures that were losing their
token (here for person.avatarUrl)

Fixes https://github.com/twentyhq/twenty/issues/8425
Fixes https://github.com/twentyhq/twenty/issues/8498

---------

Co-authored-by: Weiko <corentin@twenty.com>
2024-11-15 15:34:58 +00:00
4db0d0f8c1 Improve phone input UI (#8266)
[FIX] #8251 

Changes made as suggested by @Bonapara. 


![image](https://github.com/user-attachments/assets/4ba6db50-f122-4f66-9361-8a0a0da0b6a0)

![image](https://github.com/user-attachments/assets/f0f1e1f4-d354-4461-9929-cd171d95835e)

![image](https://github.com/user-attachments/assets/b6b9fdef-d6fa-4e4b-aa8b-c8c3ef8b8c57)

![image](https://github.com/user-attachments/assets/7e68bf25-aff9-428f-a084-0b0631eeecef)

For the `The country code should be Tertiary instead of Primary ` task,
the library "react-phone-number-input" doesn't provide any out of the
box functionality to style the country code.

If the feature **needs** to be implemented here are the possible
solution/workarounds:

1. Finding a more customizable library that allows to change the style
of the country code

OR 

2. Implement custom country selection (😰...)

OR

3. The lib allows a custom input element and a provides a function
(onCountryChange) that triggers whenever the country changes (a country
can be changed in two ways- 1. When the user deliberately chooses it
from dropdown OR 2. Changes the code in the input)

We'll have to get the length of the country code and then style the
first X digits in the custom input field...


![image](https://github.com/user-attachments/assets/21b09c4d-fb5b-4efe-8204-aea4c9040587)

![image](https://github.com/user-attachments/assets/007c2791-a640-4bc9-b852-0f9b597679f1)

Let me know if someone has a better approach.

---------

Co-authored-by: Thomas des Francs <tdesfrancs@gmail.com>
Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
2024-11-15 16:03:48 +01:00
Félix MalfaitandGitHub c03b1ca7c6 Improve storybook test (#8516)
Just a quick fix
2024-11-15 14:49:07 +01:00
Félix MalfaitandGitHub 34a3a66451 Improve flaky storybook test (#8515)
I don't think that will solve the flaky test but at least it will
cleanup the error message to avoid confusion
2024-11-15 14:29:39 +01:00
Félix MalfaitandGitHub bd18eb8b42 Add logging for scopeid error (#8513)
Can't figure out https://github.com/twentyhq/twenty/issues/8347 so I'm
adding logs, maybe it'll help debug in the future!
2024-11-15 14:16:09 +01:00
Thomas des FrancsandGitHub 30bcdda323 Modal Background & box shadow fixes (#8506)
# Before

![CleanShot 2024-11-14 at 19 20
59](https://github.com/user-attachments/assets/9a561416-a08c-4cc4-ac71-b3f4410950d8)

# After

![CleanShot 2024-11-14 at 19 21
34](https://github.com/user-attachments/assets/eaa78d94-a337-4d91-9c36-8ac0dd27d952)
2024-11-15 12:44:58 +01:00
martmullandGitHub 4f99b8eea1 8495 workflow display relevant columns in workflow related tables (#8502)
## After
### Workflows

![image](https://github.com/user-attachments/assets/535e0ff5-1276-41b9-aa52-d66150cd85ae)
### WorkflowRuns

![image](https://github.com/user-attachments/assets/8a7e076b-53ec-4b72-97d8-41bd77ed59ac)
### WorkflowVersions

![image](https://github.com/user-attachments/assets/7d2566b2-e6ea-4a3a-8e88-0f6850203219)

## Change Created By into Executed By in workflowRuns

![image](https://github.com/user-attachments/assets/b90b7a07-a4bc-4bd2-b7f5-ab7d2ae6ee45)
2024-11-15 10:13:36 +00:00
Thomas TrompetteandGitHub a2a272fed4 Add crud actions (#8500)
Adding update / delete / find actions

Update and delete are not really different than creation.

Find uses the same logique as for graphql filters.
Expected formats are:

Filter
```
{
  "and": [
    {
      "name": {
        "eq": "salut"
      }
    },
    {
      "employees": {
        "eq": "0"
      }
    }
  ]
}
```

Order
`[ { "name": 'AscNullsFirst' } ]`
2024-11-15 10:10:00 +01:00
Félix MalfaitandGitHub 736635a94b Begin moving to postgres spilo + adding pgvector (#8309)
We will remove the `twenty-postgres` image that was used for local
development and only use `twenty-postgres-pilo` (which we use in prod),
bringing the development environment closer to prod and avoiding having
to maintain 2 images.


Instead of provisioning the super user after the db initialization, we
directly rely on the superuser provided by Spilo for simplicity. We also
introduce a change that tries to create the right database (`default` or
`test`) based on the context.
  

How to test:
```
docker build -t twentycrm/twenty-postgres-spilo:latest -f ./packages/twenty-docker/twenty-postgres-spilo/Dockerfile .
docker images --no-trunc | grep twenty-postgres-spilo
postgres-on-docker:
	docker run \
	--name twenty_pg \
	-e PGUSER_SUPERUSER=twenty \
	-e PGPASSWORD_SUPERUSER=twenty \
	-e ALLOW_NOSSL=true \
	-v twenty_db_data:/home/postgres/pgdata \
	-p 5432:5432 \
	REPLACE_WITH_IMAGE_ID
```
2024-11-15 09:38:30 +01:00
WeikoandGitHub cfe3515aa6 Set cache metadata version to infinite TTL (#8507)
## Context
To avoid having a corrupt metadata version, we want to remove TTL for
that key.

## Test
<img width="592" alt="Screenshot 2024-11-15 at 00 02 05"
src="https://github.com/user-attachments/assets/9da0ae33-26a8-4e7b-82d0-dd691135a08f">
2024-11-15 00:05:42 +01:00
Charles BochetandGitHub 5384b4aba5 Fix record board export not taking filters into account (#8505)
Fix Export CSV action not taking into account the filters applied on the
Kanban index view
2024-11-14 23:28:53 +01:00
a799370483 Aggregated queries #1 (#8345)
First step of https://github.com/twentyhq/twenty/issues/6868

Adds min.., max.. queries for DATETIME fields
adds min.., max.., avg.., sum.. queries for NUMBER fields 

(count distinct operation and composite fields such as CURRENCY handling
will be dealt with in a future PR)

<img width="1422" alt="Capture d’écran 2024-11-06 à 15 48 46"
src="https://github.com/user-attachments/assets/4bcdece0-ad3e-4536-9720-fe4044a36719">

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
Co-authored-by: Weiko <corentin@twenty.com>
2024-11-14 18:05:05 +01:00
c966533f26 fix: search error in filter & sort dropdowns (#8493)
Fixes: #8483

Co-authored-by: Félix Malfait <felix@twenty.com>
2024-11-14 17:51:54 +01:00
51c54d4c5b validation on Select field (#8316)
fix #8204
I changed "API keys" to "API values".
Stopped inputting special characters in Select field option keys.

@lucasbordeau please check the changes and tell me if I need to do any
other changes. :)

---------

Co-authored-by: Félix Malfait <felix@twenty.com>
2024-11-14 17:46:18 +01:00
15b8b9b158 Feature : Adding percentage option to Input Number (#8481)
fixing #7375

---------

Co-authored-by: guillim <guillaume@twenty.com>
2024-11-14 14:23:25 +01:00
martmullandGitHub 090f612c4b Fix open api specs for MULTI_SELECT (#8494)
## Before

![image](https://github.com/user-attachments/assets/b7384fb3-0f32-498b-99bb-27b8c15db00c)

## After

![image](https://github.com/user-attachments/assets/a8429849-559d-4494-8636-e5a6ddda7b47)
2024-11-14 12:07:31 +01:00
martmullandGitHub 9ac949dec8 [Workflow] Add search in variable dropdown (#8479)
- fix Icon variable Plus
- add search input 
- fix dropdown height

## Before

![image](https://github.com/user-attachments/assets/49f73efd-21cc-4ecd-a494-f51edc34dc57)


## After

![image](https://github.com/user-attachments/assets/2af2c7ee-72fd-4dae-a1ef-19e75e1ac026)
2024-11-14 11:40:06 +01:00
BOHEUSandGitHub d72068eb99 Fix BullMQ deprecation warning (#8486)
Related to #8470
2024-11-13 19:38:29 +01:00
Harsh SinghandGitHub c98a8a2258 fix: dropdown toggle functionality (#8476)
Fixes: #8468
2024-11-13 19:36:21 +01:00
KhudditeandGitHub 2fb920f68c Fix typo in branch name (#8480)
Fixes #8471 

Updated `0.33.0-canaray` -> `0.33.0-canary`

![CleanShot 2024-11-13 at 09 45
36](https://github.com/user-attachments/assets/6a365542-9b4d-4279-9ef4-966d22863eba)
2024-11-13 19:35:15 +01:00
nitinandGitHub 795cb12a12 minor fix - spacing on Data model title fixed (#8467) 2024-11-13 19:34:15 +01:00
Nicolas RouanneandGitHub cde96cf526 Fix/validate access token user not found (#8484)
# Description
Closes #7244 

See details about implementation:
https://github.com/twentyhq/twenty/issues/7244#issuecomment-2473845859
and
https://github.com/twentyhq/twenty/issues/7244#issuecomment-2473905514

# Changes
- return a `USER_NOT_FOUND` error instead of `INVALID_INPUT` error
- tweak unit tests to correctly test `AuthExceptionCode`, as it wasn't
properly tested; it was actually a _false positive_. This is because
[`toThrow`](https://jestjs.io/docs/expect#tothrowerror) from jest only
checks the `message`, and not any other method / attributes from the
`Error`. It's a know behaviour and not considered a bug, see
https://github.com/jestjs/jest/issues/13232#issuecomment-1252392845
2024-11-13 18:50:30 +01:00
Baptiste DevessierandGitHub 898006f89d Prevent automatic zoom when focusing inputs on iOS (#8477)
This is the result of a long discussion we had here:
https://github.com/twentyhq/twenty/issues/8001.

The goal is to stop iOS from automatically zooming when the user focuses
on an input whose font size is less than 16px.

The options were:

1. Disable zoom for all devices
2. Disable zoom for devices detected as iOS devices, which doesn't
prevent users from zooming manually but fixes the auto-zoom bug
3. Set the font size of the inputs to be equal to or greater than
16px—this change would take a lot of time

To me, the second option is the best, as iOS prevents developers from
disabling zoom. They saw that it was overused and chose to restrict this
setting. Setting a `maximum-scale` doesn't prevent users from zooming,
but it fixes the initial bug we had.

My implementation can be seen as [progressive
enhancement](https://developer.mozilla.org/en-US/docs/Glossary/Progressive_Enhancement
): If we can detect that the user uses an iOS device, we'll set the
`maximum-scale` viewport property. Relying on the user agent is always
unstable, and the check might fail unpredictably. We might not disallow
auto-zoom for some iOS devices.

However, I think we can either:

- Invest some time to choose a more reliable user detection pattern if
the one I suggest is not sufficient ([we find many different checks on
the
internet](https://stackoverflow.com/questions/9038625/detect-if-device-is-ios),
I'm not sure which one is the best)
- Choose to apply the viewport setting to all devices and remove the JS
code. According to my tests, it doesn't prevent zooming on desktops.
However, it does on Android phones. I think it's not lovely to disallow
zoom, but if the team agrees that we should go this way, I won't
disagree.

I know my JavaScript code does not follow a pattern we want to spread in
the app. The synchronous script will run as soon as possible to ensure
the viewport is correctly set when the website launches. This shouldn't
be an example followed by others.

Thanks, @harshit078, for your help in thinking about the best option.

I'm tagging @lucasbordeau and @charlesBochet for a technical review.

I would appreciate if someone could test on a more recent iOS device
than mine.

Here is a demonstration of the behavior on iOS:


https://github.com/user-attachments/assets/d49fb65f-dd76-455c-9ac0-d4c002a7fe89
2024-11-13 15:34:20 +01:00
Thomas TrompetteandGitHub faeea2b887 Create record action (#8460)
- Add create record action
- Migrate all step name => action in a common folder
- Separate types
2024-11-13 15:21:40 +01:00
martmullandGitHub ba79a1d324 Fix style (#8475)
## Before

![image](https://github.com/user-attachments/assets/1c96c30c-da06-4caa-a05d-1c58006dcfa5)

## After

![image](https://github.com/user-attachments/assets/523fac64-7521-4c0f-bfa8-457d48493628)
2024-11-13 13:32:40 +00:00
Thomas des FrancsandGitHub d2af97276d 0.32 changelog (#8461)
<img width="800" alt="0 32-webhooks"
src="https://github.com/user-attachments/assets/0c91bda3-4a8d-4808-bb8c-3b351a186a21">

<img width="800" alt="0 32-improved-cmdk"
src="https://github.com/user-attachments/assets/ebb98c2e-4b79-4dad-8946-e9ecd6c51bbc">
2024-11-13 12:57:30 +01:00
martmullandGitHub 269eaf4422 Update zapier trigger payload (#8464)
- fixes zapier tests
2024-11-12 17:58:36 +01:00
31f03764d6 Improve the layout of the Workflow Visualizer (#8372)
- Increase the dimensions of the ReactFlow nodes. This allows to ditch
scaling which made it hard to get the width of the nodes as they were
visually scaled by 1.3.
- Center the flow when the flow mounts and when the state of the right
drawer opens.
- Put the node type inside of the node so it doesn't overlap with the
arrow
- Make the edges non deletable

We'll have to make a refactor so the viewport can be animated properly:
https://github.com/twentyhq/twenty/issues/8387.


https://github.com/user-attachments/assets/69494a32-5403-4898-be75-7fc38058e263

---------

Co-authored-by: Félix Malfait <felix@twenty.com>
2024-11-12 17:52:12 +01:00
martmullandGitHub aadcb49dcb Fix missing timeline activity events (#8459)
Fixes bug introduced in https://github.com/twentyhq/twenty/pull/8193

Taking into account linked event name `linked-{eventName}` as before
issue

## Before
`linked-created` and `linked-updated` activity targets were not created
in `timelineActivity` table

## After
`linked-created` and `linked-updated` activity targets are created in
`timelineActivity` table
2024-11-12 12:04:58 +01:00
bec4da496d Data settings new layout - anchor navigation (#8334)
Follow-up of https://github.com/twentyhq/twenty/pull/7979
Navigation between settings and fields tabs is now reflected in URL. 
<img width="1106" alt="Capture d’écran 2024-11-07 à 18 38 57"
src="https://github.com/user-attachments/assets/24b153ef-9e68-4aa2-8e3a-6bf70834c5ad">

---------

Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com>
Co-authored-by: gitstart-twenty <140154534+gitstart-twenty@users.noreply.github.com>
Co-authored-by: Weiko <corentin@twenty.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
2024-11-11 14:06:38 +01:00
Charles BochetandGitHub 9d6a850ee8 Mark main version as 0.33 canary (#8453) 2024-11-11 11:59:33 +01:00
KhudditeandGitHub ff77f85aee Fix broken documentation pages in mobile view (#8432)
Fixes: #8396

1. Summary
The document content container is missing `width` and has only `padding`
CSS property, which means the width can overflow its parent based on the
content. The code block inside headings was missing `fontSize` for
mobile view, it was set for only desktop views.
    
2. Solution
I set `width` for document content container and `fontSize` for code
blocks in headings for mobile view.
    
3. Screenshots

![localhost_3000_developers_local-setup(iPad
Mini)](https://github.com/user-attachments/assets/4adf695f-3849-4ddc-8629-be03a70d32b1)
![localhost_3000_developers(iPhone 12
Pro)](https://github.com/user-attachments/assets/52254b3a-674b-4db0-9e6c-a68d59cb4401)
2024-11-11 09:32:00 +01:00
29d92abaff fix: bookmarkIcon flash on hover exit (#8448)
Fixes: #8447

Co-authored-by: Félix Malfait <felix@twenty.com>
2024-11-11 09:30:03 +01:00
c19e54f24b Hide tabs (#7841)
@FelixMalfait WDYT?
We can refactor shouldDisplay Files/Tasks/Notes Tab etc into a hook.

---------

Co-authored-by: Félix Malfait <felix@twenty.com>
2024-11-11 09:26:27 +01:00
Harsh SinghandGitHub 6d62dd9fd1 fix: object activate dropdown (#8438)
Fixes: #8436 
Fixes: #8435 
& other duplicate ```DropdownMenu```
2024-11-11 09:26:07 +01:00
51d1305e27 fix: timeline padding (#8440)
Fixes: #8437

Co-authored-by: Félix Malfait <felix@twenty.com>
2024-11-09 08:19:28 +01:00
Harshit SinghandGitHub 8ee827d05d fix: Developers page dropdown not optimised for mobile viewport (#8392)
## Description

- This PR is a minor fix to issue #8379 
- Fixed dropdown for mobile viewports

## Changes


https://github.com/user-attachments/assets/76692233-996e-4a1a-884a-84d31464fc85
2024-11-09 07:59:15 +01:00
Charles BochetandGitHub eb316074ef Add People API upgrade instruction to upgrade guide (#8441)
I'm updating the docs as we now require the People API to be available
to use messaging sync. This has been reported by a user self-hosting the
app on discord.
2024-11-08 20:34:10 +01:00
e3e638579b [FIX] Text overflow on timeline (#8325)
FIX: #6977 

Implementation:

1. Parent (Summary componenet) width is set to 100%. (dosen't grow even
if the child exceeds width)
2. span element is set to `text-overflow: ellipses` when overflown.

---------

Co-authored-by: Félix Malfait <felix@twenty.com>
2024-11-08 18:20:41 +00:00
6ec8a5b76e [FIX] slash-menu-height-fix (#8327)
FIX #8326 

I've used the `height: fit-content` property just for customSlashMenu
but I think it will work for all dropdown menu's.
I tested it for a few and works fine, but not sure for edge cases. 

Let me know if the height should be changed to `fir-content`


![image](https://github.com/user-attachments/assets/dacbedb5-08e0-4d08-8952-21d8b9de1176)

---------

Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
2024-11-08 16:22:18 +00:00
martmullandGitHub 354ee86cb9 8311 serverless function functions can be executed with any input (#8380)
- remove ts-morph
- update inputSchema shape

![image](https://github.com/user-attachments/assets/e62f3fdb-5be8-4666-8172-44f73a1981b9)


https://github.com/user-attachments/assets/913cd305-9e7c-48da-b20f-c974a8ac7cea

## TODO
- have inputTypes to match the inputSchema type (string, number,
boolean, etc...), only string for now
- handle required/optional inputs
- handle case when inputSchema changes, fix data reset when switching
function
2024-11-08 16:15:27 +00:00
0381996fb9 fix: dropdown menu doesn't close and remains open (#8302)
## Description

- Fixes #8285 
- Added fix for both Currency and PhoneCountry dropdown

## Changes



https://github.com/user-attachments/assets/cbf85100-7791-40da-a676-2c87c6a32976

---------

Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
2024-11-08 16:13:15 +00:00
Lucas BordeauandGitHub 045f569d62 Fixed dropdown menu field settings (#8374)
2 dropdown menu components were used. Using only one and using dropdown
props for passing width to its internal dropdown menu component.
2024-11-08 17:11:37 +01:00
Raphaël BosiandGitHub e8bf81de5b 8172 update the right drawer action menu to open with command o (#8375)
Closes #8172 

- Added a shortcut property to the button component
- Displays the actions inside a dropdown
- The dropdown is toggled either by clicking on the button or with the
`command + O` shortcut



https://github.com/user-attachments/assets/4c4c88fa-85dc-404e-bb42-f2b0d57c8960
2024-11-08 17:08:09 +01:00
khudditeandGitHub 0bf2cb69da Fix multi-dropdown field can't have no options selected (#8391)
Fixes: #8224 

1. Summary
All multi-dropdowns across the application don't accept empty options
because emptiness is perceived as an invalid state.

2. Solution
The issue came down to the back-end and the specific string utility
function that converts a string separated by `,` to an array of options.
But the problem with it is that it returns `['']` for an empty string
representing an emptiness. And then `['']` fails on the parser because
simply `''` is not a valid option the user selected for the dropdown. So
I updated the string utility function to return an empty array for cases
like `'', '{}', '{ }'`, etc

3. Recording


https://github.com/user-attachments/assets/071fe5d2-2123-4deb-878c-67f62d9b3431
2024-11-08 16:10:14 +01:00
Raphaël BosiandGitHub 5a53ef1ade Make filters work on export csv action (#8389)
- Create a new component state `contextStoreFiltersComponentState` and
refactor `contextStoreTargetedRecordsRuleComponentState`
- Refactor `computeContextStoreFilters` to use filters when no records
are selected
2024-11-08 15:38:45 +01:00
d44f7a46b6 fix: Misalignment and Excessive Padding in Relation Card (#8292)
## Description

- This PR solves the issue #8249 
- Maintained the overall padding, aligned content to left matching and
decreased Spacing between the card title and content should be smaller

## Changes

<img width="346" alt="Screenshot 2024-11-03 at 2 37 13 AM"
src="https://github.com/user-attachments/assets/91ba35bb-ff25-4001-af15-1fa10e5e1772">

---------

Co-authored-by: Thomas des Francs <tdesfrancs@gmail.com>
2024-11-08 14:10:15 +00:00
61cdc0e6da fix: kanban column margin should extend to bottom (#8394)
Fixes: #7868 

[Screencast from 2024-11-08
13-33-47.webm](https://github.com/user-attachments/assets/1de620d8-8f05-43f8-bde9-a2c9cbea4b9f)

---------

Co-authored-by: ehconitin <nitinkoche03@gmail.com>
2024-11-08 14:55:45 +01:00
Raphaël BosiandGitHub aa270950d9 Make csv export unavailable when only one record is selected (#8409)
Make csv export unavailable when only one record is selected
2024-11-08 14:50:04 +01:00
Félix MalfaitandGitHub a7a7d62502 Fix CI timeout (#8408) 2024-11-08 13:53:38 +01:00
Baptiste DevessierandGitHub f3e3c186dc Fix noninteractive toggle (#8383)
- Use a label to make the whole card interactive
- Disallow the Toggle component to shrink; it used to on mobile devices

A focus indicator is missing for the Toggle component. We'll have to add
one.
2024-11-08 12:42:15 +01:00
MarieandGitHub 8b5e90aca9 Update searchVector expression based on rich text fields (#8390)
Search vector fields based on `RICH_TEXT` fields were generated using a
treatment on `RICH_TEXT` fields's `body`
column, to only extract and index the core text.
([PR](https://github.com/twentyhq/twenty/pull/7953))

Actually our RICH_TEXT fields are of datatype `text` in our database,
allowing users to insert non-json values, which breaks the search vector
generation (as it expects json values).

Our vision is unclear for now: for instance we may want to turn
RICH_TEXT into a composite field where the plain text would be stored in
a different column.

So for now, we will (1) treat rich_text data as text, and (2) update the
search vector expressions for the existing workspaces.
2024-11-08 12:41:11 +01:00
Thomas TrompetteandGitHub 813c57fba6 Create workflow setup command (#8406)
Steps to enable workflows:
- enable feature flags
- run metadata sync
- run this command

If the feature flag is not true, the command will fail. Which will be
useful to prevent seeding a wrong workspace.

Including a little fix for send email aciton error
2024-11-08 12:40:11 +01:00
Félix MalfaitandGitHub d8831512d4 Add CI timeouts and enable playwright (#8405) 2024-11-08 12:24:22 +01:00
Félix MalfaitandGitHub b2004fe6b4 Fix contributor website import script (#8404)
We had duplicate entries in the database for issueLabels/ prLabels
2024-11-08 10:57:17 +01:00
f06cdbdfc6 refactor webhookAnalytics call and enrich analytics module (#8253)
**TLDR**

Refactor WebhoonAnalytics Graph to a more abstract version
AnalyticsGraph (in analytics module). Thus enabling the components to be
used on different instances (ex: new endpoint, new kind of graph).

**In order to test:**

1. Set ANALYTICS_ENABLED to true
2. Set TINYBIRD_JWT_TOKEN to the ADMIN token from the workspace
twenty_analytics_playground
3. Set TINYBIRD_JWT_TOKEN to the datasource or your admin token from the
workspace twenty_analytics_playground
4. Create a Webhook in twenty and set wich events it needs to track
5. Run twenty-worker in order to make the webhooks work.
6. Do your tasks in order to populate the data
7. Enter to settings> webhook>your webhook and the statistics section
should be displayed.

---------

Co-authored-by: Félix Malfait <felix@twenty.com>
2024-11-08 10:00:51 +01:00
f9c076df31 o365 calendar sync (#8044)
Implemented:

* Account Connect
* Calendar sync via delta ids then requesting single events


I think I would split the messaging part into a second pr - that's a
step more complex then the calendar :)

---------

Co-authored-by: bosiraphael <raphael.bosi@gmail.com>
2024-11-07 18:13:22 +01:00
83f3963bfb Be able to specify front port (#8382)
- Added REACT_APP_PORT in front .env
- Use value if specified otherwise 3001 by default

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2024-11-07 18:11:51 +01:00
6264d509bd Migrate to twenty-ui - navigation/menu-item (#8213)
This PR was created by [GitStart](https://gitstart.com/) to address the
requirements from this ticket:
[TWNTY-7536](https://clients.gitstart.com/twenty/5449/tickets/TWNTY-7536).

 --- 

### Description

Migrate all menu items components to twenty ui and update imports.

```typescript
MenuItem
MenuItemAvata
MenuItemCommand
MenuItemCommandHotKeys
MenuItemDraggable
MenuItemMultiSelect
MenuItemMultiSelectAvatar
MenuItemMultiSelectTag
MenuItemNavigate
MenuItemSelect
MenuItemSelectAvatar
MenuItemSelectColor
MenuItemSelectTag
MenuItemSuggestion
MenuItemToggle
```

\
Also migrate all other dependent components and utilities like
`Checkbox` & `Toggle`\
\
Fixes twentyhq/private-issues#82

---------

Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com>
Co-authored-by: gitstart-twenty <140154534+gitstart-twenty@users.noreply.github.com>
Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
2024-11-07 16:51:39 +00:00
Raphaël BosiandGitHub f9a136ab6d Update CanAccessMessageThreadService (#8388)
Trying to fix #7830
2024-11-07 17:32:41 +01:00
Raphaël BosiandGitHub fb22efd9e9 Fix CalendarOngoingStaleJob being in wrong queue (#8385)
Fix CalendarOngoingStaleJob being in the wrong queue
(`MessageQueue.messagingQueue` instead of `MessageQueue.calendarQueue`)
2024-11-07 17:29:00 +01:00
d9c0530dd3 Integration test : Sync mode + db reset option + cleaning (#8376)
Run the CI integrationin sync mode
and add the option to run it without db reset
cleaning all the useless integration test

---------

Co-authored-by: guillim <guillaume@twenty.com>
2024-11-07 17:22:47 +01:00
ac233b771c Simplify multi-object picker logic with search (#8010)
Simplifying the logic around multi-object pickers and search by getting
rid of the behaviour that keeped selected elements even when they did
not match the search filter (eg keeping selected record "Brian Chesky"
in dropdown even when search input is "Qonto"). This allows us to
simplify the fetch queries around the search to only do one query.

---------

Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
2024-11-07 17:09:19 +01:00
2ab4aa1377 Fix npx nx run start (twenty:server:worker was not triggered) (#8384)
twenty:server:worker was not triggered in npx nx run start

Co-authored-by: guillim <guillaume@twenty.com>
2024-11-07 15:57:12 +01:00
BOHEUSandGitHub c571c9bdca Playwright POM (#8109)
Related to #6641
2024-11-07 15:38:28 +01:00
BOHEUSandGitHub c3343d3600 Playwright basic utils (#7930)
Related to #6641
2024-11-07 15:34:53 +01:00
4f2b055ee0 fix: Minor bugs in UI (#7891)
## Description

- This PR fixed #7890

---------

Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
2024-11-07 14:04:33 +00:00
MarieandGitHub 60349d0989 Fix broken relation picker in Kanban (#8377)
Fixes https://github.com/twentyhq/twenty/issues/8233

Typing a search input was triggering a re-render of the whole
RecordBoardCard, resetting the search input to its initial value, an
empty string, making it impossible to actually type anything.
useRelationPicker had (legacy?) useless dependencies to recoil states
that caused the rerenders.
2024-11-07 13:55:21 +00:00
7bab65b569 Implement object fields and settings new layout (#7979)
### Description

- This PR has as the base branch the TWNTY-5491 branch, but we also had
to include updates from the main branch, and currently, there are
conflicts in the TWNTY-5491, that cause errors on typescript in this PR,
so, we can update once the conflicts are resolved on the base branch,
but the functionality can be reviewed anyway
- We Implemented a new layout of object details settings and new, the
data is auto-saved in `Settings `tab of object detail
- There is no indication to the user that data are saved automatically
in the design, currently we are disabling the form

### Demo\

<https://www.loom.com/share/4198c0aa54b5450780a570ceee574838?sid=b4ef0a42-2d41-435f-9f5f-1b16816939f7>

### Refs

#TWNTY-5491

---------

Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com>
Co-authored-by: gitstart-twenty <140154534+gitstart-twenty@users.noreply.github.com>
Co-authored-by: Marie Stoppa <marie.stoppa@essec.edu>
Co-authored-by: Weiko <corentin@twenty.com>
2024-11-07 14:50:53 +01:00
prathameshpatil5181andGitHub 3be30651b7 fix : 7223 Clicking Outside Fields domain link email phone Close Them (#7804)
fixes #7223

https://github.com/user-attachments/assets/1150e96f-4fb5-40ba-ac17-89d8b2ab16e7
2024-11-07 12:40:28 +00:00
martmullandGitHub f3a38679ae Add try catch to command (#8381)
fixes 0-32 command
2024-11-07 11:27:33 +01:00
545cfbd83e Update documentation padding on mobile devices (#8318)
close #8086 

- Technical explanation of the issue
The mobile documentation pages have a fixed width of `340px`, regardless
of the device. And they are centered horizontally, so the horizontal
padding is determined automatically.

- Explanation of the fix
I've updated the styling of those pages to use fixed padding `32px`
instead and let it determine the width (`deviceWidth - 64px`).
    
- Screenshots
    
![CleanShot 2024-11-04 at 15 01
59](https://github.com/user-attachments/assets/d2ecf215-cbee-4ea0-b627-53ac756095bc)
![CleanShot 2024-11-04 at 15 02
23](https://github.com/user-attachments/assets/bb03854f-17ee-43dc-bba2-feeddc6a2750)

---------

Co-authored-by: Félix Malfait <felix@twenty.com>
2024-11-07 08:50:20 +01:00
Thomas TrompetteandGitHub 117e502e80 Clean available fields in variable dropdown (#8371)
As title

We do not want relations yet in picker
2024-11-06 16:54:23 +01:00
Jérémy MandGitHub ffd790c8fd fix: don't use previous view group state when creating a new view (#8370)
When creating a new view we don't want to use view-groups from previous
view.
2024-11-06 16:33:51 +01:00
Raphaël BosiandGitHub a6007d4376 Fix action menu dropdown (#8368)
Fix action menu dropdown not closing when clicking outside the table or
board and introduce helper functions to get the action menu component
ids.
2024-11-06 16:11:31 +01:00
Charles BochetandGitHub 278ab4c513 Fix loginToken and legacy apiToken not working (#8369) 2024-11-06 15:56:14 +01:00
4b5d096441 Fix of broken API Auth (#8338)
Fix done this morning with @FelixMalfait  from #8295

---------

Co-authored-by: guillim <guillaume@twenty.com>
Co-authored-by: Félix Malfait <felix@twenty.com>
2024-11-06 14:45:33 +01:00
24656e777e Fix : Enter hotKey issue onPress of ConfirmationModal (#7802)
**Description**

Fixes https://github.com/twentyhq/twenty/issues/7753
After entering proper value to input and pressing Enter, respective
action is being performed for all the popus.
This fix is is applicable to all the scenarios mentioned in
https://github.com/twentyhq/twenty/issues/6663 as well



https://github.com/user-attachments/assets/b7ed387f-1f36-4c93-b795-15a7b95c9958

Signed-off-by: Jayabharathi S <jayabharathi.s@thoughtworks.com>
Co-authored-by: Jayabharathi S <jayabharathi.s@thoughtworks.com>
Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
2024-11-06 13:39:27 +00:00
Baptiste DevessierandGitHub 452a30fc06 Add nxw.js file (#8362)
It makes the Nx VS Code extension work on my computer. The generated
file says it must be commited.
2024-11-06 14:24:07 +01:00
Félix MalfaitandGitHub b627c55b9a Add blue focus on text inputs (#8343)
We removed the blue focus on phone/domain/array/email floating inputs
but we want to keep it in the app settings.

<img width="644" alt="Screenshot 2024-11-05 at 15 55 04"
src="https://github.com/user-attachments/assets/afcbe6b2-2d6b-4e0d-8397-4268d529127c">
<img width="606" alt="Screenshot 2024-11-05 at 15 55 23"
src="https://github.com/user-attachments/assets/004becf8-41e7-45d6-9ad9-9e487b8db8f3">
<img width="351" alt="Screenshot 2024-11-05 at 15 55 33"
src="https://github.com/user-attachments/assets/6a4c06e6-04d3-46bf-940b-9fd61ee91995">
<img width="330" alt="Screenshot 2024-11-05 at 15 55 41"
src="https://github.com/user-attachments/assets/e6fc8bbd-eca3-47bc-93f1-d6ff8d3d8a13">
<img width="588" alt="Screenshot 2024-11-05 at 15 56 07"
src="https://github.com/user-attachments/assets/0d0f5e80-3501-4346-94a1-6ea4b77ee7ba">
<img width="211" alt="Screenshot 2024-11-05 at 15 56 31"
src="https://github.com/user-attachments/assets/9cd85f4d-8052-4c6b-a694-84c691c6217d">
2024-11-06 14:23:34 +01:00
khudditeandGitHub 5a293b8d60 Update menu title font size based on whether or not it's clickable (#8354)
Fixes #8350 

1. Summary

https://www.figma.com/design/xt8O9mFeLl46C5InWwoMrN/Twenty?node-id=36424-125120&node-type=instance&t=psxuagFLo1Cu26Vz-0

Based on Figma, the menu header should have `base/medium` instead of
`small/medium` when it's not clickable or dropdown. However, for
dropdowns, we should keep it as `small/medium`. Menu items should stay
as `base/regular`.

2. Solution
Utilized `onClick` prop to decide the font size of the menu header. That
way, Dropdowns stay as `base/small` while non-clickable headers are
updated to `base/medium`

3. Screenshots 
***please check out font size and weight for each case***

header: ![CleanShot 2024-11-05 at 17 45
23](https://github.com/user-attachments/assets/29bd6737-7470-452b-8483-a3adc9cd4db7)

menu item: ![CleanShot 2024-11-05 at 17 46
46](https://github.com/user-attachments/assets/4664156a-ad81-4437-ba71-51f88813dd88)

dropdown: ![CleanShot 2024-11-05 at 17 47
38](https://github.com/user-attachments/assets/c109f4cc-3a16-4c8a-9f4b-861138cc825a)
2024-11-06 14:08:29 +01:00
18d04de676 fix: RightDrawer doesn't save context values when clickedOutside (#7729)
## Description

- This PR fixes #7728 

## Changes


https://github.com/user-attachments/assets/1e66cab3-9009-4c01-9ac6-22651b0ff5e7

---------

Co-authored-by: bosiraphael <raphael.bosi@gmail.com>
Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
2024-11-06 11:46:30 +01:00
Raphaël BosiandGitHub 7f51eb8c3c Add the possibility to run workflows with manual trigger from the command K with no records selected (#8342)
https://github.com/user-attachments/assets/9f094439-8d19-4a6b-883b-456294f691d8
2024-11-06 11:43:18 +01:00
ac7d740135 fix: when field metadata SELECT type is edited update view groups (#8344)
Co-authored-by: Charles Bochet <charles@twenty.com>
2024-11-06 11:41:44 +01:00
Lucas BordeauandGitHub e36363fe15 Fix scroll wrapper (#8349)
Fixed scroll wrapper with conditionnal rendering
2024-11-06 10:05:17 +01:00
Harsh SinghandGitHub 2d6b239da4 fix: Prevent isDisabled prop from passing to DOM in Settings/Security Link (#8317)
Fixes: #8297
2024-11-06 10:02:06 +01:00
ca91dc2dc6 Add useUploadAttachment hook (#7617) (#7690)
Reusing the useUploadAttachment Hook

In the implementation of the feature to ensure the attachment table is
updated whenever new images are added to a RICH_TEXT field #7617 , it is
likely that the useUploadAttachment hook is reused.

The useUploadAttachment hook is responsible for handling the upload of
attachments, including images, and returning the uploaded file URL. By
reusing this hook, you can leverage its existing functionality to handle
image uploads within the RICH_TEXT field.

In this case, the modified image handling logic would utilize the
useUploadAttachment hook to upload new images added to the RICH_TEXT
content. The hook would then return the uploaded file URL, which would
be used to update the attachment table with the details of the newly
added images.

By reusing the useUploadAttachment hook, you can avoid duplicating code
and ensure consistency in the way attachments are handled throughout the
application.

Fixes #6565

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
2024-11-05 21:18:31 +00:00
Raphaël BosiandGitHub 9e051d7900 8304 - Fix Action Menu Buttons Alignment (#8348)
Closes #8304

The position of the modal container wasn't absolute, so the gap was also
applied after the `ShowPageMoreButton`
2024-11-05 18:19:01 +01:00
Charles BochetandGitHub 88ba057b2c Fix 0.32 bis (#8346)
Various UI fixes according to discussions with Design team
2024-11-05 18:14:44 +01:00
3793f6c451 fix: content getting hide on drag and drop in stage view cards (#7621)
## ISSUE

-  Closes #7388 

## Demo



https://github.com/user-attachments/assets/193813aa-def9-406b-9fe7-397627bb1242

- [ ] Table Row Drag WIP

---------

Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
2024-11-05 16:03:24 +01:00
Charles BochetandGitHub 84b0b78b6f Refactor kanban new card creation (#8339)
On the kanban page, the record creation was changed a few weeks ago to
enable creation on top / bottom of the columns.

However, this introduced a glitch (missing background opacity). While
fixing it, I have refactored the component structure to:
- separate "New" button from the Empty record card
2024-11-05 15:16:38 +01:00
Thomas TrompetteandGitHub be8141ce5e Infer function input in workflow step (#8308)
- add `inputSchema` column in serverless function. This is an array of
parameters, with their name and type
- on serverless function id update, get the `inputSchema` + store empty
settings in step
- from step settings, build the form 

TODO in next PR:
- use field type to decide what kind of form should be printed
- have a strategy to handle object as input



https://github.com/user-attachments/assets/ed96f919-24b5-4baf-a051-31f76f45e575
2024-11-05 14:57:06 +01:00
Raphaël BosiandGitHub d1531aa1b6 8191 command k workflow trigger for selected record (#8315)
Closes #8191 


https://github.com/user-attachments/assets/694da229-cc91-4df2-97a0-49cd5dabcf12
2024-11-05 13:37:29 +01:00
Lucas BordeauandGitHub 0893774cc1 Fixed expandable list and navigation menu (#8336)
For release 0.32

- Fixed expandable list dropdown UI bugs
- Added ScrollWrapper on navigation menus
2024-11-05 11:34:00 +00:00
9b0c74251f Fix actions setter when opening the command menu (#8263)
Fix standard actions overriding navigate and create commands when
opening the command menu.

Before fix:
<img width="493" alt="Capture d’écran 2024-10-31 à 18 08 56"
src="https://github.com/user-attachments/assets/015bd798-baa4-4f84-8886-e355c0ef1455">

After fix:
<img width="499" alt="Capture d’écran 2024-10-31 à 18 08 34"
src="https://github.com/user-attachments/assets/02ba7fc4-ec90-4c13-9830-d884c0da37d9">

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2024-11-05 11:01:08 +01:00
Charles BochetandGitHub 88d6f5e59e Bump to 0.32 (#8324) 2024-11-05 00:19:05 +01:00
Charles Bochet dbd4292b6a Add backfill view groups command 2024-11-04 23:59:34 +01:00
Charles BochetandGitHub 4fc690b42c Fix 0.32 (#8319)
- Removing unique constraint creation in 0.32 as we have a dependency on
sync-metadata and sync-metadata has a dependency on it if we keep it.
- sync-metadata does not support well the deletion of activity +
activityTarget, silently swallow the exception for now
2024-11-04 22:08:07 +01:00
Harsh SinghandGitHub 8e82b08acb fix: settings error layout (#7674)
Fixes: #7460 

![Screenshot from 2024-10-14
15-27-52](https://github.com/user-attachments/assets/bbae5c6f-0b36-4f98-92c5-de27b1eb06ad)

**Changes & Why**

Since all the settings pages lie in the Outlet of DefaultLayout, there
was no way to handle it apart from creating a separate errorFallback for
the settings route.
So, I created a settingsErrorFallback component that uses the same
styling of settings pages.
Created ErrorBoundaryWrapper that checks if its settings route then show
SettingsErrorFallback else show GenericErrorFallback.
Now, for the breadcrumb part. I found that all the settings pages use
hardcoded title. So, I created generateBreadcrumbLinks function that
will provide different title and links based on how it's respective
settings page has them.
If this approach looks fine, I will add the other remaining titles and
links to the generateBreadcrumbLinks function and move that whole
function to its separate file. And will fix linting errors.

If there is any different approach to handle it, lemme know. I'm happy
to implement it.
2024-11-04 17:27:29 +00:00
ZiaCodesandGitHub 66c0aa5e52 feat: improved table scrolling (#7731)
This PR fixes #7515

Demo:


https://github.com/user-attachments/assets/8181cda0-3b77-43bf-b605-ba43f2290b84
2024-11-04 16:55:13 +00:00
Charles BochetandGitHub 52e5f7daeb Unselect record table records on table body click (#8306)
We have previously fixed the unselection of table records on click
outside. However, the ref was mispositioned as it selected the full
height table. In the case of low record numbers, we also want the
unselection to happen on table body click
2024-11-04 17:44:50 +01:00
martmullandGitHub 695991881f 6071 return only updated fields of records in zapier update trigger (#8193)
- move webhook triggers into `entity-events-to-db.listener.ts`
- refactor event management
- add a `@OnDatabaseEvent` decorator to manage database events
- add updatedFields in updated events
- update openApi webhooks docs
- update zapier integration
2024-11-04 17:44:36 +01:00
MarieandGitHub 741020fbb0 Fix gap in object edition page (#8310)
Fixing 

![image](https://github.com/user-attachments/assets/794968c2-1d13-49f2-9367-e93285a7d10f)

Note - this page design be updated in the next release
(https://github.com/twentyhq/twenty/pull/7979)
2024-11-04 17:36:03 +01:00
MarieandGitHub 76e8bf33ac Fix relation picker for activity target (#8303)
[This PR](https://github.com/twentyhq/twenty/pull/8210) introduced a
regression, causing noteId or taskId (respectively for noteTarget or
taskTarget creation) to be overwritten with an undefined value in the
input for noteTarget or taskTarget creation.
This is because in ActivityTargetInlineCellEditMode, in addition to the
noteId and taskId we are declaring, we are looking into the object
(noteTarget or taskTarget)'s fields and prefilling the record-to-create
with a value, potentially undefined, for all of the object fields.
So when looping over noteTarget's fields, we would find the `note`
relation field, and eventually add `note: undefined` to the
record-to-create input, in addition to the non-empty and valid existing
`noteId`.
Then in sanitizeRecordInput, from the note added right above, we add an
empty noteId to the input from node, overwriting the "good" noteId.

There are several ways to fix this, I chose to update prefillRecord not
to add an empty "note" object that makes no sense in addition to the
"noteId" we already have at this stage.
It is also possible to update `sanitizeRecordInput` not to overwrite a
value from a relation (noteId from note relation) if there is already a
value in the input.
2024-11-04 14:39:48 +01:00
Jérémy MandGitHub 258fd07839 feat: use new component state api for record table (#8143)
This PR drop the use of the old component state api in favour of the new
component state api V2.
2024-11-04 12:07:07 +01:00
Félix MalfaitandGitHub 740ca550cc Fix Danger CI not running (#8299)
The Danger CI was not running anymore (we need it for CLA/Congrats bot)
2024-11-04 08:37:44 +01:00
b66bdd9de5 [FIX] remove blue outline for Phones, Emails, and Domains fields (#8268)
FIX: #8252

---------

Co-authored-by: Félix Malfait <felix@twenty.com>
2024-11-04 08:32:27 +01:00
BOHEUSandGitHub 8b1f34dbfb IconButton Secondary color (#8286)
Related to #8212
2024-11-03 17:18:32 +01:00
BOHEUSandGitHub d350662984 Fix docs with missing npx (#8288)
Related to #8082

Created this PR on purpose after both #8083 and #8161 were closed and
respective branches were deleted by the author
2024-11-03 16:49:36 +01:00
LairtonandGitHub 0c6c22b852 Fix typo in default member's last name (#8293)
Fixes #8290

Correct the last name of the default member "Phil Shiler" to "Phil
Schiler" in the
`packages/twenty-server/src/database/typeorm-seeds/workspace/workspace-members.ts`
file.

* Change the last name from "Shiler" to "Schiler" for the user with the
email `phil.schiler@apple.dev`.

---

For more details, open the [Copilot Workspace
session](https://copilot-workspace.githubnext.com/twentyhq/twenty/issues/8290?shareId=13cc0610-8aaf-45f9-9e96-2a723ed60218).
2024-11-03 16:41:25 +01:00
Félix MalfaitandGitHub 558cc6810e Fix assignee not displayed on tasks (#8280)
Fix an issue where the assignee of a task wasn't displayed on the task
record's show page
2024-11-01 18:26:56 +01:00
6630fc4a6a Fixed typo in task's status (#8274)
Related to #8100

---------

Co-authored-by: Félix Malfait <felix@twenty.com>
2024-11-01 11:33:30 +01:00
BOHEUSandGitHub f70ed7fb5a Remove oss.gg banner from README.md (#8275) 2024-11-01 11:28:56 +01:00
Raphaël BosiandGitHub 234a5db80c Fix hotkey scope when opening command menu (#8258)
Fix hotkey scope when opening command menu
2024-11-01 09:25:10 +01:00
Raphaël BosiandGitHub a71a350ed2 Fix disabled + focus button (#8259)
Before fix:
<img width="302" alt="Capture d’écran 2024-10-31 à 16 56 03"
src="https://github.com/user-attachments/assets/20e219a7-7020-4076-8e8a-bf4892dc0863">
After fix:
<img width="312" alt="Capture d’écran 2024-10-31 à 16 55 54"
src="https://github.com/user-attachments/assets/4b759b08-85cb-40ff-aacd-09b078f08033">
2024-11-01 09:24:51 +01:00
Lucas BordeauandGitHub c93d2bcd5e Fixed many dropdown bugs (#8256)
Many dropdown bugs have been fixed, more refactoring is needed.

Dropdown fixed : 
- Filter select
- Sort select
- Visible field select
- Hidden field select
- Multi item picker (phones, links, emails, etc.)
- Phone country select
2024-11-01 09:23:01 +01:00
Charles BochetandGitHub a287edd91b Kanban full name (#8261) 2024-11-01 09:19:55 +01:00
Félix MalfaitandGitHub 86a0ea7c43 Delete oss-gg directory (#8271)
As per title
2024-11-01 09:10:24 +01:00
e5641c5c53 fix #7085 breadcrumb fix for mobile viewport (#7419)
ISSUE
Closes https://github.com/twentyhq/twenty/issues/7085

DEMO 


https://github.com/user-attachments/assets/39692906-c02e-4e4c-9205-82447fa142df

---------

Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
2024-10-31 17:17:13 +00:00
Thomas TrompetteandGitHub 74291e531c Fix storybook tests (#8260)
Before 
<img width="717" alt="Capture d’écran 2024-10-31 à 16 58 34"
src="https://github.com/user-attachments/assets/b8ec61f3-11c2-497f-9e4f-183b7989fb59">

After
<img width="717" alt="Capture d’écran 2024-10-31 à 16 58 14"
src="https://github.com/user-attachments/assets/8e0a1fbf-19c4-4cd0-ab7b-58ebb5ded1f5">



Before
<img width="586" alt="Capture d’écran 2024-10-31 à 16 57 59"
src="https://github.com/user-attachments/assets/eb6caf91-3953-4a8f-a847-17a50cc40d02">

After
<img width="586" alt="Capture d’écran 2024-10-31 à 16 57 29"
src="https://github.com/user-attachments/assets/9eee3502-66b4-41c9-a924-b5d3ddb921e3">
2024-10-31 17:19:44 +01:00
Jérémy MandGitHub 3fbd312141 fix: no more dashed line (#8254)
Fix bug introduced by #8152 where `<Tag />` component doesn't have
dashed lines anymore.
<img width="114" alt="Screenshot 2024-10-31 at 3 10 10 PM"
src="https://github.com/user-attachments/assets/25c9cb91-7be2-407b-9f07-a3811fb2d082">
<img width="134" alt="Screenshot 2024-10-31 at 3 10 03 PM"
src="https://github.com/user-attachments/assets/c44a551f-0e02-4fd4-b779-2076df513b03">
2024-10-31 15:32:51 +01:00
Raphaël BosiandGitHub b1a96e2e04 Fix logged out scopeId error (#8250)
Fix logged out scopeId error
2024-10-31 15:01:54 +01:00
Harshit SinghandGitHub c9fcce6590 fix: Emails input field stays in errored state (#8243)
## Description

- This PR fixes the issue #8235 
- Error state resets when error state is removed

## Changes



https://github.com/user-attachments/assets/0aeb99fe-56c8-437a-ad2c-97e245a44158
2024-10-31 13:26:59 +01:00
aff55f49fe 🕹️ feat(cli): script to migrate (contacts and companies) from Attio to Twenty (#8046)
I made an MVP of a Command Line Interface to help migrate (just contacts
and companies for now) from Attio to Twenty. I made this rushing but
here's the code of the script:
[code](https://github.com/chrisdadev13/twenty-cli/tree/main) and a
little a
[demo](https://www.loom.com/share/f98f34f8d9b34728998847d3b97a16b7) :)

<img width="650" alt="Screenshot 2024-10-24 at 8 56 27 PM"
src="https://github.com/user-attachments/assets/2668084c-941a-4150-875c-1f2b60c1c9ba">

Since Twenty is open source, this kind of tools can be a great way to
catch contributions and also improve migrations process. I mean, now
with the CLI you can only migrate from Attio, but what if tomorrow
someone extends the tool to easily migrate from Salesforce, or any other
CRM, to Twenty? 🤔

Co-authored-by: Charles Bochet <charlesBochet@users.noreply.github.com>
2024-10-31 13:09:02 +01:00
Charles BochetandGitHub 034e558758 Deprecate useListenClickOutsideByClassNameListener (#8242) 2024-10-31 12:46:21 +01:00
Lucas BordeauandGitHub d46820472c Fix view filter creation on new view (#8199)
Wrong view was used for the creation from another view (source and
target view were inverted)
2024-10-31 12:44:20 +01:00
Baptiste DevessierandGitHub b3f95d6db9 Ensure the text of select control is aligned on the left (#8238)
Fixes:


![image](https://github.com/user-attachments/assets/900596ed-1426-49cd-a2f3-4b81eacbb7d0)

The regression is due a recent change I made to the SelectControl
component: https://github.com/twentyhq/twenty/pull/8125.

The SelectControls get applied `text-align: center` due to the styles
`react-datepicker` applies to the header component. My grid
implementation makes the label take all the available width. I could
have let it take an `auto` width, but I think it's better to set the
`text-align` property and ensure the `SelectControl` component behaves
predictably.
2024-10-31 12:03:45 +01:00
Raphaël BosiandGitHub b1e9922660 Fix context store filters (#8236)
Fix context store filters
2024-10-31 11:51:51 +01:00
Baptiste DevessierandGitHub d0dc8bae4f Fix save record table cell when clicking outside table (#8230) 2024-10-31 11:45:40 +01:00
Thomas TrompetteandGitHub f5bde0251b Put back object type in settings form (#8234)
Before
<img width="673" alt="Capture d’écran 2024-10-31 à 11 15 27"
src="https://github.com/user-attachments/assets/78d81f5b-88c0-40b7-8901-104365ecdd49">


After
<img width="673" alt="Capture d’écran 2024-10-31 à 11 15 07"
src="https://github.com/user-attachments/assets/9427da22-a75b-4257-b948-28807b110b26">
2024-10-31 10:27:54 +00:00
Aditya DeshlahreandGitHub f465a7bc11 ossgg: side quest content/design challenge blogs + figma link add (#8182)
### Twenty side quest content challenge

#### Self Hosting Blog

- [BLOG
Live](https://dev.to/adityadeshlahre/complete-guide-to-self-hosting-twenty-crm-2h08)

#### Points 750

#### Details Review of Twenty

- [BLOG
Live](https://dev.to/adityadeshlahre/transform-your-customer-relationships-with-the-leading-open-source-crm-twenty-161d)

#### Points 750

Please give it a read 

### Twenty side quest design challenge

- [Figma
Link](https://www.figma.com/design/4hlpS6LOIaJqDbd6T6SlXc/CustomTwentyByAdityDeshlahre?node-id=478-19796&t=Dp8EBpl0FxVjiGHT-1)

- [prototype
preview](https://www.figma.com/proto/4hlpS6LOIaJqDbd6T6SlXc/CustomTwentyByAdityDeshlahre?node-id=478-19796&t=Dp8EBpl0FxVjiGHT-1)

#### Please check prototype for most updated theme 

### theme:POV

![image](https://github.com/user-attachments/assets/16775432-e0ee-462e-8041-1fd5e6f5d6f0)

### ProperMint


![image](https://github.com/user-attachments/assets/c8355c6b-092c-4e14-abc0-2c8475bf0754)

![image](https://github.com/user-attachments/assets/befb0964-59e2-4113-8396-282fd1b51da3)

![image](https://github.com/user-attachments/assets/7c6a59fe-6215-4b5f-8e52-188abfeef310)

##### Updated Side button

![image](https://github.com/user-attachments/assets/abdf5ef0-b802-461f-b83f-b2d38eda5443)

#### Points 750

### Total Points : 2250 { if every thing seems good then 🤣 }

Thank You 🙂
2024-10-31 11:09:51 +01:00
Charles BochetandGitHub 99837f9752 Fix integration tests (#8229)
Removing leftovers of the deprecated "activity" object which is fixing
our integration tests
2024-10-31 10:36:29 +01:00
RajuGangitlaandGitHub 2bfd0fe252 ossgg: article, blog, migration script, n8n workflow (#8183)
Total points : **3750 points** 

1. Self hosting guide (750 points)

[link](https://dev.to/raju_gangitla_91920e1427f/self-hosting-twenty-crm-a-complete-guide-559n)

2. Blog posted on my company website  (750 points)
[blog](https://zedblock.com/blog/twenty-crm)

3. i wrote a script for data migration from zoho to twenty (750 points)
here is the [github
link](https://github.com/RajuGangitla/twenty-migration-scripts)
here is the [video
link](https://www.loom.com/share/f072bf31fb46449d98d6826a3a824fe9?sid=21f2c3f4-f286-43a2-98aa-d1fb92c3a86e)

4. created a n8n workfow for which will add, update and delete people
data in google sheets whenver we change in twenty dashbaord (750 points)
i attached the template json down below 
here is the
[video](https://www.loom.com/share/89f86ef895e946fbbbbae3cc90559bb7?sid=5015c1da-b472-46c3-b144-1d170bdf5c9f)


[twenty_leads_to_google_sheets.json](https://github.com/user-attachments/files/17576685/twenty_leads_to_google_sheets.json)

5. Wrote a comprehensive guide on " integrate Twenty with marketing
automation tool (n8n, Zapier). " (750 points)
Here is the
[link](https://dev.to/raju_gangitla_91920e1427f/automating-people-data-sync-n8n-workflow-for-twenty-crm-and-google-sheets-5789)
2024-10-31 10:28:31 +01:00
WeikoandGitHub 82f33efe9c Add missing CopyWebhookOperationIntoOperationsCommand to 0.32 upgrade global command (#8219)
## Context
This command was missing in the global upgrade command, this PR simply
adds it.
2024-10-31 09:56:44 +01:00
MarieandGitHub e5d492d09f Fix empty option selected in single entity select (#8208)
SingleEntitySelect was wrongfully showing the empty option (eg "No
company") as selected if the selected option was not showing in the
list, because of a search filter for instance (eg selected option is
"Linkedin" but search filter is "a").

Fixing this and removing misleading prop selectedEntity from components
where it is never passed.
2024-10-31 09:41:44 +01:00
WeikoandGitHub d19bc2c224 Fix SimplifySearchVectorExpressionCommand (#8218)
## Context
This command was introduced to simplify searchVector expressions that
were added in v0.31.x for existing workspaces.
New search vector columns have been added later during 0.32 development
and should not be migrated, this actually breaks the command because we
run sync-metadata before the upgrade command.

The fix removes the throw since this is expected and return early if the
search vector was not matched with an object that needs migration.

## Test
checkout v0.31.0
reset:db command
checkout this PR
run typeorm migrations
run upgrade 0-32 command
2024-10-30 17:47:52 +01:00
Thomas TrompetteandGitHub c7c16f7114 Fix date picker size (#8216)
<img width="760" alt="Capture d’écran 2024-10-30 à 16 54 19"
src="https://github.com/user-attachments/assets/b9b0f717-d93e-48d4-9df5-b817eab5b704">
2024-10-30 17:34:05 +01:00
Raphaël BosiandGitHub 7a5d52e88d Update action menu bar (#8178)
Closes #8023
2024-10-30 17:22:42 +01:00
MarieandGitHub 7dfde04957 Fix advanced settings display (#8196)
In [this PR (fix navigation
overflow)](https://github.com/twentyhq/twenty/pull/7795) we introduced a
regression, hidding the left-side animation with advanced settings:
<img width="285" alt="Capture d’écran 2024-10-30 à 12 56 22"
src="https://github.com/user-attachments/assets/46d7b1e5-4759-42e9-9bcb-aaa0fedfe542">

<img width="274" alt="Capture d’écran 2024-10-30 à 12 56 31"
src="https://github.com/user-attachments/assets/d3c3d337-f6fc-4509-a920-4c2c7506f061">
2024-10-30 16:18:44 +00:00
Charles Bochet 3957658e1c Fix storybook tests 2024-10-30 17:02:07 +01:00
MarieandGitHub 692c4ba6fb Add simple configuration to ts_query (#8215)
In the expression of our searchVector fields, we use the "simple"
configuration (over the default "english" one), to avoid picking a
language that's irrelevant to the user.
I initially forgot to add the same configuration to the query that is
being sent using ts_query.
Adding it will also allow the search to work for a single character,
while so far a single letter was most of the time considered a "stop
word" (a word with no semantic value, like "a").
2024-10-30 16:58:51 +01:00
martmullandGitHub 7f90ac2df8 Handle case where fieldValue is null (#8210)
Allow null values when updating relation to fix detach action
2024-10-30 16:53:02 +01:00
martmullandGitHub 7b467822f1 Fix tinybird Ci (#8211)
Ignore ci job if no change in tinybird
2024-10-30 15:36:47 +00:00
Charles BochetandGitHub b7d5c05a74 Fix front tests (#8207) 2024-10-30 15:50:56 +01:00
50c912d57f Delete unused objects (#7823)
Fixes #7113

---------

Co-authored-by: Weiko <corentin@twenty.com>
2024-10-30 13:35:43 +01:00
57d9b8e8b4 feat: generate secret function and replaced few instances (#7810)
This PR fixes #4588

---------

Co-authored-by: Félix Malfait <felix@twenty.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
2024-10-30 12:07:11 +01:00
Lucas BordeauandGitHub 1782865ff8 Added feature flag for advanced filter (#8194)
Added feature flag for advanced filter
2024-10-30 12:06:46 +01:00
Atharva_404andGitHub cb3ceba893 Update 2-tweet-about-fav-twenty-feature.md (#8185)
Added my entry

### Points
50

### Issues
Solves #8186 

### Proof
Here is a screenshot of proof:

![image](https://github.com/user-attachments/assets/95a63e21-44fe-4a5b-a974-02e11b03f43a)
2024-10-30 09:10:08 +01:00
Harsh Shrikant BhatandGitHub 16a29bc217 ossgg: Promotional video with animation and 3d Objects (#8184)
https://x.com/HarshBhatX/status/1851481457761370559

It is too big in size to upload here 🤓.

Points:
750
2024-10-30 09:09:03 +01:00
Atharva_404andGitHub c1c55d0208 Update 1-quote-tweet-20-oss-gg-launch.md (#8187)
Added my entry

### Points
50

### Issue
#8188 

### Link to the tweet
https://x.com/0x_atharva/status/1851503532840566919
2024-10-30 09:08:00 +01:00
Baptiste DevessierandGitHub d887a857ca Revert "fix: Country Dropdown not closing with AddressInput " (#8174)
Reverts twentyhq/twenty#8147
2024-10-29 15:55:18 +01:00
WeikoandGitHub 31ecaf2a0d fix object metadata renaming (#8175)
## Context
Latest refactoring broke the findOneWithinWorkspace method which is
called during object update, I'm simply reverting this change.
object-metadata-relation.service was naively computing a namePlural
based on the nameSingular while we already had that info in the DB...
Should fix some issues with renaming as well because the original field
was not computed with the right name.
2024-10-29 14:45:27 +00:00
Raphaël BosiandGitHub fe2c8bb43b 7339 implement contextual actions inside the commandmenu (#8000)
Closes #7339


https://github.com/user-attachments/assets/b623caa4-c1b3-448e-8880-4a8301802ba8
2024-10-29 15:10:45 +01:00
martmullandGitHub 8bb07c4a4f 8130 creating a new company in twenty doesnt activate on zapier (#8166)
- fix webhook.operation format change from august 2024 not spread in
twenty-zapier
- added a comment so it does not happen again
- add a fix for the new webhook.operations column that would produce
another issue
2024-10-29 13:56:01 +01:00
Muhammad AbdullahandGitHub 77a4aa2649 added light background for better hover visibility on dark theme (#8043)
fixes: #7969 

## What does this PR do?

Apply a lighter background color to enhance the hover effect in dark
mode.


![twenty-hover](https://github.com/user-attachments/assets/3d218060-2328-481e-9e66-250abd276dc0)
2024-10-29 10:42:04 +00:00
2e10070fdb fix(sso): improve enterprise key var management (#8152)
Resolve https://github.com/twentyhq/twenty/issues/8070

---------

Co-authored-by: Félix Malfait <felix@twenty.com>
2024-10-29 11:39:00 +01:00
95b475c855 Fixes "No Result" flash and add a separator (#8140)
Fix for #8137

---------

Co-authored-by: Félix Malfait <felix@twenty.com>
2024-10-29 11:36:25 +01:00
Harsh SinghandGitHub c0484aa9a2 fix: dropdown max-height and padding bottom (#8167)
Fixes: #6105 

Also fixed side effect due to previous PR:

[Screencast from 2024-10-29
13-54-44.webm](https://github.com/user-attachments/assets/f15db853-ca1c-4be8-9362-610122c4d988)
2024-10-29 11:00:35 +01:00
Félix MalfaitandGitHub f79e904dd6 Enable Tinybird CI (#8168)
Test to enable it in a second PR. I think it needed to merged in main
first
2024-10-29 10:43:04 +01:00
8ef4efa0f5 add twenty-tinybird package (#8030)
https://github.com/twentyhq/private-issues/issues/75

**TLDR**

Add twenty-server package, wich contains the last tinybird datasources
and pipes used in analytics.

This new version of the API endpoints, pipes and datasources are
inspired by the implementation of dub.co
(https://github.com/dubinc/dub/blob/main/packages/tinybird/).

It contains the webhooks analytics, serverless functions duration and
serverless functions error count analytics. As well as


**In order to test**

- Follow the instructions in the README.md on twenty-tinybird using your
admin token from twenty_analytics_playground if you want to modify them.
- For a better experience add the extension Tinybird support for VsCode 
- If you want more info about datasources and pipes please read the
tinybird docs.

---------

Co-authored-by: Félix Malfait <felix@twenty.com>
Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
2024-10-29 10:31:05 +01:00
Aditya DeshlahreandGitHub 6fba3e0805 ossgg: completed all side quest-wizard (#8158)
# Quest Wizard completed all side quest

- bug #8132
- all other side quest done #7848
- meme #7848
- gif #7848
- fav feat about twenty #7848
- initial contribution tweet #7848

# point 300

thank You 🙂
2024-10-29 10:11:32 +01:00
Ashish ViradiyaandGitHub ac2798b78f Article on 20CRM (#8155)
total point: 1500
Links:
Selft hosting: 

https://medium.com/@ashishviradiya153/comprehensive-guide-to-self-hosting-twenty-crm-26e7fa36c846
about 20:

https://medium.com/@ashishviradiya153/is-twenty-crm-the-right-tool-for-your-business-heres-my-honest-review-0d41e9d8a7eb
2024-10-29 10:05:19 +01:00
7901dbc02f fix: Country Dropdown not closing with AddressInput (#8147)
## Description

- This PR fixes #8080 
- The Country Selector dropdown closes with Address Input `clickOutside`
function

## Changes


https://github.com/user-attachments/assets/1ab85175-9ce9-40d2-ac52-14bfe87e254f

---------

Co-authored-by: Devessier <baptiste@devessier.fr>
2024-10-29 10:03:28 +01:00
martmullandGitHub 94f2e1067b Revert "fix: dropdowns should have a max-height & padding from screen" (#8165)
Reverts twentyhq/twenty#8055
2024-10-29 08:54:16 +00:00
a725245c2f Add padding to navigation header (#8050)
This PR adds padding to the header to align the logo with other icons on
the sidebar.

## Before


![image](https://github.com/user-attachments/assets/6501bbbf-bf06-4d9f-bff7-2d36c1b63a37)


## After


![image](https://github.com/user-attachments/assets/24610cf8-eab2-49bd-b611-e68a66228fd6)

---------

Co-authored-by: martmull <martmull@hotmail.fr>
2024-10-29 07:56:16 +00:00
Jesse CookeandGitHub 88de2872d8 Don't require host for postgres (twentyhq#8157) (#8159)
Not sure if this will pass the tests; I don't have TS experience so I'll
see what CI does with it.

Fixes #8157
2024-10-29 08:46:54 +01:00
Thomas TrompetteandGitHub 409def8431 Fix manual trigger output schema (#8150)
- add schema for manual trigger
- split into sub functions
- handle case with no variables
2024-10-28 17:42:09 +00:00
69c24968c1 fix for horizontal bar while login in (#8073)
Fix for #8071

---------

Co-authored-by: martmull <martmull@hotmail.fr>
2024-10-28 17:07:00 +00:00
e648d942a2 fix: dropdowns should have a max-height & padding from screen (#8055)
Fixes: #6105 

### Problem

- The dropdown gets clipped when the number of filters increases. 

### Solution

- Added scroll property to the ```DropdownMenu``` 
- Added size middleware to the floating UI hook.
- Provided padding of 20px to the size middleware, so that it maintains
distance from the bottom of the screen.

[Screencast from 2024-10-25
13-47-04.webm](https://github.com/user-attachments/assets/c2315ee2-6092-4c4a-8126-dba7ac3bf49b)

---------

Co-authored-by: martmull <martmull@hotmail.fr>
2024-10-28 16:59:57 +00:00
cabae4c462 fix: TimeZone dropdown clips through screen in Mobile viewport (#7935)
## Description

- This PR fixes the issue #7934

---------

Co-authored-by: martmull <martmull@hotmail.fr>
2024-10-28 16:11:41 +00:00
ca54bc1813 Fix country selector text overflow issue (#8125)
Closes #7906 

Modified the two children(`TextInputV2` and `CountrySelect`) in the
`StyledHalfRowContainer` component to always be equal in size and divide
the available space equally.
The `StyledIconChevronDown` component has a `flex-shrink: 0` to prevent
it from completely disappearing. The same applies for the
`selectedOption.Icon`.
A `p` tag had to be added to the label to correctly handle the text
overflow.

---------

Co-authored-by: Devessier <baptiste@devessier.fr>
2024-10-28 16:20:29 +01:00
Thomas TrompetteandGitHub 2ba98ddadd Handle NBSP in tiptap parsing (#8148)
Tiptap uses non breaking spaces between nodes (like variables). Those
html characters are not properly handles in emails. Replacing by regular
spaces during parsing.

I tried to fix it in settings but looks like this is only for preserving
those nbsp and not for removal (see
https://github.com/ueberdosis/tiptap/pull/254)
2024-10-28 15:50:14 +01:00
fc8c9d9167 Migrate to twenty-ui - input components (#7914)
### Description

Migrate Input components: 

- CardPicker
- Radio
- RadioGroup
- Checkbox
- Toggle
- IconListViewGrip

### Demo

Radio Component on Storybook


![](https://assets-service.gitstart.com/4814/2d0c7436-9fab-4f3d-a5c4-be874e885789.png)

Checkbox component on Storybook


![](https://assets-service.gitstart.com/4814/07bcc040-cc92-4c7e-9be8-ca1a5f454993.png)

###### Fixes twentyhq/private-issues#92

Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
2024-10-28 15:36:58 +01:00
BOHEUSandGitHub ff388f56ea Add info about disabling background checks (#8145)
#8144
2024-10-28 15:06:47 +01:00
Charles Bochet ad1e835150 Remove broken e2e tests 2024-10-28 14:48:14 +01:00
f202cdb4cb [Server Integration tests] Enrich integration GraphQL API tests #4 (#8015)
This PR was created by [GitStart](https://gitstart.com/) to address the
requirements from this ticket:
[TWNTY-7526](https://clients.gitstart.com/twenty/5449/tickets/TWNTY-7526).

 --- 

### Description

We are using standard field and object IDs because there is a problem
when creating them as we would with helpers.

We were creating custom objects and removing them in afterAll, but there
is a problem that causes a conflict in the object IDs if the tests run
at the same time. The solution would be to modify the test command as
mentioned here:

<https://github.com/typeorm/typeorm/issues/6125>

Currently, we are using the standard IDs but we can create the objects
within the test if you want, but we would need to make them run in
sequence

### Demo


![](https://assets-service.gitstart.com/16336/70c5550e-8570-45d7-a613-a3d6b79e7c00.png)

### Refs

#7526

---------

Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
2024-10-28 14:24:24 +01:00
Balaji KrishnamurthyandGitHub 288fb1dbda Delete API key button now visible in light mode (#8094)
Closes #7179 
The font color of the button has been set to use
`theme.font.color.danger`. This means that the color will be red
regardless of whether the theme is inverted or not, which was the issue
before.
Merge conflicts have been resolved.
2024-10-28 14:14:39 +01:00
BOHEUSandGitHub f9779c4b5e CreateWorkspace typo fix (#8146)
Follow up of #8115
2024-10-28 14:13:57 +01:00
28815f54fe Refactor object metadata service (#8123)
## Context
ObjectMetadataService became quite large and handles too many
responsibilities. I'm trying to refactor a bit this part in preparation
of a larger work that will combine object-metadata services and
sync-metadata logic

- Created a STANDARD_OBJECT_ICONS that can be reused in relation
creation to refer to a standard object icon.
- Created a STANDARD_OBJECT_FIELD_IDS that can be used with an object
name to get its standard field ids.
- Moved migration, record and relation creations to dedicated services,
refactored to improve performances and readability
- Refactored some validation logic

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2024-10-28 14:13:15 +01:00
9b6359984d Migrate to twenty-ui - input/code-editor (#8072)
This PR was created by [GitStart](https://gitstart.com/) to address the
requirements from this ticket:
[TWNTY-7062](https://clients.gitstart.com/twenty/5449/tickets/TWNTY-7062).

 --- 

### Description.  

Migrate `code-editor` component to twenty ui.\
\
Fixes twentyhq/private-issues#94

---------

Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
2024-10-28 13:34:06 +01:00
fa0933b292 Migrate to twenty-ui - layout/section (#8068)
This PR was created by [GitStart](https://gitstart.com/) to address the
requirements from this ticket:
[TWNTY-7533](https://clients.gitstart.com/twenty/5449/tickets/TWNTY-7533).

 --- 

Description \
\
Move Section component from twenty-front to twenty-ui and update
imports\
\
\
Fixes twentyhq/private-issues#85

Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com>
2024-10-28 13:08:55 +01:00
martmullandGitHub 1aa961dedf 101 featch available variables from previous steps (#8062)
- add outputSchema in workflow step settings
- use outputSchemas to compute step available variables


https://github.com/user-attachments/assets/6b851d8e-625c-49ff-b29c-074cd86cbfee
2024-10-28 11:25:29 +00:00
Igor KowalskiandGitHub 3ae987be92 folderStructure.json refactor (#8088)
#7911 

If you encounter any issues or have any questions regarding the library,
feel free to write
[here](https://github.com/Igorkowalski94/eslint-plugin-project-structure/discussions/new?category=help),
I’d be happy to help.
2024-10-28 12:06:58 +01:00
sateshcharanandGitHub 67b654f55d [oss.gg] create-n8n-template (#8045)
workflow screeshot:

![image](https://github.com/user-attachments/assets/89f7270d-c664-4af8-9752-7d94af6bd0b9)

working video:

https://drive.google.com/file/d/1D4-RbbXlz-tCrGYM1Bot3bLlzKSdjJ_k/view?usp=sharing

Hi,

I’ve completed the task of integrating TwentyCRM through n8n, but I’m
having trouble uploading the [template
](https://drive.google.com/file/d/1PCp_i6y24aIoyhatWec-wz-MOzJbJoww/view?usp=sharing)
due to an issue with my email account. I’ve already reached out to their
support team for assistance. In the meantime, I kindly request that you
consider this as a valid contribution for the challenge until the issue
is resolved.

Thank you!
2024-10-28 11:49:15 +01:00
ZiaCodesandGitHub dc4c25cbae feat: Develop a script to facilitate the migration of data from another CRM to Twenty (#8122)
Develop a script to facilitate the migration of data from another CRM to
Twenty (750 points)

I had to write a script to add data to HubSpot CRM :)
I wrote migration script to move data from HubSpot --> Twenty.

Here's the GitHub
[Repo](https://github.com/Khaan25/twenty-migration-script) - Video
attached in files

Hope it will be beneficial for people and Twenty Community :)
2024-10-28 10:50:58 +01:00
fafdaed04c Update 3-create-custom-interfact-theme-20.md (#8139)
Designed a new Theme for the Twently's website on Figma

What side quest or challenge are you solving?
Create a custom theme for Twenty's interface (150-750 points): Duplicate
the Figma file and customize the variables to create a new theme for
Twenty’s interface.

Points
150-750 points

Description
Design of a new theme (coffee) for twenty's website in figma.

Provide proof that you've completed the task
By : VanshdeepSingh

Link to the Figma file of the design:


https://www.figma.com/design/akgDOb37YLUW9iWLB155EV/Twenty-(Copy)?node-id=478-19796&t=8Gz1yqls2Q3dsN9h-1

Prototype:


https://www.figma.com/proto/akgDOb37YLUW9iWLB155EV/Twenty-(Copy)?node-id=1406-44830&node-type=canvas&t=eBvFkq4KeD1Sgkbn-1&scaling=min-zoom&content-scaling=fixed&page-id=478%3A19796&starting-point-node-id=1406%3A44830

Images:


![image](https://github.com/user-attachments/assets/a49f6604-7f05-4da1-90e4-02540c699858)

![image](https://github.com/user-attachments/assets/50839ef0-0144-43d1-a889-7f8120245038)

![image](https://github.com/user-attachments/assets/48ee03b1-f0c1-435d-9e44-dfe2a0d91356)

Co-authored-by: Charles Bochet <charlesBochet@users.noreply.github.com>
2024-10-28 10:47:25 +01:00
sateshcharanandGitHub ba548bbb68 [oss.gg] create-youtube-video-about-20 (#8129)
quest:
create youtube video

points
750

video link
https://youtu.be/qfZyhrhCeyo

task performed:

- I've created a detailed video showcasing Twenty with a walkthrough on
Twenty Dashboard with all it's elements, promoted 3 blogs posts of
Twenty as well
    - one with detailed guide on twenty 
    - one on self hosting twenty 
    - one for integrating with n8n
 
- I've also demonstrated the working of n8n integrated workflow towards
the end of video, i hope this shows enough proof to merge #8045
2024-10-28 10:42:46 +01:00
Aditya DeshlahreandGitHub ad738d6947 ossgg: content challenge promo video (#8131)
## promotional video for Twenty

https://youtu.be/65sOHce1gjw

points : 750 

please check it out once 🙂 
I hope you will like it!
2024-10-28 10:39:55 +01:00
Bhavesh MishraandGitHub 1d9e7694c5 oss.gg fixed misleading title on the main repo (#8134)
This Pr fix the issue (#8093)

In the oss.gg folder under the no-code-challenge directory, the file
title is incorrect. The current title reads, “Write a self-host guide
blog regarding Twenty CRM,” but the actual task is to “write a blog on
integrating n8n or Zapier marketing tool with Twenty CRM."

Expected behavior

The file title should accurately reflect the actual task to avoid
confusion. It should read: “Write a blog on integrating n8n or Zapier
marketing tool with Twenty CRM."

Example:
• File Path: oss.gg/no-code-challenge/
• Suggested Fix: Update the file title to match the actual task

Points
50
2024-10-28 10:35:30 +01:00
Harsh Shrikant BhatandGitHub 58a4076b54 ossgg: Self-host guide and Article (#8141)
## What does this PR do?

Wrote an article and self-host guide for Twenty CRM:

Article:
https://www.harshbhat.me/blog/twenty-crm

Self-host guide:
https://www.harshbhat.me/blog/twenty-self-host

POINTS:
1500
2024-10-28 10:29:24 +01:00
sateshcharanandGitHub 0148431e5d [oss.gg] create-custom-theme (#8099)
![image](https://github.com/user-attachments/assets/cc24e328-a8d1-4a56-8560-76fab76e217c)


![image](https://github.com/user-attachments/assets/468dd145-b094-4948-8ebb-096dc23835aa)


![image](https://github.com/user-attachments/assets/59a45426-33c2-4d55-a226-ff3fd3e635cd)

Quest:
create-custom-interfact-theme

Points:
750

[Figma
URL](https://www.figma.com/design/2qlAPS3llwf8jrWKGHEf6O/Twenty-(sateshcharan)?node-id=1633-94880&t=GIceWxqyY0ajWXnZ-1)
Hope you like the design !
2024-10-28 09:08:39 +00:00
sateshcharanandGitHub 96607f33a5 [oss.gg] create-promotional-video-20-share (#8119)
quest:
create-promotional-video-20-share

video link
https://youtube.com/shorts/OK52eaq0pAQ?feature=share

points:
750

hope you like it :)
2024-10-27 16:55:04 +01:00
Félix MalfaitandGitHub 6d810b94ed Fix sidebar re-ordering (#8124)
Followup of
https://github.com/twentyhq/twenty/pull/7940#issuecomment-2434447952
2024-10-27 16:20:38 +01:00
1296cea7e8 Add a helper to the password (#8078)
Fix #7601

---------

Co-authored-by: Weiko <corentin@twenty.com>
2024-10-27 15:09:37 +01:00
BOHEUSandGitHub 5d990594f3 Typo fixes in docs (#8115) 2024-10-27 14:58:43 +01:00
MarieandGitHub a72f51ae6c Fix support custom object renaming (#8089)
In this PR
1) (FE) fixing update of name not taken into account if toggle value is
changed in the same transaction
2) (BE) moving same nameSingular and namePlural validation before
effective update
2024-10-27 14:56:08 +01:00
Vardhaman BhandariandGitHub 80b831d26c Oss.gg Side Quest: Write a blog post about sharing your experience using Twenty (#8121)
#8120

Side Quest: Write a blog post about sharing your experience using Twenty
in a detailed format on any platform.

Points : 750

Proof :
https://dev.to/vardhaman619/my-experience-with-modern-open-source-crm-twenty-crm-2hen


![blog-post-about-experiance-with-twenty](https://github.com/user-attachments/assets/01dfdb26-26ea-4bbe-a6eb-b0778b3fb11e)
2024-10-27 14:42:05 +01:00
Karan Singh ChandelandGitHub bf7d7fa4f9 add: blog side quest in oss.gg (#8108)
#8105 
Side Quest: Write a blog post about sharing your experience using Twenty
in a detailed format on any platform. Points: 750 Points Proof: Add your
oss handle and blog link to the list below.

Added My Submission Entry in oss.gg
2024-10-27 06:48:12 +01:00
ZiaCodesandGitHub be4cb734d9 feat: Create a YouTube video about Twenty (750 points) (#8092)
Create a YouTube video about Twenty (750 points)

I've created a detailed video showcasing Twenty and walkthrough Twenty
Dashboard with all it's elements and shared my 2 blogs posts as well -
one with detailed guide on twenty and other one on self hosting twenty
on our own server.
2024-10-27 06:36:36 +01:00
092f0b5fe9 feat: Promotional Video (#8113)
Create a promotional video for Twenty and share it (750 points)

Hope you like it :)

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
2024-10-27 06:35:12 +01:00
sateshcharanandGitHub 7c717efc5f [oss.gg] selfthost-guide-blog-post (#8075)
![image](https://github.com/user-attachments/assets/de35a89b-01a8-4b5d-986d-fc122ce0e741)

Quest:
Write a comprehensive guide on how to integrate Twenty with marketing
automation tool (n8n, Zapier). Include a concrete use case and explain
how to leverage AI to write API requests for non-developers and share
it.

Points:
1500

Hope you like the content !
2024-10-26 13:35:49 +02:00
Yash ParmarandGitHub 293f55e9c2 [🕹️]: content challenges quest 3: write a self host guide blog[750 points] (#8079)
I have completed the content challenges quest 3 that is write a self
host guide blog.

Here is the [blog
link](https://medium.com/@yashp3020/a-comprehensive-guide-to-self-hosting-twenty-crm-with-docker-compose-40ea3fb4afdc)
2024-10-26 12:18:33 +02:00
d1e403e099 side quest: 6_quest_wizard (300 points) (#8076)
Proof:
<img width="1337" alt="Screenshot 2024-10-26 at 12 37 06 AM"
src="https://github.com/user-attachments/assets/8eed8447-63f2-4d2a-9c01-29f39ccd41ca">
<img width="1337" alt="Screenshot 2024-10-26 at 12 36 53 AM"
src="https://github.com/user-attachments/assets/0e4b4091-dbe0-4fde-b6ed-d88a21311e44">
<img width="1337" alt="Screenshot 2024-10-26 at 12 36 41 AM"
src="https://github.com/user-attachments/assets/5828d2bd-31d8-4a92-b9e2-9390ba3182aa">
<img width="1337" alt="Screenshot 2024-10-26 at 12 36 27 AM"
src="https://github.com/user-attachments/assets/993b5352-36f0-4850-8031-b1d58643febc">
<img width="1337" alt="Screenshot 2024-10-26 at 12 34 57 AM"
src="https://github.com/user-attachments/assets/425b78e0-560b-4b2c-9872-935dcafb7755">

Co-authored-by: Apple <apple@Apples-MacBook-Pro.local>
2024-10-26 12:16:15 +02:00
MarieandGitHub d51a797d91 Replace shouldSyncNameAndLabel with isLabelSyncedWithName (#8067)
For consistency. 
This was not deployed yet so allowing myself just to rename everything,
meaning developers will need to reset their db.
2024-10-25 18:28:58 +02:00
MarieandGitHub e5175194ac Fix search on workspace member (#8066)
Adding search vectors on workspaceMember and tasks
2024-10-25 18:24:54 +02:00
63a3e070c5 [#8058 | 6741] Fix. showing icon on hover (#8061)
### What type of PR is this? (check all applicable)
- [X] Bug Fix

## Description
This PR include fix required for issue #8058 and #6741 .


- Fixes visibility of currency symbol on hover over field
- Fixes visibility of task icon symbol on hover over field


## Related Tickets & Documents
- Closes #8058 
- Closes #6741

---------

Co-authored-by: Félix Malfait <felix@twenty.com>
2024-10-25 17:11:08 +02:00
pau-not-paulandGitHub 016642a940 fix: read only cells flash on click (#8057)
Fix for https://github.com/twentyhq/twenty/issues/6807
2024-10-25 17:00:52 +02:00
9c923ba8d5 fix glitch for relation picker search (#8040)
Fix for #7957

---------

Co-authored-by: Félix Malfait <felix@twenty.com>
2024-10-25 16:51:52 +02:00
Sanskar JainandGitHub f633f0d330 fix issue of search not working in dev docs (#8065)
Fix for #8047
2024-10-25 16:46:30 +02:00
MarieandGitHub 9303e39bcf Fix broken filter in search resolver (#8064)
The recent addition of a "orWhere" condition to[ improve the search algo
quality](https://github.com/twentyhq/twenty/pull/7955) accidentally
broke the filter, being considered an independent "or" wondition while
we still want the filter to apply.
2024-10-25 16:17:19 +02:00
Thomas TrompetteandGitHub 2e73d020a3 Text area using variables (#8034)
- Adding multiline props to component
- Update design and logic accordingly 
- Fix hotkey scope for right drawer



https://github.com/user-attachments/assets/65ff9641-71a4-4828-a62b-e09327b63150
2024-10-25 12:55:56 +00:00
Baptiste DevessierandGitHub 0144553667 Add Manual Triggers (#8024)
In this PR:

- Add support for manual triggers in the backend
- Add a right drawer to let users select the type of trigger they want
- Create a specific right drawer for database event triggers
- Create a right drawer for manual triggers; let the user select where
the manual trigger should be made available
- Create a default trigger as soon as the user selects the type of
trigger they want. It prevents the user to see empty selects for record
type and event type. By default, the database event trigger will be set
to "company.created". It should be visible enough for users to
understand what happens and choose another record type or event type.



https://github.com/user-attachments/assets/29a21985-1823-4890-9eb3-e4f876459c7a
2024-10-25 14:24:56 +02:00
bf2ba25a6e Add shortcut metadata to data models & CommandMenu (#7977)
Resolves https://github.com/twentyhq/twenty/issues/7503

---------

Co-authored-by: Félix Malfait <felix@twenty.com>
2024-10-25 11:38:30 +02:00
7edfa61571 feat: Disable Continue Button for Invalid Email in Sign in/Sign up (#8022)
This PR fixes #7967

Here's a preview of the working solution:


https://github.com/user-attachments/assets/8918e0ac-c45a-48d2-ac90-004b05ec76f3

---------

Co-authored-by: Félix Malfait <felix@twenty.com>
2024-10-24 21:30:54 +02:00
Félix MalfaitandGitHub 9a62bed748 Fix performance test (#8036)
There was a broken story due to missing context
2024-10-24 18:28:51 +02:00
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
Baptiste DevessierandGitHub e44d525e83 Prevent workflow right drawer flickering when selecting an action type (#8028)
In this PR:

- Use a stable id for create-step nodes; it makes it possible to
preserve their selected attribute and keep them open even after the flow
is re-generated
- Preemptively open the WorkflowStepEdit right drawer for the created
action



https://github.com/user-attachments/assets/c19e6820-e198-4d06-98ae-898bd6e53e33

Fixes https://github.com/twentyhq/private-issues/issues/123
2024-10-24 17:27:56 +02:00
315820ec86 Feat: Advanced filter (#7700)
Design:


![twenty-advanced-filters-design](https://github.com/user-attachments/assets/7d99971c-9ee1-4a78-a2fb-7ae5a9b3a836)

Not ready to be merged yet!

---------

Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
2024-10-24 16:59:59 +02:00
1dfeba39eb Migrate to twenty-ui - layout/card (#8003)
This PR was created by [GitStart](https://gitstart.com/) to address the
requirements from this ticket:
[TWNTY-7532](https://clients.gitstart.com/twenty/5449/tickets/TWNTY-7532).

 --- 

### Description

Migrate:

- Card
- CardContent
- CardFooter
- CardHeader

### Demo

Card in Storybook


![](https://assets-service.gitstart.com/4814/d6759b99-7d5f-4177-acdf-1c57786330a3.png)

###### Fixes twentyhq/private-issues#86

---------

Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
2024-10-24 16:36:06 +02:00
Bhavesh MishraandGitHub 9b5d0e7850 Oss.gg Content creation promotional video on social site (#8033)
I have created a promotional video of Twenty crm on YouTube and have
shared it features.

[Click here](https://youtube.com/shorts/lC4oqm7UlCI?si=Md-nsfK9F6Shzjkv)

Points
750
2024-10-24 16:35:41 +02:00
Harsh SinghandGitHub 4e8d8ce744 fix: relation picker should not move once openened (#8026)
Fixes: #7959 

### Problem
- When searching in the dropdown, the results list would shrink based on
matching items
- This dynamic height change caused the dropdown to flip its position on
each keystroke

### Solution
- Added ```hasMinHeight``` as optional props to the
```DropdownMenuItemsContainer``` to maintain consistent height
- This prevents unwanted position recalculations and flipping while user
types
- The dropdown now stays in its initial position throughout the search
interaction

[Screencast from 2024-10-24
15-43-03.webm](https://github.com/user-attachments/assets/741317b7-fc5e-4874-8221-aa626a1a1747)
2024-10-24 16:33:50 +02:00
4ceee4ab8f Migrate to twenty-ui - feedback/loader (#7997)
This PR was created by [GitStart](https://gitstart.com/) to address the
requirements from this ticket:
[TWNTY-7528](https://clients.gitstart.com/twenty/5449/tickets/TWNTY-7528).

 --- 

### Description

- Move loader components to `twenty-ui`    
  
Fixes  twentyhq/private-issues#90

---------

Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
2024-10-24 16:19:32 +02:00
5fdf9acd08 Update 3-create-custom-interfact-theme-20.md (#7974)
What are you solving : Create a custom theme for Twenty's interface

Points : 300points

Description : Duplicated the Figma file and customized the variables to
create a new theme for Twenty’s interface.

Proof : 
![Screenshot 2024-10-22
232502](https://github.com/user-attachments/assets/a3e1c4ac-75ba-4583-90fe-99e04fc41a54)
link :
https://www.figma.com/design/XE21QdkFuy0IJHtmW7TURa/Twenty-(rajeevDewangan)?node-id=0-1&node-type=canvas&t=BYBulCT6hpJu6E8G-0

Co-authored-by: Thomas des Francs <tdesfrancs@gmail.com>
2024-10-24 16:18:47 +02:00
ShreyandGitHub 084c15a564 feat: 20 guide (#8027)
it's a local setup + hosting guide.
2024-10-24 16:17:52 +02:00
e8d96cfd10 feat: view groups (#7176)
Fix #4244 and #4356

This pull request introduces the new "view groups" capability, enabling
the reordering, hiding, and showing of columns in Kanban mode. The core
enhancement includes the addition of a new entity named `ViewGroup`,
which manages column behaviors and interactions.

#### Key Changes:
1. **ViewGroup Entity**:  
The newly added `ViewGroup` entity is responsible for handling the
organization and state of columns.
This includes:
   - The ability to reorder columns.
- The option to hide or show specific columns based on user preferences.

#### Conclusion:
This PR adds a significant new feature that enhances the flexibility of
Kanban views through the `ViewGroup` entity.
We'll later add the view group logic to table view too.

---------

Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
2024-10-24 15:38:52 +02:00
ZiaCodesandGitHub 68a060a046 feat: Custom Theme for Twenty (#8021)
![image](https://github.com/user-attachments/assets/6969f521-c089-471a-b4ff-d19fc7916c5c)
2024-10-24 15:16:54 +02:00
4e59f00e3f Use 'role' = button for chip navigation (#8011)
Closes #7817
Added role attribute to the div element of the Chip component. This
assigns the role of "button" to the container, which is important for
accessibility. It indicates that this div should be treated as a button
by assistive technologies like screen readers.

---------

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
Co-authored-by: Félix Malfait <felix@twenty.com>
2024-10-24 14:20:45 +02:00
445ab83c14 Migrate to twenty-ui - feedback/progress-bar (#8002)
This PR was created by [GitStart](https://gitstart.com/) to address the
requirements from this ticket:
[TWNTY-7527](https://clients.gitstart.com/twenty/5449/tickets/TWNTY-7527).

 --- 

### Description

Migrate `feedback/progress-bar` to twenty ui:

- CircularProgressBar
- ProgressBar

### Demo

ProgressBar on Storybook


![](https://assets-service.gitstart.com/4814/10b11cf5-e52e-420c-b70b-274c532f5f94.png)

CircularProgressBar on Storybook


![](https://assets-service.gitstart.com/4814/e483d3db-1b4c-4062-af40-c596c406c221.png)

###### Fixes twentyhq/private-issues#91

Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
2024-10-24 14:05:04 +02:00
414f2ac498 Support custom object renaming (#7504)
This PR was created by [GitStart](https://gitstart.com/) to address the
requirements from this ticket:
[TWNTY-5491](https://clients.gitstart.com/twenty/5449/tickets/TWNTY-5491).
This ticket was imported from:
[TWNTY-5491](https://github.com/twentyhq/twenty/issues/5491)

 --- 

### Description

**How To Test:**\
1. Reset db using `npx nx database:reset twenty-server` on this PR

1. Run both backend and frontend
2. Navigate to `settings/data-model/objects/ `page
3. Select a `Custom `object from the list or create a new `Custom
`object
4. Navigate to custom object details page and click on edit button
5. Finally edit the object details.

**Issues and bugs**
The Typecheck is failing but we could not see this error locally
There is a bug after updating the label of a custom object. View title
is not updated till refreshing the page. We could not find a consistent
way to update this, should we reload the page after editing an object?


![](https://assets-service.gitstart.com/45430/03cd560f-a4f6-4ce2-9d78-6d3a9f56d197.png)###
Demo



<https://www.loom.com/share/64ecb57efad7498d99085cb11480b5dd?sid=28d0868c-e54f-454d-8432-3f789be9e2b7>

### Refs

#5491

---------

Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com>
Co-authored-by: gitstart-twenty <140154534+gitstart-twenty@users.noreply.github.com>
Co-authored-by: Marie Stoppa <marie.stoppa@essec.edu>
Co-authored-by: Charles Bochet <charles@twenty.com>
Co-authored-by: Weiko <corentin@twenty.com>
2024-10-24 11:52:30 +00:00
c6ef14acc4 Migrate to twenty-ui - navigation/navigation-bar (#7996)
This PR was created by [GitStart](https://gitstart.com/) to address the
requirements from this ticket:
[TWNTY-7537](https://clients.gitstart.com/twenty/5449/tickets/TWNTY-7537).

 --- 

### Description

- Move navigation-bar components to `twenty-ui`  

Fixes  twentyhq/private-issues#81

Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
2024-10-24 13:45:52 +02:00
c7bc301dba Use search in multi object pickers (#7909)
Fixes https://github.com/twentyhq/twenty/issues/3298.
We still have some existing glitches in the picker yet to fix.

---------

Co-authored-by: Weiko <corentin@twenty.com>
2024-10-24 13:43:57 +02:00
67fb750ef6 Migrate to twenty-ui - input/color-scheme (#7995)
This PR was created by [GitStart](https://gitstart.com/) to address the
requirements from this ticket:
[TWNTY-7063](https://clients.gitstart.com/twenty/5449/tickets/TWNTY-7063).

 --- 

### Description

- Move color-scheme components to `twenty-ui`

Fixes  twentyhq/private-issues#93

Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
2024-10-24 13:39:25 +02:00
5ad8ff81f9 [Server Integration tests] Enrich integration GraphQL API tests #2 (#7978)
This PR was created by [GitStart](https://gitstart.com/) to address the
requirements from this ticket:
[TWNTY-7526](https://clients.gitstart.com/twenty/5449/tickets/TWNTY-7526).

 --- 

### Description

For workspace members, the deletion of multiple members is a special
case that is not permitted by the method for regular users. As a result,
we ensure that multiple deletions are not processed.

For certain tests, both an account ID and a user ID are required. We are
utilizing Tim's account for all testing purposes, as specified by the
token in `jest-integration.config.ts`. To streamline this process, we
have defined a constant to store and reference the account ID and user
ID during testing.Refs

#7526

### Dem


![](https://assets-service.gitstart.com/16336/4df04650-70ff-4eb6-b43f-25edecc8e66f.png)

Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com>
2024-10-24 13:25:21 +02:00
0a28c15747 Migrate to twenty-ui - input/button (#7994)
This PR was created by [GitStart](https://gitstart.com/) to address the
requirements from this ticket:
[TWNTY-7529](https://clients.gitstart.com/twenty/5449/tickets/TWNTY-7529).

 --- 

### Description

- Migrated all button components to `twenty-ui`    \
  \
  `Button`\
  `ButtonGroup`\
  `ColorPickerButton`\
  `FloatingButton`\
  `FloatingButtonGroup`\
  `FloatingIconButton`\
  `FloatingIconButtonGroup`\
  `IconButton`\
  `IconButtonGroup`\
  `LightButton`\
  `LightIconButton`\
  `LightIconButtonGroup`\
  `MainButton`\
  \
  Fixes twentyhq/private-issues#89

Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
2024-10-24 13:20:02 +02:00
ZiaCodesandGitHub 60e44ccf73 feat: Self-hosting guide (750 points) (#8019)
![image](https://github.com/user-attachments/assets/73d3c515-2d12-4013-bd44-9ac759cf777f)
2024-10-24 11:48:02 +02:00
1f84e61da8 Added "Select an option" as default none selector on Workflow Visualizer (#7867)
## What does this PR do?
Shows "Select an option" as a default selector on the select component
for the trigger step in the workflow visualizer

Fixes #7432

<img width="1470" alt="Screenshot 2024-10-20 at 12 48 39 AM"
src="https://github.com/user-attachments/assets/189c2a7a-8abd-4411-90b4-d0e1de487fd5">
<img width="1470" alt="Screenshot 2024-10-20 at 12 48 50 AM"
src="https://github.com/user-attachments/assets/f451068c-0184-40cb-9cab-f139df400cc6">

---------

Co-authored-by: Devessier <baptiste@devessier.fr>
2024-10-24 10:54:22 +02:00
nitinandGitHub a35d888c12 Chip right height according to view (#7976) 2024-10-23 19:33:35 +00:00
Félix MalfaitandGitHub d9429b1a83 Delete unused file (#8014)
Oops, this shouldn't have been merged, it was in the wrong directory
2024-10-23 20:43:13 +02:00
Bhavesh MishraandGitHub 6b3cd4dc14 Oss.gg A detailed Guide to self-host Twenty CRM on you local server (#8012)
This Pr consist of a Blog which I wrote on hashnode in which I have
explained in-dept how to setup/host twenty on your local server or cloud
with troubleshooting guide.

I have added output images as refers as well.

check it out 
[Click
here](https://k5lo7h.hashnode.dev/a-detailed-guide-to-self-host-twenty-crm-on-you-local-server)

**Points
750**
2024-10-23 20:26:06 +02:00
Harsh SinghandGitHub dd6b8be0d3 fix: date-picker flips in records cell even when there is enough space (#7905)
Fixes: #7897 

This PR fixes the flipping of the date-picker in the record's cell even
if there is enough space below the table.
I attached a screencast to show that it's working fine now. 

With this, it only flips when there is less space to accommodate the
date-picker comp. Also, I tested this after adding lots of records to
see if the scrolling behaviour is intact or not. And I found no issues,
it's working as expected.

[Screencast from 2024-10-21
13-39-42.webm](https://github.com/user-attachments/assets/615fac80-ae2e-4d26-8f94-55d7ee3f91c2)
2024-10-23 19:14:28 +02:00
Thomas TrompetteandGitHub 2e8b8452c1 Add available variables dropdown (#7964)
- Add variable dropdown
- Insert variables on click
- Save variable as `{{stepName.object.myVar}}` and display only `myVar`


https://github.com/user-attachments/assets/9b49e32c-15e6-4b64-9901-0e63664bc3e8
2024-10-23 18:32:10 +02:00
18778c55ac Multiple operations on webhooks (#7807)
fixes #7792 

WIP :)



https://github.com/user-attachments/assets/91f16744-c002-4f24-9cdd-cff79743cab1

---------

Co-authored-by: martmull <martmull@hotmail.fr>
2024-10-23 15:57:46 +00:00
Rajeev DewanganandGitHub 165dd87264 Update 1-quote-tweet-20-oss-gg-launch.md (#8008)
What side quest you solving : Like & Re-Tweet oss.gg Launch Tweet

Points : 50

Proof : 
![Screenshot 2024-10-23
205849](https://github.com/user-attachments/assets/ad30fc02-6325-41b8-a8c1-a38d0528d984)
2024-10-23 17:40:12 +02:00
Rajeev DewanganandGitHub c38a6c6af9 Update 2-tweet-about-fav-twenty-feature.md (#8009)
What side quest are you doing : Share a tweet about your favorite
feature in Twenty

Points : 50

Proof : 
![Screenshot 2024-10-23
205918](https://github.com/user-attachments/assets/25d4ded1-1a93-4c14-a193-420d5b2a11a0)
2024-10-23 17:39:50 +02:00
dcf92ae7f1 Migrate to twenty-ui - utilities/dimensions (#7949)
This PR was created by [GitStart](https://gitstart.com/) to address the
requirements from this ticket:
[TWNTY-7539](https://clients.gitstart.com/twenty/5449/tickets/TWNTY-7539).

 --- 

### Description

- Move the utilities/dimensions from twenty-front to twenty-ui and
update imports\

Fixes twentyhq/private-issues#79

---------

Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
2024-10-23 17:09:32 +02:00
849d7c2423 Implement search for rich text fields and use it for notes (#7953)
Co-authored-by: Weiko <corentin@twenty.com>
2024-10-23 15:49:10 +02:00
Ngan PhanandGitHub 45b3992784 fix: Default View Font Color and Reordering (#7940)
This PR fixes issue #6114 
I removed the separate check for default item and add it into the
draggable list.
2024-10-23 15:44:17 +02:00
ZiaCodesandGitHub 5b6487979c feat: Write Blog Post About 20 (750 points) (#7972)
![image](https://github.com/user-attachments/assets/0aaac3a2-7862-469f-ba69-ab17352a883e)
2024-10-23 15:14:52 +02:00
a55423642a fix: context menu padding (#7918)
This pull request addresses the issue #7915 regarding the lack of
padding in the right-click record menu. This PR add padding to context
menu and reuse the existing component used for the filter/sort feature.


![image](https://github.com/user-attachments/assets/4534eba5-a7de-4142-9d5f-ff0aee86a526)

![image](https://github.com/user-attachments/assets/1690890e-cb18-4879-9a9b-3153cd6aeb26)

---------

Co-authored-by: Félix Malfait <felix@twenty.com>
2024-10-23 15:13:14 +02:00
ZiaCodesandGitHub 25a8638e4e [🕹️] Quest Wizard (300 points) (#7971)
![image](https://github.com/user-attachments/assets/b7907de9-80df-4801-9db0-deaaf196e663)

![image](https://github.com/user-attachments/assets/26687eb0-2a82-4256-97e6-f41a118513fc)

![image](https://github.com/user-attachments/assets/c9ab8c1a-0d42-4afa-ae17-9933819dbfd9)

![image](https://github.com/user-attachments/assets/76cea0cd-41cc-4508-a8fd-23d2338903c3)

![image](https://github.com/user-attachments/assets/61478b84-bced-4cb5-b66c-3d38c5610c7e)
2024-10-23 15:00:23 +02:00
412877e49a feat: design-promotional-poster (300 points) (#7970)
Link to tweet: https://x.com/zia_webdev/status/1848764487081619470


![image](https://github.com/user-attachments/assets/033c06e6-e18b-47f4-83d0-94c09519a8ac)

---------

Co-authored-by: Félix Malfait <felix@twenty.com>
2024-10-23 14:28:36 +02:00
Sanskar JainandGitHub 74ecacb791 fix x axis scroll bar issue on developer page (#7975)
This PR Fixes Issue : #7932 
I have added the CSS to remove the scroll bar from x axis of the sidebar
on the developers page.
2024-10-23 13:57:04 +02:00
ec0250616e Update install.sh (#7973)
This PR updates the install.sh script to fetch the docker-compose.yml
file from the GitHub branch or tag that matches the version specified by
the user, instead of defaulting to the main branch.

---------

Co-authored-by: Félix Malfait <felix@twenty.com>
2024-10-22 22:19:46 +02:00
Raphaël BosiandGitHub 6843a642b5 7499 refactor right drawer to have contextual actions (#7954)
Closes #7499
- Modifies context store states to be component states
- Introduces the concept of `mainContextStore` which will dictate the
available actions inside the command K
- Adds contextual actions inside the right drawer
- Creates a new type of modal variant
2024-10-22 18:35:45 +02:00
WeikoandGitHub 6c93587efb Fix cache storage (#7966) 2024-10-22 18:21:00 +02:00
113e9fc8c7 Migrate to twenty-ui - utilities/animation (#7951)
This PR was created by [GitStart](https://gitstart.com/) to address the
requirements from this ticket:
[TWNTY-7538](https://clients.gitstart.com/twenty/5449/tickets/TWNTY-7538).

 --- 

### Description

- Move animation components to `twenty-ui`    \
  \
  \
  Fixes  #7538

Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
2024-10-22 18:08:54 +02:00
edc36c707d fix #7821 added gap in record tag and count (#7822)
solves #7821 

added 4px gap in tag and count

---------

Co-authored-by: Félix Malfait <felix@twenty.com>
2024-10-22 18:02:00 +02:00
sateshcharanandGitHub 32cf88fa8d fix: [oss.gg] solves #7920 (#7962)
![image](https://github.com/user-attachments/assets/bb813194-30e9-4f1c-8633-5b7a3dca87b1)
#7920
2024-10-22 17:58:16 +02:00
7a6926ea5a feat: Design a new logo for Twenty (300 points) (#7965)
This PR fixes #7936


![image](https://github.com/user-attachments/assets/083a8475-b2f4-4cb4-9c5b-509d3823c66b)

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
2024-10-22 17:55:04 +02:00
MarieandGitHub 6dd0ebe087 Add skip option at invite team step (#7960)
Closing [#5925](https://github.com/twentyhq/twenty/issues/5925)
2024-10-22 17:52:15 +02:00
Ana Sofia Marin AlexandreandGitHub 29bd4e5f2d track serverless functions executions (#7963)
Solves: 
https://github.com/twentyhq/private-issues/issues/74

**TLDR**
When a serverless function is executed, the result is send to tinybird
event data source.

**In order to test:**

1. Set ANALYTICS_ENABLED to true
2. Put your TINYBIRD_INGEST_TOKEN from twenty_event_playground in your
.env file
3.  Don't forget to run the worker
4. Create your serverless function and run it
5. The event should be logged on the event datasource in
twenty_event_playground

**What is the structure of the payload of a serverless function event?**

Here are two examples of the payload:

`{"duration":37,"status":"SUCCESS","functionId":"a9fd87c0-af86-4e17-be3a-a6d3d961678a","functionName":"testingFunction"}`

`

{"duration":34,"status":"ERROR","errorType":"ReferenceError","functionId":"a9fd87c0-af86-4e17-be3a-a6d3d961678a","functionName":"testingFunction"}`

**Possible improvments**

- Change the status(str) to success(bool) 
- Enrich data in the payload
2024-10-22 17:51:51 +02:00
430644448a Migrate to twenty-ui - navigation/link (#7837)
This PR was created by [GitStart](https://gitstart.com/) to address the
requirements from this ticket:
[TWNTY-7535](https://clients.gitstart.com/twenty/5449/tickets/TWNTY-7535).

 --- 

### Description.  

Migrate link components to `twenty-ui` \
\
Fixes #7535

---------

Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com>
Co-authored-by: gitstart-twenty <140154534+gitstart-twenty@users.noreply.github.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
2024-10-22 17:36:26 +02:00
WeikoandGitHub 02c34d547f Fix redis connection (#7956)
## Context
bull-mq connection was not working as intended, the connection parameter
was ignored and was falling back to localhost.
This PR should fix the issue by instantiating a IORedis client following
bullmq documentation https://docs.bullmq.io/guide/connections
I also changed cache-storage module to use IORedis client as well to be
more consistent even though it was not necessary there. We could move
that instantiation to a factory class in the future.

## Test
start server + worker with correct port and wrong port with
cache-storage-type memory/redis and queue-type sync/bull-mq
2024-10-22 14:40:18 +00:00
Ana Sofia Marin AlexandreandGitHub 18cfe79b80 bug fix webhook response not sending data to tinybird (#7952)
Solves https://github.com/twentyhq/private-issues/issues/118

**TLDR**

Fix webhook response not sending data to tinybird when the url is not a
link.

**Changes in Tinybird:**

- Add column Success to webhook payload (boolean)
- Changed the parameter WebhookIdRequest to WebhookId in the
getWebhooksResponse api point.
- Those changes can be seen in the tinybird workspace
twenty_analytics_playground

**In order to test**

1. Set ANALYTICS_ENABLED to true
2. Set TINYBIRD_INGEST_TOKEN to your token from the workspace
twenty_analytics_playground
3. Set TINYBIRD_GENERATE_JWT_TOKEN to the admin kwt token from the
workspace twenty_analytics_playground
4. Set TINYBIRD_WORKSPACE_UUID to the UUID of
twenty_analytics_playground
5. Create a Webhook in twenty and set wich events it needs to track
6. Run twenty-worker in order to make the webhooks work.
7. Do your tasks in order to populate the data
8. Look at your webhooks in settings>api and webhooks> your webhook and
the statistics should be displayed
2024-10-22 15:48:11 +02:00
MarieandGitHub f0a2d38471 Improve search algorithm (#7955)
We were previously checking for matching with each search term
independently. Ex searching for "felix malfait" we were searching for
correspondances with "felix" and "malfait".
As a result record A with name "Marie-Claude Mala" and email
"ma.lala@email.com" had a biggest search score than record B "Felix
Malfait" with email felix@email.com for search "felix ma":
for record A we had 0 match with felix and 3 matches with "ma" ("marie",
"mala", "ma")
for record B we had 1 match with felix and 1 match with "ma" (with
"malfait").

So we want to give more weight to a row that would combine matches with
both terms, considering "felix malfait" altogether.
2024-10-22 15:47:16 +02:00
martmullandGitHub e767f16dbe 7415 serverless functions update environment variables in a dedicated tab in settings functions not a env file (#7939)
![image](https://github.com/user-attachments/assets/0ef9551d-d867-479e-9a76-faee6930bc0a)

![image](https://github.com/user-attachments/assets/a7aac417-4dd8-401f-8d5b-5b72f31710f6)

![image](https://github.com/user-attachments/assets/16c98e52-a2db-4ed3-b5d2-77745b4d2918)

![image](https://github.com/user-attachments/assets/847d23d6-8a58-4d8f-aff1-4f8a81862964)
2024-10-22 14:51:03 +02:00
ZiaCodesandGitHub 7fc844ea8f feat: Side quest tweet fav completed (#7944)
![image](https://github.com/user-attachments/assets/26e7b781-afbe-467f-864f-bf04058a5b2d)
2024-10-22 14:24:16 +02:00
ZiaCodesandGitHub 2aa870d6ac feat: Side quest Gif Magic completed (#7946)
![supermeme_14h47_52](https://github.com/user-attachments/assets/e7788a89-722c-4046-ae5d-c2a738daa433)
2024-10-22 14:23:52 +02:00
ZiaCodesandGitHub 6e9774dac2 feat: Side quest meme magic completed (#7945)
![image](https://github.com/user-attachments/assets/615094b3-3d6b-40dc-a986-5e725201c47c)
2024-10-22 14:23:31 +02:00
006104c548 feat: Side quest Tweet compeleted (#7943)
![image](https://github.com/user-attachments/assets/9903f9b2-4a45-4a88-a50b-ca398aa556dd)

---------

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
2024-10-22 14:22:06 +02:00
Ritansh SinghGitHubgreptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
07cdeeb595 Like & Re-Tweet oss.gg Launch Tweet #7947 (#7950)
Point: 50 Points
Task: Like & Re-Tweet oss.gg Launch Tweet
Attachement:
![retweet oss
gg](https://github.com/user-attachments/assets/6c7619be-707b-49ff-991d-15225e503b4b)

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2024-10-22 14:20:11 +02:00
Rajeev DewanganandGitHub afb246558e Update 2-write-blog-post-about-20.md (#7941)
Update oss-gg block post list for
https://github.com/twentyhq/twenty/pull/7938
2024-10-22 10:55:07 +02:00
6133a72cf6 Migrate to twenty-ui utilities/screen-size (#7836)
This PR was created by [GitStart](https://gitstart.com/) to address the
requirements from this ticket:
[TWNTY-7540](https://clients.gitstart.com/twenty/5449/tickets/TWNTY-7540).

 --- 

### Description

Move `utilities/screen-size` to the `twenty-ui` package

### Demo

The `useScreenSize` was used to render the mobile nav for example on the
landing page.

It still renders properly


![](https://assets-service.gitstart.com/4814/018fa684-c192-455d-a38b-3b212fdb3c1a.png)

###### Fixes [#7540](https://github.com/twentyhq/twenty/issues/7540)

###### Dev QA

- [x] `utilities/screen-size` should be moved to the `twenty-ui` folder

- [x] The mobile nav should still show on the landing page

Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
2024-10-22 10:34:42 +02:00
dfcf3ef879 Migrate to twenty-ui - layout/animated-placeholder (#7794)
This PR was created by [GitStart](https://gitstart.com/) to address the
requirements from this ticket:
[TWNTY-7531](https://clients.gitstart.com/twenty/5449/tickets/TWNTY-7531).

 --- 

### Description

- Migrate the `animated-placeholder` to `twenty-ui` and update all
imports.\
  \
  Fixes twentyhq/private-issues#87

Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
2024-10-22 10:28:09 +02:00
bf0a059751 [Server Integration tests] Enrich integration GraphQL API tests #3 (#7931)
This PR was created by [GitStart](https://gitstart.com/) to address the
requirements from this ticket:
[TWNTY-7526](https://clients.gitstart.com/twenty/5449/tickets/TWNTY-7526).

 --- 

### Description

NoteTargets and MessageThreads are special cases because they do not
have a notable property that we could use in "update" the test cases,\
for NoteTargets we are using the personId, testing the relation, but for
MessageThreads we are using updatedAt. To test the relations for
MessageThreads\
we would need to update another object (Message) because the relation is
ONE_TO_MANY, updating another object in a test that would update the
current tested object sounds incorrect.\
In the NoteTargets, we can update the NoteTarget object because the
relation is MANY_TO_ONE\
for some tests we need an account ID, we are using Tim's account for all
the tests (the token in jest-integration.config.ts), so we are using a
constant to use the account ID

### Refs

#7526

### Demo


![](https://assets-service.gitstart.com/28455/7f1c520e-78e4-43c3-aa89-f6fc09e0a056.png)

---------

Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com>
Co-authored-by: gitstart-twenty <140154534+gitstart-twenty@users.noreply.github.com>
2024-10-22 10:17:10 +02:00
TheFaheemandGitHub c6bc09c5a2 [oss.gg]: hubspot to twenty contact data migration script (750 points) (migration-script) (#7937)
HubSpot to Twenty CRM Contact Migration Script

Script's github repo:
https://github.com/FaheemOnHub/twenty-crm-hubspot-script

This Node.js script facilitates migrating contacts from HubSpot CRM to
Twenty CRM. The user has the option to either check for duplicates in
the Twenty CRM before migrating or directly migrate all contacts without
checking.

Video Proof added in oss-gg's twenty-dev-challenges
2024-10-22 10:13:02 +02:00
b45511c955 Migrate to twenty-ui - navigation/breadcrumb (#7793)
### Description

- Move breadcrumb components to `twenty-ui`    \
  \
  \
  Fixes  #7534

---------

Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
2024-10-21 21:53:43 +02:00
25010174f0 Adjust the line height and expand the maximum height of the plac… (#7764)
fixes: #7757

## What does this PR do?

We increased the line height from md to lg and the max height of the
placeholder subtitle text from 2.4 to 2.8 to ensure that letters are no
longer slightly cut off in the placeholder in Functions.



![twenty-placeholder-text](https://github.com/user-attachments/assets/1cfed3c4-6bae-4200-9516-4e1295da170a)

## How should this be tested?

  1. Log in
  2. Go to Settings
  3. Toggle "Advanced" settings
  4. Go to Functions

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2024-10-21 21:47:17 +02:00
34ef2d3d6d Left Padding removed in Settings Page Tabs (#7730)
Fix:  #7100 

The `TabList` component, located in
[Tablist](packages/twenty-front/src/modules/ui/layout/tab/components/TabList.tsx),
wraps the Tabs and defines the padding, and is used in multiple places.
The left padding for the Emails and Calendars sections of the Accounts
in Settings has been removed ( list appear when there are multiple
connected accounts ). However, the padding on the Record detail page
remains unchanged.

To address this, prop of css styles is added to `Tablist`, allowing for
the padding of the `TabList` component to be adjusted as required.

Additional styles can also be applied as per requirements individually
for Emails and Calendar section.


<img width="722" alt="Screenshot 2024-10-16 at 5 06 26 AM"
src="https://github.com/user-attachments/assets/3c7648ac-e2a6-4871-b58b-d25b008a06f0">
<img width="789" alt="Screenshot 2024-10-16 at 5 49 18 AM"
src="https://github.com/user-attachments/assets/a6e61b4d-0245-4744-ae87-86fe01a6bc43">
<img width="725" alt="Screenshot 2024-10-16 at 6 22 30 AM"
src="https://github.com/user-attachments/assets/e6a19095-3ee4-431f-ba19-1182552a5c8d">

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2024-10-21 21:42:37 +02:00
5e2df81211 fix: hidden settings menu affects settings layout (#7769)
This PR fixes #6746

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2024-10-21 21:28:01 +02:00
nitinandGitHub 4407b1aaa2 Minor page header fix (#7927)
<img width="1420" alt="Screenshot 2024-10-22 at 00 03 03"
src="https://github.com/user-attachments/assets/c8841991-9c0a-41fd-8fc5-f789c4a94398">

<img width="1512" alt="Screenshot 2024-10-22 at 00 04 33"
src="https://github.com/user-attachments/assets/a9bbbad9-5cc3-4019-8928-d25d02d0bda9">
2024-10-21 20:48:12 +02:00
0f0a7966b1 feat(sso): allow to use OIDC and SAML (#7246)
## What it does
### Backend
- [x] Add a mutation to create OIDC and SAML configuration
- [x] Add a mutation to delete an SSO config
- [x] Add a feature flag to toggle SSO
- [x] Add a mutation to activate/deactivate an SSO config
- [x] Add a mutation to delete an SSO config
- [x] Add strategy to use OIDC or SAML
- [ ] Improve error management

### Frontend
- [x] Add section "security" in settings
- [x] Add page to list SSO configurations
- [x] Add page and forms to create OIDC or SAML configuration
- [x] Add field to "connect with SSO" in the signin/signup process
- [x] Trigger auth when a user switch to a workspace with SSO enable
- [x] Add an option on the security page to activate/deactivate the
global invitation link
- [ ] Add new Icons for SSO Identity Providers (okta, Auth0, Azure,
Microsoft)

---------

Co-authored-by: Félix Malfait <felix@twenty.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
2024-10-21 20:07:08 +02:00
11c3f1c399 fix: width in PageHeader comp (#7866)
Fixes: #7864 


This fix prevents layout issues caused by invalid CSS and ensures that
the PageHeader component works correctly when no width prop is passed.

![Screenshot from 2024-10-20
00-03-39](https://github.com/user-attachments/assets/68340256-c756-4a56-9028-9aed32caf68e)

Co-authored-by: Charles Bochet <charles@twenty.com>
2024-10-21 18:40:32 +02:00
uluckydevandGitHub 5416773951 Fix Storybook Configuration for Windows Development Environment (#7904)
#### Description
This PR resolves issue #7903 regarding the Storybook configuration for
Windows development environments. Previously, the configuration script
generated forward slashes instead of backslashes, leading to errors when
running the command `npx nx run twenty-front:storybook:serve:dev
--configuration=modules` on Windows systems.

#### Changes Made
- Updated the Storybook configuration to ensure that backslashes are
used in file paths for Windows environments, preventing command
execution errors.

#### How to Test
1. **Run Storybook Command**:
   - On a Windows machine, execute the command:
     ```
     npx nx run twenty-front:storybook:serve:dev --configuration=modules
     ```
- Ensure that the command runs successfully without any path-related
errors.

2. **Verify Configuration**:
- Check the Storybook configuration files to confirm that paths are
using backslashes where applicable.
- Test the same command on non-Windows environments to verify that there
are no regressions.

#### Related Issue
- Fixes #7903
2024-10-21 18:28:31 +02:00
Nazar PoshtarenkoandGitHub 4578674e30 fix(website): enable // in token form URL input (#7923)
Fixes: #7861
2024-10-21 18:24:24 +02:00
1466d44b57 fix: Make the entire advanced mode toggle container clickable (#7761)
In this PR:

- Use a real `<input type="checkbox" />` element in the `<Toggle />`
component
- Create an `accessibility` module in the `twenty-ui` package
- Export the `VISIBILITY_HIDDEN` CSS object to hide visually any element
- Export a `<VisibilityHidden />` component from the `twenty-ui` package
to add visually hidden textual information easily
- Export a `<VisibilityHiddenInput />` component to create custom form
control components easily
- Use a `<label>` element for the "Advanced:" text; it will naturally
toggle the advanced settings

Fixes #7756

---------

Co-authored-by: Devessier <baptiste@devessier.fr>
2024-10-21 18:22:10 +02:00
1a0b387282 Add the role=button to search (#7594)
In this PR:

- Let the `<NavigationDrawerItem />` component render a `<button>` by
default instead of a `<div>`
- Replace `<div>` by `<span>` inside the `<NavigationDrawerItem />` as
`<button>` and `<a>` HTML elements only accept [_phrasing
content_](https://developer.mozilla.org/en-US/docs/Web/HTML/Content_categories#phrasing_content).
- Fix layout issue: the keyboard icon wasn't put on the right of the
button, I put it back

Fixes #7575

---------

Co-authored-by: Devessier <baptiste@devessier.fr>
2024-10-21 18:21:08 +02:00
7b10bfa7d2 Add filter on array and jsonb field types (#7839)
This PR was created by [GitStart](https://gitstart.com/) to address the
requirements from this ticket:
[TWNTY-6784](https://clients.gitstart.com/twenty/5449/tickets/TWNTY-6784).
This ticket was imported from:
[TWNTY-6784](https://github.com/twentyhq/twenty/issues/6784)

 --- 

### Description

- Add filter on array and jsonb field types
- We did not implement the contains any filter for arrays on the
frontend because we would need to change the UI design since this should
be an array of values, and now we have only one input

### Demo


<https://www.loom.com/share/0facf752b63f4120b5d4ea4ee9772d35?sid=d7bde469-e6a9-4298-a637-d81d40695a86>

Fixes #6784

---------

Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com>
Co-authored-by: gitstart-twenty <140154534+gitstart-twenty@users.noreply.github.com>
Co-authored-by: Weiko <corentin@twenty.com>
2024-10-21 18:11:02 +02:00
sateshcharanandGitHub 3f2751ef6c [oss.gg] write-blog-post-about-20 (750 points) (#7922)
![image](https://github.com/user-attachments/assets/3de0b8a6-1c2e-40ae-a82b-ad6d2c21f84c)
2024-10-21 18:10:18 +02:00
sateshcharanandGitHub 0e9d2708d4 [oss.gg] write-selfthost-guide-blog-post (750 points) (#7924)
![image](https://github.com/user-attachments/assets/c1817eb5-8ffa-466e-8385-1644decf48a0)
2024-10-21 18:08:36 +02:00
373926b895 Secure connexion between TinyBird and webhookResponseGraph (#7913)
TLDR:
Secure connexion between tinybird and twenty using jwt when accessing
datasource from tinybird.

Solves:
https://github.com/twentyhq/private-issues/issues/73


In order to test:

1. Set ANALYTICS_ENABLED to true
2. Set TINYBIRD_JWT_TOKEN to the ADMIN token from the workspace
twenty_analytics_playground
3. Set TINYBIRD_JWT_TOKEN to the datasource or your admin token from the
workspace twenty_analytics_playground
4. Create a Webhook in twenty and set wich events it needs to track
5. Run twenty-worker in order to make the webhooks work.
6. Do your tasks in order to populate the data
7. Enter to settings> webhook>your webhook and the statistics section
should be displayed.

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2024-10-21 17:42:52 +02:00
WeikoandGitHub edf4ae084b Add simplify-search-vector-expression to upgrade 0-32 command (#7925)
## Context
Moving this command to the global command runner for 0.32 upgrade. This
should fix searchVector expression introduced in 0.31 to later handle
soft-deleted + search filter properly.

## Test
```
git co v0.31.0
-- reset DB
git co c--add-simplify-search-vector-expression-to-upgrade-0-32
-- migrate typeorm
-- upgrade 0.32 command
```

search is working and expression is correctly set. Soft deleted records
are not shown as before but it's now possible to override that behavior
via filters.

cc @ijreilly
2024-10-21 17:23:50 +02:00
sateshcharanandGitHub 4bd8945519 [oss.gg] design-new-logo-twenty (#7917)
![image](https://github.com/user-attachments/assets/9b1fd757-1fd5-402d-ab6d-9389d738d97f)
2024-10-21 16:23:30 +02:00
sateshcharanandGitHub 9aed944da9 [oss.gg] design-promotional-poster (300 points) (#7919)
![image](https://github.com/user-attachments/assets/763c57a3-4dd1-4882-a989-d6df3f00269f)
2024-10-21 16:18:12 +02:00
sateshcharanandGitHub 1f5d9bd69e [🕹️] quest-wizard (300 points) (#7921)
![image](https://github.com/user-attachments/assets/56fa4f09-fa11-41ae-9198-dbd92c0596fd)

![image](https://github.com/user-attachments/assets/543a1f8f-b196-4b3b-be2d-7ced9dd9e0e0)

![image](https://github.com/user-attachments/assets/5d13b4a3-1f40-4e1b-a368-fe95c49cbb2c)

![image](https://github.com/user-attachments/assets/936457e6-d18c-444f-a853-162b75b9b807)

![image](https://github.com/user-attachments/assets/c48e4b5e-30a6-404b-bea3-7633a499c69b)
2024-10-21 16:08:26 +02:00
Hitarth ShethandGitHub b87c7d4a0c [FIX] install node version before corepack enable (#7809)
FIX #7696

This correctly installs the recommended node version before enabling
corepack.

![Screenshot 2024-10-14
142628](https://github.com/user-attachments/assets/674f28d5-8d1b-40fc-aaae-4195c14ea350)

Thanks!
2024-10-21 16:07:14 +02:00
Prashant KumarandGitHub 28c99cbc64 fix: use <button> tag for buttons (#7797)
## What does this PR do?
This PR updates div with button tag for buttons

Fixes #7577 

![Screenshot 2024-10-17
210955](https://github.com/user-attachments/assets/54a0c0e9-93ed-4730-a738-bf486f1f58c8)
2024-10-21 12:32:19 +00:00
Charles Bochet 784770dfe8 Disable Github runners front CIs 2024-10-21 14:23:57 +02:00
40152d3b92 7665 handle the select all case inside the action menu (#7742)
Closes #7665 
- Handle select all
- Handle Filters

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2024-10-21 14:22:03 +02:00
Charles Bochet eaab2d0dd2 Fix CI not running on main 2024-10-21 13:32:54 +02:00
Charles Bochet 2f72e22ff9 Fix CI not running on main 2024-10-21 13:19:35 +02:00
Thomas des FrancsandGitHub a5b2b3522f Updated image to correct typo (#7907)
Fixes https://github.com/twentyhq/twenty/issues/7899
2024-10-21 12:25:25 +02:00
Baptiste DevessierandGitHub e7eeb3b820 Add Workflow Run show page (#7719)
In this PR:

- Display a workflow version visualizer for the version of the workflow
the run was executed on.
- Display the output of the run as code.


https://github.com/user-attachments/assets/d617300a-bff4-4328-a35c-291dc86d81cf
2024-10-21 12:04:44 +02:00
shubham yadavandGitHub b914182b78 Update workflows to optimize CI processes (#7828)
This Pull Request addresses the need to optimize our Continuous
Integration (CI) workflows for Playwright tests and release processes.
The changes implemented aim to reduce unnecessary resource usage by
conditionally executing jobs based on relevant file changes and
Implement https://github.com/tj-actions/changed-files step

## Changes logs
- Updated `ci-test-docker-compose.yaml , ci-chrome-extension.yaml ` to
check for changed files before running tests.
- Updated `ci-front.yaml , ci-utils.yaml , ci-website.yaml ,
ci-server.yaml` to check for changed files before running tests.
- Enhanced `playwright.yml` to skip unnecessary tests based on file
changes.
2024-10-21 12:02:14 +02:00
Baptiste DevessierandGitHub fc6748de0a Add modal to confirm workflow draft version overriding (#7758)
In this PR:

- Allow the `<ConfirmationModal />` to take additional buttons to
display between the cancel and the confirm buttons.
- Create a modal that's displayed when the user tries wants to use a
workflow version as draft while a draft version already exists. The
displayed modal contains a link to the current draft version and a
button to confirm the overriding of the current draft version.

A demo:


https://github.com/user-attachments/assets/6349f418-1b11-45b3-9f5e-061ca74c2966

Closes twentyhq/private-issues#114
2024-10-21 11:51:54 +02:00
Bhavesh MishraandGitHub f3ec6a759f OSS.GG Content creation challenge (#7859)
I have the content creation challenge of twenty I have published a
detailed Youtube walkthrough to Twenty Dashboard and Created a Blog on
Hashnode about Twenty Crm with step by step guide to use Twenty.

Below are the task links
1. Create a YouTube Video about Twenty showcasing a specific way to use
Twenty effectively. Points: 750
[Watch here](https://youtu.be/KuAycGuW698?si=TyKGVyrydLzof2RI)

2. Write a blog post about sharing your experience using Twenty in a
detailed format on any platform. Points: 750
[Click
here](https://k5lo7h.hashnode.dev/twenty-crm-a-fresh-start-for-modern-businesses)

Total Points - 1500
2024-10-21 08:41:19 +02:00
Rajeev DewanganandGitHub ae1d53aa29 Write-a-blog-post-about-Twenty (#7902)
What side quest are you solving: Write a blog post about Twenty

Description: Shared my experience using Twenty in a detailed blog post

Points: 750

Proof: 

link :
https://open.substack.com/pub/rajeevdewangan/p/our-experience-using-twenty-an-open?r=4lly3x&utm_campaign=post&utm_medium=web&showWelcomeOnShare=true
![Screenshot 2024-10-21
103524](https://github.com/user-attachments/assets/9475c262-8c5e-4a74-b2c7-e690e72daba4)
2024-10-21 08:37:00 +02:00
d6810c3b42 fix: Custom fields lacks empty tag (#7777)
This PR fixes this issue #7250

---------

Co-authored-by: Félix Malfait <felix@twenty.com>
2024-10-21 08:33:59 +02:00
BOHEUSandGitHub cc4b060932 Typos in docs (#7898) 2024-10-20 23:09:28 +02:00
35bb1a82ba side quest: Like & Re-Tweet oss.gg Launch Tweet (#7877)
Description:
Liked & Tweeted @twentycrm on X

Points:
50

Proof:
Link: https://x.com/mkprasad_821/status/1847886807314120762

<img width="1369" alt="Screenshot 2024-10-20 at 11 56 54 AM"
src="https://github.com/user-attachments/assets/e17daa69-6920-4641-8282-4aa98f48762a">

---------

Co-authored-by: Apple <apple@Apples-MacBook-Pro.local>
2024-10-20 20:28:06 +02:00
f27b1169a1 meme-magic #7875 created (#7878)
Completed the sidequest of meme magic

Co-authored-by: Charles Bochet <charlesBochet@users.noreply.github.com>
2024-10-20 20:27:53 +02:00
a09c5280ee oss.gg - Side quest meme magic completed (#7879)
![image](https://github.com/user-attachments/assets/c2d52346-4fdb-49de-8b70-e3a1da3a7521)

---------

Co-authored-by: Charles Bochet <charlesBochet@users.noreply.github.com>
2024-10-20 20:26:17 +02:00
b134f62da7 oss.gg: Created a gif about twenty and uploaded to Giphy (#7884)
### Points
150

### Proof

Link to tweet: https://x.com/mkprasad_821/status/1847917157956419690
Link to giphy: https://giphy.com/gifs/uiTAwFJ0BWQsQb7jbM
<img width="1144" alt="Screenshot 2024-10-20 at 1 49 43 PM"
src="https://github.com/user-attachments/assets/cf1ccdbc-1dc0-461c-80b7-d49a59926e73">

Co-authored-by: Apple <apple@Apples-MacBook-Pro.local>
2024-10-20 20:25:24 +02:00
8b5b0da77f Design/Create new Twenty logo, tweet your design. (#7892)
### Points:
300

### Proof:
<img width="1144" alt="Screenshot 2024-10-20 at 6 13 00 PM"
src="https://github.com/user-attachments/assets/b116e978-c216-443b-a12d-7d340e1e3d09">

Co-authored-by: Apple <apple@Apples-MacBook-Pro.local>
2024-10-20 20:23:24 +02:00
44a843542c Design a promotional poster for twenty. (#7896)
### Points:
300

### Proof:

<img width="1227" alt="Screenshot 2024-10-20 at 10 00 57 PM"
src="https://github.com/user-attachments/assets/b2dfaefb-b73c-4a22-a4f0-8721150af52d">

Co-authored-by: Apple <apple@Apples-MacBook-Pro.local>
2024-10-20 20:21:23 +02:00
Charles BochetandGitHub eccf0bf8ba Enforce front project structure through ESLINT (#7863)
Fixes: https://github.com/twentyhq/twenty/issues/7329
2024-10-20 20:20:19 +02:00
f801f3aa9f oss.gg Tweet about your favourite feature in Twenty (#7880)
Point: 50

Proof:
Link: https://x.com/mkprasad_821/status/1847895747707953205

<img width="1369" alt="Screenshot 2024-10-20 at 12 31 07 PM"
src="https://github.com/user-attachments/assets/c9db7eb1-e854-4cb6-8120-5a14d27ccadd">

Co-authored-by: Apple <apple@Apples-MacBook-Pro.local>
2024-10-20 10:20:39 +02:00
dc1fbc3315 Created a meme on Twenty and posted on X (#7883)
### Points: 
150

### Proof:
Link to Tweet: https://x.com/mkprasad_821/status/1847900277510123706

![Screenshot 2024-10-20 at 12 49 12
PM](https://github.com/user-attachments/assets/ae47d070-3b98-46b7-ba89-ecce8c16ae9a)

Co-authored-by: Apple <apple@Apples-MacBook-Pro.local>
2024-10-20 10:19:42 +02:00
sateshcharanandGitHub c5138df58c oss.gg side-quest-gif-magic completed (#7873)
![image](https://github.com/user-attachments/assets/3238d111-9098-4e60-a287-87d7f13f2ace)
2024-10-20 07:57:05 +02:00
Nabhag MotivarasandGitHub ac88840bf0 fix: redis url to not be optional anymore (#7850)
## Description

- `REDIS_URL` is required 

<img width="1903" alt="Redis Required"
src="https://github.com/user-attachments/assets/5b53a4a6-29f4-4473-b7e4-52489f75204e">

---- 

- Closes #7849

- Might be related #7768

--- 

- Wasn't gracefully reseting database

``` 
   npx nx database:reset twenty-server
```
2024-10-19 17:22:47 +02:00
8368f14fb9 Bug Fix: Decreased border radius of badge and changed badge parent div padding to margin (#7835)
## What does this PR do?
Decreased the border-radius of the badge and changed the padding-top and
padding-bottom of the badge parent div to margin-top and margin-bottom

Fixes #7811

<img width="1470" alt="Screenshot 2024-10-19 at 12 27 49 AM"
src="https://github.com/user-attachments/assets/2ecb2e18-127e-4093-ba82-34b6e71656a8">
<img width="1470" alt="Screenshot 2024-10-19 at 12 28 37 AM"
src="https://github.com/user-attachments/assets/ef6b4b8d-7f9d-452f-885b-971e2ac658b9">

## How should this be tested?
Create any task, notes, or files.

---------

Co-authored-by: ehconitin <nitinkoche03@gmail.com>
2024-10-19 11:42:43 +02:00
Baptiste DevessierandGitHub 36e59d80c4 Use the correct color for workflow nodes label (#7829)
Follow the design from the Figma about the color to use.

Big up to @Bonapara for doing great job on the Figma!

It was done on stream!

Fixes #7058
2024-10-19 10:59:04 +02:00
Prashant AcharyaandGitHub 29f903a83b Added new logo images (#7840)
**Added new logo in different png format**
Fixed Issue:
Design a new logo for Twenty (300 points) #**7834**

What tool did I used?
I used logo.com as a design tool to design the logo. 

Logo I made:

![20-high-resolution-logo-black](https://github.com/user-attachments/assets/f041d22d-6d7f-4171-96b7-302a255e89e9)

![20-high-resolution-logo-white-transparent](https://github.com/user-attachments/assets/163f1b9d-cfa2-4d75-ba9d-9cb0ce54bf46)

![20-high-resolution-logo-black-transparent](https://github.com/user-attachments/assets/4648107d-c628-4a64-9bd1-94ab036c4b60)

![20-high-resolution-logo](https://github.com/user-attachments/assets/7735e623-b2e2-4484-b71c-5fc42be33362)
2024-10-19 10:58:20 +02:00
Félix MalfaitandGitHub c285f0a9df Refactoring show page (#7838)
@ehconitin following your question I did a quick refactoring of the show
page - we can push it much further but it would be better to start from
this code than from main

Edit: I will merge to avoid conflicts, this is very far from perfect but
still much better than the mess we had before
2024-10-19 00:39:10 +02:00
WeikoandGitHub d4457d756c Fix custom index creation missing indexFieldMetadatas (#7832)
## Context
Regression on custom index creation where indexFieldMetadatas were not
saved properly in the DB. This is because we recently changed save() to
upsert() in the indexMetadataService and upsert does not handle nesting
insert properly.
I'm suggesting another fix where we separate indexMetadata creation and
index migration creation in 2 different functions. Since the goal was to
be able to recreate the index after being deleted when we changed the
tsvector expression and indexMetadata was actually not deleted, we
didn't need to recreate that part (hence the upsert) and only needed to
run a migration to create the actual index in the workspace schema.
I've updated the different services and now only call
createIndexMigration when we update a search vector expression.

Note: this is also fixing the sync-metadata command when running on a
workspace with a custom object (including the seeded workspace which has
the 'rocket' custom object), failing due to the missing 'searchVector'
indexFieldMetadata
2024-10-18 18:59:50 +02:00
Charles Bochet 17b934e22b Migrate to shipfox 2024-10-18 18:36:01 +02:00
NitinPSinghandGitHub e50117e3b0 fix #7781 made kanban board title and checkbox 24px (#7815)
# issue: #7781 

- [x] titlechip to 24px
- [x] checkbox to 24px
![Screenshot 2024-10-18
134759](https://github.com/user-attachments/assets/e9d347e3-41b8-4b0d-a072-d139ed982971)
![Screenshot 2024-10-18
134708](https://github.com/user-attachments/assets/8b83f6dd-96ac-4a4e-b6ae-85d3e2923fb9)
2024-10-18 18:02:43 +02:00
martmullandGitHub 9c8eeeea9d Start twenty-server:worker when npx nx start (#7820)
- start the worker service when launching `npx nx start`
- update documentation
2024-10-18 16:13:12 +02:00
MarieandGitHub 5a23d1eea8 [sentry fix] handle undefined createdBy case (#7818)
Fix sentry
https://twenty-v7.sentry.io/issues/5998085857/?alert_rule_id=15135094&alert_type=issue&environment=prod&notification_uuid=9a6c6c3d-6bd1-4c7f-bf27-8acb3571bbc3&project=4507072499810304&referrer=discord
2024-10-18 15:14:08 +02:00
MarieandGitHub 6fef125965 Use search instead of findMany in relation pickers (#7798)
First step of #https://github.com/twentyhq/twenty/issues/3298.
Here we update the search endpoint to allow for a filter argument, which
we currently use in the relation pickers to restrict or exclude ids from
search.
In a future PR we will try to simplify the search logic in the FE
2024-10-18 14:50:04 +02:00
Ana Sofia Marin AlexandreandGitHub 8cadcdf577 add dynamic dates for webhookGraphDataUsage (#7720)
**Before:**
Only last 5 days where displayed on Developers Settings Webhook Usage
Graph.

![image](https://github.com/user-attachments/assets/7b7f2e6b-9637-489e-a7a7-5a3cb70525aa)


**Now**
Added component where you can select the time range where you want to
view the webhook usage. To do better the styling and content depassing .

<img width="652" alt="Screenshot 2024-10-15 at 16 56 45"
src="https://github.com/user-attachments/assets/d06e7f4c-a689-49a0-8839-f015ce36bab9">


**In order to test**

1. Set ANALYTICS_ENABLED to true
2. Set TINYBIRD_TOKEN to your token from the workspace
twenty_analytics_playground
3. Write your client tinybird token in
SettingsDeveloppersWebhookDetail.tsx in line 93
4. Create a Webhook in twenty and set wich events it needs to track
5. Run twenty-worker in order to make the webhooks work.
6. Do your tasks in order to populate the data
7. Enter to settings> webhook>your webhook and the statistics section
should be displayed.
8.  Select the desired time range in the dropdown

**To do list**

- Tooltip is truncated when accessing values at the right end of the
graph
- DateTicks needs to follow a more clear standard
- Update this PR with more representative images
2024-10-18 11:00:21 +02:00
martmullandGitHub 0c24001e23 Fix update event webhook triggering (#7814) 2024-10-18 10:20:21 +02:00
f6c094a56f [FIX] fix navigation overflow (#7795)
FIX #7733

Fixes the overflow and responsive problem on large and small devices. 


![image](https://github.com/user-attachments/assets/6cd8b33f-a52f-4452-b161-9c84ebbb4cce)

![image](https://github.com/user-attachments/assets/c8c0386f-e2a2-4f96-a06e-7e37f54c0564)

The 'Workspace' title is fixed and only links under it are scrolled when
overflown.

---------

Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
2024-10-18 00:49:42 +02:00
8f7ca6a0e3 Fix Google Auth displays Status: 401 on screen (#7659)
When the user presses the cancel button, the server sends the following
response:

![image](https://github.com/user-attachments/assets/cb68cf01-b32c-4680-a811-cd917db88ca9)

{"statusCode": 401, "message": "Unauthorized"}

Now, when the user clicks the cancel button, they are redirected to the
home page for login.

Related Issue
Fixes #7584

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2024-10-18 00:21:57 +02:00
6f5dc1c924 Bug Fix: created new div and p tag styles and wrap it on the workspace member as container (#7581)
Hello,
Hope you are doing well.I created a special style for the text to make
sure it stays in one line and wont exceed the width if the text width
will be more then 80px it will ecplise and set ... at the end of the
text.

I created these 2 styles variables and wrap my text in these styles 
StyledObjectSummary 
StyledEllipsisParagraph 

Fixes #7574 


#Screens Shots
<img width="1268" alt="Screenshot 2024-10-10 at 10 58 04 PM"
src="https://github.com/user-attachments/assets/2d3ef2c5-c4c8-489b-a205-50a48b986d60">

<img width="530" alt="Screenshot 2024-10-10 at 10 58 20 PM"
src="https://github.com/user-attachments/assets/e0d1cb48-dbc9-427a-99ac-54269c574360">

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2024-10-17 23:55:50 +02:00
249c7324a2 Improve error message for Graphql API (#7805)
![CleanShot 2024-10-17 at 11 39
39](https://github.com/user-attachments/assets/616b8317-de1f-4b61-b2b4-980b14b09f66)

This improves this error message.

---------

Co-authored-by: Félix Malfait <felix@twenty.com>
2024-10-17 22:40:30 +02:00
a45d3148ac fix: Blocklist table optimised for all viewports (#7618)
## Description

- This PR fixes the issue #7549 
- Optimised blocktable for all viewports

## Changes - 

<img width="1113" alt="Screenshot 2024-10-12 at 5 11 11 PM"
src="https://github.com/user-attachments/assets/29d491da-5878-4c88-b50e-6ee6c43d5bec">



https://github.com/user-attachments/assets/d5fa063d-2819-4a9d-a9b2-e3ceefe65c8d

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2024-10-17 21:37:03 +02:00
c0e6fb6fdb added left padding in filter chip (#7800)
Fixes: #7779

---------

Co-authored-by: Shashank Suman <shashanksuman@Shashanks-MacBook-Air.local>
2024-10-17 21:36:44 +02:00
Charles Bochet fad1363095 Fix CIs not running 2024-10-17 19:35:27 +02:00
58fd34071c [Server Integration tests] Enrich integration GraphQL API tests (#7699)
### Description

- We are using gql instead of strings to be able to see the graphql code
highlighted

### Demo


![](https://assets-service.gitstart.com/28455/d06016b9-c62c-4e0d-bb16-3d7dd42c5b6b.png)

Fixes #7526

---------

Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
Co-authored-by: Charles Bochet <charlesBochet@users.noreply.github.com>
2024-10-17 19:16:19 +02:00
Atharva_404andGitHub f08b8fda16 Updated 1-design-promotional-poster-20-share.md with (#7791)
Added my own entry to the list with the following poster:
### Points:
300
<br/>

![twenty](https://github.com/user-attachments/assets/bd7648a5-8012-4d73-a992-b8e7e8ed08a0)
2024-10-17 17:46:46 +02:00
Shlok KoiralaandGitHub d827d80ddc [🕹️] Twenty Design Challenges: New twenty logo by Shlok-py (#7790)
added shlok-py nmew logo for twenty
2024-10-17 17:45:55 +02:00
Nazar PoshtarenkoandGitHub c07650fd7e fix(front): move "Add to favorites" btn to start of action menu (#7785)
### What does this PR do?

Moves the "Add to favourites" action button to the beginning of the
action menu, thus moving the "Delete" button to its right edge.

Fixes #7780.

<img width="1494" alt="image"
src="https://github.com/user-attachments/assets/52498fce-278c-4f04-a5ce-26920f9ffd5a">
2024-10-17 19:41:02 +05:30
Thomas TrompetteandGitHub f338d01b4f Build code introspection service (#7760)
Starting to use ts-morph to retrieve function parameters
2024-10-17 15:08:42 +02:00
martmullandGitHub ddbfabfc99 Precise wording for api example (#7783)
Enhance composite type filter example in open-api
2024-10-17 14:41:38 +02:00
Charles Bochet f26c65fd41 Try out depot as CI provider 2024-10-17 11:50:43 +02:00
JeelandGitHub 8e86e94125 Fix: Remove Deleted filter not reflecting issue (#7676)
## PR Summary

This Pull request fixes #7626 

Adding Deleted filter from option will add filter label as "Deleted" in
tableFiltersState, But on click of "Remove Deleted filter" "Deleted at"
is used for finding tableFilter id, which results in tableFilter id as
undefined.
2024-10-16 18:20:39 +02:00
03dd7527b7 fix: Array data type accepts whitespace as input (#7707)
## Description

- This PR fixes the issue #7593

Co-authored-by: bosiraphael <raphael.bosi@gmail.com>
2024-10-16 17:52:32 +02:00
ba2ee0da72 Refactor Redis connections to use Redis URL - closes #7421 (#7736)
Closes #7421

This pull request consolidates Redis connection parameters into a single
`REDIS_URL` environment variable across various configuration files and
code modules. The most important changes include updates to environment
variable files, Docker and Kubernetes configurations, and code modules
to utilize the new `REDIS_URL` format.

### Environment Variable Updates:
*
[`packages/twenty-docker/.env.example`](diffhunk://#diff-f4b5e7acc0dde630eafb2228390ca56bd56db0d183582be6433a9ee808088a4cL8-R8):
Replaced `REDIS_HOST` and `REDIS_PORT` with `REDIS_URL`.
*
[`packages/twenty-server/.env.example`](diffhunk://#diff-c06e244338b33286ea90221635809785352a971de53f647ea65650124ae74ad2L53-R53):
Replaced `REDIS_HOST`, `REDIS_PORT`, `REDIS_USERNAME`, and
`REDIS_PASSWORD` with `REDIS_URL`.
*
[`packages/twenty-server/.env.test`](diffhunk://#diff-def44a08e699c9deca2f72c9f87951de5d33d9ccf5621eab2f34978df8ad0954L16-R16):
Replaced `REDIS_HOST`, `REDIS_PORT`, `REDIS_USERNAME`, and
`REDIS_PASSWORD` with `REDIS_URL`.

### Docker and Kubernetes Configuration Updates:
*
[`packages/twenty-docker/docker-compose.yml`](diffhunk://#diff-545fb51ad66f93f727bb8f8b375dc6858b33348d91d5e51ad931fb0bbc1affeeL28-R28):
Replaced `REDIS_HOST` and `REDIS_PORT` with `REDIS_URL` in multiple
service definitions.
[[1]](diffhunk://#diff-545fb51ad66f93f727bb8f8b375dc6858b33348d91d5e51ad931fb0bbc1affeeL28-R28)
[[2]](diffhunk://#diff-545fb51ad66f93f727bb8f8b375dc6858b33348d91d5e51ad931fb0bbc1affeeL62-R61)
*
[`packages/twenty-docker/k8s/manifests/deployment-server.yaml`](diffhunk://#diff-91623ed4e8b2088947cfa9a5dad76b6013e8db0c150d84347a215fa9ad78bf04L44-R45):
Replaced `REDIS_HOST` and `REDIS_PORT` with `REDIS_URL`.
*
[`packages/twenty-docker/k8s/manifests/deployment-worker.yaml`](diffhunk://#diff-8532debd131ce168a2527fa6a9be6405792178576ee47e2eef0cd9f3ff4a8f8cL43-R44):
Replaced `REDIS_HOST` and `REDIS_PORT` with `REDIS_URL`.
*
[`packages/twenty-docker/k8s/terraform/deployment-server.tf`](diffhunk://#diff-b4c468660ab00bd03589d0d47502c477ca83f7d876ff196534880b02ba46dce0L64-R65):
Replaced `REDIS_HOST` and `REDIS_PORT` with `REDIS_URL`.
*
[`packages/twenty-docker/k8s/terraform/deployment-worker.tf`](diffhunk://#diff-e5d6a1f68d5391e2120aef6261f22f905aa1ce0a567e31b21a27d44f313eaecaL62-R63):
Replaced `REDIS_HOST` and `REDIS_PORT` with `REDIS_URL`.

### Code Module Updates:
*
[`packages/twenty-server/src/engine/core-modules/cache-storage/cache-storage.module-factory.ts`](diffhunk://#diff-06e787a7c8a48022d5909b5df9b8c6ca192521cf32f51d7f561cee937bed6678L23-R35):
Replaced `REDIS_HOST` and `REDIS_PORT` with `REDIS_URL`.
*
[`packages/twenty-server/src/engine/core-modules/environment/environment-variables.ts`](diffhunk://#diff-26ce615693b053eda02aa48aa2e30400381a2588dcb08d4a9dc3b0bf5bdd6fe7L378-R384):
Added validation for `REDIS_URL`.
*
[`packages/twenty-server/src/engine/core-modules/message-queue/message-queue.module-factory.ts`](diffhunk://#diff-7bd644d28bdd86c159c1d71242753df5d5acd91c73c6e60b2e35caa53ed3836bR6):
Replaced `REDIS_HOST`, `REDIS_PORT`, `REDIS_USERNAME`, and
`REDIS_PASSWORD` with `REDIS_URL`.
[[1]](diffhunk://#diff-7bd644d28bdd86c159c1d71242753df5d5acd91c73c6e60b2e35caa53ed3836bR6)
[[2]](diffhunk://#diff-7bd644d28bdd86c159c1d71242753df5d5acd91c73c6e60b2e35caa53ed3836bL35-R41)

### Documentation Updates:
*
[`packages/twenty-website/src/content/developers/self-hosting/self-hosting-var.mdx`](diffhunk://#diff-c4cc78a3ce18b6edb10f1aee8990271e1d2796a8c06c1c6ae3b68db8d52278a3L37-R37):
Updated documentation to reflect the change to `REDIS_URL`.
*
[`packages/twenty-website/src/content/developers/self-hosting/upgrade-guide.mdx`](diffhunk://#diff-c7d757829f6128e1f47aa1955bde561292dce558280511fab66281afa99042a5R102-R112):
Added upgrade instructions for the new `REDIS_URL` variable.

---------

Co-authored-by: Weiko <corentin@twenty.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
2024-10-16 17:17:44 +02:00
Harsh Shrikant BhatandGitHub f827d52bbf oss.gg: meme, fav feature, gif, launch, poster, logo (#7750)
GIF: 150 points
Meme: 150 points
Retweet: 50 points
Favourite Feature: 50 points
Logo: 300 points
Poster 300 points

Total: 1000

### Points

1000


### Provide proof that you've completed the task

GIF: 


https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExcDRuenQ1emluYmM2eWo3dzJ5YnExYTRpNTZvNWIzc2M2eG05azRoOCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/mgoYSDrjIalUL7XJzm/giphy.gif

Favourite Feature tweet:

https://x.com/HarshBhatX/status/1846075312691413066


LAUNCH TWEET:

https://x.com/HarshBhatX/status/1846252536241508392


Meme:

https://x.com/HarshBhatX/status/1844698253104709899

Logo ( heavily inspired by unkey ):

https://x.com/HarshBhatX/status/1846234658712772977

Poster:

https://x.com/HarshBhatX/status/1846233330435477531
2024-10-16 16:43:05 +02:00
nitinandGitHub fad04144a3 minor fix - collapse button hover and dropdown button width (#7748)
follow up - #7414
2024-10-16 15:13:26 +02:00
Charles BochetandGitHub a16a88fa8e Move Front CI from Github runner to shipfox runner (#7749)
Trying out a CI runner provider called "ShipFox"
(https://docs.shipfox.io/)

Let's see how it works ;)
2024-10-16 14:57:35 +02:00
720fe32809 Fixes #7105: Fixed column header on Kanban boards (#7263)
Issue Reference: Fixes #7105

Description:
This pull request introduces adjustments to the styling of the
RecordBoardColumnHeader component. The modifications enhance the layout
and visual consistency of the Kanban board headers.

Changes Made:
Margin Adjustment:

Increased the bottom margin from theme.spacing(2) to theme.spacing(6)
for better spacing below the header.
Header Container Enhancements:

Added a background color sourced from the theme
(theme.background.primary) to the header container for improved
visibility and aesthetics.
Set a fixed height of 40px for the header to ensure a consistent size
across different screens.
Applied a fixed position to the header container to keep it visible at
the top during scrolling.
Added padding at the top using theme.spacing(2) for better alignment of
content within the header.


Before :



https://github.com/user-attachments/assets/fd1c2d65-5e50-489a-a388-c0c4e1bd015b



Now :


[now.webm](https://github.com/user-attachments/assets/bd4cfb86-fc14-4902-b84c-99d27b07859e)

---------

Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
2024-10-16 14:33:54 +02:00
WeikoandGitHub 082c614013 update makefile rules to use docker run (#7747)
Fixes https://github.com/twentyhq/twenty/issues/7739

FYI @BOHEUS, thanks
2024-10-16 14:32:58 +02:00
Thomas TrompetteandGitHub e811bae10e Execute variables in action input (#7715)
- send context from all previous steps rather than unique payload
- wrap input data in settings into input field
- add email into send email action settings
- update output shape

<img width="553" alt="Capture d’écran 2024-10-15 à 15 21 32"
src="https://github.com/user-attachments/assets/0f5ed004-0d6e-4a59-969b-a5710f3f3985">

<img width="761" alt="Capture d’écran 2024-10-15 à 15 20 09"
src="https://github.com/user-attachments/assets/ac140846-c383-483b-968a-eab469b76785">
2024-10-16 14:32:06 +02:00
Thomas des FrancsandGitHub a88c2fa453 Added Jobs to tsx footer (#7706)
![CleanShot 2024-10-15 at 09 32
23](https://github.com/user-attachments/assets/c2b21359-52d9-4e46-8700-0937fba5391d)

New "Jobs"
2024-10-16 11:51:37 +02:00
Charles BochetandGitHub 4d0af3eb7e Fix tests (#7722)
As per title ;)
2024-10-16 09:28:31 +02:00
Ali Yar KhanandGitHub 0a5bc02499 Oss.gg gif magic (#7725)
Task: Create a  gif related to Twenty. Tweet it, and tag  @twentycrm.

Points: 150

Proof:

![image](https://github.com/user-attachments/assets/58da313f-1a94-45ac-88a4-9a0c90eff545)
2024-10-16 09:27:39 +02:00
Charles Bochet 1b99a05dec Put back twenty-website dockerfile 2024-10-15 18:36:10 +02:00
Félix MalfaitandGitHub f3fe3abf71 Fix unique index created twice (#7718)
`isUnique` was passed to TypeORM's column creation API resulting in
double index creation because it's already done via the decorator and
then in `WorkspaceMigrationIndexFactory`

It would be interesting to move it at this field level in a later step,
which is why I also fixed `CompositeColumnActionFactory` to pass
isUnique on the correct columns, even though it's being ignored later on
2024-10-15 17:50:39 +02:00
WeikoandGitHub 7e808cf529 Remove pgGraphql from setup (#7716)
## Context
This PR removes pg_graphql from the setup. It also updates the local
setup documentation accordingly.

Note: We removed local setup scripts to align with redis installation,
the setup should be much simpler since we don't rely on pg_graphql
anymore.

## Test
tested locally with docker + mac (brew) setup
2024-10-15 16:59:44 +02:00
MarieandGitHub 1de739176c Update searchVector at label identifier update for custom fields (#7588)
By default, when custom fields are created, a searchVector field is
created based on the "name" field, which is also the label identifier by
default.
When this label identifier is updated, we want to update the
searchVector field to use this field as searchable field instead, if it
is of "searchable type" (today it is only possible to select a text or
number field as label identifier, while number fields are not
searchable).
2024-10-15 16:34:05 +02:00
Ali Yar KhanandGitHub b1cc7b7dbb Promotion Poster (#7695)
Task: Create a poster that promotes Twenty and share it on social media.
Points: 300
Attachment:

![image](https://github.com/user-attachments/assets/ec219e9c-e087-4635-80ce-e65f71302ef0)
2024-10-15 14:23:25 +02:00
nitinandGitHub a9deede9ba feat - Compact sidebar (#7414) 2024-10-15 14:02:28 +02:00
WeikoandGitHub c0610419c2 Fix unique index email people (#7713)
## Context
WorkspaceIsUnique decorator allows us to create unique indexes on our
tables. Here Emails is a composite field containing a TEXT subfield. Due
to the fact that TEXT fields are non-nullable and have empty strings as
default values, adding a unique index on a TEXT field or any composite
containing TEXT as subfields will fail and throw if we try to create
more than 1 record that does not specify a value to the TEXT field.

This PR simply removes the index for the time being until we find a
solution
2024-10-15 11:31:42 +02:00
MarieandGitHub 17ec538da5 Fix DateTimeSettingsTimeZoneSelect (#7688)
Fixing
[sentry](https://twenty-v7.sentry.io/issues/5990711011/?alert_rule_id=15135099&alert_type=issue&notification_uuid=06fea945-1c24-4ee6-94f6-99f1d7f94010&project=4507072563183616&referrer=discord)
_Cannot read properties of undefined (reading 'label')_
2024-10-15 10:57:24 +02:00
RoninandGitHub 1492340079 [Fix] : Horizontal scroll issue in dropdown (#7682)
In this PR, I changed the hard-coded width value to a dynamic value
which will be calculated based on the parent container.

This PR closes issue: #7615
2024-10-14 21:52:50 +05:30
WeikoandGitHub efba3b14be cleanup pg_graphql #1 (#7673)
## Context
This PR removes workspace-query-runner/builder in preparation for fully
deprecating pg_graphql

next steps: Remove from the setup and make a command to remove comments
on schema/tables related to pg_graphql
2024-10-14 14:19:13 +02:00
Yash ParmarandGitHub a64635a9db Oss.gg : side quest challenge 4 meme magic and 1 retweet with quote (#7663)
### Description

Here i have completed side quest challenge 1 and 4. 

Proof: 

Side quest 1: https://x.com/yashp3020/status/1845720834716959009

![twitter
image](https://github.com/user-attachments/assets/f42691ef-996f-4884-a47b-4b97362a3837)

Side quest 4: https://x.com/yashp3020/status/1845720142702842093

![Capture-2024-10-14-131006](https://github.com/user-attachments/assets/e9940485-77c7-485b-a807-9aa9e27af8d2)
2024-10-14 10:04:45 +02:00
Aditya DeshlahreandGitHub b41d1d2a4b Added oss-gg hackathon issue opening template (#7662)
## Added [oss.gg](https://oss.gg/) hackathon issue opening template 

### This is issue template is consistent in other oss-gg participating
repos. So this helps the participant to open the issue with proof of
work and makes it easy for the maintainer to award points on the simple
side quests.

### If any changes needed lmk

### {can I get some Brownie Point for this template addition}?

### Thank You 🙂 

#### DEMO

![image](https://github.com/user-attachments/assets/864b2c9e-c147-4e67-bdd7-e90eb481ba44)

![image](https://github.com/user-attachments/assets/799edbab-0039-435d-8608-1a809ddb7533)
2024-10-14 08:44:45 +02:00
1a57dd654f fix: prevent flashing of search results during input (#7592)
solves #7511

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2024-10-14 08:29:54 +02:00
Ali Yar KhanandGitHub 653085f1e6 OSS.gg Meme Around Twenty (#7660)
Task: Meme Magic: Craft a meme where the number twenty plays a role.
Tweet it, and tag @twentycrm.
Points: 150
Attachment:

![image](https://github.com/user-attachments/assets/8999dd0d-70b5-4065-9e44-e1e72132c27b)
2024-10-14 08:07:15 +02:00
BOHEUSandGitHub a7a4052109 Docker cleanup (#7655)
Related to #7648 

@charlesBochet I've deleted only dev related commands in Makefile, if
it's wrong, I'll change it ASAP
2024-10-13 20:40:27 +02:00
Ali Yar KhanandGitHub ee093edc77 OSS.GG Tweet about fav feature (#7658)
Task: Tweet favourite feature and tag Twenty CRM
Point 50
Attachment:

![image](https://github.com/user-attachments/assets/4096c349-e908-4148-8212-2f04cf7659b3)
2024-10-13 20:29:11 +02:00
Ali Yar KhanandGitHub c8365dea0d Like & Re-Tweet oss.gg Launch Tweet (#7656)
Point: 50 Points
Task: Like & Re-Tweet oss.gg Launch Tweet
Attachement:

![image](https://github.com/user-attachments/assets/d6349672-4423-4019-b22f-c1d90d7561a6)
2024-10-13 20:15:00 +02:00
05e8f8a0b1 Use <label> HTML element when possible (#7609)
This PR:

- Uses `<label>` HTML elements when possible to represent labels
- Uses the new `useId()` React hook to get an identifier to link the
label with its input; it's more suitable than generating a UUID at every
render

Fixes #7281

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2024-10-13 20:04:24 +02:00
284b2677be [Fix] - Issue with Email Validation and API Call Trigger on Login #7510 (#7596)
Purpose: Enhance email validation in the SignInUpForm component.

Changes:
- Implemented strict email format validation.
- Disabled the "Continue" button until email validation is complete.
- Displayed error messages for invalid email formats.


![image](https://github.com/user-attachments/assets/62f3c114-002e-4f9f-b18f-5309dfc43587)

---------

Co-authored-by: karankhatik <karan13699@gmail.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
2024-10-13 19:52:35 +02:00
Charles Bochet 73cb8c5561 Re-add nivo to twenty-website package 2024-10-13 19:50:56 +02:00
Nabhag MotivarasandGitHub 508252b14c fix: API ObjectMetadata labelSingular and labelPlural which eventually solves typo in dropdown (#7614)
## ISSUE 

- Closes #7478 

## Description 

- Fixes typo in dropdown + in general any apikeys label around.
2024-10-13 19:37:39 +02:00
Dylan UllrichandGitHub da7a394e0c Allow use of paru in addition to yay as aur helper (#7652)
Hello Twenty Team,

If this is not an appropriate PR, please feel to close it. I am hoping
to make larger contributions down the road.

I was getting twenty setup locally, and I had a problem with the install
script. I noticed that `yay` was named as an AUR helper, but `paru` was
not. I use [paru](https://github.com/Morganamilo/paru), and this caused
the setup script to fail.

I made a small change in the if statement that checks if `pg-graphql`
can be installed with `yay`. I included a check for `paru` on the same
line.

Thanks everyone who has made this project what it is.
2024-10-13 19:15:43 +02:00
1e6346febd [Fix] - Trim Names in Settings > Members table #7509 (#7525)
Issue: Long names in the Members table were overflowing, affecting the
layout.

Fix:
- Trimmed long names with ellipses.
- Added tooltips to display the full content on hover.
- Max-width of the text dynamically set to 90px on large screens, and
60px on mobile.

![image](https://github.com/user-attachments/assets/3b5d1c08-fe0e-4c0b-952a-0fc0f9e513bc)

---------

Co-authored-by: karankhatik <karan13699@gmail.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
2024-10-13 18:32:50 +02:00
BOHEUSandGitHub 1e2c5bb8de Typo in local-setup.mdx (#7647) 2024-10-13 18:20:07 +02:00
a4e52c5ba0 Enhance postgre sql setup script and documentation for various distros 7636 (#7637)
Co-authored-by: Your Name <you@example.com>
2024-10-13 18:19:47 +02:00
dragonnnnandGitHub bdbe495b2c Like & Re-Tweet oss.gg Launch Tweet (#7645)
Point: 50 Points
Task: Like & Re-Tweet oss.gg Launch Tweet
Attachement:

<img
src="https://github.com/user-attachments/assets/f680d8b5-a45e-47df-abfc-af6912f2231b"
width="420" height="600" alt="WhatsApp Image">
2024-10-13 16:39:34 +02:00
Teddy ASSIHandGitHub 3332dcfb80 Submission for new logo design side quest (#7642)
This is my submission for the new logo design side quest
2024-10-13 16:22:37 +02:00
8becedf552 [OSS.GG] Gif Magic Side Quest (#7644)
# Side Quest  Challenge: GIF Magic 


![twentyCRM](https://github.com/user-attachments/assets/74cabf0e-ba3c-4a86-8a5c-5e90edf4606b)

- GIF Link:
https://giphy.com/gifs/twenty-twentycrm-opensourcecrm-wCcsmnJuzzzGrfuf9B

- Related Tweet Link:
https://x.com/NabhagMotivaras/status/1845455575716352363


####  For Fun added Music to Video I recorded hehe.



https://github.com/user-attachments/assets/bedebc33-82a4-4e78-a4b2-19ab25dab364


### - Thank you Raycast 🚀

Co-authored-by: Charles Bochet <charlesBochet@users.noreply.github.com>
2024-10-13 16:20:58 +02:00
Harsh SinghandGitHub d3e503c564 fix: droppable-placeholder (#7600)
Fixes: #7597

This PR fixes the missing placeholder from Droppable component.
2024-10-13 16:06:26 +02:00
Nabhag MotivarasandGitHub 8967181212 [oss.gg] Like & Retweet side quest (#7641)
### Side Quest: Like and Retweet

----
<img width="608" alt="Like Launch Tweet"
src="https://github.com/user-attachments/assets/c03a651e-890d-49e6-bc19-bb7b02d2b671">

---

<img width="608" alt="RetweetSideQuest"
src="https://github.com/user-attachments/assets/58ff243a-10f0-4071-aada-7fafe7894068">
2024-10-13 15:56:14 +02:00
nitinandGitHub 5ca47507dc minor - ts error fix (#7635)
@FelixMalfait :) follow up - #7628
2024-10-13 14:50:29 +02:00
Atharva_404andGitHub 6c0959b2e6 Added new Logo to design new logo twenty.md (#7633)
Added my own name and Logo to the list.

Here is a small preview of the logo:
![Twenty CRM new
Logo](https://github.com/user-attachments/assets/53c265cb-898e-4ec8-bd98-7c3805c850e1)
2024-10-13 13:19:48 +02:00
Utsav bhattaraiandGitHub ce7059dcbf Update 1-quote-tweet-20-oss-gg-launch.md (#7634)
completed Side quest #7632
2024-10-13 13:19:11 +02:00
ccdef0e97b Fix: Nav Item Api & Webhook and Functions stay selected (#7628)
Fixed Nav Item Api & Webhook and Functions stay selected like data model
settings.
 Now when clicked stays selected and deos not loose its selection

Fixes #7573


https://github.com/user-attachments/assets/4cb78158-8411-4ee1-9bcc-2870344c0c62

---------

Co-authored-by: ehconitin <nitinkoche03@gmail.com>
Co-authored-by: Félix Malfait <felix@twenty.com>
2024-10-13 13:18:33 +02:00
Chirag AroraandGitHub 38d7f0bc6b Quest meme magic submission (#7619)
![Screenshot
(16)](https://github.com/user-attachments/assets/4dcb0d4e-9195-4cba-b195-1fb1d52a5e89)
2024-10-13 11:41:57 +02:00
Chirag AroraandGitHub 1a0e706462 Quest Gif Magic Submission (#7622)
![Screenshot
(17)](https://github.com/user-attachments/assets/b481f9fa-7b31-47da-b6ae-97b52162fcae)
2024-10-13 11:40:22 +02:00
Teddy ASSIHandGitHub 2bfca3b661 Design a poster promoting Twenty (#7625)
Designed a poster for twenty and then made a X post about it. 
Here is the link of the post
https://x.com/ion_finisher/status/1845168965963628802
2024-10-13 11:38:24 +02:00
Charles BochetandGitHub d252a23d04 Fix lessThan operator not applying column case (#7624)
Our postgres column naming convention is camelCase ; this forces SQL
queries to wrap column names with double quotes.

We previously forgot the quotes in a filter parsing case
2024-10-13 11:35:26 +02:00
b792d2a4d3 Add unique indexes and indexes for composite types (#7162)
Add support for indexes on composite fields and unicity constraint on
indexes

This pull request includes several changes across multiple files to
improve error handling, enforce unique constraints, and update database
migrations. The most important changes include updating error messages
for snack bars, adding a new command to enforce unique constraints, and
updating database migrations to include new fields and constraints.

### Error Handling Improvements:
*
[`packages/twenty-front/src/modules/error-handler/components/PromiseRejectionEffect.tsx`](diffhunk://#diff-e7dc05ced8e4730430f5c7fcd0c75b3aa723da438c26e0bef8130b614427dd9aL23-R23):
Updated error messages in `enqueueSnackBar` to use `error.message`
directly.
*
[`packages/twenty-front/src/modules/object-metadata/hooks/useFindManyObjectMetadataItems.ts`](diffhunk://#diff-74c126d6bc7a5ed6b63be994d298df6669058034bfbc367b11045f9f31a3abe6L44-R46):
Simplified error messages in `enqueueSnackBar`.
*
[`packages/twenty-front/src/modules/object-record/hooks/useFindDuplicateRecords.ts`](diffhunk://#diff-af23a1d99639a66c251f87473e63e2b7bceaa4ee4f70fedfa0fcffe5c7d79181L56-R58):
Simplified error messages in `enqueueSnackBar`.
*
[`packages/twenty-front/src/modules/object-record/hooks/useHandleFindManyRecordsError.ts`](diffhunk://#diff-da04296cbe280202a1eaf6b1244a30490d4f400411bee139651172c59719088eL22-R24):
Simplified error messages in `enqueueSnackBar`.

### New Command for Unique Constraints:
*
[`packages/twenty-server/src/database/commands/upgrade-version/0-31/0-31-enforce-unique-constraints.command.ts`](diffhunk://#diff-8337096c8c80dd2619a5ba691ae5145101f8ae0368a75192a050047e8c6ab7cbR1-R159):
Added a new command to enforce unique constraints on company domain
names and person emails.
*
[`packages/twenty-server/src/database/commands/upgrade-version/0-31/0-31-upgrade-version.command.ts`](diffhunk://#diff-20215e9981a53c7566e9cbff96715685125878f5bcb84fe461a7440f2e68f6fcR13-R14):
Integrated the new `EnforceUniqueConstraintsCommand` into the upgrade
process.
[[1]](diffhunk://#diff-20215e9981a53c7566e9cbff96715685125878f5bcb84fe461a7440f2e68f6fcR13-R14)
[[2]](diffhunk://#diff-20215e9981a53c7566e9cbff96715685125878f5bcb84fe461a7440f2e68f6fcR31)
[[3]](diffhunk://#diff-20215e9981a53c7566e9cbff96715685125878f5bcb84fe461a7440f2e68f6fcR64-R68)
*
[`packages/twenty-server/src/database/commands/upgrade-version/0-31/0-31-upgrade-version.module.ts`](diffhunk://#diff-da52814efc674c25ed55645f8ee2561013641a407f88423e705dd6c77b405527R7):
Registered the new `EnforceUniqueConstraintsCommand` in the module.
[[1]](diffhunk://#diff-da52814efc674c25ed55645f8ee2561013641a407f88423e705dd6c77b405527R7)
[[2]](diffhunk://#diff-da52814efc674c25ed55645f8ee2561013641a407f88423e705dd6c77b405527R24)

### Database Migrations:
*
[`packages/twenty-server/src/database/typeorm/metadata/migrations/1726757368824-migrationDebt.ts`](diffhunk://#diff-c450aeae7bc0ef4416a0ade2dc613ca3f688629f35d2a32f90a09c3f494febdcR1-R53):
Added a migration to update the `relationMetadata_ondeleteaction_enum`
and set default values.
*
[`packages/twenty-server/src/database/typeorm/metadata/migrations/1726757368825-addIsUniqueToIndexMetadata.ts`](diffhunk://#diff-8f1e14bd7f6835ec2c3bb39bcc51e3c318a3008d576a981e682f4c985e746fbfR1-R19):
Added a migration to include the `isUnique` field in `indexMetadata`.
*
[`packages/twenty-server/src/database/typeorm/metadata/migrations/1726762935841-addCompostiveColumnToIndexFieldMetadata.ts`](diffhunk://#diff-7c96b7276c7722d41ff31de23b2de4d6e09adfdc74815356ba63bc96a2669440R1-R19):
Added a migration to include the `compositeColumn` field in
`indexFieldMetadata`.
*
[`packages/twenty-server/src/database/typeorm/metadata/migrations/1726766871572-addWhereToIndexMetadata.ts`](diffhunk://#diff-26651295a975eb50e672dce0e4e274e861f66feb1b68105eee5a04df32796190R1-R14):
Added a migration to include the `indexWhereClause` field in
`indexMetadata`.

### GraphQL Exception Handling:
*
[`packages/twenty-server/src/engine/api/graphql/workspace-query-runner/utils/workspace-query-runner-graphql-api-exception-handler.util.ts`](diffhunk://#diff-58445eb362dc89e31107777d39b592d7842d2ab09a223012ccd055da325270a8R1-R4):
Enhanced exception handling for `QueryFailedError` to provide more
specific error messages for unique constraint violations.
[[1]](diffhunk://#diff-58445eb362dc89e31107777d39b592d7842d2ab09a223012ccd055da325270a8R1-R4)
[[2]](diffhunk://#diff-58445eb362dc89e31107777d39b592d7842d2ab09a223012ccd055da325270a8R23-R59)
*
[`packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/factories/create-many-resolver.factory.ts`](diffhunk://#diff-233d58ab2333586dd45e46e33d4f07e04a4b8adde4a11a48e25d86985e5a7943L58-R58):
Updated the `workspaceQueryRunnerGraphqlApiExceptionHandler` call to
include context.
*
[`packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/factories/create-one-resolver.factory.ts`](diffhunk://#diff-68b803f0762c407f5d2d1f5f8d389655a60654a2dd2394a81318655dcd44dc43L58-R58):
Updated the `workspaceQueryRunnerGraphqlApiExceptionHandler` call to
include context.

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2024-10-13 10:21:03 +02:00
Charles Bochet d1d4af0c63 Make main the new 0.32 canary 2024-10-12 17:48:20 +02:00
2555 changed files with 81924 additions and 44094 deletions
@@ -0,0 +1,33 @@
name: oss.gg hack submission 🕹️
description: "Submit your contribution for the for the oss.gg hackathon"
title: "[🕹️]"
labels: 🕹️ oss.gg, player submission, hacktoberfest
assignees: []
body:
- type: textarea
id: contribution-name
attributes:
label: What side quest or challenge are you solving?
description: Add the name of the side quest or challenge.
validations:
required: true
- type: textarea
id: points
attributes:
label: Points
description: How many points are assigned to this contribution?
validations:
required: true
- type: textarea
id: description
attributes:
label: Description
description: What's the task your performed?
validations:
- type: textarea
id: proof
attributes:
label: Provide proof that you've completed the task
description: Screenshots, loom recordings, links to the content you shared or interacted with.
validations:
required: true
+1
View File
@@ -5,6 +5,7 @@ on:
- main
jobs:
deploy-main:
timeout-minutes: 3
runs-on: ubuntu-latest
steps:
- name: Repository Dispatch
+1
View File
@@ -5,6 +5,7 @@ on:
- 'v*'
jobs:
deploy-tag:
timeout-minutes: 3
runs-on: ubuntu-latest
steps:
- name: Repository Dispatch
+21 -6
View File
@@ -3,19 +3,16 @@ on:
push:
branches:
- main
paths:
- 'package.json'
- 'packages/twenty-chrome-extension/**'
pull_request:
paths:
- 'package.json'
- 'packages/twenty-chrome-extension/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
chrome-extension-build:
timeout-minutes: 15
runs-on: ubuntu-latest
env:
VITE_SERVER_BASE_URL: http://localhost:3000
@@ -26,7 +23,25 @@ jobs:
with:
access_token: ${{ github.token }}
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check for changed files
id: changed-files
uses: tj-actions/changed-files@v11
with:
files: |
package.json
packages/twenty-chrome-extension/**
- name: Install dependencies
if: steps.changed-files.outputs.any_changed == 'true'
uses: ./.github/workflows/actions/yarn-install
- name: Chrome Extension / Run build
if: steps.changed-files.outputs.any_changed == 'true'
run: npx nx build twenty-chrome-extension
- name: Mark as Valid if No Changes
if: steps.changed-files.outputs.changed != 'true'
run: |
echo "No relevant changes detected. Marking as valid."
+52
View File
@@ -0,0 +1,52 @@
name: CI E2E Tests
on:
push:
branches:
- main
pull_request:
branches:
- '**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
timeout-minutes: 30
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: lts/*
- name: Check for changed files
id: changed-files
uses: tj-actions/changed-files@v11
with:
files: |
packages/**
playwright.config.ts
- name: Skip if no relevant changes
if: steps.changed-files.outputs.any_changed == 'false'
run: echo "No relevant changes detected. Marking as valid."
- name: Install dependencies
if: steps.changed-files.outputs.any_changed == 'true'
uses: ./.github/workflows/actions/yarn-install
- name: Install Playwright Browsers
if: steps.changed-files.outputs.any_changed == 'true'
run: yarn playwright install --with-deps
- name: Run Playwright tests
if: steps.changed-files.outputs.any_changed == 'true'
run: yarn test:e2e companies
- uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report
path: playwright-report/
retention-days: 30
+97 -12
View File
@@ -3,21 +3,16 @@ on:
push:
branches:
- main
paths:
- 'package.json'
- 'packages/twenty-front/**'
- 'packages/twenty-ui/**'
pull_request:
paths:
- 'package.json'
- 'packages/twenty-front/**'
- 'packages/twenty-ui/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
front-sb-build:
timeout-minutes: 30
runs-on: ubuntu-latest
env:
REACT_APP_SERVER_BASE_URL: http://localhost:3000
@@ -29,21 +24,43 @@ jobs:
access_token: ${{ github.token }}
- name: Fetch local actions
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check for changed files
id: changed-files
uses: tj-actions/changed-files@v11
with:
files: |
package.json
packages/twenty-front/**
packages/twenty-ui/**
- name: Skip if no relevant changes
if: steps.changed-files.outputs.any_changed == 'false'
run: echo "No relevant changes. Skipping CI."
- name: Install dependencies
if: steps.changed-files.outputs.any_changed == 'true'
uses: ./.github/workflows/actions/yarn-install
- name: Diagnostic disk space issue
if: steps.changed-files.outputs.any_changed == 'true'
run: df -h
- name: Front / Restore Storybook Task Cache
if: steps.changed-files.outputs.any_changed == 'true'
uses: ./.github/workflows/actions/task-cache
with:
tag: scope:frontend
tasks: storybook:build
- name: Front / Write .env
if: steps.changed-files.outputs.any_changed == 'true'
run: npx nx reset:env twenty-front
- name: Front / Build storybook
if: steps.changed-files.outputs.any_changed == 'true'
run: npx nx storybook:build twenty-front
front-sb-test:
runs-on: ci-8-cores
timeout-minutes: 30
runs-on: shipfox-8vcpu-ubuntu-2204
needs: front-sb-build
strategy:
matrix:
@@ -54,36 +71,72 @@ jobs:
steps:
- name: Fetch local actions
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check for changed files
id: changed-files
uses: tj-actions/changed-files@v11
with:
files: |
packages/twenty-front/**
- name: Skip if no relevant changes
if: steps.changed-files.outputs.any_changed == 'false'
run: echo "No relevant changes. Skipping CI."
- name: Install dependencies
if: steps.changed-files.outputs.any_changed == 'true'
uses: ./.github/workflows/actions/yarn-install
- name: Install Playwright
if: steps.changed-files.outputs.any_changed == 'true'
run: cd packages/twenty-front && npx playwright install
- name: Front / Restore Storybook Task Cache
if: steps.changed-files.outputs.any_changed == 'true'
uses: ./.github/workflows/actions/task-cache
with:
tag: scope:frontend
tasks: storybook:build
- name: Front / Write .env
if: steps.changed-files.outputs.any_changed == 'true'
run: npx nx reset:env twenty-front
- name: Run storybook tests
if: steps.changed-files.outputs.any_changed == 'true'
run: npx nx storybook:serve-and-test:static twenty-front --configuration=${{ matrix.storybook_scope }}
front-sb-test-performance:
runs-on: ci-8-cores
timeout-minutes: 30
runs-on: shipfox-8vcpu-ubuntu-2204
env:
REACT_APP_SERVER_BASE_URL: http://localhost:3000
NX_REJECT_UNKNOWN_LOCAL_CACHE: 0
steps:
- name: Fetch local actions
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check for changed files
id: changed-files
uses: tj-actions/changed-files@v11
with:
files: |
packages/twenty-front/**
- name: Skip if no relevant changes
if: steps.changed-files.outputs.any_changed == 'false'
run: echo "No relevant changes. Skipping CI."
- name: Install dependencies
if: steps.changed-files.outputs.any_changed == 'true'
uses: ./.github/workflows/actions/yarn-install
- name: Install Playwright
if: steps.changed-files.outputs.any_changed == 'true'
run: cd packages/twenty-front && npx playwright install
- name: Front / Write .env
if: steps.changed-files.outputs.any_changed == 'true'
run: npx nx reset:env twenty-front
- name: Run storybook tests
run: npx nx storybook:serve-and-test:static:performance twenty-front
if: steps.changed-files.outputs.any_changed == 'true'
run: npx nx run twenty-front:storybook:serve-and-test:static:performance
front-chromatic-deployment:
timeout-minutes: 30
if: contains(github.event.pull_request.labels.*.name, 'run-chromatic') || github.event_name == 'push'
needs: front-sb-build
runs-on: ubuntu-latest
@@ -95,21 +148,38 @@ jobs:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check for changed files
id: changed-files
uses: tj-actions/changed-files@v11
with:
files: |
packages/twenty-front/**
- name: Skip if no relevant changes
if: steps.changed-files.outputs.any_changed == 'false'
run: echo "No relevant changes. Skipping CI."
- name: Install dependencies
if: steps.changed-files.outputs.any_changed == 'true'
uses: ./.github/workflows/actions/yarn-install
- name: Front / Restore Storybook Task Cache
if: steps.changed-files.outputs.any_changed == 'true'
uses: ./.github/workflows/actions/task-cache
with:
tag: scope:frontend
tasks: storybook:build
- name: Front / Write .env
if: steps.changed-files.outputs.any_changed == 'true'
run: |
cd packages/twenty-front
touch .env
echo "REACT_APP_SERVER_BASE_URL: $REACT_APP_SERVER_BASE_URL" >> .env
- name: Publish to Chromatic
if: steps.changed-files.outputs.any_changed == 'true'
run: npx nx run twenty-front:chromatic:ci
front-task:
timeout-minutes: 30
runs-on: ubuntu-latest
env:
NX_REJECT_UNKNOWN_LOCAL_CACHE: 0
@@ -125,20 +195,35 @@ jobs:
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check for changed files
id: changed-files
uses: tj-actions/changed-files@v11
with:
files: |
packages/twenty-front/**
- name: Skip if no relevant changes
if: steps.changed-files.outputs.any_changed == 'false'
run: echo "No relevant changes. Skipping CI."
- name: Install dependencies
if: steps.changed-files.outputs.any_changed == 'true'
uses: ./.github/workflows/actions/yarn-install
- name: Front / Restore ${{ matrix.task }} task cache
if: steps.changed-files.outputs.any_changed == 'true'
uses: ./.github/workflows/actions/task-cache
with:
tag: scope:frontend
tasks: ${{ matrix.task }}
- name: Reset .env
if: steps.changed-files.outputs.any_changed == 'true'
uses: ./.github/workflows/actions/nx-affected
with:
tag: scope:frontend
tasks: reset:env
- name: Run ${{ matrix.task }} task
if: steps.changed-files.outputs.any_changed == 'true'
uses: ./.github/workflows/actions/nx-affected
with:
tag: scope:frontend
tasks: ${{ matrix.task }}
tasks: ${{ matrix.task }}
+1
View File
@@ -15,6 +15,7 @@ on:
jobs:
create_pr:
timeout-minutes: 10
runs-on: ubuntu-latest
steps:
- name: Checkout
+1
View File
@@ -6,6 +6,7 @@ on:
jobs:
tag_and_release:
timeout-minutes: 10
runs-on: ubuntu-latest
if: github.event.pull_request.merged == true && contains(github.event.pull_request.labels.*.name, 'release')
steps:
+73 -15
View File
@@ -3,32 +3,34 @@ on:
push:
branches:
- main
paths:
- 'package.json'
- 'packages/twenty-server/**'
- 'packages/twenty-emails/**'
pull_request:
paths:
- 'package.json'
- 'packages/twenty-server/**'
- 'packages/twenty-emails/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
server-setup:
timeout-minutes: 30
runs-on: ubuntu-latest
env:
NX_REJECT_UNKNOWN_LOCAL_CACHE: 0
services:
postgres:
image: twentycrm/twenty-postgres
image: twentycrm/twenty-postgres-spilo
env:
POSTGRES_PASSWORD: postgres
POSTGRES_USER: postgres
PGUSER_SUPERUSER: postgres
PGPASSWORD_SUPERUSER: twenty
ALLOW_NOSSL: "true"
SPILO_PROVIDER: "local"
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
redis:
image: redis
ports:
@@ -38,25 +40,47 @@ jobs:
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check for changed files
id: changed-files
uses: tj-actions/changed-files@v11
with:
files: |
package.json
packages/twenty-server/**
packages/twenty-emails/**
- name: Install dependencies
if: steps.changed-files.outputs.any_changed == 'true'
uses: ./.github/workflows/actions/yarn-install
- name: Server / Restore Task Cache
if: steps.changed-files.outputs.any_changed == 'true'
uses: ./.github/workflows/actions/task-cache
with:
tag: scope:backend
- name: Server / Run lint & typecheck
if: steps.changed-files.outputs.any_changed == 'true'
uses: ./.github/workflows/actions/nx-affected
with:
tag: scope:backend
tasks: lint,typecheck
- name: Server / Build
if: steps.changed-files.outputs.any_changed == 'true'
run: npx nx build twenty-server
- name: Server / Write .env
if: steps.changed-files.outputs.any_changed == 'true'
run: npx nx reset:env twenty-server
- name: Server / Create DB
if: steps.changed-files.outputs.any_changed == 'true'
run: |
PGPASSWORD=twenty psql -h localhost -p 5432 -U postgres -d postgres -c 'CREATE DATABASE "default";'
PGPASSWORD=twenty psql -h localhost -p 5432 -U postgres -d postgres -c 'CREATE DATABASE "test";'
- name: Worker / Run
if: steps.changed-files.outputs.any_changed == 'true'
run: npx nx run twenty-server:worker:ci
server-test:
timeout-minutes: 30
runs-on: ubuntu-latest
needs: server-setup
env:
@@ -66,29 +90,50 @@ jobs:
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check for changed files
id: changed-files
uses: tj-actions/changed-files@v11
with:
files: |
package.json
packages/twenty-server/**
packages/twenty-emails/**
- name: Install dependencies
if: steps.changed-files.outputs.any_changed == 'true'
uses: ./.github/workflows/actions/yarn-install
- name: Server / Restore Task Cache
if: steps.changed-files.outputs.any_changed == 'true'
uses: ./.github/workflows/actions/task-cache
with:
tag: scope:backend
- name: Server / Run Tests
if: steps.changed-files.outputs.any_changed == 'true'
uses: ./.github/workflows/actions/nx-affected
with:
tag: scope:backend
tasks: test
server-integration-test:
timeout-minutes: 30
runs-on: ubuntu-latest
needs: server-setup
services:
postgres:
image: twentycrm/twenty-postgres
image: twentycrm/twenty-postgres-spilo
env:
POSTGRES_PASSWORD: postgres
POSTGRES_USER: postgres
PGUSER_SUPERUSER: postgres
PGPASSWORD_SUPERUSER: twenty
ALLOW_NOSSL: "true"
SPILO_PROVIDER: "local"
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
redis:
image: redis
ports:
@@ -100,17 +145,30 @@ jobs:
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check for changed files
id: changed-files
uses: tj-actions/changed-files@v11
with:
files: |
package.json
packages/twenty-server/**
packages/twenty-emails/**
- name: Install dependencies
if: steps.changed-files.outputs.any_changed == 'true'
uses: ./.github/workflows/actions/yarn-install
- name: Server / Restore Task Cache
if: steps.changed-files.outputs.any_changed == 'true'
uses: ./.github/workflows/actions/task-cache
with:
tag: scope:backend
- name: Server / Run Integration Tests
if: steps.changed-files.outputs.any_changed == 'true'
uses: ./.github/workflows/actions/nx-affected
with:
tag: scope:backend
tasks: "test:integration"
tasks: "test:integration:with-db-reset"
- name: Server / Upload reset-logs file
if: always()
uses: actions/upload-artifact@v4
+44 -11
View File
@@ -1,20 +1,31 @@
name: 'Test Docker Compose'
on:
pull_request:
paths:
- 'packages/twenty-docker/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
timeout-minutes: 30
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Check for changed files
id: changed-files
uses: tj-actions/changed-files@v11
with:
files: |
packages/twenty-docker/**
docker-compose.yml
- name: Skip if no relevant changes
if: steps.changed-files.outputs.any_changed != 'true'
run: echo "No relevant changes detected. Marking as valid."
- name: Run compose
if: steps.changed-files.outputs.any_changed == 'true'
run: |
echo "Patching docker-compose.yml..."
# change image to localbuild using yq
@@ -25,23 +36,42 @@ jobs:
yq eval 'del(.services.db.image)' -i docker-compose.yml
yq eval '.services.db.build.context = "../../"' -i docker-compose.yml
yq eval '.services.db.build.dockerfile = "./packages/twenty-docker/twenty-postgres/Dockerfile"' -i docker-compose.yml
yq eval '.services.db.build.dockerfile = "./packages/twenty-docker/twenty-postgres-spilo/Dockerfile"' -i docker-compose.yml
echo "Setting up .env file..."
cp .env.example .env
echo "Generating secrets..."
echo "# === Randomly generated secrets ===" >>.env
echo "ACCESS_TOKEN_SECRET=$(openssl rand -base64 32)" >>.env
echo "LOGIN_TOKEN_SECRET=$(openssl rand -base64 32)" >>.env
echo "REFRESH_TOKEN_SECRET=$(openssl rand -base64 32)" >>.env
echo "FILE_TOKEN_SECRET=$(openssl rand -base64 32)" >>.env
echo "POSTGRES_ADMIN_PASSWORD=$(openssl rand -base64 32)" >>.env
echo "APP_SECRET=$(openssl rand -base64 32)" >>.env
echo "PGPASSWORD_SUPERUSER=$(openssl rand -base64 32)" >>.env
echo "Starting server..."
docker compose up -d
echo "Docker compose up..."
docker compose up -d || {
echo "Docker compose failed to start"
docker compose logs
exit 1
}
docker compose logs db server -f &
pid=$!
echo "Waiting for database to start..."
count=0
while [ ! $(docker inspect --format='{{.State.Health.Status}}' twenty-db-1) = "healthy" ]; do
sleep 1;
count=$((count+1));
if [ $(docker inspect --format='{{.State.Status}}' twenty-db-1) = "exited" ]; then
echo "Database exited"
docker compose logs db
exit 1
fi
if [ $count -gt 300 ]; then
echo "Failed to start database after 5 minutes"
docker compose logs db
exit 1
fi
echo "Still waiting for database... (${count}/60)"
done
echo "Waiting for server to start..."
count=0
while [ ! $(docker inspect --format='{{.State.Health.Status}}' twenty-server-1) = "healthy" ]; do
@@ -49,11 +79,14 @@ jobs:
count=$((count+1));
if [ $(docker inspect --format='{{.State.Status}}' twenty-server-1) = "exited" ]; then
echo "Server exited"
docker compose logs server
exit 1
fi
if [ $count -gt 300 ]; then
echo "Failed to start server"
echo "Failed to start server after 5 minutes"
docker compose logs server
exit 1
fi
echo "Still waiting for server... (${count}/300s)"
done
working-directory: ./packages/twenty-docker/
+26
View File
@@ -0,0 +1,26 @@
name: CI Tinybird
on:
push:
branches:
- main
paths:
- 'package.json'
- 'packages/twenty-tinybird/**'
pull_request:
paths:
- 'package.json'
- 'packages/twenty-tinybird/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
ci:
uses: tinybirdco/ci/.github/workflows/ci.yml@main
with:
data_project_dir: packages/twenty-tinybird
secrets:
tb_admin_token: ${{ secrets.TB_ADMIN_TOKEN }}
tb_host: https://api.eu-central-1.aws.tinybird.co
+5 -1
View File
@@ -15,10 +15,13 @@ permissions:
statuses: write
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
# We don't cancel in-progress because this workflow is triggered on
# pull_request_target, which means the ref can be the same accross two PRs.
# cancel-in-progress: true
jobs:
danger-js:
timeout-minutes: 3
runs-on: ubuntu-latest
if: github.event.action != 'closed'
steps:
@@ -31,6 +34,7 @@ jobs:
DANGER_GITHUB_API_TOKEN: ${{ github.token }}
congratulate:
timeout-minutes: 3
runs-on: ubuntu-latest
if: github.event.action == 'closed' && github.event.pull_request.merged == true
steps:
+36 -11
View File
@@ -3,37 +3,62 @@ on:
push:
branches:
- main
paths:
- 'package.json'
- 'packages/twenty-website/**'
pull_request:
paths:
- 'package.json'
- 'packages/twenty-website/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
website-build:
timeout-minutes: 3
runs-on: ubuntu-latest
services:
postgres:
image: twentycrm/twenty-postgres
image: twentycrm/twenty-postgres-spilo
env:
POSTGRES_PASSWORD: twenty
POSTGRES_USER: twenty
PGUSER_SUPERUSER: postgres
PGPASSWORD_SUPERUSER: twenty
ALLOW_NOSSL: "true"
SPILO_PROVIDER: "local"
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check for changed files
id: changed-files
uses: tj-actions/changed-files@v11
with:
files: 'package.json, packages/twenty-website/**'
- name: Install dependencies
if: steps.changed-files.outputs.changed == 'true'
uses: ./.github/workflows/actions/yarn-install
- name: Server / Create DB
if: steps.changed-files.outputs.any_changed == 'true'
run: PGPASSWORD=twenty psql -h localhost -p 5432 -U postgres -d postgres -c 'CREATE DATABASE "default";'
- name: Website / Run migrations
if: steps.changed-files.outputs.changed == 'true'
run: npx nx database:migrate twenty-website
env:
DATABASE_PG_URL: postgres://twenty:twenty@localhost:5432/default
DATABASE_PG_URL: postgres://postgres:twenty@localhost:5432/default
- name: Website / Build Website
if: steps.changed-files.outputs.changed == 'true'
run: npx nx build twenty-website
env:
DATABASE_PG_URL: postgres://twenty:twenty@localhost:5432/default
DATABASE_PG_URL: postgres://postgres:twenty@localhost:5432/default
- name: Mark as VALID
if: steps.changed-files.outputs.changed != 'true' # If no changes, mark as valid
run: echo "No relevant changes detected. CI is valid."
-27
View File
@@ -1,27 +0,0 @@
name: Playwright Tests
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: lts/*
- name: Install dependencies
run: npm install -g yarn && yarn
- name: Install Playwright Browsers
run: yarn playwright install --with-deps
- name: Run Playwright tests
run: yarn test:e2e companies
- uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report
path: playwright-report/
retention-days: 30
+1
View File
@@ -29,3 +29,4 @@ storybook-static
.nyc_output
test-results/
dump.rdb
.tinyb
+1 -1
View File
@@ -45,5 +45,5 @@
"search.exclude": {
"**/.yarn": true,
},
"eslint.debug": true
"eslint.debug": true,
}
-4
View File
@@ -24,10 +24,6 @@
"name": "packages/twenty-emails",
"path": "../packages/twenty-emails"
},
{
"name": "packages/twenty-postgres",
"path": "../packages/twenty-postgres"
},
{
"name": "packages/twenty-server",
"path": "../packages/twenty-server"
+49
View File
@@ -1,3 +1,8 @@
This project is mostly licensed under the GNU General Public License (GPL) as described below. However, certain files within this project are licensed under a different commercial license. These files are clearly marked with the following comment at the top of the file: /* @license Enterprise */
Files with this comment are not licensed under the aGPL v3, but instead are subject to the commercial license terms defined later in this file.
GNU AFFERO GENERAL PUBLIC LICENSE
Version 3, 19 November 2007
@@ -659,3 +664,47 @@ specific requirements.
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU AGPL, see
<https://www.gnu.org/licenses/>.
------------------------------------
The Twenty.com Commercial License (the “Commercial License”)
Copyright (c) 2023-present Twenty.com, PBC
With regard to Twenty's Software:
This part of the software and associated documentation files (the "Software") may only be
used in production, if you (and any entity that you represent) have agreed to,
and are in compliance with, the Terms available
at https://twenty.com/legal/terms, or other agreements governing
the use of the Software, as mutually agreed by you and Twenty.com, PBC ("Twenty"),
and otherwise have a valid Twenty Enterprise Edition subscription
for the correct number of hosts and seats as defined in the Commercial Terms.
Subject to the foregoing sentence,
you are free to modify this Software and publish patches to the Software. You agree
that Twenty and/or its licensors (as applicable) retain all right, title and interest in
and to all such modifications and/or patches, and all such modifications and/or
patches may only be used, copied, modified, displayed, distributed, or otherwise
exploited with a valid Commercial Subscription for the correct number of hosts and seats.
Notwithstanding the foregoing, you may copy and modify the Software for development
and testing purposes, without requiring a subscription. You agree that Twenty.Com and/or
its licensors (as applicable) retain all right, title and interest in and to all such
modifications. You are not granted any other rights beyond what is expressly stated herein.
Subject to the foregoing, it is forbidden to copy, merge, publish, distribute, sublicense,
and/or sell the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
For all third party components incorporated into the Twenty Software, those
components are licensed under the original license provided by the owner of the
applicable component.
+18 -24
View File
@@ -1,26 +1,20 @@
docker-dev-build:
make -C packages/twenty-docker dev-build
docker-dev-up:
make -C packages/twenty-docker dev-up
docker-dev-start:
make -C packages/twenty-docker dev-start
docker-dev-stop:
make -C packages/twenty-docker dev-stop
docker-dev-sh:
make -C packages/twenty-docker dev-sh
postgres-on-docker:
make -C packages/twenty-postgres provision-on-docker
docker run -d \
--name twenty_pg \
-e PGUSER_SUPERUSER=postgres \
-e PGPASSWORD_SUPERUSER=twenty \
-e ALLOW_NOSSL=true \
-v twenty_db_data:/home/postgres/pgdata \
-p 5432:5432 \
twentycrm/twenty-postgres-spilo:latest
@echo "Waiting for PostgreSQL to be ready..."
@until PGPASSWORD=twenty psql -h localhost -p 5432 -U postgres -d postgres \
-c 'SELECT pg_is_in_recovery();' 2>/dev/null | grep -q 'f'; do \
sleep 1; \
done
PGPASSWORD=twenty psql -h localhost -p 5432 -U postgres -d postgres \
-c "CREATE DATABASE \"default\" WITH OWNER postgres;" \
-c "CREATE DATABASE \"test\" WITH OWNER postgres;"
postgres-on-macos-arm:
make -C packages/twenty-postgres provision-on-macos-arm
postgres-on-macos-intel:
make -C packages/twenty-postgres provision-on-macos-intel
postgres-on-linux:
make -C packages/twenty-postgres provision-on-linux
redis-on-docker:
docker run -d --name twenty_redis -p 6379:6379 redis/redis-stack-server:latest
-9
View File
@@ -1,12 +1,3 @@
<p align="center">
<a href="https://oss.gg/">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://github.com/twentyhq/twenty/blob/33be2dbbe14eea00445010ecb9cd53ed603c01d5/packages/twenty-website/public/images/readme/Github%20Read-me%20banner.png">
<source media="(prefers-color-scheme: light)" srcset="https://github.com/twentyhq/twenty/blob/33be2dbbe14eea00445010ecb9cd53ed603c01d5/packages/twenty-website/public/images/readme/Github%20Read-me%20banner.png">
<img src="./packages/twenty-website/public/images/readme/Github%20Read-me%20banner.png" alt="Hacktoberfest" />
</picture>
</a>
</p>
<br>
<p align="center">
Executable → Regular
+5 -6
View File
@@ -45,7 +45,7 @@ trap on_exit EXIT
# Use environment variables VERSION and BRANCH, with defaults if not set
version=${VERSION:-$(curl -s https://api.github.com/repos/twentyhq/twenty/releases/latest | grep '"tag_name":' | cut -d '"' -f 4)}
branch=${BRANCH:-main}
branch=${BRANCH:-$version}
echo "🚀 Using version $version and branch $branch"
@@ -72,7 +72,7 @@ done
echo "📁 Creating directory '$dir_name'"
mkdir -p "$dir_name" && cd "$dir_name" || { echo "❌ Failed to create/access directory '$dir_name'"; exit 1; }
# Copy the twenty/packages/twenty-docker/docker-compose.yml file in it
# Copy twenty/packages/twenty-docker/docker-compose.yml in it
echo -e "\t• Copying docker-compose.yml"
curl -sLo docker-compose.yml https://raw.githubusercontent.com/twentyhq/twenty/$branch/packages/twenty-docker/docker-compose.yml
@@ -91,10 +91,9 @@ fi
# Generate random strings for secrets
echo "# === Randomly generated secrets ===" >>.env
echo "ACCESS_TOKEN_SECRET=$(openssl rand -base64 32)" >>.env
echo "LOGIN_TOKEN_SECRET=$(openssl rand -base64 32)" >>.env
echo "REFRESH_TOKEN_SECRET=$(openssl rand -base64 32)" >>.env
echo "FILE_TOKEN_SECRET=$(openssl rand -base64 32)" >>.env
echo "APP_SECRET=$(openssl rand -base64 32)" >>.env
echo "" >>.env
echo "PGPASSWORD_SUPERUSER=$(openssl rand -hex 16)" >>.env
echo "" >>.env
echo "POSTGRES_ADMIN_PASSWORD=$(openssl rand -base64 32)" >>.env
+2 -12
View File
@@ -108,12 +108,11 @@
"storybook:build": {
"executor": "nx:run-commands",
"cache": true,
"dependsOn": ["^build"],
"inputs": ["^default", "excludeTests"],
"outputs": ["{projectRoot}/{options.output-dir}"],
"options": {
"cwd": "{projectRoot}",
"command": "storybook build",
"command": "VITE_DISABLE_ESLINT_CHECKER=true storybook build",
"output-dir": "storybook-static",
"config-dir": ".storybook"
}
@@ -192,16 +191,7 @@
"executor": "nx:run-commands",
"options": {
"commands": [
"npx concurrently --kill-others --success=first -n SB,TEST 'nx storybook:serve:static {projectName} --port={args.port}' 'npx wait-on tcp:{args.port} && nx storybook:test {projectName} --port={args.port}'"
],
"port": 6006
}
},
"storybook:serve-and-test:static:performance": {
"executor": "nx:run-commands",
"options": {
"commands": [
"npx concurrently --kill-others --success=first -n SB,TEST 'nx storybook:serve:dev {projectName} --configuration=performance --port={args.port}' 'npx wait-on tcp:{args.port} && nx storybook:test:no-coverage {projectName} --port={args.port} --configuration=performance'"
"npx concurrently --kill-others --success=first -n SB,TEST 'nx storybook:serve:static {projectName} --port={args.port} --configuration={args.performance}' 'npx wait-on tcp:{args.port} && nx storybook:test {projectName} --port={args.port} --configuration={args.scope}'"
],
"port": 6006
}
@@ -1,21 +0,0 @@
**Side Quest**: Create a YouTube Video about Twenty showcasing a specific way to use Twenty effectively.
**Points**: 750 Points
**Proof**: Add your oss handle and YouTube video link to the list below.
Please follow the following schema:
---
» 05-April-2024 by YOUR oss.gg HANDLE » YouTube Link: https://link.to/content
---
////////////////////////////
Your turn 👇
////////////////////////////
» 02-October-2024 by [yourhandle](https://oss.gg/yourhandle) YouTube Link: [YouTube](https://twenty.com/)
---
@@ -1,21 +0,0 @@
**Side Quest**: Write a blog post about sharing your experience using Twenty in a detailed format on any platform.
**Points**: 750 Points
**Proof**: Add your oss handle and blog link to the list below.
Please follow the following schema:
---
» 05-April-2024 by YOUR oss.gg HANDLE » blog Link: https://link.to/content
---
////////////////////////////
Your turn 👇
////////////////////////////
» 02-October-2024 by [yourhandle](https://oss.gg/yourhandle) blog Link: [blog](https://twenty.com/)
---
@@ -1,21 +0,0 @@
**Side Quest**: Write a blog post about self-hosting Twenty in a detailed format on any platform.
**Points**: 750 Points
**Proof**: Add your oss handle and blog link to the list below.
Please follow the following schema:
---
» 05-April-2024 by YOUR oss.gg HANDLE » blog Link: https://link.to/content
---
////////////////////////////
Your turn 👇
////////////////////////////
» 02-October-2024 by [yourhandle](https://oss.gg/yourhandle) blog Link: [blog](https://twenty.com/)
---
@@ -1,21 +0,0 @@
**Side Quest**: Create a promotional video for Twenty and share it on social media.
**Points**: 750 Points
**Proof**: Add your oss handle and video link to the list below.
Please follow the following schema:
---
» 05-April-2024 by YOUR oss.gg HANDLE » video Link: https://link.to/content
---
////////////////////////////
Your turn 👇
////////////////////////////
» 02-October-2024 by [yourhandle](https://oss.gg/yourhandle) video Link: [video](https://twenty.com/)
---
@@ -1,23 +0,0 @@
**Side Quest**: Design a promotional poster of Twenty and share it on social media.
**Points**: 300 Points
**Proof**: Add your oss handle and poster link to the list below.
Please follow the following schema:
---
» 05-April-2024 by YOUR oss.gg HANDLE » poster Link: https://link.to/content
---
////////////////////////////
Your turn 👇
////////////////////////////
» 02-October-2024 by [yourhandle](https://oss.gg/yourhandle) poster Link: [poster](https://twenty.com/)
» 11-October-2024 by [thefool76](https://oss.gg/thefool76) poster Link: [poster](https://drive.google.com/file/d/1cIC1eitvY6zKVTXKq2LnVrS_2Ho9H8-P/view?usp=sharing)
---
@@ -1,24 +0,0 @@
**Side Quest**: Design/Create new Twenty logo, tweet your design, and mention @twentycrm.
**Points**: 300 Points
**Proof**: Create a logo uploade it on any of the platform and add your oss handle and logo link to the list below.
Please follow the following schema:
---
» 05-April-2024 by YOUR oss.gg HANDLE » Logo Link: https://link.to/content » tweet Link: https://link.to/content
---
////////////////////////////
Your turn 👇
////////////////////////////
» 08-October-2024 by [adityadeshlahre](https://oss.gg/adityadeshlahre) Logo Link: [logo](https://drive.google.com/drive/folders/13k22xMnX2fhnWK94vas_hO1t-ImqXcHZ?usp=drive_link) » tweet Link: [tweet](https://x.com/adityadeshlahre/status/1843354963176718374)
» 11-October-2024 by [thefool76](https://oss.gg/thefool76) Logo Link: [logo](https://drive.google.com/file/d/1DxSwNY_i90kGgWzPQj5SxScBz_6r02l4/view?usp=sharing) » tweet Link: [tweet](https://x.com/thefool1135/status/1844693487067034008)
---
@@ -1,21 +0,0 @@
**Side Quest**: Duplicate the Figma file from the main repo and customize the variables to create a unique interface theme for Twenty.
**Points**: 750 Points
**Proof**: Add your oss handle and Figma link to the list below.
Please follow the following schema:
---
» 05-April-2024 by YOUR oss.gg HANDLE » Figma Link: https://link.to/content
---
////////////////////////////
Your turn 👇
////////////////////////////
» 02-October-2024 by [yourhandle](https://oss.gg/yourhandle) Figma Link: [Figma](https://twenty.com/)
---
@@ -1,21 +0,0 @@
**Side Quest**: Develop a script to facilitate the migration of data from another CRM to Twenty.
**Points**: 750 Points
**Proof**: Add your oss handle and record video and share link to the list below. In video show the working proof of your created script.
Please follow the following schema:
---
» 05-April-2024 by YOUR oss.gg HANDLE » video Link: https://link.to/content
---
////////////////////////////
Your turn 👇
////////////////////////////
» 02-October-2024 by [yourhandle](https://oss.gg/yourhandle) video Link: [video](https://twenty.com/)
---
@@ -1,21 +0,0 @@
**Side Quest**: Develop an integration for Raycast that enables users to create records on any object within Twenty directly from Raycast.
**Points**: 1500 Points
**Proof**: Add your oss handle and record video and share link to the list below. In video show the workflow of the your integration created and perform some task.
Please follow the following schema:
---
» 05-April-2024 by YOUR oss.gg HANDLE » video Link: https://link.to/content
---
////////////////////////////
Your turn 👇
////////////////////////////
» 02-October-2024 by [yourhandle](https://oss.gg/yourhandle) video Link: [video](https://twenty.com/)
---
@@ -1,21 +0,0 @@
**Side Quest**: Create an n8n workflow that empowers Twenty by connecting it to another tool.
**Points**: 750 Points
**Proof**: Add your oss handle and template link to the list below.
Please follow the following schema:
---
» 05-April-2024 by YOUR oss.gg HANDLE » template Link: https://link.to/content
---
////////////////////////////
Your turn 👇
////////////////////////////
» 02-October-2024 by [yourhandle](https://oss.gg/yourhandle) template Link: [template](https://twenty.com/)
---
@@ -1,21 +0,0 @@
**Side Quest**: Write a comprehensive guide on how to integrate Twenty with marketing automation tool (n8n, Zapier). Include a concrete use case and explain how to leverage AI to write API requests for non-developers and share it.
**Points**: 1500 Points
**Proof**: Add your oss handle and guide link to the list below.
Please follow the following schema:
---
» 05-April-2024 by YOUR oss.gg HANDLE » guide Link: https://link.to/content
---
////////////////////////////
Your turn 👇
////////////////////////////
» 02-October-2024 by [yourhandle](https://oss.gg/yourhandle) guide Link: [guide](https://twenty.com/)
---
@@ -1,30 +0,0 @@
**Side Quest**: Like & Re-Tweet oss.gg Launch Tweet. Quote-tweet it tagging @twentycrm to say youll be contributing.
**Points**: 50 Points
**Proof**: Add a screenshot of the retweet to the PR description. Add a link to your retweet in the list below.
Please follow the following schema:
---
» 05-April-2024 by YOUR NAME
» Link to Tweet: https://x.com/...
---
////////////////////////////
Your turn 👇
////////////////////////////
» 10-October-2024 by Devansh Baghel
» Link to Tweet: https://x.com/DevanshBaghel5/status/1844359648037748954
» 11-October-2024 by Bhavesh Mishra
» Link to Tweet: https://x.com/thefool1135/status/1844453425188405326
» 11-October-2024 by Chirag Arora
» Link to Tweet: https://x.com/Chirag8023/status/1844689900668682699
» 11-October-2024 by Aritra Sadhukhan
» Link to Tweet: https://x.com/AritraDevelops/status/1844670236512878646
@@ -1,26 +0,0 @@
**Side Quest**: Share a tweet about your favorite feature in Twenty. Tweet about your favorite feature in Twenty and mention @twentycrm.
**Points**: 50 Points
**Proof**: Add a screenshot of the tweet to the PR description. Add a link to your tweet in the list below.
Please follow the following schema:
---
» 05-April-2024 by YOUR NAME
» Link to Tweet: https://x.com/...
---
////////////////////////////
Your turn 👇
////////////////////////////
» 10-October-2024 by Devansh Baghel
» Link to Tweet: https://x.com/DevanshBaghel5/status/1844384722119704972
» 11-October-2024 by Bhavesh Mishra
» Link to Tweet: https://x.com/thefool1135/status/1844456500380696969
---
-23
View File
@@ -1,23 +0,0 @@
**Side Quest**: Create a bug report. Use the Twenty bug issue template to report a bug in detail, including steps to reproduce it.
**Points**: 50-150 Points
**Proof**: Add a link to your bug report in the list below.
Please follow the following schema:
---
» 05-April-2024 by YOUR NAME
» Link to bug report: https://github.com/twentyhq/twenty/issues/...
---
////////////////////////////
Your turn 👇
////////////////////////////
» 10-October-2024 by Devansh Baghel
» Link to bug report: https://github.com/twentyhq/twenty/issues/7560
---
-26
View File
@@ -1,26 +0,0 @@
**Side Quest**: Meme Magic: Craft a meme where the number twenty plays a role. Tweet it, and tag @twentycrm.
**Points**: 150 Points
**Proof**: Add a screenshot of meme to the PR description. Add a link to your tweet in the list below.
Please follow the following schema:
---
» 05-April-2024 by YOUR NAME
» Link to Tweet: https://x.com/...
---
////////////////////////////
Your turn 👇
////////////////////////////
» 10-October-2024 by Teddy ASSIH
» Link to Tweet: https://x.com/ion_finisher/status/1844389252253299173
» 11-October-2024 by Bhavesh Mishra
» Link to Tweet: https://x.com/thefool1135/status/1844458836402503931
---
-26
View File
@@ -1,26 +0,0 @@
**Side Quest**: Gif Magic: Create a gif related to Twenty. Tweet it, and tag @twentycrm.
**Points**: 150 Points
**Proof**: Add a screenshot of GIF on Giphy to the PR description. Add a link to your GIPHY in the list below.
Please follow the following schema:
---
» 05-April-2024 by YOUR NAME
» Link to gif: https://giphy.com/...
---
////////////////////////////
Your turn 👇
////////////////////////////
» 10-October-2024 by Teddy ASSIH
» Link to gif: https://giphy.com/gifs/oss-crm-twenty-VWDHAIlGTbc6Nqdza9
» 11-October-2024 by Bhavesh Mishra
» Link to gif: https://shorturl.at/yln9H
---
@@ -1,19 +0,0 @@
**Side Quest**: Complete all Twenty side quests
**Points**: 300 Points
**Proof**: Add screenshots for each side quest to the PR description. Add your name to the list below.
Please follow the following schema:
---
» 05-April-2024 by YOUR NAME
////////////////////////////
Your turn 👇
////////////////////////////
» 01-October-2024 by X
---
+6 -1
View File
@@ -23,6 +23,7 @@
"@linaria/core": "^6.2.0",
"@linaria/react": "^6.2.1",
"@mdx-js/react": "^3.0.0",
"@microsoft/microsoft-graph-client": "^3.0.7",
"@nestjs/apollo": "^11.0.5",
"@nestjs/axios": "^3.0.1",
"@nestjs/cli": "^9.0.0",
@@ -49,6 +50,7 @@
"@stoplight/elements": "^8.0.5",
"@swc/jest": "^0.2.29",
"@tabler/icons-react": "^2.44.0",
"@tiptap/extension-hard-break": "^2.9.1",
"@types/dompurify": "^3.0.5",
"@types/facepaint": "^1.2.5",
"@types/lodash.camelcase": "^4.3.7",
@@ -176,6 +178,7 @@
"scroll-into-view": "^1.16.2",
"semver": "^7.5.4",
"sharp": "^0.32.1",
"slash": "^5.1.0",
"stripe": "^14.17.0",
"ts-key-enum": "^2.0.12",
"tslib": "^2.3.0",
@@ -199,6 +202,7 @@
"@graphql-codegen/typescript": "^3.0.4",
"@graphql-codegen/typescript-operations": "^3.0.4",
"@graphql-codegen/typescript-react-apollo": "^3.3.7",
"@microsoft/microsoft-graph-types": "^2.40.0",
"@nestjs/cli": "^9.0.0",
"@nestjs/schematics": "^9.0.0",
"@nestjs/testing": "^9.0.0",
@@ -294,6 +298,7 @@
"eslint-plugin-jsx-a11y": "^6.8.0",
"eslint-plugin-prefer-arrow": "^1.2.3",
"eslint-plugin-prettier": "^5.1.2",
"eslint-plugin-project-structure": "^3.9.1",
"eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.4",
@@ -347,7 +352,7 @@
"version": "0.2.1",
"nx": {},
"scripts": {
"start": "npx nx run-many -t start -p twenty-server twenty-front"
"start": "npx concurrently --kill-others 'npx nx run-many -t start -p twenty-server twenty-front' 'npx wait-on tcp:3000 && npx nx run twenty-server:worker'"
},
"workspaces": {
"packages": [
@@ -1,6 +1,5 @@
import styled from '@emotion/styled';
import { Loader } from '@/ui/display/loader/components/Loader';
import styled from '@emotion/styled';
const StyledContainer = styled.div`
align-items: center;
@@ -3,7 +3,7 @@ import styled from '@emotion/styled';
type H2TitleProps = {
title: string;
description?: string;
addornment?: React.ReactNode;
adornment?: React.ReactNode;
};
const StyledContainer = styled.div`
@@ -33,11 +33,11 @@ const StyledDescription = styled.h3`
margin-top: ${({ theme }) => theme.spacing(3)};
`;
export const H2Title = ({ title, description, addornment }: H2TitleProps) => (
export const H2Title = ({ title, description, adornment }: H2TitleProps) => (
<StyledContainer>
<StyledTitleContainer>
<StyledTitle>{title}</StyledTitle>
{addornment}
{adornment}
</StyledTitleContainer>
{description && <StyledDescription>{description}</StyledDescription>}
</StyledContainer>
@@ -1,5 +1,5 @@
import React from 'react';
import styled from '@emotion/styled';
import React, { useId } from 'react';
interface TextInputProps {
label?: string;
@@ -18,7 +18,7 @@ const StyledContainer = styled.div<{ fullWidth?: boolean }>`
margin-bottom: ${({ theme }) => theme.spacing(4)};
`;
const StyledLabel = styled.span`
const StyledLabel = styled.label`
color: ${({ theme }) => theme.font.color.light};
font-size: ${({ theme }) => theme.font.size.xs};
font-weight: ${({ theme }) => theme.font.weight.semiBold};
@@ -65,12 +65,15 @@ const TextInput: React.FC<TextInputProps> = ({
placeholder,
icon,
}) => {
const inputId = useId();
return (
<StyledContainer fullWidth={fullWidth}>
{label && <StyledLabel>{label}</StyledLabel>}
{label && <StyledLabel htmlFor={inputId}>{label}</StyledLabel>}
<StyledInputContainer>
{icon && <StyledIcon>{icon}</StyledIcon>}
<StyledInput
id={inputId}
type="text"
value={value}
onChange={(e) => onChange(e.target.value)}
+4 -7
View File
@@ -1,18 +1,15 @@
TAG=latest
# POSTGRES_ADMIN_PASSWORD=replace_me_with_a_strong_password
#PGUSER_SUPERUSER=postgres
#PGPASSWORD_SUPERUSER=replace_me_with_a_strong_password
PG_DATABASE_HOST=db:5432
REDIS_URL=redis://redis:6379
SERVER_URL=http://localhost:3000
# REDIS_HOST=redis
# REDIS_PORT=6379
# Use openssl rand -base64 32 for each secret
# ACCESS_TOKEN_SECRET=replace_me_with_a_random_string_access
# LOGIN_TOKEN_SECRET=replace_me_with_a_random_string_login
# REFRESH_TOKEN_SECRET=replace_me_with_a_random_string_refresh
# FILE_TOKEN_SECRET=replace_me_with_a_random_string_refresh
# APP_SECRET=replace_me_with_a_random_string
SIGN_IN_PREFILLED=true
-36
View File
@@ -1,37 +1,9 @@
dev-build:
@docker compose -f dev/docker-compose.yml down -v
@docker compose -f dev/docker-compose.yml build
dev-up:
@docker compose -f dev/docker-compose.yml up -d
dev-start:
@docker compose -f dev/docker-compose.yml start
dev-stop:
@docker compose -f dev/docker-compose.yml stop
dev-down:
@docker compose -f dev/docker-compose.yml down -v
dev-sh:
@docker compose -f dev/docker-compose.yml exec twenty-dev sh
dev-postgres-build:
@docker stop twenty_postgres || true
@docker rm twenty_postgres || true
@docker volume rm twenty_db_data || true
@docker compose -f dev/docker-compose.yml up --build postgres -d
prod-build:
@cd ../.. && docker build -f ./packages/twenty-docker/twenty/Dockerfile --tag twenty . && cd -
prod-run:
@docker run -d -p 3000:3000 --name twenty twenty
prod-postgres-build:
@cd ../.. && docker build -f ./packages/twenty-docker/twenty-postgres/Dockerfile --tag twenty-postgres . && cd -
prod-postgres-run:
@docker run -d -p 5432:5432 -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=postgres --name twenty-postgres twenty-postgres
@@ -40,11 +12,3 @@ prod-website-build:
prod-website-run:
@docker run -d -p 3000:3000 --name twenty-website twenty-website
release-postgres:
@cd ../.. && docker buildx build \
--push \
--no-cache \
--platform linux/amd64,linux/arm64 \
-f ./packages/twenty-docker/twenty-postgres/Dockerfile -t twentycrm/twenty-postgres:$(version) -t twentycrm/twenty-postgres:latest . \
&& cd -
+13 -20
View File
@@ -22,11 +22,10 @@ services:
- "3000:3000"
environment:
PORT: 3000
PG_DATABASE_URL: postgres://twenty:twenty@${PG_DATABASE_HOST}/default
PG_DATABASE_URL: postgres://${PGUSER_SUPERUSER:-postgres}:${PGPASSWORD_SUPERUSER:-twenty}@${PG_DATABASE_HOST:-db:5432}/default
SERVER_URL: ${SERVER_URL}
FRONT_BASE_URL: ${FRONT_BASE_URL:-$SERVER_URL}
REDIS_PORT: ${REDIS_PORT:-6379}
REDIS_HOST: ${REDIS_HOST:-redis}
REDIS_URL: ${REDIS_URL:-redis://redis:6379}
ENABLE_DB_MIGRATIONS: "true"
@@ -36,10 +35,7 @@ services:
STORAGE_S3_NAME: ${STORAGE_S3_NAME}
STORAGE_S3_ENDPOINT: ${STORAGE_S3_ENDPOINT}
ACCESS_TOKEN_SECRET: ${ACCESS_TOKEN_SECRET}
LOGIN_TOKEN_SECRET: ${LOGIN_TOKEN_SECRET}
REFRESH_TOKEN_SECRET: ${REFRESH_TOKEN_SECRET}
FILE_TOKEN_SECRET: ${FILE_TOKEN_SECRET}
APP_SECRET: ${APP_SECRET}
depends_on:
change-vol-ownership:
condition: service_completed_successfully
@@ -56,11 +52,10 @@ services:
image: twentycrm/twenty:${TAG}
command: ["yarn", "worker:prod"]
environment:
PG_DATABASE_URL: postgres://twenty:twenty@${PG_DATABASE_HOST}/default
PG_DATABASE_URL: postgres://${PGUSER_SUPERUSER:-postgres}:${PGPASSWORD_SUPERUSER:-twenty}@${PG_DATABASE_HOST:-db:5432}/default
SERVER_URL: ${SERVER_URL}
FRONT_BASE_URL: ${FRONT_BASE_URL:-$SERVER_URL}
REDIS_PORT: ${REDIS_PORT:-6379}
REDIS_HOST: ${REDIS_HOST:-redis}
REDIS_URL: ${REDIS_URL:-redis://redis:6379}
ENABLE_DB_MIGRATIONS: "false" # it already runs on the server
@@ -69,10 +64,7 @@ services:
STORAGE_S3_NAME: ${STORAGE_S3_NAME}
STORAGE_S3_ENDPOINT: ${STORAGE_S3_ENDPOINT}
ACCESS_TOKEN_SECRET: ${ACCESS_TOKEN_SECRET}
LOGIN_TOKEN_SECRET: ${LOGIN_TOKEN_SECRET}
REFRESH_TOKEN_SECRET: ${REFRESH_TOKEN_SECRET}
FILE_TOKEN_SECRET: ${FILE_TOKEN_SECRET}
APP_SECRET: ${APP_SECRET}
depends_on:
db:
condition: service_healthy
@@ -81,13 +73,16 @@ services:
restart: always
db:
image: twentycrm/twenty-postgres:${TAG}
image: twentycrm/twenty-postgres-spilo:${TAG}
volumes:
- db-data:/bitnami/postgresql
- db-data:/home/postgres/pgdata
environment:
POSTGRES_PASSWORD: ${POSTGRES_ADMIN_PASSWORD}
PGUSER_SUPERUSER: ${PGUSER_SUPERUSER:-postgres}
PGPASSWORD_SUPERUSER: ${PGPASSWORD_SUPERUSER:-twenty}
ALLOW_NOSSL: "true"
SPILO_PROVIDER: "local"
healthcheck:
test: pg_isready -U twenty -d default
test: pg_isready -U ${PGUSER_SUPERUSER:-postgres} -h localhost -d postgres
interval: 5s
timeout: 5s
retries: 10
@@ -95,8 +90,6 @@ services:
redis:
image: redis
ports:
- "6379:6379"
restart: always
volumes:
@@ -30,10 +30,10 @@ spec:
image: twentycrm/twenty-postgres:latest
imagePullPolicy: Always
env:
- name: POSTGRES_PASSWORD
- name: PGUSER_SUPERUSER
value: "postgres"
- name: PGPASSWORD_SUPERUSER
value: "twenty"
- name: BITNAMI_DEBUG
value: "true"
ports:
- containerPort: 5432
name: tcp
@@ -48,7 +48,7 @@ spec:
stdin: true
tty: true
volumeMounts:
- mountPath: /bitnami/postgresql
- mountPath: /home/postgres/pgdata
name: twentycrm-db-data
dnsPolicy: ClusterFirst
restartPolicy: Always
@@ -40,11 +40,9 @@ spec:
- name: FRONT_BASE_URL
value: "https://crm.example.com:443"
- name: "PG_DATABASE_URL"
value: "postgres://twenty:twenty@twenty-db.twentycrm.svc.cluster.local/default"
- name: "REDIS_HOST"
value: "twentycrm-redis.twentycrm.svc.cluster.local"
- name: "REDIS_PORT"
value: 6379
value: "postgres://postgres:twenty@twenty-db.twentycrm.svc.cluster.local/default"
- name: "REDIS_URL"
value: "redis://twentycrm-redis.twentycrm.svc.cluster.local:6379"
- name: ENABLE_DB_MIGRATIONS
value: "true"
- name: SIGN_IN_PREFILLED
@@ -57,26 +55,11 @@ spec:
value: "7d"
- name: "LOGIN_TOKEN_EXPIRES_IN"
value: "1h"
- name: ACCESS_TOKEN_SECRET
- name: APP_SECRET
valueFrom:
secretKeyRef:
name: tokens
key: accessToken
- name: LOGIN_TOKEN_SECRET
valueFrom:
secretKeyRef:
name: tokens
key: loginToken
- name: REFRESH_TOKEN_SECRET
valueFrom:
secretKeyRef:
name: tokens
key: refreshToken
- name: FILE_TOKEN_SECRET
valueFrom:
secretKeyRef:
name: tokens
key: fileToken
ports:
- containerPort: 3000
name: http-tcp
@@ -31,7 +31,7 @@ spec:
- name: FRONT_BASE_URL
value: "https://crm.example.com:443"
- name: PG_DATABASE_URL
value: "postgres://twenty:twenty@twenty-db.twentycrm.svc.cluster.local/default"
value: "postgres://postgres:twenty@twenty-db.twentycrm.svc.cluster.local/default"
- name: ENABLE_DB_MIGRATIONS
value: "false" # it already runs on the server
- name: STORAGE_TYPE
@@ -40,30 +40,13 @@ spec:
value: "bull-mq"
- name: "CACHE_STORAGE_TYPE"
value: "redis"
- name: "REDIS_HOST"
value: "twentycrm-redis.twentycrm.svc.cluster.local"
- name: "REDIS_PORT"
value: 6379
- name: ACCESS_TOKEN_SECRET
- name: "REDIS_URL"
value: "redis://twentycrm-redis.twentycrm.svc.cluster.local:6379"
- name: APP_SECRET
valueFrom:
secretKeyRef:
name: tokens
key: accessToken
- name: LOGIN_TOKEN_SECRET
valueFrom:
secretKeyRef:
name: tokens
key: loginToken
- name: REFRESH_TOKEN_SECRET
valueFrom:
secretKeyRef:
name: tokens
key: refreshToken
- name: FILE_TOKEN_SECRET
valueFrom:
secretKeyRef:
name: tokens
key: fileToken
command:
- yarn
- worker:prod
@@ -51,7 +51,7 @@ To make configuration changes to how this doc is generated, see `./.terraform-do
| <a name="input_twentycrm_app_hostname"></a> [twentycrm\_app\_hostname](#input\_twentycrm\_app\_hostname) | The protocol, DNS fully qualified hostname, and port used to access TwentyCRM in your environment. Ex: https://crm.example.com:443 | `string` | n/a | yes |
| <a name="input_twentycrm_pgdb_admin_password"></a> [twentycrm\_pgdb\_admin\_password](#input\_twentycrm\_pgdb\_admin\_password) | TwentyCRM password for postgres database. | `string` | n/a | yes |
| <a name="input_twentycrm_app_name"></a> [twentycrm\_app\_name](#input\_twentycrm\_app\_name) | A friendly name prefix to use for every component deployed. | `string` | `"twentycrm"` | no |
| <a name="input_twentycrm_db_image"></a> [twentycrm\_db\_image](#input\_twentycrm\_db\_image) | TwentyCRM image for database deployment. This defaults to latest. | `string` | `"twentycrm/twenty-postgres:latest"` | no |
| <a name="input_twentycrm_db_image"></a> [twentycrm\_db\_image](#input\_twentycrm\_db\_image) | TwentyCRM image for database deployment. This defaults to latest. | `string` | `"twentycrm/twenty-postgres-spilo:latest"` | no |
| <a name="input_twentycrm_db_pv_capacity"></a> [twentycrm\_db\_pv\_capacity](#input\_twentycrm\_db\_pv\_capacity) | Storage capacity provisioned for database persistent volume. | `string` | `"10Gi"` | no |
| <a name="input_twentycrm_db_pv_path"></a> [twentycrm\_db\_pv\_path](#input\_twentycrm\_db\_pv\_path) | Local path to use to store the physical volume if using local storage on nodes. | `string` | `""` | no |
| <a name="input_twentycrm_db_pvc_requests"></a> [twentycrm\_db\_pvc\_requests](#input\_twentycrm\_db\_pvc\_requests) | Storage capacity reservation for database persistent volume claim. | `string` | `"10Gi"` | no |
@@ -61,12 +61,8 @@ resource "kubernetes_deployment" "twentycrm_server" {
value = "postgres://twenty:${var.twentycrm_pgdb_admin_password}@${kubernetes_service.twentycrm_db.metadata.0.name}.${kubernetes_namespace.twentycrm.metadata.0.name}.svc.cluster.local/default"
}
env {
name = "REDIS_HOST"
value = "${kubernetes_service.twentycrm_redis.metadata.0.name}.${kubernetes_namespace.twentycrm.metadata.0.name}.svc.cluster.local"
}
env {
name = "REDIS_PORT"
value = 6379
name = "REDIS_URL"
value = "redis://${kubernetes_service.twentycrm_redis.metadata.0.name}.${kubernetes_namespace.twentycrm.metadata.0.name}.svc.cluster.local:6379"
}
env {
name = "ENABLE_DB_MIGRATIONS"
@@ -95,7 +91,7 @@ resource "kubernetes_deployment" "twentycrm_server" {
value = "1h"
}
env {
name = "ACCESS_TOKEN_SECRET"
name = "APP_SECRET"
value_from {
secret_key_ref {
name = "tokens"
@@ -104,36 +100,6 @@ resource "kubernetes_deployment" "twentycrm_server" {
}
}
env {
name = "LOGIN_TOKEN_SECRET"
value_from {
secret_key_ref {
name = "tokens"
key = "loginToken"
}
}
}
env {
name = "REFRESH_TOKEN_SECRET"
value_from {
secret_key_ref {
name = "tokens"
key = "refreshToken"
}
}
}
env {
name = "FILE_TOKEN_SECRET"
value_from {
secret_key_ref {
name = "tokens"
key = "fileToken"
}
}
}
port {
container_port = 3000
protocol = "TCP"
@@ -59,13 +59,8 @@ resource "kubernetes_deployment" "twentycrm_worker" {
}
env {
name = "REDIS_HOST"
value = "${kubernetes_service.twentycrm_redis.metadata.0.name}.${kubernetes_namespace.twentycrm.metadata.0.name}.svc.cluster.local"
}
env {
name = "REDIS_PORT"
value = 6379
name = "REDIS_URL"
value = "redis://${kubernetes_service.twentycrm_redis.metadata.0.name}.${kubernetes_namespace.twentycrm.metadata.0.name}.svc.cluster.local:6379"
}
env {
@@ -83,7 +78,7 @@ resource "kubernetes_deployment" "twentycrm_worker" {
}
env {
name = "ACCESS_TOKEN_SECRET"
name = "APP_SECRET"
value_from {
secret_key_ref {
name = "tokens"
@@ -92,36 +87,6 @@ resource "kubernetes_deployment" "twentycrm_worker" {
}
}
env {
name = "LOGIN_TOKEN_SECRET"
value_from {
secret_key_ref {
name = "tokens"
key = "loginToken"
}
}
}
env {
name = "REFRESH_TOKEN_SECRET"
value_from {
secret_key_ref {
name = "tokens"
key = "refreshToken"
}
}
}
env {
name = "FILE_TOKEN_SECRET"
value_from {
secret_key_ref {
name = "tokens"
key = "fileToken"
}
}
}
resources {
requests = {
cpu = "250m"
@@ -29,7 +29,7 @@ variable "twentycrm_server_image" {
variable "twentycrm_db_image" {
type = string
default = "twentycrm/twenty-postgres:latest"
default = "twentycrm/twenty-postgres-spilo:latest"
description = "TwentyCRM image for database deployment. This defaults to latest."
}
+12
View File
@@ -0,0 +1,12 @@
pull_version=${VERSION:-$(curl -s https://api.github.com/repos/twentyhq/twenty/releases/latest | grep '"tag_name":' | cut -d '"' -f 4)}
pull_branch=${BRANCH:-$pull_version}
version_num=${pull_version#v}
target_version="0.32.4"
# We moved the install script to a different location in v0.32.4
if [[ -n "$BRANCH" ]] || [[ "$(printf '%s\n' "$target_version" "$version_num" | sort -V | head -n1)" != "$version_num" ]]; then
curl -sL "https://raw.githubusercontent.com/twentyhq/twenty/$pull_branch/packages/twenty-docker/scripts/install.sh" | bash -s -- "$VERSION" "$BRANCH"
else
curl -sL "https://raw.githubusercontent.com/twentyhq/twenty/$pull_branch/install.sh" | bash -s -- "$VERSION" "$BRANCH"
fi
+166
View File
@@ -0,0 +1,166 @@
#!/bin/bash
echo "🔧 Checking dependencies..."
if ! command -v docker &>/dev/null; then
echo -e "\t❌ Docker is not installed or not in PATH. Please install Docker first.\n\t\tSee https://docs.docker.com/get-docker/"
exit 1
fi
# Check if docker compose plugin is installed
if ! docker compose version &>/dev/null; then
echo -e "\t❌ Docker Compose is not installed or not in PATH (n.b. docker-compose is deprecated)\n\t\tUpdate docker or install docker-compose-plugin\n\t\tOn Linux: sudo apt-get install docker-compose-plugin\n\t\tSee https://docs.docker.com/compose/install/"
exit 1
fi
# Check if docker is started
if ! docker info &>/dev/null; then
echo -e "\t❌ Docker is not running.\n\t\tPlease start Docker Desktop, Docker or check documentation at https://docs.docker.com/config/daemon/start/"
exit 1
fi
if ! command -v curl &>/dev/null; then
echo -e "\t❌ Curl is not installed or not in PATH.\n\t\tOn macOS: brew install curl\n\t\tOn Linux: sudo apt install curl"
exit 1
fi
# Check if docker compose version is >= 2
if [ "$(docker compose version --short | cut -d' ' -f3 | cut -d'.' -f1)" -lt 2 ]; then
echo -e "\t❌ Docker Compose is outdated. Please update Docker Compose to version 2 or higher.\n\t\tSee https://docs.docker.com/compose/install/linux/"
exit 1
fi
# Check if docker-compose is installed, if so issue a warning if version is < 2
if command -v docker-compose &>/dev/null; then
if [ "$(docker-compose version --short | cut -d' ' -f3 | cut -d'.' -f1)" -lt 2 ]; then
echo -e "\n\t⚠️ 'docker-compose' is installed but outdated. Make sure to use 'docker compose' or to upgrade 'docker-compose' to version 2.\n\t\tSee https://docs.docker.com/compose/install/standalone/\n"
fi
fi
# Catch errors
set -e
function on_exit {
# $? is the exit status of the last command executed
local exit_status=$?
if [ $exit_status -ne 0 ]; then
echo "❌ Something went wrong, exiting: $exit_status"
fi
}
trap on_exit EXIT
# Use environment variables VERSION and BRANCH, with defaults if not set
version=${VERSION:-$(curl -s https://api.github.com/repos/twentyhq/twenty/releases/latest | grep '"tag_name":' | cut -d '"' -f 4)}
branch=${BRANCH:-$version}
echo "🚀 Using version $version and branch $branch"
dir_name="twenty"
function ask_directory {
read -p "📁 Enter the directory name to setup the project (default: $dir_name): " answer
if [ -n "$answer" ]; then
dir_name=$answer
fi
}
ask_directory
while [ -d "$dir_name" ]; do
read -p "🚫 Directory '$dir_name' already exists. Do you want to overwrite it? (y/N) " answer
if [ "$answer" = "y" ]; then
break
else
ask_directory
fi
done
# Create a directory named twenty
echo "📁 Creating directory '$dir_name'"
mkdir -p "$dir_name" && cd "$dir_name" || { echo "❌ Failed to create/access directory '$dir_name'"; exit 1; }
# Copy twenty/packages/twenty-docker/docker-compose.yml in it
echo -e "\t• Copying docker-compose.yml"
curl -sLo docker-compose.yml https://raw.githubusercontent.com/twentyhq/twenty/$branch/packages/twenty-docker/docker-compose.yml
# Copy twenty/packages/twenty-docker/.env.example to .env
echo -e "\t• Setting up .env file"
curl -sLo .env https://raw.githubusercontent.com/twentyhq/twenty/$branch/packages/twenty-docker/.env.example
# Replace TAG=latest by TAG=<latest_release or version input>
if [[ $(uname) == "Darwin" ]]; then
# Running on macOS
sed -i '' "s/TAG=latest/TAG=$version/g" .env
else
# Assuming Linux
sed -i'' "s/TAG=latest/TAG=$version/g" .env
fi
# Generate random strings for secrets
echo "# === Randomly generated secrets ===" >>.env
echo "APP_SECRET=$(openssl rand -base64 32)" >>.env
echo "" >>.env
echo "PGPASSWORD_SUPERUSER=$(openssl rand -hex 16)" >>.env
echo -e "\t• .env configuration completed"
port=3000
# Check if command nc is available
if command -v nc &> /dev/null; then
# Check if port 3000 is already in use, propose to change it
while nc -zv localhost $port &>/dev/null; do
read -p "🚫 Port $port is already in use. Do you want to use another port? (Y/n) " answer
if [ "$answer" = "n" ]; then
continue
fi
read -p "Enter a new port number: " new_port
if [[ $(uname) == "Darwin" ]]; then
sed -i '' "s/$port:$port/$new_port:$port/g" docker-compose.yml
sed -E -i '' "s|^SERVER_URL=http://localhost:[0-9]+|SERVER_URL=http://localhost:$new_port|g" .env
else
sed -i'' "s/$port:$port/$new_port:$port/g" docker-compose.yml
sed -E -i'' "s|^SERVER_URL=http://localhost:[0-9]+|SERVER_URL=http://localhost:$new_port|g" .env
fi
port=$new_port
done
fi
# Ask user if they want to start the project
read -p "🚀 Do you want to start the project now? (Y/n) " answer
if [ "$answer" = "n" ]; then
echo "✅ Project setup completed. Run 'docker compose up -d' to start."
exit 0
else
echo "🐳 Starting Docker containers..."
docker compose up -d
# Check if port is listening
echo "Waiting for server to be healthy, it might take a few minutes while we initialize the database..."
# Tail logs of the server until it's ready
docker compose logs -f server &
pid=$!
while [ ! $(docker inspect --format='{{.State.Health.Status}}' twenty-server-1) = "healthy" ]; do
sleep 1
done
kill $pid
echo ""
echo "✅ Server is up and running"
fi
function ask_open_browser {
read -p "🌐 Do you want to open the project in your browser? (Y/n) " answer
if [ "$answer" = "n" ]; then
echo "✅ Setup completed. Access your project at http://localhost:$port"
exit 0
fi
}
# Ask user if they want to open the project
# Running on macOS
if [[ $(uname) == "Darwin" ]]; then
ask_open_browser
open "http://localhost:$port"
# Assuming Linux
else
# xdg-open is not installed, we could be running in a non gui environment
if command -v xdg-open >/dev/null 2>&1; then
ask_open_browser
xdg-open "http://localhost:$port"
else
echo "✅ Setup completed. Your project is available at http://localhost:$port"
fi
fi
@@ -1,13 +1,12 @@
ARG POSTGRES_VERSION=15
ARG SPILO_VERSION=3.2-p1
ARG PG_GRAPHQL_VERSION=1.5.6
ARG WRAPPERS_VERSION=0.2.0
# Build the mysql_fdw extension
FROM debian:bookworm as build-mysql_fdw
FROM debian:bookworm AS build-mysql_fdw
ARG POSTGRES_VERSION
ENV DEBIAN_FRONTEND noninteractive
ENV DEBIAN_FRONTEND=noninteractive
RUN apt update && \
apt install -y \
build-essential \
@@ -18,14 +17,14 @@ RUN apt update && \
# Install mysql_fdw
RUN git clone https://github.com/EnterpriseDB/mysql_fdw.git
WORKDIR mysql_fdw
WORKDIR /mysql_fdw
RUN make USE_PGXS=1
# Build libssl for wrappers
FROM ubuntu:22.04 as build-libssl
FROM ubuntu:22.04 AS build-libssl
ENV DEBIAN_FRONTEND noninteractive
ENV DEBIAN_FRONTEND=noninteractive
RUN apt update && \
apt install -y \
build-essential \
@@ -38,10 +37,9 @@ WORKDIR /build/openssl
RUN ./config && make && make install
# Extend the Spilo image with the pg_graphql and mysql_fdw extensions
# Extend the Spilo image with the mysql_fdw extensions
FROM ghcr.io/zalando/spilo-${POSTGRES_VERSION}:${SPILO_VERSION}
ARG POSTGRES_VERSION
ARG PG_GRAPHQL_VERSION
ARG WRAPPERS_VERSION
ARG TARGETARCH
@@ -63,14 +61,6 @@ RUN curl -L "https://github.com/supabase/wrappers/releases/download/v${WRAPPERS_
COPY --from=build-libssl /usr/local/lib/libssl* /usr/local/lib/libcrypto* /usr/lib/
COPY --from=build-libssl /usr/local/lib/engines-1.1 /usr/lib/engines-1.1
# Copy pg_graphql
COPY ./packages/twenty-postgres/linux/${TARGETARCH}/${POSTGRES_VERSION}/pg_graphql/${PG_GRAPHQL_VERSION}/pg_graphql--${PG_GRAPHQL_VERSION}.sql \
/usr/share/postgresql/${POSTGRES_VERSION}/extension
COPY ./packages/twenty-postgres/linux/${TARGETARCH}/${POSTGRES_VERSION}/pg_graphql/${PG_GRAPHQL_VERSION}/pg_graphql.control \
/usr/share/postgresql/${POSTGRES_VERSION}/extension
COPY ./packages/twenty-postgres/linux/${TARGETARCH}/${POSTGRES_VERSION}/pg_graphql/${PG_GRAPHQL_VERSION}/pg_graphql.so \
/usr/lib/postgresql/${POSTGRES_VERSION}/lib/pg_graphql.so
# Copy mysql_fdw
COPY --from=build-mysql_fdw /mysql_fdw/mysql_fdw.so \
/usr/lib/postgresql/${POSTGRES_VERSION}/lib/mysql_fdw.so
@@ -1,54 +0,0 @@
ARG IMAGE_TAG='15.5.0-debian-11-r15'
FROM bitnami/postgresql:${IMAGE_TAG}
ARG PG_MAIN_VERSION=15
ARG PG_GRAPHQL_VERSION=1.5.6
ARG WRAPPERS_VERSION=0.2.0
ARG TARGETARCH
USER root
RUN set -eux; \
ARCH="$(dpkg --print-architecture)"; \
case "${ARCH}" in \
aarch64|arm64) \
TARGETARCH='arm64'; \
;; \
amd64|x86_64) \
TARGETARCH='amd64'; \
;; \
*) \
echo "Unsupported arch: ${ARCH}"; \
exit 1; \
;; \
esac;
RUN apt update && apt install build-essential git curl default-libmysqlclient-dev -y
# Install precompiled pg_graphql extensions
COPY ./packages/twenty-postgres/linux/${TARGETARCH}/${PG_MAIN_VERSION}/pg_graphql/${PG_GRAPHQL_VERSION}/pg_graphql--${PG_GRAPHQL_VERSION}.sql \
/opt/bitnami/postgresql/share/extension/
COPY ./packages/twenty-postgres/linux/${TARGETARCH}/${PG_MAIN_VERSION}/pg_graphql/${PG_GRAPHQL_VERSION}/pg_graphql.control \
/opt/bitnami/postgresql/share/extension/
COPY ./packages/twenty-postgres/linux/${TARGETARCH}/${PG_MAIN_VERSION}/pg_graphql/${PG_GRAPHQL_VERSION}/pg_graphql.so \
/opt/bitnami/postgresql/lib/
# Install precompiled supabase wrappers extensions
RUN curl -L "https://github.com/supabase/wrappers/releases/download/v${WRAPPERS_VERSION}/wrappers-v${WRAPPERS_VERSION}-pg${PG_MAIN_VERSION}-${TARGETARCH}-linux-gnu.deb" -o wrappers.deb
RUN dpkg --install wrappers.deb
RUN cp /usr/share/postgresql/${PG_MAIN_VERSION}/extension/wrappers* /opt/bitnami/postgresql/share/extension/
RUN cp /usr/lib/postgresql/${PG_MAIN_VERSION}/lib/wrappers* /opt/bitnami/postgresql/lib/
RUN export PATH=/usr/local/pgsql/bin/:$PATH
RUN export PATH=/usr/local/mysql/bin/:$PATH
RUN git clone https://github.com/EnterpriseDB/mysql_fdw.git
WORKDIR mysql_fdw
RUN make USE_PGXS=1
RUN make USE_PGXS=1 install
COPY ./packages/twenty-docker/twenty-postgres/init.sql /docker-entrypoint-initdb.d/
USER 1001
ENTRYPOINT ["/opt/bitnami/scripts/postgresql/entrypoint.sh"]
CMD ["/opt/bitnami/scripts/postgresql/run.sh"]
@@ -1,4 +0,0 @@
CREATE DATABASE "default";
CREATE DATABASE "test";
CREATE USER twenty PASSWORD 'twenty';
ALTER ROLE twenty superuser;
+2 -1
View File
@@ -52,9 +52,10 @@ RUN apk add --no-cache curl jq
RUN npm install -g tsx
RUN apk add --no-cache postgresql-client
COPY ./packages/twenty-docker/twenty/entrypoint.sh /app/entrypoint.sh
RUN chmod +x /app/entrypoint.sh
WORKDIR /app/packages/twenty-server
ARG REACT_APP_SERVER_BASE_URL
@@ -1,9 +1,18 @@
#!/bin/sh
set -e
# Check if the initialization has already been done and that we enabled automatic migration
if [ "${ENABLE_DB_MIGRATIONS}" = "true" ] && [ ! -f /app/docker-data/db_status ]; then
echo "Running database setup and migrations..."
# Creating the database if it doesn't exist
PGUSER=$(echo $PG_DATABASE_URL | awk -F '//' '{print $2}' | awk -F ':' '{print $1}')
PGPASS=$(echo $PG_DATABASE_URL | awk -F ':' '{print $3}' | awk -F '@' '{print $1}')
PGHOST=$(echo $PG_DATABASE_URL | awk -F '@' '{print $2}' | awk -F ':' '{print $1}')
PGPORT=$(echo $PG_DATABASE_URL | awk -F ':' '{print $4}' | awk -F '/' '{print $1}')
PGPASSWORD=${PGPASS} psql -h ${PGHOST} -p ${PGPORT} -U ${PGUSER} -d postgres -tc "SELECT 1 FROM pg_database WHERE datname = 'default'" | grep -q 1 || \
PGPASSWORD=${PGPASS} psql -h ${PGHOST} -p ${PGPORT} -U ${PGUSER} -d postgres -c "CREATE DATABASE \"default\""
# Run setup and migration scripts
NODE_OPTIONS="--max-old-space-size=1500" tsx ./scripts/setup-db.ts
yarn database:migrate:prod
@@ -0,0 +1,22 @@
import * as fs from 'fs';
import path from 'path';
export const envVariables = (variables: string) => {
let payload = `
PG_DATABASE_URL=postgres://postgres:twenty@localhost:5432/default
FRONT_BASE_URL=http://localhost:3001
ACCESS_TOKEN_SECRET=replace_me_with_a_random_string_access
LOGIN_TOKEN_SECRET=replace_me_with_a_random_string_login
REFRESH_TOKEN_SECRET=replace_me_with_a_random_string_refresh
FILE_TOKEN_SECRET=replace_me_with_a_random_string_refresh
REDIS_URL=redis://localhost:6379
`;
payload = payload.concat(variables);
fs.writeFile(
path.join(__dirname, '..', '..', 'twenty-server', '.env'),
payload,
(err) => {
throw err;
},
);
};
@@ -0,0 +1,36 @@
import { Locator, Page } from '@playwright/test';
export class ConfirmationModal {
private readonly input: Locator;
private readonly cancelButton: Locator;
private readonly confirmButton: Locator;
constructor(public readonly page: Page) {
this.page = page;
this.input = page.getByTestId('confirmation-modal-input');
this.cancelButton = page.getByRole('button', { name: 'Cancel' });
this.confirmButton = page.getByTestId('confirmation-modal-confirm-button');
}
async typePlaceholderToInput() {
await this.page
.getByTestId('confirmation-modal-input')
.fill(
await this.page
.getByTestId('confirmation-modal-input')
.getAttribute('placeholder'),
);
}
async typePhraseToInput(value: string) {
await this.page.getByTestId('confirmation-modal-input').fill(value);
}
async clickCancelButton() {
await this.page.getByRole('button', { name: 'Cancel' }).click();
}
async clickConfirmButton() {
await this.page.getByTestId('confirmation-modal-confirm-button').click();
}
}
@@ -0,0 +1,28 @@
const nth = (d: number) => {
if (d > 3 && d < 21) return 'th';
switch (d % 10) {
case 1:
return 'st';
case 2:
return 'nd';
case 3:
return 'rd';
default:
return 'th';
}
};
// label looks like this: Choose Wednesday, October 30th, 2024
// eslint-disable-next-line prefer-arrow/prefer-arrow-functions
export function formatDate(value: string): string {
const date = new Date(value);
return 'Choose '.concat(
date.toLocaleDateString('en-US', { weekday: 'long' }),
', ',
date.toLocaleDateString('en-US', { month: 'long' }),
' ',
nth(date.getDate()),
', ',
date.toLocaleDateString('en-US', { year: 'numeric' }),
);
}
@@ -0,0 +1,6 @@
import { Locator, Page } from '@playwright/test';
export class GoogleLogin {
// TODO: map all things like inputs and buttons
// (what's the correct way for proceeding with Google interaction? log in each time test is performed?)
}
@@ -0,0 +1,23 @@
import { Locator, Page } from '@playwright/test';
export class IconSelect {
private readonly iconSelectButton: Locator;
private readonly iconSearchInput: Locator;
constructor(public readonly page: Page) {
this.iconSelectButton = page.getByLabel('Click to select icon (');
this.iconSearchInput = page.getByPlaceholder('Search icon');
}
async selectIcon(name: string) {
await this.iconSelectButton.click();
await this.iconSearchInput.fill(name);
await this.page.getByTitle(name).click();
}
async selectRelationIcon(name: string) {
await this.iconSelectButton.nth(1).click();
await this.iconSearchInput.fill(name);
await this.page.getByTitle(name).click();
}
}
@@ -0,0 +1,267 @@
import { Locator, Page } from '@playwright/test';
import { formatDate } from './formatDate.function';
export class InsertFieldData {
private readonly address1Input: Locator;
private readonly address2Input: Locator;
private readonly cityInput: Locator;
private readonly stateInput: Locator;
private readonly postCodeInput: Locator;
private readonly countrySelect: Locator;
private readonly arrayValueInput: Locator;
private readonly arrayAddValueButton: Locator;
// boolean react after click so no need to write special locator
private readonly currencySelect: Locator;
private readonly currencyAmountInput: Locator;
private readonly monthSelect: Locator;
private readonly yearSelect: Locator;
private readonly previousMonthButton: Locator;
private readonly nextMonthButton: Locator;
private readonly clearDateButton: Locator;
private readonly dateInput: Locator;
private readonly firstNameInput: Locator;
private readonly lastNameInput: Locator;
private readonly addURLButton: Locator;
private readonly setAsPrimaryButton: Locator;
private readonly addPhoneButton: Locator;
private readonly addMailButton: Locator;
constructor(public readonly page: Page) {
this.page = page;
this.address1Input = page.locator(
'//label[contains(., "ADDRESS 1")]/../div[last()]/input',
);
this.address2Input = page.locator(
'//label[contains(., "ADDRESS 2")]/../div[last()]/input',
);
this.cityInput = page.locator(
'//label[contains(., "CITY")]/../div[last()]/input',
);
this.stateInput = page.locator(
'//label[contains(., "STATE")]/../div[last()]/input',
);
this.postCodeInput = page.locator(
'//label[contains(., "POST CODE")]/../div[last()]/input',
);
this.countrySelect = page.locator(
'//span[contains(., "COUNTRY")]/../div[last()]/input',
);
this.arrayValueInput = page.locator("//input[@placeholder='Enter value']");
this.arrayAddValueButton = page.locator(
"//div[@data-testid='tooltip' and contains(.,'Add item')]",
);
this.currencySelect = page.locator(
'//body/div[last()]/div/div/div[first()]/div/div',
);
this.currencyAmountInput = page.locator("//input[@placeholder='Currency']");
this.monthSelect; // TODO: add once some other attributes are added
this.yearSelect;
this.previousMonthButton;
this.nextMonthButton;
this.clearDateButton = page.locator(
"//div[@data-testid='tooltip' and contains(., 'Clear')]",
);
this.dateInput = page.locator("//input[@placeholder='Type date and time']");
this.firstNameInput = page.locator("//input[@placeholder='First name']"); // may fail if placeholder is `F&zwnj;&zwnj;irst name` instead of `First name`
this.lastNameInput = page.locator("//input[@placeholder='Last name']"); // may fail if placeholder is `L&zwnj;&zwnj;ast name` instead of `Last name`
this.addURLButton = page.locator(
"//div[@data-testid='tooltip' and contains(., 'Add URL')]",
);
this.setAsPrimaryButton = page.locator(
"//div[@data-testid='tooltip' and contains(., 'Set as primary')]",
);
this.addPhoneButton = page.locator(
"//div[@data-testid='tooltip' and contains(., 'Add Phone')]",
);
this.addMailButton = page.locator(
"//div[@data-testid='tooltip' and contains(., 'Add Email')]",
);
}
// address
async typeAddress1(value: string) {
await this.address1Input.fill(value);
}
async typeAddress2(value: string) {
await this.address2Input.fill(value);
}
async typeCity(value: string) {
await this.cityInput.fill(value);
}
async typeState(value: string) {
await this.stateInput.fill(value);
}
async typePostCode(value: string) {
await this.postCodeInput.fill(value);
}
async selectCountry(value: string) {
await this.countrySelect.click();
await this.page
.locator(`//div[@data-testid='tooltip' and contains(., '${value}')]`)
.click();
}
// array
async typeArrayValue(value: string) {
await this.arrayValueInput.fill(value);
}
async clickAddItemButton() {
await this.arrayAddValueButton.click();
}
// currency
async selectCurrency(value: string) {
await this.currencySelect.click();
await this.page
.locator(`//div[@data-testid='tooltip' and contains(., '${value}')]`)
.click();
}
async typeCurrencyAmount(value: string) {
await this.currencyAmountInput.fill(value);
}
// date(-time)
async typeDate(value: string) {
await this.dateInput.fill(value);
}
async selectMonth(value: string) {
await this.monthSelect.click();
await this.page
.locator(`//div[@data-testid='tooltip' and contains(., '${value}')]`)
.click();
}
async selectYear(value: string) {
await this.yearSelect.click();
await this.page
.locator(`//div[@data-testid='tooltip' and contains(., '${value}')]`)
.click();
}
async clickPreviousMonthButton() {
await this.previousMonthButton.click();
}
async clickNextMonthButton() {
await this.nextMonthButton.click();
}
async selectDay(value: string) {
await this.page
.locator(`//div[@aria-label='${formatDate(value)}']`)
.click();
}
async clearDate() {
await this.clearDateButton.click();
}
// email
async typeEmail(value: string) {
await this.page.locator(`//input[@placeholder='Email']`).fill(value);
}
async clickAddMailButton() {
await this.addMailButton.click();
}
// full name
async typeFirstName(name: string) {
await this.firstNameInput.fill(name);
}
async typeLastName(name: string) {
await this.lastNameInput.fill(name);
}
// JSON
// placeholder is dependent on the name of field
async typeJSON(placeholder: string, value: string) {
await this.page
.locator(`//input[@placeholder='${placeholder}']`)
.fill(value);
}
// link
async typeLink(value: string) {
await this.page.locator("//input[@placeholder='URL']").fill(value);
}
async clickAddURL() {
await this.addURLButton.click();
}
// (multi-)select
async selectValue(value: string) {
await this.page
.locator(`//div[@data-testid='tooltip' and contains(., '${value}')]`)
.click();
}
// number
// placeholder is dependent on the name of field
async typeNumber(placeholder: string, value: string) {
await this.page
.locator(`//input[@placeholder='${placeholder}']`)
.fill(value);
}
// phones
async selectCountryPhoneCode(countryCode: string) {
await this.page
.locator(
`//div[@data-testid='tooltip' and contains(., '${countryCode}')]`,
)
.click();
}
async typePhoneNumber(value: string) {
await this.page.locator(`//input[@placeholder='Phone']`).fill(value);
}
async clickAddPhoneButton() {
await this.addPhoneButton.click();
}
// rating
// if adding rating for the first time, hover must be used
async selectRating(rating: number) {
await this.page.locator(`//div[@role='slider']/div[${rating}]`).click();
}
// text
// placeholder is dependent on the name of field
async typeText(placeholder: string, value: string) {
await this.page
.locator(`//input[@placeholder='${placeholder}']`)
.fill(value);
}
async clickSetAsPrimaryButton() {
await this.setAsPrimaryButton.click();
}
async searchValue(value: string) {
await this.page.locator(`//div[@placeholder='Search']`).fill(value);
}
async clickEditButton() {
await this.page
.locator("//div[@data-testid='tooltip' and contains(., 'Edit')]")
.click();
}
async clickDeleteButton() {
await this.page
.locator("//div[@data-testid='tooltip' and contains(., 'Delete')]")
.click();
}
}
@@ -0,0 +1,5 @@
import { Locator, Page } from '@playwright/test';
export class StripePage {
// TODO: implement all necessary methods (staging/sandbox page - does it differ anyhow from normal page?)
}
@@ -0,0 +1,25 @@
import { Locator, Page } from '@playwright/test';
export class UploadImage {
private readonly imagePreview: Locator;
private readonly uploadButton: Locator;
private readonly removeButton: Locator;
constructor(public readonly page: Page) {
this.imagePreview = page.locator('.css-6eut39'); //TODO: add attribute to make it independent of theme
this.uploadButton = page.getByRole('button', { name: 'Upload' });
this.removeButton = page.getByRole('button', { name: 'Remove' });
}
async clickImagePreview() {
await this.imagePreview.click();
}
async clickUploadButton() {
await this.uploadButton.click();
}
async clickRemoveButton() {
await this.removeButton.click();
}
}
@@ -0,0 +1,115 @@
import { Locator, Page } from '@playwright/test';
export class LeftMenu {
private readonly workspaceDropdown: Locator;
private readonly leftMenu: Locator;
private readonly searchSubTab: Locator;
private readonly settingsTab: Locator;
private readonly peopleTab: Locator;
private readonly companiesTab: Locator;
private readonly opportunitiesTab: Locator;
private readonly opportunitiesTabAll: Locator;
private readonly opportunitiesTabByStage: Locator;
private readonly tasksTab: Locator;
private readonly tasksTabAll: Locator;
private readonly tasksTabByStatus: Locator;
private readonly notesTab: Locator;
private readonly rocketsTab: Locator;
private readonly workflowsTab: Locator;
constructor(public readonly page: Page) {
this.page = page;
this.workspaceDropdown = page.getByTestId('workspace-dropdown');
this.leftMenu = page.getByRole('button').first();
this.searchSubTab = page.getByText('Search');
this.settingsTab = page.getByRole('link', { name: 'Settings' });
this.peopleTab = page.getByRole('link', { name: 'People' });
this.companiesTab = page.getByRole('link', { name: 'Companies' });
this.opportunitiesTab = page.getByRole('link', { name: 'Opportunities' });
this.opportunitiesTabAll = page.getByRole('link', {
name: 'All',
exact: true,
});
this.opportunitiesTabByStage = page.getByRole('link', { name: 'By Stage' });
this.tasksTab = page.getByRole('link', { name: 'Tasks' });
this.tasksTabAll = page.getByRole('link', { name: 'All tasks' });
this.tasksTabByStatus = page.getByRole('link', { name: 'Notes' });
this.notesTab = page.getByRole('link', { name: 'Notes' });
this.rocketsTab = page.getByRole('link', { name: 'Rockets' });
this.workflowsTab = page.getByRole('link', { name: 'Workflows' });
}
async selectWorkspace(workspaceName: string) {
await this.workspaceDropdown.click();
await this.page
.getByTestId('tooltip')
.filter({ hasText: workspaceName })
.click();
}
async changeLeftMenu() {
await this.leftMenu.click();
}
async openSearchTab() {
await this.searchSubTab.click();
}
async goToSettings() {
await this.settingsTab.click();
}
async goToPeopleTab() {
await this.peopleTab.click();
}
async goToCompaniesTab() {
await this.companiesTab.click();
}
async goToOpportunitiesTab() {
await this.opportunitiesTab.click();
}
async goToOpportunitiesTableView() {
await this.opportunitiesTabAll.click();
}
async goToOpportunitiesKanbanView() {
await this.opportunitiesTabByStage.click();
}
async goToTasksTab() {
await this.tasksTab.click();
}
async goToTasksTableView() {
await this.tasksTabAll.click();
}
async goToTasksKanbanView() {
await this.tasksTabByStatus.click();
}
async goToNotesTab() {
await this.notesTab.click();
}
async goToRocketsTab() {
await this.rocketsTab.click();
}
async goToWorkflowsTab() {
await this.workflowsTab.click();
}
async goToCustomObject(customObjectName: string) {
await this.page.getByRole('link', { name: customObjectName }).click();
}
async goToCustomObjectView(name: string) {
await this.page.getByRole('link', { name: name }).click();
}
}
export default LeftMenu;
@@ -0,0 +1,187 @@
import { Locator, Page } from '@playwright/test';
export class LoginPage {
private readonly loginWithGoogleButton: Locator;
private readonly loginWithEmailButton: Locator;
private readonly termsOfServiceLink: Locator;
private readonly privacyPolicyLink: Locator;
private readonly emailField: Locator;
private readonly continueButton: Locator;
private readonly forgotPasswordButton: Locator;
private readonly passwordField: Locator;
private readonly revealPasswordButton: Locator;
private readonly signInButton: Locator;
private readonly signUpButton: Locator;
private readonly previewImageButton: Locator;
private readonly uploadImageButton: Locator;
private readonly deleteImageButton: Locator;
private readonly workspaceNameField: Locator;
private readonly firstNameField: Locator;
private readonly lastNameField: Locator;
private readonly syncEverythingWithGoogleRadio: Locator;
private readonly syncSubjectAndMetadataWithGoogleRadio: Locator;
private readonly syncMetadataWithGoogleRadio: Locator;
private readonly syncWithGoogleButton: Locator;
private readonly noSyncButton: Locator;
private readonly inviteLinkField1: Locator;
private readonly inviteLinkField2: Locator;
private readonly inviteLinkField3: Locator;
private readonly copyInviteLink: Locator;
private readonly finishButton: Locator;
constructor(public readonly page: Page) {
this.page = page;
this.loginWithGoogleButton = page.getByRole('button', {
name: 'Continue with Google',
});
this.loginWithEmailButton = page.getByRole('button', {
name: 'Continue With Email',
});
this.termsOfServiceLink = page.getByRole('link', {
name: 'Terms of Service',
});
this.privacyPolicyLink = page.getByRole('link', { name: 'Privacy Policy' });
this.emailField = page.getByPlaceholder('Email');
this.continueButton = page.getByRole('button', {
name: 'Continue',
exact: true,
});
this.forgotPasswordButton = page.getByText('Forgot your password?');
this.passwordField = page.getByPlaceholder('Password');
this.revealPasswordButton = page.getByTestId('reveal-password-button');
this.signInButton = page.getByRole('button', { name: 'Sign in' });
this.signUpButton = page.getByRole('button', { name: 'Sign up' });
this.previewImageButton = page.locator('.css-1qzw107'); // TODO: fix
this.uploadImageButton = page.getByRole('button', { name: 'Upload' });
this.deleteImageButton = page.getByRole('button', { name: 'Remove' });
this.workspaceNameField = page.getByPlaceholder('Apple');
this.firstNameField = page.getByPlaceholder('Tim');
this.lastNameField = page.getByPlaceholder('Cook');
this.syncEverythingWithGoogleRadio = page.locator(
'input[value="SHARE_EVERYTHING"]',
);
this.syncSubjectAndMetadataWithGoogleRadio = page.locator(
'input[value="SUBJECT"]',
);
this.syncMetadataWithGoogleRadio = page.locator('input[value="METADATA"]');
this.syncWithGoogleButton = page.getByRole('button', {
name: 'Sync with Google',
});
this.noSyncButton = page.getByText('Continue without sync');
this.inviteLinkField1 = page.getByPlaceholder('tim@apple.dev');
this.inviteLinkField2 = page.getByPlaceholder('craig@apple.dev');
this.inviteLinkField3 = page.getByPlaceholder('mike@apple.dev');
this.copyInviteLink = page.getByRole('button', {
name: 'Copy invitation link',
});
this.finishButton = page.getByRole('button', { name: 'Finish' });
}
async loginWithGoogle() {
await this.loginWithGoogleButton.click();
}
async clickLoginWithEmail() {
await this.loginWithEmailButton.click();
}
async clickContinueButton() {
await this.continueButton.click();
}
async clickTermsLink() {
await this.termsOfServiceLink.click();
}
async clickPrivacyPolicyLink() {
await this.privacyPolicyLink.click();
}
async typeEmail(email: string) {
await this.emailField.fill(email);
}
async typePassword(email: string) {
await this.passwordField.fill(email);
}
async clickSignInButton() {
await this.signInButton.click();
}
async clickSignUpButton() {
await this.signUpButton.click();
}
async clickForgotPassword() {
await this.forgotPasswordButton.click();
}
async revealPassword() {
await this.revealPasswordButton.click();
}
async previewImage() {
await this.previewImageButton.click();
}
async clickUploadImage() {
await this.uploadImageButton.click();
}
async deleteImage() {
await this.deleteImageButton.click();
}
async typeWorkspaceName(workspaceName: string) {
await this.workspaceNameField.fill(workspaceName);
}
async typeFirstName(firstName: string) {
await this.firstNameField.fill(firstName);
}
async typeLastName(lastName: string) {
await this.lastNameField.fill(lastName);
}
async clickSyncEverythingWithGoogleRadio() {
await this.syncEverythingWithGoogleRadio.click();
}
async clickSyncSubjectAndMetadataWithGoogleRadio() {
await this.syncSubjectAndMetadataWithGoogleRadio.click();
}
async clickSyncMetadataWithGoogleRadio() {
await this.syncMetadataWithGoogleRadio.click();
}
async clickSyncWithGoogleButton() {
await this.syncWithGoogleButton.click();
}
async noSyncWithGoogle() {
await this.noSyncButton.click();
}
async typeInviteLink1(email: string) {
await this.inviteLinkField1.fill(email);
}
async typeInviteLink2(email: string) {
await this.inviteLinkField2.fill(email);
}
async typeInviteLink3(email: string) {
await this.inviteLinkField3.fill(email);
}
async clickCopyInviteLink() {
await this.copyInviteLink.click();
}
async clickFinishButton() {
await this.finishButton.click();
}
}
@@ -0,0 +1,196 @@
import { Locator, Page } from '@playwright/test';
export class MainPage {
// TODO: add missing elements (advanced filters, import/export popups)
private readonly tableViews: Locator;
private readonly addViewButton: Locator;
private readonly viewIconSelect: Locator;
private readonly viewNameInput: Locator;
private readonly viewTypeSelect: Locator;
private readonly createViewButton: Locator;
private readonly deleteViewButton: Locator;
private readonly filterButton: Locator;
private readonly searchFieldInput: Locator;
private readonly advancedFilterButton: Locator;
private readonly addFilterButton: Locator;
private readonly resetFilterButton: Locator;
private readonly saveFilterAsViewButton: Locator;
private readonly sortButton: Locator;
private readonly sortOrderButton: Locator;
private readonly optionsButton: Locator;
private readonly fieldsButton: Locator;
private readonly goBackButton: Locator;
private readonly hiddenFieldsButton: Locator;
private readonly editFieldsButton: Locator;
private readonly importButton: Locator;
private readonly exportButton: Locator;
private readonly deletedRecordsButton: Locator;
private readonly createNewRecordButton: Locator;
private readonly addToFavoritesButton: Locator;
private readonly deleteFromFavoritesButton: Locator;
private readonly exportBottomBarButton: Locator;
private readonly deleteRecordsButton: Locator;
constructor(public readonly page: Page) {
this.tableViews = page.getByText('·');
this.addViewButton = page
.getByTestId('tooltip')
.filter({ hasText: /^Add view$/ });
this.viewIconSelect = page.getByLabel('Click to select icon (');
this.viewNameInput; // can be selected using only actual value
this.viewTypeSelect = page.locator(
"//span[contains(., 'View type')]/../div",
);
this.createViewButton = page.getByRole('button', { name: 'Create' });
this.deleteViewButton = page.getByRole('button', { name: 'Delete' });
this.filterButton = page.getByText('Filter');
this.searchFieldInput = page.getByPlaceholder('Search fields');
this.advancedFilterButton = page
.getByTestId('tooltip')
.filter({ hasText: /^Advanced filter$/ });
this.addFilterButton = page.getByRole('button', { name: 'Add Filter' });
this.resetFilterButton = page.getByTestId('cancel-button');
this.saveFilterAsViewButton = page.getByRole('button', {
name: 'Save as new view',
});
this.sortButton = page.getByText('Sort');
this.sortOrderButton = page.locator('//li');
this.optionsButton = page.getByText('Options');
this.fieldsButton = page.getByText('Fields');
this.goBackButton = page.getByTestId('dropdown-menu-header-end-icon');
this.hiddenFieldsButton = page
.getByTestId('tooltip')
.filter({ hasText: /^Hidden Fields$/ });
this.editFieldsButton = page
.getByTestId('tooltip')
.filter({ hasText: /^Edit Fields$/ });
this.importButton = page
.getByTestId('tooltip')
.filter({ hasText: /^Import$/ });
this.exportButton = page
.getByTestId('tooltip')
.filter({ hasText: /^Export$/ });
this.deletedRecordsButton = page
.getByTestId('tooltip')
.filter({ hasText: /^Deleted */ });
this.createNewRecordButton = page.getByTestId('add-button');
this.addToFavoritesButton = page.getByText('Add to favorites');
this.deleteFromFavoritesButton = page.getByText('Delete from favorites');
this.exportBottomBarButton = page.getByText('Export');
this.deleteRecordsButton = page.getByText('Delete');
}
async clickTableViews() {
await this.tableViews.click();
}
async clickAddViewButton() {
await this.addViewButton.click();
}
async typeViewName(name: string) {
await this.viewNameInput.clear();
await this.viewNameInput.fill(name);
}
// name can be either be 'Table' or 'Kanban'
async selectViewType(name: string) {
await this.viewTypeSelect.click();
await this.page.getByTestId('tooltip').filter({ hasText: name }).click();
}
async createView() {
await this.createViewButton.click();
}
async deleteView() {
await this.deleteViewButton.click();
}
async clickFilterButton() {
await this.filterButton.click();
}
async searchFields(name: string) {
await this.searchFieldInput.clear();
await this.searchFieldInput.fill(name);
}
async clickAdvancedFilterButton() {
await this.advancedFilterButton.click();
}
async addFilter() {
await this.addFilterButton.click();
}
async resetFilter() {
await this.resetFilterButton.click();
}
async saveFilterAsView() {
await this.saveFilterAsViewButton.click();
}
async clickSortButton() {
await this.sortButton.click();
}
//can be Ascending or Descending
async setSortOrder(name: string) {
await this.sortOrderButton.click();
await this.page.getByTestId('tooltip').filter({ hasText: name }).click();
}
async clickOptionsButton() {
await this.optionsButton.click();
}
async clickFieldsButton() {
await this.fieldsButton.click();
}
async clickBackButton() {
await this.goBackButton.click();
}
async clickHiddenFieldsButton() {
await this.hiddenFieldsButton.click();
}
async clickEditFieldsButton() {
await this.editFieldsButton.click();
}
async clickImportButton() {
await this.importButton.click();
}
async clickExportButton() {
await this.exportButton.click();
}
async clickDeletedRecordsButton() {
await this.deletedRecordsButton.click();
}
async clickCreateNewRecordButton() {
await this.createNewRecordButton.click();
}
async clickAddToFavoritesButton() {
await this.addToFavoritesButton.click();
}
async clickDeleteFromFavoritesButton() {
await this.deleteFromFavoritesButton.click();
}
async clickExportBottomBarButton() {
await this.exportBottomBarButton.click();
}
async clickDeleteRecordsButton() {
await this.deleteRecordsButton.click();
}
}
@@ -0,0 +1,150 @@
import { Locator, Page } from '@playwright/test';
export class RecordDetails {
// TODO: add missing components in tasks, notes, files, emails, calendar tabs
private readonly closeRecordButton: Locator;
private readonly previousRecordButton: Locator;
private readonly nextRecordButton: Locator;
private readonly favoriteRecordButton: Locator;
private readonly addShowPageButton: Locator;
private readonly moreOptionsButton: Locator;
private readonly deleteButton: Locator;
private readonly uploadProfileImageButton: Locator;
private readonly timelineTab: Locator;
private readonly tasksTab: Locator;
private readonly notesTab: Locator;
private readonly filesTab: Locator;
private readonly emailsTab: Locator;
private readonly calendarTab: Locator;
private readonly detachRelationButton: Locator;
constructor(public readonly page: Page) {
this.page = page;
}
async clickCloseRecordButton() {
await this.closeRecordButton.click();
}
async clickPreviousRecordButton() {
await this.previousRecordButton.click();
}
async clickNextRecordButton() {
await this.nextRecordButton.click();
}
async clickFavoriteRecordButton() {
await this.favoriteRecordButton.click();
}
async createRelatedNote() {
await this.addShowPageButton.click();
await this.page
.locator('//div[@data-testid="tooltip" and contains(., "Note")]')
.click();
}
async createRelatedTask() {
await this.addShowPageButton.click();
await this.page
.locator('//div[@data-testid="tooltip" and contains(., "Task")]')
.click();
}
async clickMoreOptionsButton() {
await this.moreOptionsButton.click();
}
async clickDeleteRecordButton() {
await this.deleteButton.click();
}
async clickUploadProfileImageButton() {
await this.uploadProfileImageButton.click();
}
async goToTimelineTab() {
await this.timelineTab.click();
}
async goToTasksTab() {
await this.tasksTab.click();
}
async goToNotesTab() {
await this.notesTab.click();
}
async goToFilesTab() {
await this.filesTab.click();
}
async goToEmailsTab() {
await this.emailsTab.click();
}
async goToCalendarTab() {
await this.calendarTab.click();
}
async clickField(name: string) {
await this.page
.locator(
`//div[@data-testid='tooltip' and contains(., '${name}']/../../../div[last()]/div/div`,
)
.click();
}
async clickFieldWithButton(name: string) {
await this.page
.locator(
`//div[@data-testid='tooltip' and contains(., '${name}']/../../../div[last()]/div/div`,
)
.hover();
await this.page
.locator(
`//div[@data-testid='tooltip' and contains(., '${name}']/../../../div[last()]/div/div[last()]/div/button`,
)
.click();
}
async clickRelationEditButton(name: string) {
await this.page.getByRole('heading').filter({ hasText: name }).hover();
await this.page
.locator(`//header[contains(., "${name}")]/div[last()]/div/button`)
.click();
}
async detachRelation(name: string) {
await this.page.locator(`//a[contains(., "${name}")]`).hover();
await this.page
.locator(`, //a[contains(., "${name}")]/../div[last()]/div/div/button`)
.hover();
await this.detachRelationButton.click();
}
async deleteRelationRecord(name: string) {
await this.page.locator(`//a[contains(., "${name}")]`).hover();
await this.page
.locator(`, //a[contains(., "${name}")]/../div[last()]/div/div/button`)
.hover();
await this.deleteButton.click();
}
async selectRelationRecord(name: string) {
await this.page
.locator(`//div[@data-testid="tooltip" and contains(., "${name}")]`)
.click();
}
async searchRelationRecord(name: string) {
await this.page.getByPlaceholder('Search').fill(name);
}
async createNewRelationRecord() {
await this.page
.locator('//div[@data-testid="tooltip" and contains(., "Add New")]')
.click();
}
}
@@ -0,0 +1,54 @@
import { Locator, Page } from '@playwright/test';
export class AccountsSection {
private readonly addAccountButton: Locator;
private readonly deleteAccountButton: Locator;
private readonly addBlocklistField: Locator;
private readonly addBlocklistButton: Locator;
private readonly connectWithGoogleButton: Locator;
constructor(public readonly page: Page) {
this.page = page;
this.addAccountButton = page.getByRole('button', { name: 'Add account' });
this.deleteAccountButton = page
.getByTestId('tooltip')
.getByText('Remove account');
this.addBlocklistField = page.getByPlaceholder(
'eddy@gmail.com, @apple.com',
);
this.addBlocklistButton = page.getByRole('button', {
name: 'Add to blocklist',
});
this.connectWithGoogleButton = page.getByRole('button', {
name: 'Connect with Google',
});
}
async clickAddAccount() {
await this.addAccountButton.click();
}
async deleteAccount(email: string) {
await this.page
.locator(`//span[contains(., "${email}")]/../div/div/div/button`)
.click();
await this.deleteAccountButton.click();
}
async addToBlockList(domain: string) {
await this.addBlocklistField.fill(domain);
await this.addBlocklistButton.click();
}
async removeFromBlocklist(domain: string) {
await this.page
.locator(
`//div[@data-testid='tooltip' and contains(., '${domain}')]/../../div[last()]/button`,
)
.click();
}
async linkGoogleAccount() {
await this.connectWithGoogleButton.click();
}
}
@@ -0,0 +1,30 @@
import { Locator, Page } from '@playwright/test';
export class CalendarSection {
private readonly eventVisibilityEverythingOption: Locator;
private readonly eventVisibilityMetadataOption: Locator;
private readonly contactAutoCreation: Locator;
constructor(public readonly page: Page) {
this.page = page;
this.eventVisibilityEverythingOption = page.locator(
'input[value="SHARE_EVERYTHING"]',
);
this.eventVisibilityMetadataOption = page.locator(
'input[value="METADATA"]',
);
this.contactAutoCreation = page.getByRole('checkbox').nth(1);
}
async changeVisibilityToEverything() {
await this.eventVisibilityEverythingOption.click();
}
async changeVisibilityToMetadata() {
await this.eventVisibilityMetadataOption.click();
}
async toggleAutoCreation() {
await this.contactAutoCreation.click();
}
}
@@ -0,0 +1,189 @@
import { Locator, Page } from '@playwright/test';
export class DataModelSection {
private readonly searchObjectInput: Locator;
private readonly addObjectButton: Locator;
private readonly objectSingularNameInput: Locator;
private readonly objectPluralNameInput: Locator;
private readonly objectDescription: Locator;
private readonly synchronizeLabelAPIToggle: Locator;
private readonly objectAPISingularNameInput: Locator;
private readonly objectAPIPluralNameInput: Locator;
private readonly objectMoreOptionsButton: Locator;
private readonly editObjectButton: Locator;
private readonly deleteObjectButton: Locator;
private readonly activeSection: Locator;
private readonly inactiveSection: Locator;
private readonly searchFieldInput: Locator;
private readonly addFieldButton: Locator;
private readonly viewFieldDetailsMoreOptionsButton: Locator;
private readonly nameFieldInput: Locator;
private readonly descriptionFieldInput: Locator;
private readonly deactivateMoreOptionsButton: Locator;
private readonly activateMoreOptionsButton: Locator;
private readonly deactivateButton: Locator; // TODO: add attribute to make it one button
private readonly activateButton: Locator;
private readonly cancelButton: Locator;
private readonly saveButton: Locator;
constructor(public readonly page: Page) {
this.searchObjectInput = page.getByPlaceholder('Search an object...');
this.addObjectButton = page.getByRole('button', { name: 'Add object' });
this.objectSingularNameInput = page.getByPlaceholder('Listing', {
exact: true,
});
this.objectPluralNameInput = page.getByPlaceholder('Listings', {
exact: true,
});
this.objectDescription = page.getByPlaceholder('Write a description');
this.synchronizeLabelAPIToggle = page.getByRole('checkbox').nth(1);
this.objectAPISingularNameInput = page.getByPlaceholder('listing', {
exact: true,
});
this.objectAPIPluralNameInput = page.getByPlaceholder('listings', {
exact: true,
});
this.objectMoreOptionsButton = page.getByLabel('Object Options');
this.editObjectButton = page.getByTestId('tooltip').getByText('Edit');
this.deactivateMoreOptionsButton = page
.getByTestId('tooltip')
.getByText('Deactivate');
this.activateMoreOptionsButton = page
.getByTestId('tooltip')
.getByText('Activate');
this.deleteObjectButton = page.getByTestId('tooltip').getByText('Delete');
this.activeSection = page.getByText('Active', { exact: true });
this.inactiveSection = page.getByText('Inactive');
this.searchFieldInput = page.getByPlaceholder('Search a field...');
this.addFieldButton = page.getByRole('button', { name: 'Add field' });
this.viewFieldDetailsMoreOptionsButton = page
.getByTestId('tooltip')
.getByText('View');
this.nameFieldInput = page.getByPlaceholder('Employees');
this.descriptionFieldInput = page.getByPlaceholder('Write a description');
this.deactivateButton = page.getByRole('button', { name: 'Deactivate' });
this.activateButton = page.getByRole('button', { name: 'Activate' });
this.cancelButton = page.getByRole('button', { name: 'Cancel' });
this.saveButton = page.getByRole('button', { name: 'Save' });
}
async searchObject(name: string) {
await this.searchObjectInput.fill(name);
}
async clickAddObjectButton() {
await this.addObjectButton.click();
}
async typeObjectSingularName(name: string) {
await this.objectSingularNameInput.fill(name);
}
async typeObjectPluralName(name: string) {
await this.objectPluralNameInput.fill(name);
}
async typeObjectDescription(name: string) {
await this.objectDescription.fill(name);
}
async toggleSynchronizeLabelAPI() {
await this.synchronizeLabelAPIToggle.click();
}
async typeObjectSingularAPIName(name: string) {
await this.objectAPISingularNameInput.fill(name);
}
async typeObjectPluralAPIName(name: string) {
await this.objectAPIPluralNameInput.fill(name);
}
async checkObjectDetails(name: string) {
await this.page.getByRole('link').filter({ hasText: name }).click();
}
async activateInactiveObject(name: string) {
await this.page
.locator(`//div[@title="${name}"]/../../div[last()]`)
.click();
await this.activateButton.click();
}
// object can be deleted only if is custom and inactive
async deleteInactiveObject(name: string) {
await this.page
.locator(`//div[@title="${name}"]/../../div[last()]`)
.click();
await this.deleteObjectButton.click();
}
async editObjectDetails() {
await this.objectMoreOptionsButton.click();
await this.editObjectButton.click();
}
async deactivateObjectWithMoreOptions() {
await this.objectMoreOptionsButton.click();
await this.deactivateButton.click();
}
async searchField(name: string) {
await this.searchFieldInput.fill(name);
}
async checkFieldDetails(name: string) {
await this.page.locator(`//div[@title="${name}"]`).click();
}
async checkFieldDetailsWithButton(name: string) {
await this.page
.locator(`//div[@title="${name}"]/../../div[last()]`)
.click();
await this.viewFieldDetailsMoreOptionsButton.click();
}
async deactivateFieldWithButton(name: string) {
await this.page
.locator(`//div[@title="${name}"]/../../div[last()]`)
.click();
await this.deactivateMoreOptionsButton.click();
}
async activateFieldWithButton(name: string) {
await this.page
.locator(`//div[@title="${name}"]/../../div[last()]`)
.click();
await this.activateMoreOptionsButton.click();
}
async clickAddFieldButton() {
await this.addFieldButton.click();
}
async typeFieldName(name: string) {
await this.nameFieldInput.clear();
await this.nameFieldInput.fill(name);
}
async typeFieldDescription(description: string) {
await this.descriptionFieldInput.clear();
await this.descriptionFieldInput.fill(description);
}
async clickInactiveSection() {
await this.inactiveSection.click();
}
async clickActiveSection() {
await this.activeSection.click();
}
async clickCancelButton() {
await this.cancelButton.click();
}
async clickSaveButton() {
await this.saveButton.click();
}
}
@@ -0,0 +1,123 @@
import { Locator, Page } from '@playwright/test';
export class DevelopersSection {
private readonly readDocumentationButton: Locator;
private readonly createAPIKeyButton: Locator;
private readonly regenerateAPIKeyButton: Locator;
private readonly nameOfAPIKeyInput: Locator;
private readonly expirationDateAPIKeySelect: Locator;
private readonly createWebhookButton: Locator;
private readonly webhookURLInput: Locator;
private readonly webhookDescription: Locator;
private readonly webhookFilterObjectSelect: Locator;
private readonly webhookFilterActionSelect: Locator;
private readonly cancelButton: Locator;
private readonly saveButton: Locator;
private readonly deleteButton: Locator;
constructor(public readonly page: Page) {
this.page = page;
this.readDocumentationButton = page.getByRole('link', {
name: 'Read documentation',
});
this.createAPIKeyButton = page.getByRole('link', {
name: 'Create API Key',
});
this.createWebhookButton = page.getByRole('link', {
name: 'Create Webhook',
});
this.nameOfAPIKeyInput = page
.getByPlaceholder('E.g. backoffice integration')
.first();
this.expirationDateAPIKeySelect = page
.locator('div')
.filter({ hasText: /^Never$/ })
.nth(3); // good enough if expiration date will change only 1 time
this.regenerateAPIKeyButton = page.getByRole('button', {
name: 'Regenerate Key',
});
this.webhookURLInput = page.getByPlaceholder('URL');
this.webhookDescription = page.getByPlaceholder('Write a description');
this.webhookFilterObjectSelect = page
.locator('div')
.filter({ hasText: /^All Objects$/ })
.nth(3); // works only for first filter
this.webhookFilterActionSelect = page
.locator('div')
.filter({ hasText: /^All Actions$/ })
.nth(3); // works only for first filter
this.cancelButton = page.getByRole('button', { name: 'Cancel' });
this.saveButton = page.getByRole('button', { name: 'Save' });
this.deleteButton = page.getByRole('button', { name: 'Delete' });
}
async openDocumentation() {
await this.readDocumentationButton.click();
}
async createAPIKey() {
await this.createAPIKeyButton.click();
}
async typeAPIKeyName(name: string) {
await this.nameOfAPIKeyInput.clear();
await this.nameOfAPIKeyInput.fill(name);
}
async selectAPIExpirationDate(date: string) {
await this.expirationDateAPIKeySelect.click();
await this.page.getByText(date, { exact: true }).click();
}
async regenerateAPIKey() {
await this.regenerateAPIKeyButton.click();
}
async deleteAPIKey() {
await this.deleteButton.click();
}
async deleteWebhook() {
await this.deleteButton.click();
}
async createWebhook() {
await this.createWebhookButton.click();
}
async typeWebhookURL(url: string) {
await this.webhookURLInput.fill(url);
}
async typeWebhookDescription(description: string) {
await this.webhookDescription.fill(description);
}
async selectWebhookObject(object: string) {
// TODO: finish
}
async selectWebhookAction(action: string) {
// TODO: finish
}
async deleteWebhookFilter() {
// TODO: finish
}
async clickCancelButton() {
await this.cancelButton.click();
}
async clickSaveButton() {
await this.saveButton.click();
}
async checkAPIKeyDetails(name: string) {
await this.page.locator(`//a/div[contains(.,'${name}')][first()]`).click();
}
async checkWebhookDetails(name: string) {
await this.page.locator(`//a/div[contains(.,'${name}')][first()]`).click();
}
}
@@ -0,0 +1,61 @@
import { Locator, Page } from '@playwright/test';
export class EmailsSection {
private readonly visibilityEverythingRadio: Locator;
private readonly visibilitySubjectRadio: Locator;
private readonly visibilityMetadataRadio: Locator;
private readonly autoCreationReceivedRadio: Locator;
private readonly autoCreationSentRadio: Locator;
private readonly autoCreationNoneRadio: Locator;
private readonly excludeNonProfessionalToggle: Locator;
private readonly excludeGroupToggle: Locator;
constructor(public readonly page: Page) {
this.page = page;
this.visibilityEverythingRadio = page.locator(
'input[value="SHARE_EVERYTHING"]',
);
this.visibilitySubjectRadio = page.locator('input[value="SUBJECT"]');
this.visibilityMetadataRadio = page.locator('input[value="METADATA"]');
this.autoCreationReceivedRadio = page.locator(
'input[value="SENT_AND_RECEIVED"]',
);
this.autoCreationSentRadio = page.locator('input[value="SENT"]');
this.autoCreationNoneRadio = page.locator('input[value="NONE"]');
// first checkbox is advanced settings toggle
this.excludeNonProfessionalToggle = page.getByRole('checkbox').nth(1);
this.excludeGroupToggle = page.getByRole('checkbox').nth(2);
}
async changeVisibilityToEverything() {
await this.visibilityEverythingRadio.click();
}
async changeVisibilityToSubject() {
await this.visibilitySubjectRadio.click();
}
async changeVisibilityToMetadata() {
await this.visibilityMetadataRadio.click();
}
async changeAutoCreationToAll() {
await this.autoCreationReceivedRadio.click();
}
async changeAutoCreationToSent() {
await this.autoCreationSentRadio.click();
}
async changeAutoCreationToNone() {
await this.autoCreationNoneRadio.click();
}
async toggleExcludeNonProfessional() {
await this.excludeNonProfessionalToggle.click();
}
async toggleExcludeGroup() {
await this.excludeGroupToggle.click();
}
}
@@ -0,0 +1,55 @@
import { Locator, Page } from '@playwright/test';
export class ExperienceSection {
private readonly lightThemeButton: Locator;
private readonly darkThemeButton: Locator;
private readonly timezoneDropdown: Locator;
private readonly dateFormatDropdown: Locator;
private readonly timeFormatDropdown: Locator;
private readonly searchInput: Locator;
constructor(public readonly page: Page) {
this.page = page;
this.lightThemeButton = page.getByText('AaLight'); // it works
this.darkThemeButton = page.getByText('AaDark');
this.timezoneDropdown = page.locator(
'//span[contains(., "Time zone")]/../div/div/div',
);
this.dateFormatDropdown = page.locator(
'//span[contains(., "Date format")]/../div/div/div',
);
this.timeFormatDropdown = page.locator(
'//span[contains(., "Time format")]/../div/div/div',
);
this.searchInput = page.getByPlaceholder('Search');
}
async changeThemeToLight() {
await this.lightThemeButton.click();
}
async changeThemeToDark() {
await this.darkThemeButton.click();
}
async selectTimeZone(timezone: string) {
await this.timezoneDropdown.click();
await this.page.getByText(timezone, { exact: true }).click();
}
async selectTimeZoneWithSearch(timezone: string) {
await this.timezoneDropdown.click();
await this.searchInput.fill(timezone);
await this.page.getByText(timezone, { exact: true }).click();
}
async selectDateFormat(dateFormat: string) {
await this.dateFormatDropdown.click();
await this.page.getByText(dateFormat, { exact: true }).click();
}
async selectTimeFormat(timeFormat: string) {
await this.timeFormatDropdown.click();
await this.page.getByText(timeFormat, { exact: true }).click();
}
}
@@ -0,0 +1,159 @@
import { Locator, Page } from '@playwright/test';
export class FunctionsSection {
private readonly newFunctionButton: Locator;
private readonly functionNameInput: Locator;
private readonly functionDescriptionInput: Locator;
private readonly editorTab: Locator;
private readonly codeEditorField: Locator;
private readonly resetButton: Locator;
private readonly publishButton: Locator;
private readonly testButton: Locator;
private readonly testTab: Locator;
private readonly runFunctionButton: Locator;
private readonly inputField: Locator;
private readonly settingsTab: Locator;
private readonly searchVariableInput: Locator;
private readonly addVariableButton: Locator;
private readonly nameVariableInput: Locator;
private readonly valueVariableInput: Locator;
private readonly cancelVariableButton: Locator;
private readonly saveVariableButton: Locator;
private readonly editVariableButton: Locator;
private readonly deleteVariableButton: Locator;
private readonly cancelButton: Locator;
private readonly saveButton: Locator;
private readonly deleteButton: Locator;
constructor(public readonly page: Page) {
this.newFunctionButton = page.getByRole('button', { name: 'New Function' });
this.functionNameInput = page.getByPlaceholder('Name');
this.functionDescriptionInput = page.getByPlaceholder('Description');
this.editorTab = page.getByTestId('tab-editor');
this.codeEditorField = page.getByTestId('dummyInput'); // TODO: fix
this.resetButton = page.getByRole('button', { name: 'Reset' });
this.publishButton = page.getByRole('button', { name: 'Publish' });
this.testButton = page.getByRole('button', { name: 'Test' });
this.testTab = page.getByTestId('tab-test');
this.runFunctionButton = page.getByRole('button', { name: 'Run Function' });
this.inputField = page.getByTestId('dummyInput'); // TODO: fix
this.settingsTab = page.getByTestId('tab-settings');
this.searchVariableInput = page.getByPlaceholder('Search a variable');
this.addVariableButton = page.getByRole('button', { name: 'Add Variable' });
this.nameVariableInput = page.getByPlaceholder('Name').nth(1);
this.valueVariableInput = page.getByPlaceholder('Value');
this.cancelVariableButton = page.locator('.css-uwqduk').first(); // TODO: fix
this.saveVariableButton = page.locator('.css-uwqduk').nth(1); // TODO: fix
this.editVariableButton = page.getByText('Edit', { exact: true });
this.deleteVariableButton = page.getByText('Delete', { exact: true });
this.cancelButton = page.getByRole('button', { name: 'Cancel' });
this.saveButton = page.getByRole('button', { name: 'Save' });
this.deleteButton = page.getByRole('button', { name: 'Delete function' });
}
async clickNewFunction() {
await this.newFunctionButton.click();
}
async typeFunctionName(name: string) {
await this.functionNameInput.fill(name);
}
async typeFunctionDescription(description: string) {
await this.functionDescriptionInput.fill(description);
}
async checkFunctionDetails(name: string) {
await this.page.getByRole('link', { name: `${name} nodejs18.x` }).click();
}
async clickEditorTab() {
await this.editorTab.click();
}
async clickResetButton() {
await this.resetButton.click();
}
async clickPublishButton() {
await this.publishButton.click();
}
async clickTestButton() {
await this.testButton.click();
}
async typeFunctionCode() {
// TODO: finish once utils are merged
}
async clickTestTab() {
await this.testTab.click();
}
async runFunction() {
await this.runFunctionButton.click();
}
async typeFunctionInput() {
// TODO: finish once utils are merged
}
async clickSettingsTab() {
await this.settingsTab.click();
}
async searchVariable(name: string) {
await this.searchVariableInput.fill(name);
}
async addVariable() {
await this.addVariableButton.click();
}
async typeVariableName(name: string) {
await this.nameVariableInput.fill(name);
}
async typeVariableValue(value: string) {
await this.valueVariableInput.fill(value);
}
async editVariable(name: string) {
await this.page
.locator(
`//div[@data-testid='tooltip' and contains(., '${name}')]/../../div[last()]/div/div/button`,
)
.click();
await this.editVariableButton.click();
}
async deleteVariable(name: string) {
await this.page
.locator(
`//div[@data-testid='tooltip' and contains(., '${name}')]/../../div[last()]/div/div/button`,
)
.click();
await this.deleteVariableButton.click();
}
async cancelVariable() {
await this.cancelVariableButton.click();
}
async saveVariable() {
await this.saveVariableButton.click();
}
async clickCancelButton() {
await this.cancelButton.click();
}
async clickSaveButton() {
await this.saveButton.click();
}
async clickDeleteButton() {
await this.deleteButton.click();
}
}
@@ -0,0 +1,29 @@
import { Locator, Page } from '@playwright/test';
export class GeneralSection {
private readonly workspaceNameField: Locator;
private readonly supportSwitch: Locator;
private readonly deleteWorkspaceButton: Locator;
constructor(public readonly page: Page) {
this.page = page;
this.workspaceNameField = page.getByPlaceholder('Apple');
this.supportSwitch = page.getByRole('checkbox').nth(1);
this.deleteWorkspaceButton = page.getByRole('button', {
name: 'Delete workspace',
});
}
async changeWorkspaceName(workspaceName: string) {
await this.workspaceNameField.clear();
await this.workspaceNameField.fill(workspaceName);
}
async changeSupportSwitchState() {
await this.supportSwitch.click();
}
async clickDeleteWorkSpaceButton() {
await this.deleteWorkspaceButton.click();
}
}
@@ -0,0 +1,48 @@
import { Locator, Page } from '@playwright/test';
export class MembersSection {
private readonly inviteMembersField: Locator;
private readonly inviteMembersButton: Locator;
private readonly inviteLinkButton: Locator;
constructor(public readonly page: Page) {
this.page = page;
this.inviteMembersField = page.getByPlaceholder(
'tim@apple.com, jony.ive@apple',
);
this.inviteMembersButton = page.getByRole('button', { name: 'Invite' });
this.inviteLinkButton = page.getByRole('button', { name: 'Copy link' });
}
async copyInviteLink() {
await this.inviteLinkButton.click();
}
async sendInviteEmail(email: string) {
await this.inviteMembersField.click();
await this.inviteMembersField.fill(email);
await this.inviteMembersButton.click();
}
async deleteMember(email: string) {
await this.page
.locator(`//div[contains(., '${email}')]/../../div[last()]/div/button`)
.click();
}
async deleteInviteEmail(email: string) {
await this.page
.locator(
`//div[contains(., '${email}')]/../../div[last()]/div/button[first()]`,
)
.click();
}
async refreshInviteEmail(email: string) {
await this.page
.locator(
`//div[contains(., '${email}')]/../../div[last()]/div/button[last()]`,
)
.click();
}
}
@@ -0,0 +1,250 @@
import { Locator, Page } from '@playwright/test';
export class NewFieldSection {
private readonly searchTypeFieldInput: Locator;
private readonly currencyFieldLink: Locator;
private readonly currencyDefaultUnitSelect: Locator;
private readonly emailsFieldLink: Locator;
private readonly linksFieldLink: Locator;
private readonly phonesFieldLink: Locator;
private readonly addressFieldLink: Locator;
private readonly textFieldLink: Locator;
private readonly numberFieldLink: Locator;
private readonly decreaseDecimalsButton: Locator;
private readonly decimalsNumberInput: Locator;
private readonly increaseDecimalsButton: Locator;
private readonly booleanFieldLink: Locator;
private readonly defaultBooleanSelect: Locator;
private readonly dateTimeFieldLink: Locator;
private readonly dateFieldLink: Locator;
private readonly relativeDateToggle: Locator;
private readonly selectFieldLink: Locator;
private readonly multiSelectFieldLink: Locator;
private readonly setAsDefaultOptionButton: Locator;
private readonly removeOptionButton: Locator;
private readonly addOptionButton: Locator;
private readonly ratingFieldLink: Locator;
private readonly JSONFieldLink: Locator;
private readonly arrayFieldLink: Locator;
private readonly relationFieldLink: Locator;
private readonly relationTypeSelect: Locator;
private readonly objectDestinationSelect: Locator;
private readonly relationFieldNameInput: Locator;
private readonly fullNameFieldLink: Locator;
private readonly UUIDFieldLink: Locator;
private readonly nameFieldInput: Locator;
private readonly descriptionFieldInput: Locator;
constructor(public readonly page: Page) {
this.searchTypeFieldInput = page.getByPlaceholder('Search a type');
this.currencyFieldLink = page.getByRole('link', { name: 'Currency' });
this.currencyDefaultUnitSelect = page.locator(
"//span[contains(., 'Default Unit')]/../div",
);
this.emailsFieldLink = page.getByRole('link', { name: 'Emails' }).nth(1);
this.linksFieldLink = page.getByRole('link', { name: 'Links' });
this.phonesFieldLink = page.getByRole('link', { name: 'Phones' });
this.addressFieldLink = page.getByRole('link', { name: 'Address' });
this.textFieldLink = page.getByRole('link', { name: 'Text' });
this.numberFieldLink = page.getByRole('link', { name: 'Number' });
this.decreaseDecimalsButton = page.locator(
"//div[contains(., 'Number of decimals')]/../div[last()]/div/div/button[2]",
);
this.decimalsNumberInput = page.locator(
// would be better if first div was span tag
"//div[contains(., 'Number of decimals')]/../div[last()]/div/div/div/div/input[2]",
);
this.increaseDecimalsButton = page.locator(
"//div[contains(., 'Number of decimals')]/../div[last()]/div/div/button[3]",
);
this.booleanFieldLink = page.getByRole('link', { name: 'True/False' });
this.defaultBooleanSelect = page.locator(
"//span[contains(., 'Default Value')]/../div",
);
this.dateTimeFieldLink = page.getByRole('link', { name: 'Date and Time' });
this.dateFieldLink = page.getByRole('link', { name: 'Date' });
this.relativeDateToggle = page.getByRole('checkbox').nth(1);
this.selectFieldLink = page.getByRole('link', { name: 'Select' });
this.multiSelectFieldLink = page.getByRole('link', {
name: 'Multi-select',
});
this.setAsDefaultOptionButton = page
.getByTestId('tooltip')
.getByText('Set as default');
this.removeOptionButton = page
.getByTestId('tooltip')
.getByText('Remove option');
this.addOptionButton = page.getByRole('button', { name: 'Add option' });
this.ratingFieldLink = page.getByRole('link', { name: 'Rating' });
this.JSONFieldLink = page.getByRole('link', { name: 'JSON' });
this.arrayFieldLink = page.getByRole('link', { name: 'Array' });
this.relationFieldLink = page.getByRole('link', { name: 'Relation' });
this.relationTypeSelect = page.locator(
"//span[contains(., 'Relation type')]/../div",
);
this.objectDestinationSelect = page.locator(
"//span[contains(., 'Object destination')]/../div",
);
this.relationIconSelect = page.getByLabel('Click to select icon (').nth(1);
this.relationFieldNameInput = page.getByPlaceholder('Field name');
this.fullNameFieldLink = page.getByRole('link', { name: 'Full Name' });
this.UUIDFieldLink = page.getByRole('link', { name: 'Unique ID' });
this.nameFieldInput = page.getByPlaceholder('Employees');
this.descriptionFieldInput = page.getByPlaceholder('Write a description');
}
async searchTypeField(name: string) {
await this.searchTypeFieldInput.fill(name);
}
async clickCurrencyType() {
await this.currencyFieldLink.click();
}
async selectDefaultUnit(name: string) {
await this.currencyDefaultUnitSelect.click();
await this.page.getByTestId('tooltip').filter({ hasText: name }).click();
}
async clickEmailsType() {
await this.emailsFieldLink.click();
}
async clickLinksType() {
await this.linksFieldLink.click();
}
async clickPhonesType() {
await this.phonesFieldLink.click();
}
async clickAddressType() {
await this.addressFieldLink.click();
}
async clickTextType() {
await this.textFieldLink.click();
}
async clickNumberType() {
await this.numberFieldLink.click();
}
async decreaseDecimals() {
await this.decreaseDecimalsButton.click();
}
async typeNumberOfDecimals(amount: number) {
await this.decimalsNumberInput.fill(String(amount));
}
async increaseDecimals() {
await this.increaseDecimalsButton.click();
}
async clickBooleanType() {
await this.booleanFieldLink.click();
}
// either True of False
async selectDefaultBooleanValue(value: string) {
await this.defaultBooleanSelect.click();
await this.page.getByTestId('tooltip').filter({ hasText: value }).click();
}
async clickDateTimeType() {
await this.dateTimeFieldLink.click();
}
async clickDateType() {
await this.dateFieldLink.click();
}
async toggleRelativeDate() {
await this.relativeDateToggle.click();
}
async clickSelectType() {
await this.selectFieldLink.click();
}
async clickMultiSelectType() {
await this.multiSelectFieldLink.click();
}
async addSelectOption() {
await this.addOptionButton.click();
}
async setOptionAsDefault() {
// TODO: finish
await this.setAsDefaultOptionButton.click();
}
async deleteSelectOption() {
// TODO: finish
await this.removeOptionButton.click();
}
async changeOptionAPIName() {
// TODO: finish
}
async changeOptionColor() {
// TODO: finish
}
async changeOptionName() {
// TODO: finish
}
async clickRatingType() {
await this.ratingFieldLink.click();
}
async clickJSONType() {
await this.JSONFieldLink.click();
}
async clickArrayType() {
await this.arrayFieldLink.click();
}
async clickRelationType() {
await this.relationFieldLink.click();
}
// either 'Has many' or 'Belongs to one'
async selectRelationType(name: string) {
await this.relationTypeSelect.click();
await this.page.getByTestId('tooltip').filter({ hasText: name }).click();
}
async selectObjectDestination(name: string) {
await this.objectDestinationSelect.click();
await this.page.getByTestId('tooltip').filter({ hasText: name }).click();
}
async typeRelationName(name: string) {
await this.relationFieldNameInput.clear();
await this.relationFieldNameInput.fill(name);
}
async clickFullNameType() {
await this.fullNameFieldLink.click();
}
async clickUUIDType() {
await this.UUIDFieldLink.click();
}
async typeFieldName(name: string) {
await this.nameFieldInput.clear();
await this.nameFieldInput.fill(name);
}
async typeFieldDescription(description: string) {
await this.descriptionFieldInput.clear();
await this.descriptionFieldInput.fill(description);
}
}
@@ -0,0 +1,44 @@
import { Locator, Page } from '@playwright/test';
export class ProfileSection {
private readonly firstNameField: Locator;
private readonly lastNameField: Locator;
private readonly emailField: Locator;
private readonly changePasswordButton: Locator;
private readonly deleteAccountButton: Locator;
constructor(public readonly page: Page) {
this.page = page;
this.firstNameField = page.getByPlaceholder('Tim');
this.lastNameField = page.getByPlaceholder('Cook');
this.emailField = page.getByRole('textbox').nth(2);
this.changePasswordButton = page.getByRole('button', {
name: 'Change Password',
});
this.deleteAccountButton = page.getByRole('button', {
name: 'Delete account',
});
}
async changeFirstName(firstName: string) {
await this.firstNameField.clear();
await this.firstNameField.fill(firstName);
}
async changeLastName(lastName: string) {
await this.lastNameField.clear();
await this.lastNameField.fill(lastName);
}
async getEmail() {
await this.emailField.textContent();
}
async sendChangePasswordEmail() {
await this.changePasswordButton.click();
}
async deleteAccount() {
await this.deleteAccountButton.click();
}
}
@@ -0,0 +1,13 @@
import { Locator, Page } from '@playwright/test';
export class SecuritySection {
private readonly inviteByLinkToggle: Locator;
constructor(public readonly page: Page) {
this.inviteByLinkToggle = page.locator('input[type="checkbox"]').nth(1);
}
async toggleInviteByLink() {
await this.inviteByLinkToggle.click();
}
}
@@ -0,0 +1,104 @@
import { Locator, Page } from '@playwright/test';
export class SettingsPage {
private readonly exitSettingsLink: Locator;
private readonly profileLink: Locator;
private readonly experienceLink: Locator;
private readonly accountsLink: Locator;
private readonly emailsLink: Locator;
private readonly calendarsLink: Locator;
private readonly generalLink: Locator;
private readonly membersLink: Locator;
private readonly dataModelLink: Locator;
private readonly developersLink: Locator;
private readonly functionsLink: Locator;
private readonly securityLink: Locator;
private readonly integrationsLink: Locator;
private readonly releasesLink: Locator;
private readonly logoutLink: Locator;
private readonly advancedToggle: Locator;
constructor(public readonly page: Page) {
this.page = page;
this.exitSettingsLink = page.getByRole('button', { name: 'Exit Settings' });
this.profileLink = page.getByRole('link', { name: 'Profile' });
this.experienceLink = page.getByRole('link', { name: 'Experience' });
this.accountsLink = page.getByRole('link', { name: 'Accounts' });
this.emailsLink = page.getByRole('link', { name: 'Emails', exact: true });
this.calendarsLink = page.getByRole('link', { name: 'Calendars' });
this.generalLink = page.getByRole('link', { name: 'General' });
this.membersLink = page.getByRole('link', { name: 'Members' });
this.dataModelLink = page.getByRole('link', { name: 'Data model' });
this.developersLink = page.getByRole('link', { name: 'Developers' });
this.functionsLink = page.getByRole('link', { name: 'Functions' });
this.integrationsLink = page.getByRole('link', { name: 'Integrations' });
this.securityLink = page.getByRole('link', { name: 'Security' });
this.releasesLink = page.getByRole('link', { name: 'Releases' });
this.logoutLink = page.getByText('Logout');
this.advancedToggle = page.locator('input[type="checkbox"]').first();
}
async leaveSettingsPage() {
await this.exitSettingsLink.click();
}
async goToProfileSection() {
await this.profileLink.click();
}
async goToExperienceSection() {
await this.experienceLink.click();
}
async goToAccountsSection() {
await this.accountsLink.click();
}
async goToEmailsSection() {
await this.emailsLink.click();
}
async goToCalendarsSection() {
await this.calendarsLink.click();
}
async goToGeneralSection() {
await this.generalLink.click();
}
async goToMembersSection() {
await this.membersLink.click();
}
async goToDataModelSection() {
await this.dataModelLink.click();
}
async goToDevelopersSection() {
await this.developersLink.click();
}
async goToFunctionsSection() {
await this.functionsLink.click();
}
async goToSecuritySection() {
await this.securityLink.click();
}
async goToIntegrationsSection() {
await this.integrationsLink.click();
}
async goToReleasesIntegration() {
await this.releasesLink.click();
}
async logout() {
await this.logoutLink.click();
}
async toggleAdvancedSettings() {
await this.advancedToggle.click();
}
}
@@ -0,0 +1,94 @@
import { Page } from '@playwright/test';
const MAC = process.platform === 'darwin';
async function keyDownCtrlOrMeta(page: Page) {
if (MAC) {
await page.keyboard.down('Meta');
} else {
await page.keyboard.down('Control');
}
}
async function keyUpCtrlOrMeta(page: Page) {
if (MAC) {
await page.keyboard.up('Meta');
} else {
await page.keyboard.up('Control');
}
}
export async function withCtrlOrMeta(page: Page, key: () => Promise<void>) {
await keyDownCtrlOrMeta(page);
await key();
await keyUpCtrlOrMeta(page);
}
export async function selectAllByKeyboard(page: Page) {
await keyDownCtrlOrMeta(page);
await page.keyboard.press('a', { delay: 50 });
await keyUpCtrlOrMeta(page);
}
export async function copyByKeyboard(page: Page) {
await keyDownCtrlOrMeta(page);
await page.keyboard.press('c', { delay: 50 });
await keyUpCtrlOrMeta(page);
}
export async function cutByKeyboard(page: Page) {
await keyDownCtrlOrMeta(page);
await page.keyboard.press('x', { delay: 50 });
await keyUpCtrlOrMeta(page);
}
export async function pasteByKeyboard(page: Page) {
await keyDownCtrlOrMeta(page);
await page.keyboard.press('v', { delay: 50 });
await keyUpCtrlOrMeta(page);
}
export async function companiesShortcut(page: Page) {
await page.keyboard.press('g', { delay: 50 });
await page.keyboard.press('c');
}
export async function notesShortcut(page: Page) {
await page.keyboard.press('g', { delay: 50 });
await page.keyboard.press('n');
}
export async function opportunitiesShortcut(page: Page) {
await page.keyboard.press('g', { delay: 50 });
await page.keyboard.press('o');
}
export async function peopleShortcut(page: Page) {
await page.keyboard.press('g', { delay: 50 });
await page.keyboard.press('p');
}
export async function rocketsShortcut(page: Page) {
await page.keyboard.press('g', { delay: 50 });
await page.keyboard.press('r');
}
export async function tasksShortcut(page: Page) {
await page.keyboard.press('g', { delay: 50 });
await page.keyboard.press('t');
}
export async function workflowsShortcut(page: Page) {
await page.keyboard.press('g', { delay: 50 });
await page.keyboard.press('w');
}
export async function settingsShortcut(page: Page) {
await page.keyboard.press('g', { delay: 50 });
await page.keyboard.press('s');
}
export async function customShortcut(page: Page, shortcut: string) {
await page.keyboard.press('g', { delay: 50 });
await page.keyboard.press(shortcut);
}
@@ -0,0 +1,14 @@
import { Locator, Page } from '@playwright/test';
import { selectAllByKeyboard } from './keyboardShortcuts';
// https://github.com/microsoft/playwright/issues/14126
// code must have \n at the end of lines otherwise everything will be in one line
export const pasteCodeToCodeEditor = async (
page: Page,
locator: Locator,
code: string,
) => {
await locator.click();
await selectAllByKeyboard(page);
await page.keyboard.type(code);
};
@@ -0,0 +1,15 @@
import { Page } from '@playwright/test';
import path from 'path';
export const fileUploader = async (
page: Page,
trigger: () => Promise<void>,
filename: string,
) => {
const fileChooserPromise = page.waitForEvent('filechooser');
await trigger();
const fileChooser = await fileChooserPromise;
await fileChooser.setFiles(
path.join(__dirname, '..', 'test_files', filename),
);
};
@@ -1,7 +1,4 @@
import { test, expect } from '../lib/fixtures/screenshot';
import { config } from 'dotenv';
import path = require('path');
config({ path: path.resolve(__dirname, '..', '.env') });
test.describe('Basic check', () => {
test('Checking if table in Companies is visible', async ({ page }) => {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "twenty-emails",
"version": "0.31.1",
"version": "0.33.0",
"description": "",
"author": "",
"private": true,
+5 -1
View File
@@ -2,6 +2,10 @@ REACT_APP_SERVER_BASE_URL=http://localhost:3000
GENERATE_SOURCEMAP=false
# ———————— Optional ————————
# REACT_APP_PORT=3001
# CHROMATIC_PROJECT_TOKEN=
# VITE_DISABLE_TYPESCRIPT_CHECKER=true
# VITE_DISABLE_ESLINT_CHECKER=true
# VITE_DISABLE_ESLINT_CHECKER=true
# VITE_ENABLE_SSL=false
# SSL_KEY_PATH="./certs/your-cert.key"
# SSL_CERT_PATH="./certs/your-cert.crt"
+12 -1
View File
@@ -1,3 +1,5 @@
const path = require('path');
module.exports = {
extends: ['../../.eslintrc.cjs', '../../.eslintrc.react.cjs'],
ignorePatterns: [
@@ -21,7 +23,16 @@ module.exports = {
parserOptions: {
project: ['packages/twenty-front/tsconfig.{json,*.json}'],
},
rules: {},
plugins: ['project-structure'],
settings: {
'project-structure/folder-structure-config-path':path.resolve(
__dirname,
'folderStructure.json'
)
},
rules: {
'project-structure/folder-structure': 'error',
},
},
],
};
+4 -1
View File
@@ -41,4 +41,7 @@ dist-ssr
*.sw?
.vite/
.nyc_output/
.nyc_output/
# eslint-plugin-project-structure
projectStructure.cache.json
+6 -1
View File
@@ -50,8 +50,13 @@ const config: StorybookConfig = {
const { mergeConfig } = await import('vite');
return mergeConfig(config, {
// Add dependencies to pre-optimization
resolve: {
alias: {
'react-dom/client': 'react-dom/profiling',
},
},
});
},
logLevel: 'error',
};
export default config;
@@ -29,6 +29,7 @@ initialize({
with payload ${JSON.stringify(requestBody)}\n
This request should be mocked with MSW`);
},
quiet: true,
});
const preview: Preview = {
@@ -0,0 +1,65 @@
{
"$schema": "../../node_modules/eslint-plugin-project-structure/folderStructure.schema.json",
"projectRoot": "packages/twenty-front",
"structureRoot": "src",
"regexParameters": {
"camelCase": "^[a-z]+([A-Za-z0-9]+)+",
"kebab-case": "[a-z][a-z0-9]*(?:-[a-z0-9]+)*"
},
"structure": [
{ "name": "*" },
{ "name": "*", "children": [] },
{ "name": "modules", "ruleId": "modulesFolderRule" }
],
"rules": {
"modulesFolderRule": {
"children": [
{ "ruleId": "moduleFolderRule" },
{ "name": "types", "children": [] }
]
},
"moduleFolderRule": {
"name": "{kebab-case}",
"folderRecursionLimit": 6,
"children": [
{ "ruleId": "moduleFolderRule" },
{ "name": "hooks", "ruleId": "hooksLeafFolderRule" },
{ "name": "utils", "ruleId": "utilsLeafFolderRule" },
{ "name": "states", "children": [] },
{ "name": "types", "children": [] },
{ "name": "graphql", "children": [] },
{ "name": "components", "children": [] },
{ "name": "effect-components", "children": [] },
{ "name": "constants", "children": [] },
{ "name": "validation-schemas", "children": [] },
{ "name": "contexts", "children": [] },
{ "name": "scopes", "children": [] },
{ "name": "services", "children": [] },
{ "name": "errors", "children": [] }
]
},
"hooksLeafFolderRule": {
"folderRecursionLimit": 2,
"children": [
{ "name": "use{PascalCase}.(ts|tsx)" },
{
"name": "__tests__",
"children": [{ "name": "use{PascalCase}.test.(ts|tsx)" }]
},
{ "name": "internal", "ruleId": "hooksLeafFolderRule" }
]
},
"utilsLeafFolderRule": {
"children": [
{ "name": "{camelCase}.ts" },
{
"name": "__tests__",
"children": [{ "name": "{camelCase}.test.ts" }]
}
]
}
}
}
+16 -1
View File
@@ -6,7 +6,6 @@
<link rel="icon" href="/icons/android/android-launchericon-48-48.png" />
<link rel="apple-touch-icon" href="/icons/ios/192.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="theme-color" content="#000000" />
<meta name="description" content="A modern open-source CRM" />
<meta
@@ -30,6 +29,22 @@
<title>Twenty</title>
<script src="/env-config.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script type="module">
const disableInputAutoZoom = () => {
const viewportMetadata = document.querySelector('meta[name=viewport]');
if (viewportMetadata !== null) {
viewportMetadata.setAttribute('content', 'width=device-width, initial-scale=1.0, maximum-scale=1.0');
}
}
const isIOS = /iPad|iPhone/.test(navigator.userAgent);
if (isIOS) {
disableInputAutoZoom();
}
</script>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
+2 -2
View File
@@ -25,9 +25,9 @@ const jestConfig: JestConfigWithTsJest = {
extensionsToTreatAsEsm: ['.ts', '.tsx'],
coverageThreshold: {
global: {
statements: 60,
statements: 58,
lines: 55,
functions: 50,
functions: 47,
},
},
collectCoverageFrom: ['<rootDir>/src/**/*.ts'],
+1 -1
View File
@@ -10,7 +10,7 @@ const modulesCoverage = {
branches: 25,
statements: 49,
lines: 50,
functions: 40,
functions: 38,
include: ['src/modules/**/*'],
exclude: ['src/**/*.ts'],
};
+7 -1
View File
@@ -1,6 +1,6 @@
{
"name": "twenty-front",
"version": "0.31.1",
"version": "0.33.0",
"private": true,
"type": "module",
"scripts": {
@@ -33,6 +33,12 @@
"@nivo/calendar": "^0.87.0",
"@nivo/core": "^0.87.0",
"@nivo/line": "^0.87.0",
"@tiptap/extension-document": "^2.9.0",
"@tiptap/extension-paragraph": "^2.9.0",
"@tiptap/extension-placeholder": "^2.9.0",
"@tiptap/extension-text": "^2.9.0",
"@tiptap/extension-text-style": "^2.8.0",
"@tiptap/react": "^2.8.0",
"@xyflow/react": "^12.0.4",
"transliteration": "^2.3.5"
}

Some files were not shown because too many files have changed in this diff Show More