-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Basic import for select in CSV #6047
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PR Summary
- Added support for importing and matching 'Select' fields in CSV
- Updated
templateFields
to handle 'Select' field types and options - Enhanced
ValidationStep
to supportmatchedSelect
andmatchedSelectOptions
- Improved
setColumn
to handle different field types (select, checkbox, input) - Commented out
width
property inDropdownMenu
for better select support
4 file(s) reviewed, 2 comment(s)
Edit PR Review Bot Settings
const allMatched = | ||
matchedOptions.filter((o) => o.value).length === uniqueData?.length; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🪶 style: Consider optimizing the filter and length comparison for better performance.
const value = fieldOptions.find( | ||
(fieldOption) => | ||
fieldOption.value === record.entry || | ||
fieldOption.label === record.entry, | ||
)?.value; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧠 logic: Potential issue if fieldOptions
is undefined. Ensure fieldOptions
is always defined or handle the case when it's not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haven't tested the functionality yet but code LGTM! CI is failing on one of the tests 🙂 @FelixMalfait
@@ -143,6 +143,10 @@ export const ValidationStep = <T extends string>({ | |||
(importColumn) => | |||
(importColumn.type === ColumnType.matched && | |||
importColumn.value === column.key) || | |||
(importColumn.type === ColumnType.matchedSelect && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For more clarity? Wdyt? Not sure haha
generateColumns(fields)
.map((column) => {
const isColumnMatched = (
importColumn: Column<string>,
columnKey: string,
): boolean => {
const matchTypes = [
ColumnType.matched,
ColumnType.matchedSelect,
ColumnType.matchedSelectOptions,
];
return (
matchTypes.includes(importColumn.type) &&
importColumn.value === columnKey
);
};
const hasBeenImported = importedColumns.some(
(importColumn) =>
isColumnMatched(importColumn, column.key) ||
column.key === 'select-row',
);
if (!hasBeenImported && !showUnmatchedColumns) return null;
return column;
})
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Much nicer 😍 thanks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -12,33 +13,56 @@ export const setColumn = <T extends string>( | |||
field?: Field<T>, | |||
data?: MatchColumnsStepProps<T>['data'], | |||
): Column<T> => { | |||
switch (field?.fieldType.type) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why removing the switch case pattern here? If it's too big maybe we can split the code inside functions?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tbh I'm not sure why but the switch/case caused a wired typescript issue which I didn't figure out
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PR Summary
(updates since last review)
- Enhanced
setColumn
function to handle 'select' field types - Updated
setColumn.test.ts
to check formatchedSelectOptions
- Improved field matching in
MatchColumnsStep
andValidationStep
components
1 file(s) reviewed, no comment(s)
Edit PR Review Bot Settings
* Add label to mocked connections (#5858) <img width="865" alt="Capture d’écran 2024-06-13 à 17 48 03" src="https://github.com/twentyhq/twenty/assets/22936103/2d313448-fbd5-4ff1-a65b-afd4df86117a"> * fix timeline activity pagination overflow (#5861) ## Before <img width="250" alt="Screenshot 2024-06-13 at 18 51 56" src="https://github.com/twentyhq/twenty/assets/1834158/d6c7f5fa-3cc7-48bc-a711-29345e93af92"> ## After <img width="284" alt="Screenshot 2024-06-13 at 18 51 41" src="https://github.com/twentyhq/twenty/assets/1834158/25029e0a-c1b0-4458-b715-dbab217eeee0"> * Add log for errors on message import (#5863) As per title :) * Support orderBy as array (#5681) closes: #4301 --------- Co-authored-by: Félix Malfait <[email protected]> * fix: text field overflow beyond cell limits (#5834) - fixes #5775 https://github.com/twentyhq/twenty/assets/47355538/9e440018-ec1e-4faa-a9f3-7131615cf9f1 --------- Co-authored-by: Charles Bochet <[email protected]> Co-authored-by: Lucas Bordeau <[email protected]> * Collapsible menu (#5846) A mini PR to discuss with @Bonapara tomorrow Separating remote objects from others and making the menu collapsible (style to be changed) <img width="225" alt="Screenshot 2024-06-12 at 23 25 59" src="https://github.com/twentyhq/twenty/assets/6399865/b4b69d36-6770-43a2-a5e8-bfcdf0a629ea"> Biggest issue is we don't use local storage today so the collapsed state gets lost. I see we have localStorageEffect with recoil. Maybe store it there? Seems easy but don't want to introduce a bad pattern. Todo: - style update - collapsible favorites - persistent storage * Fix workspaceLogo in invite-email (#5865) ## Fixes wrong image url in email ![image](https://github.com/twentyhq/twenty/assets/29927851/5fb1524b-874d-4723-8450-0284382bbeb3) ## Done - duplicates and adapt `getImageAbsoluteURIOrBase64` from `twenty-front` in `twenty-email` - send `SERVER_URL` to email builder * Fix error log on message import (#5866) Modify #5863 to log the connected account id rather than the message channel id to be consistent with the other logs and stringify the error. * Fix sentry error (#5848) Fixes https://twenty-v7.sentry.io/issues/5363536663/?environment=prod&project=4507072499810304&query=is%3Aunresolved+issue.priority%3A%5Bhigh%2C+medium%5D&referrer=issue-stream&statsPeriod=7d&stream_index=0 - handle error properly in twenty-server - display backend error message * Fix overflow on notes (#5853) ##before ![image](https://github.com/twentyhq/twenty/assets/29927851/c1784340-0741-4701-b11f-d2cf50fab9fb) ##after ![image](https://github.com/twentyhq/twenty/assets/29927851/c095eaf1-15c4-4e68-8cff-c175f99856d0) * Record horizontal scrolling mobile (#5843) I have fixed the scrolling the record container page on mobile making it hidden. This PR aims to fix #5745 --------- Co-authored-by: Lucas Bordeau <[email protected]> * fix: 404 generate API key link (#5871) - update api key link in the docs * Wrote 0.20 changelog (#5870) Created the changelog for 0.2 * Fix website docs (#5873) There was a 500 on the playground and the switch between core and metadata * Added Thai Baht support (#5881) Hey, saw Thai Baht support was [requested](https://github.com/twentyhq/twenty/issues/5876) and thought it was a cool first issue to get to know the project a little bit. * feat: Enhancements to MessageQueue Module with Decorators (#5657) ### Overview This PR introduces significant enhancements to the MessageQueue module by integrating `@Processor`, `@Process`, and `@InjectMessageQueue` decorators. These changes streamline the process of defining and managing queue processors and job handlers, and also allow for request-scoped handlers, improving compatibility with services that rely on scoped providers like TwentyORM repositories. ### Key Features 1. **Decorator-based Job Handling**: Use `@Processor` and `@Process` decorators to define job handlers declaratively. 2. **Request Scope Support**: Job handlers can be scoped per request, enhancing integration with request-scoped services. ### Usage #### Defining Processors and Job Handlers The `@Processor` decorator is used to define a class that processes jobs for a specific queue. The `@Process` decorator is applied to methods within this class to define specific job handlers. ##### Example 1: Specific Job Handlers ```typescript import { Processor, Process, InjectMessageQueue } from 'src/engine/integrations/message-queue'; @Processor('taskQueue') export class TaskProcessor { @Process('taskA') async handleTaskA(job: { id: string, data: any }) { console.log(`Handling task A with data:`, job.data); // Logic for task A } @Process('taskB') async handleTaskB(job: { id: string, data: any }) { console.log(`Handling task B with data:`, job.data); // Logic for task B } } ``` In the example above, `TaskProcessor` is responsible for processing jobs in the `taskQueue`. The `handleTaskA` method will only be called for jobs with the name `taskA`, while `handleTaskB` will be called for `taskB` jobs. ##### Example 2: General Job Handler ```typescript import { Processor, Process, InjectMessageQueue } from 'src/engine/integrations/message-queue'; @Processor('generalQueue') export class GeneralProcessor { @Process() async handleAnyJob(job: { id: string, name: string, data: any }) { console.log(`Handling job ${job.name} with data:`, job.data); // Logic for any job } } ``` In this example, `GeneralProcessor` handles all jobs in the `generalQueue`, regardless of the job name. The `handleAnyJob` method will be invoked for every job added to the `generalQueue`. #### Adding Jobs to a Queue You can use the `@InjectMessageQueue` decorator to inject a queue into a service and add jobs to it. ##### Example: ```typescript import { Injectable } from '@nestjs/common'; import { InjectMessageQueue, MessageQueue } from 'src/engine/integrations/message-queue'; @Injectable() export class TaskService { constructor( @InjectMessageQueue('taskQueue') private readonly taskQueue: MessageQueue, ) {} async addTaskA(data: any) { await this.taskQueue.add('taskA', data); } async addTaskB(data: any) { await this.taskQueue.add('taskB', data); } } ``` In this example, `TaskService` adds jobs to the `taskQueue`. The `addTaskA` and `addTaskB` methods add jobs named `taskA` and `taskB`, respectively, to the queue. #### Using Scoped Job Handlers To utilize request-scoped job handlers, specify the scope in the `@Processor` decorator. This is particularly useful for services that use scoped repositories like those in TwentyORM. ##### Example: ```typescript import { Processor, Process, InjectMessageQueue, Scope } from 'src/engine/integrations/message-queue'; @Processor({ name: 'scopedQueue', scope: Scope.REQUEST }) export class ScopedTaskProcessor { @Process('scopedTask') async handleScopedTask(job: { id: string, data: any }) { console.log(`Handling scoped task with data:`, job.data); // Logic for scoped task, which might use request-scoped services } } ``` Here, the `ScopedTaskProcessor` is associated with `scopedQueue` and operates with request scope. This setup is essential when the job handler relies on services that need to be instantiated per request, such as scoped repositories. ### Migration Notes - **Decorators**: Refactor job handlers to use `@Processor` and `@Process` decorators. - **Request Scope**: Utilize the scope option in `@Processor` if your job handlers depend on request-scoped services. Fix #5628 --------- Co-authored-by: Weiko <[email protected]> * 5236 expandable list leave options when editing (#5890) Fixes https://github.com/twentyhq/twenty/issues/5236 ## After ![image](https://github.com/twentyhq/twenty/assets/29927851/5f0f910c-11b0-40ce-9c59-34e7ce0c2741) * 5581 get httpsapitwentycomrestmetadata relations not working (#5867) Filtering relations is not allowed (see`packages/twenty-server/src/engine/metadata-modules/relation-metadata/dtos/relation-metadata.dto.ts`) so we remove filtering for find many relation we also fixed some bug in result structure and metadata open-api schema * Fix verticale line timeline activity (#5894) Before <img width="400" alt="Capture d’écran 2024-06-17 à 10 23 17" src="https://github.com/twentyhq/twenty/assets/22936103/01408d7b-9a6c-4a21-9f08-c8cf304e2ea0"> After <img width="400" alt="Capture d’écran 2024-06-17 à 10 05 39" src="https://github.com/twentyhq/twenty/assets/22936103/df384726-bbf9-4828-ad47-d1c91724947d"> * Added and optimized missing RatingFieldDisplay component (#5904) The display for Rating field type was missing, I just added it based on RatingInput in readonly mode and optimized a bit for performance also. Fixes https://github.com/twentyhq/twenty/issues/5900 * Fix secondaryLinks field input (#5911) PR https://github.com/twentyhq/twenty/pull/5785/files broke links update. Also, dropdown "Add link" will be displayed only if a link is already added. Otherwise, it should be a normal input. * add multiple filters of same FieldMetadataType (#5892) fixes: #5378 * Add South Korean won to currency codes (#5914) Greetings from Seoul! I found this amazing project a few days ago, and trying to introduce it to my team. However there is a tiny but significant problem, that South Korean won is not available in twenty. So I added `KRW` to the enum `CurrencyCode` and the constant `SETTINGS_FIELD_CURRENCY_CODES`. I tested it locally and apparently works fine. * Upgrade pg graphql version to 1.5.6 (#5937) - update `pg_graphql` version doc - update `pg_graphql` version to 1.5.6 * Add loader and transition for details page tabs (#5935) Closes https://github.com/twentyhq/twenty/issues/5656 https://github.com/twentyhq/twenty/assets/22936103/3e4beea2-9aa9-4015-bb99-ee22adb53b63 * website / Fix broken links, slow loading, and prod errors (#5932) The code is in a bad state, this is just fixing it but not improving the structure * 5582 get httpsapitwentycomrestmetadata objects filters dont work (#5906) - Remove filters from metadata rest api - add limite before and after parameters for metadata - remove update from metadata relations - fix typing issue - fix naming - fix before parameter --------- Co-authored-by: Félix Malfait <[email protected]> * Add http status to graphql errors (#5896) Graphql errors are not properly filtered by our handler. We still receive errors like `NOT_FOUND` in sentry while they should be filtered. Example [here](https://twenty-v7.sentry.io/issues/5490383016/?environment=prod&project=4507072499810304&query=is%3Aunresolved+issue.priority%3A%5Bhigh%2C+medium%5D&referrer=issue-stream&statsPeriod=7d&stream_index=6). We associate statuses with errors in our map `graphQLPredefinedExceptions` but we cannot retrieve the status from the error. This PR lists the codes that should be filtered. To test: - call `findDuplicates` with an invalid id - before, server would breaks - now the error is simply returned * Handle no concurrency option (#5952) Fix error in local `teamConcurrency must be an integer between 1 and 1000` * Favicons are being re-rendered on hover (#5849) ### Description Favicons are being re-rendered on hover ### Refs #3523 ### Demo https://www.loom.com/share/e3944d940a014283af8c26baac1fed57?sid=e3e96a81-3a54-4969-8602-99c64bb3ffe7 Fixes #3523 --------- Co-authored-by: gitstart-twenty <[email protected]> Co-authored-by: v1b3m <[email protected]> Co-authored-by: Thiago Nascimbeni <[email protected]> Co-authored-by: Lucas Bordeau <[email protected]> * Add a ⏎ shortcut on Select options (#5641) fixes #5540 Added onkeyDown to 1. Create new option and 2. Move focus to it. [screen-capture (6).webm](https://github.com/twentyhq/twenty/assets/69167444/ede54ad8-22db-4b09-9617-4d999c6c08c7) --------- Co-authored-by: Lucas Bordeau <[email protected]> * Added a mechanism to reset error boundary on page change. (#5913) Previously the error boundary component was re-rendering with the same state as long as we stayed in the same router, so for page change inside an index container, it would stay on error state. The fix is to memorize the location the error page is on during its first render, and then to reset the error boundary if it gets re-rendered with a different location even in the same index container. Fixes : #3592 * fix(twenty-front): update DateTimeInput styles to apply top border radius to date picker (#5946) update DateTimeInput styled components to prevent the StyledInput from overflowing out of it's parent container <img width="860" alt="Screenshot 2024-06-19 at 9 55 04 AM" src="https://github.com/twentyhq/twenty/assets/19223383/8c5daf6a-9eb6-4ecd-a2e9-aa2ba8db3874"> Fixes #5940 * (5943) Match country selector button's background to phone number input's background (#5956) Fixes #5943 ### Before Light <img width="218" alt="Screenshot 2024-06-19 at 12 37 22 PM" src="https://github.com/twentyhq/twenty/assets/57673080/981d1877-be4e-4071-9a8d-9d0ed7e933ab"> Dark <img width="223" alt="Screenshot 2024-06-19 at 12 39 42 PM" src="https://github.com/twentyhq/twenty/assets/57673080/a3730ef5-21ba-4d90-998d-d330aec350ad"> ### After Light <img width="216" alt="Screenshot 2024-06-19 at 12 39 00 PM" src="https://github.com/twentyhq/twenty/assets/57673080/eef3b743-1b28-43a5-8c1c-bd944a4915c7"> Dark <img width="228" alt="Screenshot 2024-06-19 at 12 39 29 PM" src="https://github.com/twentyhq/twenty/assets/57673080/5bf10e51-5a07-4d55-99f1-734517b22781"> * [Bug] Put back subject is email right drawer (#5955) Fix https://github.com/twentyhq/twenty/issues/5903 * Data Skeleton Loading on Indexes (#5828) ### Description Data Skeleton Loading on Indexes ### Refs #4459 ### Demo https://github.com/twentyhq/twenty/assets/140154534/d9c9b0fa-2d8c-4b0d-8d48-cae09530622a Fixes #4459 --------- Co-authored-by: gitstart-twenty <[email protected]> Co-authored-by: v1b3m <[email protected]> Co-authored-by: Matheus <[email protected]> Co-authored-by: Lucas Bordeau <[email protected]> * 5934 create alert banner component (#5950) Closes #5934 --------- Co-authored-by: Lucas Bordeau <[email protected]> * Fix reconnect google account bug (#5905) Update syncStage to FULL_MESSAGE_LIST_FETCH_PENDING when reconnecting the account to trigger a full sync on the next cron iteration. * 5898 Create a cron to monitor messageChannelSyncStatus (#5933) Closes #5898 * Feat : Introduced Delay Options for Tooltip (#5766) Fixes https://github.com/twentyhq/twenty/issues/5727 --------- Co-authored-by: Rushikesh Tarapure <[email protected]> Co-authored-by: Lucas Bordeau <[email protected]> * add object id column to csv export (#5971) closes: #5893 --------- Co-authored-by: Félix Malfait <[email protected]> * fix: Column header menu Filter button (#5973) fixes: #5957 https://github.com/twentyhq/twenty/assets/13139771/51d42aa5-c774-4cbe-adca-b95ea6e17bbd * Fix date picker wrong on certain timezones (#5972) Timezone with a negative offset weren't working good with date pickers. I split the logic for display and parsing between date only and datetime. Date time is sending and displaying using timezone, and date only is sending and displaying by forcing the date to take its UTC day and month and 00:00:00 time. This way its consistent across all timezones. * Add the support of Empty and Non-Empty filter (#5773) * Fix(view): `Create` Button is not visible when creating `Kanban` View (#5969) Closes #5915 This issue occurs only when there is no select field. The user then creates a new one in settings and returns back to the view picker. And the bug arises, it because `viewPickerKanbanFieldMetadataId` is not being set correctly. When a user navigate to settings, the dirty state should be set to false. As a result, after re-rendering the view picker component, it triggers the effect to set `viewPickerKanbanFieldMetadataId` --------- Co-authored-by: Achsan <[email protected]> Co-authored-by: Lucas Bordeau <[email protected]> * Add disabled style on non-draggable menu items (#5974) Closes https://github.com/twentyhq/twenty/issues/5653 <img width="256" alt="Capture d’écran 2024-06-20 à 17 19 44" src="https://github.com/twentyhq/twenty/assets/22936103/c9d7e58f-818b-44f2-8aa4-4d85c8e1b6be"> <img width="231" alt="Capture d’écran 2024-06-20 à 17 20 03" src="https://github.com/twentyhq/twenty/assets/22936103/5e981e93-9d59-403a-bb6b-0ff75151ace2"> * Update LOGGER_DRIVER env var description (#5968) Update the docs to accurately reflect `LoggerDriverType`. Using `sentry` throws an error on startup. ``` export enum LoggerDriverType { Console = 'console', } ``` Happy to change the wording of course. * Fix: Selected Line Not Fully Highlighted in Blue (#5966) Fixes: #5942 <img width="1517" alt="Screenshot 2024-06-19 at 5 07 35 PM" src="https://github.com/twentyhq/twenty/assets/63531478/c88a98e9-7ce3-43fe-a496-1a5dfe796b81"> --------- Co-authored-by: Lucas Bordeau <[email protected]> * fix: background colors for record table (#5967) # Summary - Address issue #5959 - Update background color on hover & click for record table # Test Plan ![Kapture 2024-06-19 at 20 32 44](https://github.com/twentyhq/twenty/assets/10789158/18a58c09-040a-47e6-953d-aac6f3803486) * Fix links chip design (#5963) Fix https://github.com/twentyhq/twenty/issues/5938 and https://github.com/twentyhq/twenty/issues/5655 - Make sure chip count is displayed - Fix padding - Fix background colors, border - Add hover and active states --------- Co-authored-by: Lucas Bordeau <[email protected]> * Navigation Panel UI Sizing Changes (#5964) ## Fixes #5902 : - [x] Navigation items' height should be risen to 28px. > For clarity: - [x] Also increased the height of NavigationDrawerSectionTitle to 28px to match navigation item. - [x] The gap between sections should be reduced to 12px > Was already completed it seems. - [x] The workspace switcher should be aligned with the navigation items --------- Co-authored-by: Lucas Bordeau <[email protected]> * feat: add brazilian real currency (#5989) Added support to Brazilian Real currency code, added the new code on `CurrencyCode.ts` and on `SETTINGS_FIELD_CURRENCY_CODES` * feat: drop calendar repository (#5824) This PR is replacing and removing all the raw queries and repositories with the new `TwentyORM` and injection system using `@InjectWorkspaceRepository`. Some logic that was contained inside repositories has been moved to the services. In this PR we're only replacing repositories for calendar feature. --------- Co-authored-by: Weiko <[email protected]> Co-authored-by: bosiraphael <[email protected]> Co-authored-by: Charles Bochet <[email protected]> * [FlexibleSchema] Add IndexMetadata decorator (#5981) ## Context Our Flexible Schema engine dynamically generates entities/tables/APIs for us but was not flexible enough to build indexes in the DB. With more and more features involving heavy queries such as Messaging, we are now adding a new WorkspaceIndex() decorator for our standard objects (will come later for custom objects). This decorator will give enough information to the workspace sync metadata manager to generate the proper migrations that will create or drop indexes on demand. To be aligned with the rest of the engine, we are adding 2 new tables: IndexMetadata and IndexFieldMetadata, that will store the info of our indexes. ## Implementation ```typescript @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.person, namePlural: 'people', labelSingular: 'Person', labelPlural: 'People', description: 'A person', icon: 'IconUser', }) export class PersonWorkspaceEntity extends BaseWorkspaceEntity { @WorkspaceField({ standardId: PERSON_STANDARD_FIELD_IDS.email, type: FieldMetadataType.EMAIL, label: 'Email', description: 'Contact’s Email', icon: 'IconMail', }) @WorkspaceIndex() email: string; ``` By simply adding the WorkspaceIndex decorator, sync-metadata command will create a new index for that column. We can also add composite indexes, note that the order is important for PSQL. ```typescript @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.person, namePlural: 'people', labelSingular: 'Person', labelPlural: 'People', description: 'A person', icon: 'IconUser', }) @WorkspaceIndex(['phone', 'email']) export class PersonWorkspaceEntity extends BaseWorkspaceEntity { ``` Currently composite fields and relation fields are not handled by @WorkspaceIndex() and you will need to use this notation instead ```typescript @WorkspaceIndex(['companyId', 'nameFirstName']) export class PersonWorkspaceEntity extends BaseWorkspaceEntity { ``` <img width="700" alt="Screenshot 2024-06-21 at 15 15 45" src="https://github.com/twentyhq/twenty/assets/1834158/ac6da1d9-d315-40a4-9ba6-6ab9ae4709d4"> Next step: We might need to implement more complex index expressions, this is why we have an expression column in IndexMetadata. What I had in mind for the decorator, still open to discussion ```typescript @WorkspaceIndex(['nameFirstName', 'nameLastName'], { expression: "$1 || ' ' || $2"}) export class PersonWorkspaceEntity extends BaseWorkspaceEntity { ``` --------- Co-authored-by: Charles Bochet <[email protected]> * Improve tests (#5994) Our tests on FE are red, which is a threat to code quality. I'm adding a few unit tests to improve the coverage and lowering a bit the lines coverage threshold * Fix infinite scroll issue on table (#5996) We had an issue on infinite scroll on table view. The fetch more logic was modifying isTableLastRowVisible state (which is wrong, how could it know)? This was done to prevent loading too much data at once. This was causing some race condition on isTableLastRowVisible (as the table itself was also changing it depending on the real visibility of the line) I have remove this hacky usage of isTableLastRowVisible and replaced it by a setTimeout to let the user some time to scroll and introduce a throttle logic. * Remove Right-Edge Gap in Table Cell Display (#5992) fixes #5941 ![Screenshot from 2024-06-23 17-24-24](https://github.com/twentyhq/twenty/assets/59247136/ae67603a-824d-4e6b-b873-2d58e6296341) --------- Co-authored-by: Lucas Bordeau <[email protected]> * Refactor infiniteScoll to use debouncing (#5999) Same as https://github.com/twentyhq/twenty/pull/5996 but with useDebounced as asked in review * Create feature flag for calendar V2 (#5998) Create feature flag for calendar V2 * Turned on tooltip on kanban cards with shortDelay (#5991) fixes: #5982 Demo: https://github.com/twentyhq/twenty/assets/58113282/6593381c-c01a-4259-9caa-8612247a9e95 --------- Co-authored-by: Lucas Bordeau <[email protected]> * feat: add australian dollar currency (#5990) Hi Twenty team, I'd love to have Australian dollar as an option in Twenty! Please let me me know if I have missed anything I need to change to enable this. Thanks for a a great product --------- Co-authored-by: Lucas Bordeau <[email protected]> * Add update chevron (#5988) Fixes #5986 1. Added right chevron to Fields Menu Item <img width="735" alt="Screenshot 2024-06-21 at 5 59 46 PM" src="https://github.com/twentyhq/twenty/assets/63531478/1515aba0-6732-424d-a0b3-5cc826a35b16"> 2. Changed color of Hidden fields menu item chevron and stroke of left chevron <img width="735" alt="Screenshot 2024-06-21 at 6 21 30 PM" src="https://github.com/twentyhq/twenty/assets/63531478/20952197-2f09-486c-a3bb-5b6c285a6996"> --------- Co-authored-by: Lucas Bordeau <[email protected]> * Fix(view): Show Kanban View Creation (#5985) # This PR - Revise my previous work (PR #5969) Because it would break the current logic and cause unexpected behavior. (Issue #5979) - Solve (Issue #5915) with another way @lucasbordeau What do you think about my current approach? @JarWarren Please check it out—I'd love to get your feedback too! --------- Co-authored-by: Achsan <[email protected]> Co-authored-by: Lucas Bordeau <[email protected]> * Remove multi select usage (#6004) As per title! Also, I'm removing an incorrect logic in the enum migration runner that takes care of the case where we have no defaultValue but non nullable which is not a valid business case. * Create new sync statuses and stages for calendar (#5997) Create fields: - syncStatus - syncStage - syncStageStartedAt * 5951 create a command to trigger the import of a single message (#5962) Closes #5951 --------- Co-authored-by: Charles Bochet <[email protected]> * Add calendar cron command on self-hosting-var.mdx (#6009) To enable Google Calendar integration, you need to run `yarn command:prod cron:calendar:google-calendar-sync` in the worker container. However, currently, the self-hosting guide does not tell you how to do it. If you just follow the guide, only Gmail integration will be enabled. So I added the command for calendar sync cron on self-hosting-var.mdx. * Remove useless api position parameter (#6010) - remove buggy addition of position parameter - check created records are in first position by default * Fix sign up broken because of missing workspace schema (#6013) Allow workspace datasource factory to return null if the workspace schema has not been created yet * 5615 create messageongoingstalecron (#6005) Closes #5615 * feat: Dynamic hook registration for WorkspaceQueryHooks (#6008) #### Overview This PR introduces a new API for dynamically registering and executing pre and post query hooks in the Workspace Query Hook system using the `@WorkspaceQueryHook` decorator. This approach eliminates the need for manual provider registration, and fix the issue of `undefined` or `null` repository using `@InjectWorkspaceRepository`. #### New API **Define a Hook** Use the `@WorkspaceQueryHook` decorator to define pre or post hooks: ```typescript @WorkspaceQueryHook({ key: `calendarEvent.findMany`, scope: Scope.REQUEST, }) export class CalendarEventFindManyPreQueryHook implements WorkspaceQueryHookInstance { async execute(userId: string, workspaceId: string, payload: FindManyResolverArgs): Promise<void> { if (!payload?.filter?.id?.eq) { throw new BadRequestException('id filter is required'); } // Implement hook logic here } } ``` This API simplifies the registration and execution of query hooks, providing a more flexible and maintainable approach. --------- Co-authored-by: Weiko <[email protected]> * Fix billing signup when workspace does not exist (#6018) * Removed performance optimization and put back previous system with recoil states for edit mode and soft focus to avoid side effects. (#6019) Fixes https://github.com/twentyhq/twenty/issues/6016 This was another side effect of the optimization made on RecordTableCellContainer to avoid using recoil states, but which causes too many unpredictable side effects. I just put back the previous system which works well. We'll see how to optimize it again later. * Remove message-import cache when connectedAccount is removed (#6021) * Upsert endpoint and CSV import upsert (#5970) This PR introduces an `upsert` parameter (along the existing `data` param) for `createOne` and `createMany` mutations. When upsert is set to `true`, the function will look for records with the same id if an id was passed. If not id was passed, it will leverage the existing duplicate check mechanism to find a duplicate. If a record is found, then the function will perform an update instead of a create. Unfortunately I had to remove some nice tests that existing on the args factory. Those tests where mostly testing the duplication rule generation logic but through a GraphQL angle. Since I moved the duplication rule logic to a dedicated service, if I kept the tests but mocked the service we wouldn't really be testing anything useful. The right path would be to create new tests for this service that compare the JSON output and not the GraphQL output but I chose not to work on this as it's equivalent to rewriting the tests from scratch and I have other competing priorities. * Add mutationMaximumRecordAffected to clientConfig (#6039) We are exposing the server mutationMaximumRecordAffected value via clientConfig so it can be used by the FE. This is a first step for https://github.com/twentyhq/twenty/issues/6025 <img width="610" alt="Screenshot 2024-06-26 at 14 58 26" src="https://github.com/twentyhq/twenty/assets/1834158/9d192976-fd22-45d2-bdaa-a8ff6bb90ca2"> * Don't display unmatched columns in csv import (#6037) Adding a toggle so that, by default, we don't see dozens of fields but only the field we matched, during the data validation step in csv export <img width="785" alt="Screenshot 2024-06-26 at 13 25 36" src="https://github.com/twentyhq/twenty/assets/6399865/ae558eb5-7461-4bc8-a836-ecff8b6d0dff"> * Fix search in csv import (#6045) A mini quality of life improvements, the search was case-sensitive which was frustrating * Rename mutation maximum affected records (#6042) As per my last comment on https://github.com/twentyhq/twenty/pull/6039, we decided to rename this var * Basic import for select in CSV (#6047) Enables basic support for Select import and field matching in CSV. It's not pretty! But it's better than what we had before. We should iterate on that quickly <img width="591" alt="Screenshot 2024-06-26 at 18 41 16" src="https://github.com/twentyhq/twenty/assets/6399865/99f67f39-3f0f-4074-aac6-3200954be08a"> * Add boolean with toggle in csv import (#6050) Better UI when importing boolean via CSV (with a toggle) * Improve gmail error handling by catching and throttling for 400 failedPrecondition (#6044) Closes #5897 * Fix cache flush in messaging-channel-sync-status.service (#6024) Fix cache flush in messaging-channel-sync-status.service * hide delete button for selection over 100 - issue #6023 (#6030) hide the "Delete" Button when more than 100 records are Selected --------- Co-authored-by: Weiko <[email protected]> * Relations many in table view (#5842) Closes #5924. Adding the "many" side of relations in the table view, and fixing some issues (glitch in Multi record select, cache update after update). --------- Co-authored-by: Lucas Bordeau <[email protected]> * feat: manually implement joinColumn (#6022) This PR introduce a new decorator named `@WorkspaceJoinColumn`, the goal of this one is to manually declare the join columns inside the workspace entities, so we don't have to rely on `ObjectRecord` type. This decorator can be used that way: ```typescript @WorkspaceRelation({ standardId: ACTIVITY_TARGET_STANDARD_FIELD_IDS.company, type: RelationMetadataType.MANY_TO_ONE, label: 'Company', description: 'ActivityTarget company', icon: 'IconBuildingSkyscraper', inverseSideTarget: () => CompanyWorkspaceEntity, inverseSideFieldKey: 'activityTargets', }) @WorkspaceIsNullable() company: Relation<CompanyWorkspaceEntity> | null; // The argument is the name of the relation above @WorkspaceJoinColumn('company') companyId: string | null; ``` * Update create-workspace.mdx (#6053) Fix a dead link that was redirecting to a 400 * Manage isFocused state for table cells (#6058) as per title * Replace ObjectRecord<MessageChannelWorkspaceEntity> with MessageChannelWorkspaceEntity (#6059) Replace ObjectRecord<MessageChannelWorkspaceEntity> with MessageChannelWorkspaceEntity * Fixed board card field max width (#6061) Add a max-width to prevent overflow of board card fields * fix navigation panel workspace picker padding (#6062) ## Before <img width="223" alt="Screenshot 2024-06-27 at 15 23 26" src="https://github.com/twentyhq/twenty/assets/1834158/18cb5e15-352f-4e65-9cff-6e396abe4318"> ## After <img width="229" alt="Screenshot 2024-06-27 at 15 23 07" src="https://github.com/twentyhq/twenty/assets/1834158/53502c23-d9b4-4967-9e56-26e62e5e50ea"> <img width="225" alt="Screenshot 2024-06-27 at 15 25 23" src="https://github.com/twentyhq/twenty/assets/1834158/fbb751ba-2bde-44f0-9c70-a9091e9b9012"> * Create fields for calendar and messaging settings v2 (#6049) Create fields for calendar and messaging settings v2 * Change messaging batch size and cron pattern (#6063) Change messaging batch size and cron pattern to accelerate messages import * 5901 refactor email and calendar auto contact creation to create them by batch (#6038) Closes #5901 * Refactor messaging refresh access token (#6034) - Put error handling outside of `refreshAndSaveAccessToken` - return after failing to refresh access token in `processMessageBatchImport` - remove unnecessary token refresh in `processMessageListFetch` * 5095 move onboardingstatus computation from frontend to backend (#5954) - move front `onboardingStatus` computing to server side - add logic to `useSetNextOnboardingStatus` - update some missing redirections in `usePageChangeEffectNavigateLocation` - separate subscriptionStatus from onboardingStatus * 0.21 changelog (#6072) * Clarify storybook tests (#6073) In this PR, I'm simplifying storybook setup: 1) Remove build --test configuration that prevent autodocs. We are not using autodocs at all (the dev experience is not good enough), so I have completely disabled it. 2) Clarify `serve` vs `test` vs `serve-and-test` configurations After this PR: - you can serve storybook in two modes: `npx nx run twenty-front:storybook:serve:dev` and `npx nx run twenty-front:storybook:serve:static` - you can run tests agains an already served storybook (this is useful in dev so you don't have to rebuild everytime to run tests): `npx nx run twenty-front:storybook:test` - you can conbine both: `npx nx run twenty-front:storybook:serve-and-test:static` * Fix tests * Fix tests on RelationManyFieldDisplay * Improve use set next onboarding state (#6076) querying workspaceMembers may be slow leads to wrong setNextOnboardingStatus value. So we added a resolved field in workspace to get workspaceMemberCount directly * Allow s3 credentials via env (#6066) closes #5072 * Remove CSS modules (#6017) CSS modules were used as a first test for performance optimization. We later found out that Linaria was a better tradeoff. This PR removes what was implemented in CSS modules and also the CSS theme file that was created that was overlapping with the TS theme files. * feat: message cleaner drop repository (#6052) This PR use the new `TwentyORM` for the message-cleaner module by using the new injection system with `@InjectWorkspaceRepository`. * fix: message cleaner find operator (#6080) This PR fix an issue with the `IsNull()` find operator applied on one-to-many relation, this one is not supported by TypeORM. We can instead filter by an empty array to retrieve object with empty relations. * Fix: Tasks-List-page-Person-Switcher (#6077) Fixes #6007, adds context to the ObjectFilter DropdownRecordSelect * Add exceptions for metadata modules (#6070) Class exception for each metadata module + handler to map on graphql error TODO left : - find a way to call handler on auto-resolvers nestjs query (probably interceptors) - discuss what should be done for pre-hooks errors - discuss what should be done for Unauthorized exception * 5748 Create contacts for emails sent and received by email aliases (#5855) Closes #5748 - Create feature flag - Add scope `https://www.googleapis.com/auth/profile.emails.read` when connecting an account - Get email aliases with google people API, store them in connectedAccount and refresh them before each message-import - Update the contact creation logic accordingly - Refactor --------- Co-authored-by: Charles Bochet <[email protected]> * Change Messaging import frequency * Fix lint and used constant (#6082) - Fixed lint after merge of #6077 - Used constant for dropdown id * Fix demo seed script by using usage of deprecated sub status * Use invalid field input error for invalid object metadata input (#6083) As title * Fix Active Workspaces check (#6084) We have recently deprecated our subscriptionStatus on workspace to replace it by a check on existing subscription (+ freeAccess featureFlag) but the logic was not properly implemented * feature to reset value in select field (#6067) Fixes #6064 https://github.com/twentyhq/twenty/assets/55168611/8c553422-6ad2-4e6b-bd00-962dd81c0a93 --------- Co-authored-by: Lucas Bordeau <[email protected]> * Reorganise calendar module (#6089) Refactor Calendar into functional sub modules <img width="437" alt="image" src="https://github.com/twentyhq/twenty/assets/12035771/d9de3285-a226-4fe8-b3ef-2d8a21def2a5"> --------- Co-authored-by: bosiraphael <[email protected]> * Fix calendar import cron job (#6096) An error was introduced in the calendar cron job because we tried to inject the workspace context inside the calendarChannelRepository where we didn't have access to that context. * feat: refactor workspace sync fields (#6069) This PR was first here to fix the issue related to ticket #5004, after some testing it seems that changing the name of a relation is actually properly working, if we rename `ONE-TO-MANY` side, the only things that is going to be updated is the FieldMetadata as the `joinColumn` is stored on the opposite object. For `MANY-TO-ONE` relations, the `joinColumn` migration is properly generated. We need to take care that if we rename a side of a relation, sometimes the opposite side doesn't have `inverseSideFieldKey` implemented and used by default the name of the opposite object, so this is going to throw an error as the field can't be found in the object. --------- Co-authored-by: Marie <[email protected]> * Use return await to catch exceptions (#6109) So the exceptions are handled properly and filtered in sentry * Fix rating field not editable if null (#6110) ## Context Rating fields were not editable on the show page and kanban view when they were null, this is because we don't have a way to leave the empty state for fields that are editModeContentOnly. ~~This is actually an issue for bool fields (which is the other field type that has editModeContentOnly) as well but they have default values can't go be edited to NULL so it's not visible.~~ Actually let's fix bool, this could happen too Hovering over "Empty" will now show the RatingField edit mode. I'm not 100% sure about this solution though, we could also make this behaviour on click? I preferred over since this is the behaviour on the table view 🤔 ## Test https://github.com/twentyhq/twenty/assets/1834158/6825b5c3-2c62-41f2-8e03-343bc0e895e2 * Fix pg-boss worker not working with dynamic injection (#6119) * Fix workspace sync issue (#6121) Fixing an issue with typeORM not fetching existing metadata collection while syncing fields and relations * fix: small PR fixes workspace-sync-fields (#6107) Small fixes of PR #6069 * Decrease messaging import batch size * Improve performance/robustness of worker * Text-to-SQL proof of concept (#5788) Added: - An "Ask AI" command to the command menu. - A simple GraphQL resolver that converts the user's question into a relevant SQL query using an LLM, runs the query, and returns the result. <img width="428" alt="Screenshot 2024-06-09 at 20 53 09" src="https://github.com/twentyhq/twenty/assets/171685816/57127f37-d4a6-498d-b253-733ffa0d209f"> No security concerns have been addressed, this is only a proof-of-concept and not intended to be enabled in production. All changes are behind a feature flag called `IS_ASK_AI_ENABLED`. --------- Co-authored-by: Félix Malfait <[email protected]> * Hotfix tests after AI PR (#6124) I merged https://github.com/twentyhq/twenty/pull/5788 too quickly and didn't noticed it was broken with https://github.com/twentyhq/twenty/pull/6069 * fix: message queue injection issue (#6126) * Forbid names above 63 characters to comply with pg identifier limit (#6095) Fixes #6032. Pg has a char limit on identifiers (= table, columns, enum names) of 63 bytes. Let's limit the metadata names that will be converted to identifiers (objects names, fields names, relation names, enum values) to 63 chars. For the sake of simplicity in the FE we will limit the input length of labels. --------- Co-authored-by: Charles Bochet <[email protected]> * Fix website doc search (#6134) NEXT_PUBLIC environnement variable values are set at build time and not run time. Build is currently performed in Github actions so setting those vars at runtime has no effect. We can use a package to automatically pass those variables at runtime * Implement Settings Tabs (#6136) In this PR: - Renaming SettingsAccountsEmailBlocklist to SettingsAccountsEmailBlocklist as the blocklist is not tied to emails/messaging but is user level - Changing the UI settings UI by removing /emails/{id} page and adding tabs on /emails page <img width="1512" alt="image" src="https://github.com/twentyhq/twenty/assets/12035771/d215a891-fff9-477d-915d-0d7a697742e8"> * Add command to update boolean fields null values (#6113) We have recently decided that boolean fields should only accept truthy or falsy value, with users deciding of a default value at creation. This command helps cleaning the existing data, by 1. updating all boolean fields default values from null to false 2. updating all boolean fields values for records from null to false --------- Co-authored-by: Weiko <[email protected]> * Fix sort with Email and FullName field types and add sort/filter to labelIdentifier column (#6132) Fixes https://github.com/twentyhq/twenty/issues/5958 <img width="1088" alt="Screenshot 2024-07-04 at 16 23 25" src="https://github.com/twentyhq/twenty/assets/1834158/746c45a4-7112-4322-8c26-04f3e98add06"> <img width="1280" alt="Screenshot 2024-07-04 at 16 15 39" src="https://github.com/twentyhq/twenty/assets/1834158/9b9ecc60-9787-44a3-9ba7-0b33ec378e6f"> * 5421 box shadow on frozen header and first column (#6130) - Refactored components in table - Added a isTableRecordScrolledLeftState and isTableRecordScrolledTopState to subscribe to table scroll - Added a zIndex logic that subscribes to those new states in new tinier components --------- Co-authored-by: Charles Bochet <[email protected]> * Fix storybook tests (#6150) The PRs merged on Friday introduced regressions on our storybook tests suite * Refactor Calendar Settings into tabs (#6153) This PR migrates Calendar Settings into Tabs: <img width="1512" alt="image" src="https://github.com/twentyhq/twenty/assets/12035771/2531d0f1-ddfd-46c6-8678-bd76d78447b6"> * Add new Settings to front-end (#6154) <img width="1512" alt="image" src="https://github.com/twentyhq/twenty/assets/12035771/cfcc6ac9-feeb-4d91-aa68-bd0119780d6d"> * Small fixes on accounts settings (#6157) - Add keys in components map * Add message import granulary on non-pro emails, group emails and received contact creation (#6156) 1) Remove featureFlag 2) Base contactCreation on messageChannel.autoContactCreationPolicy 4) add excludeProfessionalEmails + excludeGroupEmails logic * Fix z-index issue on dropdown (#6160) Recently, we've forced all dropdown menu to be displayed in portal. This loses the z-index hieararchy structure and forces us to specify a higher z-index in order for dropdown menus to be displayed on top * Bump version to 0.21 (#6161) * Refactor calendar to use new sync statuses and stages (#6141) - Refactor calendar modules and some messaging modules to better organize them by business rules and decouple them - Work toward a common architecture for the different calendar providers by introducing interfaces for the drivers - Modify cron job to use the new sync statuses and stages * Navigate to field settings page on Go to Settings (#6128) Fixes #5661. Thanks @AdvaitChandorkar07 * Fix wrong email direction (#6163) Closes #6162 * Fix contactCreation ignoring connectedAccount mainHandle * Update render deploy configuration (#6167) * Add missing objectMetadataId column in auditLog (#6164) Insert inside AuditLog table are all failing due to objectMetadataId column missing. The FieldMetadata was sharing the same standard-id with another one (objectName) so it was skipped during the comparison step of the sync-metadata. Running a sync-metadata again should fix this issue. Note that this column is non-nullable so if the table contains existing records, it will fail. However, since the insert was failing I'm assuming the table is empty anyway. * Modify messaging message channel sync status monitoring cron pattern (#6173) Change from every hour to every 10 minutes, starting at 2 minutes past the hour * [Flexible Schema] Create indexes for join columns (#6165) ## Context We want to add an index on our foreign keys since PG does not do it for us. An index can sometimes be expensive and not always meaningful depending on different usages but in our case we decided to apply an index for every foreign keys. ```typescript @WorkspaceIndex() @WorkspaceJoinColumn('author') authorId: string; ``` This syntax is valid but since we want to apply it to every join column I've decided to update the code of WorkspaceJoinColumn so it properly registers a new index at the same time which is less error-prone. Note: We had a bug on index name generation since postgres index names are unique per schema and not table, the object metadata id (hashed) has been added to the formula that generates the name of the index ## Test Sync metadata. We have 45 join columns as of today per workspace, we should see 45 rows inside IndexMetadata table * Authorize 0 depth (#6171) Authorize depth 0 ![image](https://github.com/twentyhq/twenty/assets/29927851/2e82eaba-01b4-440f-8412-d2878007a3b1) ![image](https://github.com/twentyhq/twenty/assets/29927851/f0137671-20dc-4e44-97b8-7a8e4c583493) ## Edit ### Depth = 0 ``` { "data": { "people": [ { "id": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "email": "[email protected]", "jobTitle": "", "phone": "+33789012345", "city": "Seattle", "avatarUrl": "", "position": 1, "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "companyId": "20202020-3ec3-4fe3-8997-b76aa0bfa408", "name": { "firstName": "Christoph", "lastName": "Callisto" }, "linkedinLink": { "label": "", "url": "" }, "xLink": { "label": "", "url": "" } }, ... ]} ``` ### Depth = 1 ``` { "data": { "people": [ { "id": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "email": "[email protected]", "jobTitle": "", "phone": "+33789012345", "city": "Seattle", "avatarUrl": "", "position": 1, "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "companyId": "20202020-3ec3-4fe3-8997-b76aa0bfa408", "name": { "firstName": "Christoph", "lastName": "Callisto" }, "linkedinLink": { "label": "", "url": "" }, "xLink": { "label": "", "url": "" }, "activityTargets": [], "favorites": [], "attachments": [], "timelineActivities": [], "company": { "id": "20202020-3ec3-4fe3-8997-b76aa0bfa408", "name": "Linkedin", "domainName": "linkedin.com", "address": "", "employees": null, "idealCustomerProfile": false, "position": 1, "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "accountOwnerId": null, "linkedinLink": { "label": "", "url": "" }, "xLink": { "label": "", "url": "" }, "annualRecurringRevenue": { "amountMicros": null, "currencyCode": "" } }, "messageParticipants": [ { "id": "20202020-0f2a-49d8-8aa2-ec8786153a0b", "role": "from", "handle": "outgoing", "displayName": "Christoph", "createdAt": "2024-07-08T16:08:50.028Z", "updatedAt": "2024-07-08T16:08:50.028Z", "messageId": "20202020-2b8a-405d-8f42-e820ca921421", "personId": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "workspaceMemberId": "20202020-0687-4c41-b707-ed1bfca972a7" }, { "id": "20202020-fc7d-4ad8-9aea-b78bcbf79cdd", "role": "from", "handle": "outgoing", "displayName": "Christoph", "createdAt": "2024-07-08T16:08:50.028Z", "updatedAt": "2024-07-08T16:08:50.028Z", "messageId": "20202020-04c8-4f24-93f2-764948e95014", "personId": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "workspaceMemberId": "20202020-0687-4c41-b707-ed1bfca972a7" } ], "calendarEventParticipants": [ { "id": "da8f47c3-8055-49ad-b7e4-9c9d5bbc1ecc", "handle": "[email protected]", "displayName": "Christoph Calisto", "isOrganizer": true, "responseStatus": "ACCEPTED", "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "calendarEventId": "86083141-1c0e-494c-a1b6-85b1c6fefaa5", "personId": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "workspaceMemberId": null } ], "pointOfContactForOpportunities": [ { "id": "20202020-be10-412b-a663-16bd3c2228e1", "name": "Opportunity 1", "closeDate": "2024-07-08T16:08:50.018Z", "probability": "0.5", "stage": "NEW", "position": 1, "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "pointOfContactId": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "companyId": "20202020-3ec3-4fe3-8997-b76aa0bfa408", "amount": { "amountMicros": 100000, "currencyCode": "USD" } } ] }, ... ]} ``` ### Depth = 2 ``` { "data": { "people": [ { "id": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "email": "[email protected]", "jobTitle": "", "phone": "+33789012345", "city": "Seattle", "avatarUrl": "", "position": 1, "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "companyId": "20202020-3ec3-4fe3-8997-b76aa0bfa408", "name": { "firstName": "Christoph", "lastName": "Callisto" }, "linkedinLink": { "label": "", "url": "" }, "xLink": { "label": "", "url": "" }, "activityTargets": [], "favorites": [], "attachments": [], "timelineActivities": [], "company": { "id": "20202020-3ec3-4fe3-8997-b76aa0bfa408", "name": "Linkedin", "domainName": "linkedin.com", "address": "", "employees": null, "idealCustomerProfile": false, "position": 1, "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "accountOwnerId": null, "accountOwner": null, "linkedinLink": { "label": "", "url": "" }, "xLink": { "label": "", "url": "" }, "annualRecurringRevenue": { "amountMicros": null, "currencyCode": "" }, "activityTargets": [], "favorites": [], "attachments": [], "timelineActivities": [], "people": [ { "id": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "email": "[email protected]", "jobTitle": "", "phone": "+33789012345", "city": "Seattle", "avatarUrl": "", "position": 1, "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "companyId": "20202020-3ec3-4fe3-8997-b76aa0bfa408", "name": { "firstName": "Christoph", "lastName": "Callisto" }, "linkedinLink": { "label": "", "url": "" }, "xLink": { "label": "", "url": "" } }, { "id": "20202020-ac73-4797-824e-87a1f5aea9e0", "email": "[email protected]", "jobTitle": "", "phone": "+33780123456", "city": "Los Angeles", "avatarUrl": "", "position": 2, "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "companyId": "20202020-3ec3-4fe3-8997-b76aa0bfa408", "name": { "firstName": "Sylvie", "lastName": "Palmer" }, "linkedinLink": { "label": "", "url": "" }, "xLink": { "label": "", "url": "" } } ], "opportunities": [ { "id": "20202020-be10-412b-a663-16bd3c2228e1", "name": "Opportunity 1", "closeDate": "2024-07-08T16:08:50.018Z", "probability": "0.5", "stage": "NEW", "position": 1, "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "pointOfContactId": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "companyId": "20202020-3ec3-4fe3-8997-b76aa0bfa408", "amount": { "amountMicros": 100000, "currencyCode": "USD" } } ] }, "pointOfContactForOpportunities": [ { "id": "20202020-be10-412b-a663-16bd3c2228e1", "name": "Opportunity 1", "closeDate": "2024-07-08T16:08:50.018Z", "probability": "0.5", "stage": "NEW", "position": 1, "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "pointOfContactId": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "companyId": "20202020-3ec3-4fe3-8997-b76aa0bfa408", "amount": { "amountMicros": 100000, "currencyCode": "USD" }, "favorites": [], "activityTargets": [], "attachments": [], "timelineActivities": [], "pointOfContact": { "id": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "email": "[email protected]", "jobTitle": "", "phone": "+33789012345", "city": "Seattle", "avatarUrl": "", "position": 1, "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "companyId": "20202020-3ec3-4fe3-8997-b76aa0bfa408", "name": { "firstName": "Christoph", "lastName": "Callisto" }, "linkedinLink": { "label": "", "url": "" }, "xLink": { "label": "", "url": "" } }, "company": { "id": "20202020-3ec3-4fe3-8997-b76aa0bfa408", "name": "Linkedin", "domainName": "linkedin.com", "address": "", "employees": null, "idealCustomerProfile": false, "position": 1, "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "accountOwnerId": null, "linkedinLink": { "label": "", "url": "" }, "xLink": { "label": "", "url": "" }, "annualRecurringRevenue": { "amountMicros": null, "currencyCode": "" } } } ], "messageParticipants": [ { "id": "20202020-0f2a-49d8-8aa2-ec8786153a0b", "role": "from", "handle": "outgoing", "displayName": "Christoph", "createdAt": "2024-07-08T16:08:50.028Z", "updatedAt": "2024-07-08T16:08:50.028Z", "messageId": "20202020-2b8a-405d-8f42-e820ca921421", "personId": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "workspaceMemberId": "20202020-0687-4c41-b707-ed1bfca972a7", "message": { "id": "20202020-2b8a-405d-8f42-e820ca921421", "headerMessageId": "99ef24a8-2b8a-405d-8f42-e820ca921421", "direction": "outgoing", "subject": "Meeting Request", "text": "Hello, \n I hope this email finds you well. I am writing to request a meeting. I believe it would be beneficial for both parties to collaborate and explore potential opportunities. Would you be available for a meeting sometime next week? Please let me know your availability, and I will arrange a suitable time. \n Looking forward to your response.\n Best regards", "receivedAt": "2024-07-08T16:08:50.022Z", "createdAt": "2024-07-08T16:08:50.022Z", "updatedAt": "2024-07-08T16:08:50.022Z", "messageThreadId": "20202020-8bfa-453b-b99b-bc435a7d4da8" }, "person": { "id": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "email": "[email protected]", "jobTitle": "", "phone": "+33789012345", "city": "Seattle", "avatarUrl": "", "position": 1, "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "companyId": "20202020-3ec3-4fe3-8997-b76aa0bfa408", "name": { "firstName": "Christoph", "lastName": "Callisto" }, "linkedinLink": { "label": "", "url": "" }, "xLink": { "label": "", "url": "" } }, "workspaceMember": { "id": "20202020-0687-4c41-b707-ed1bfca972a7", "colorScheme": "Light", "locale": "en", "avatarUrl": "", "userEmail": "[email protected]", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "name": { "firstName": "Tim", "lastName": "Apple" } } }, { "id": "20202020-fc7d-4ad8-9aea-b78bcbf79cdd", "role": "from", "handle": "outgoing", "displayName": "Christoph", "createdAt": "2024-07-08T16:08:50.028Z", "updatedAt": "2024-07-08T16:08:50.028Z", "messageId": "20202020-04c8-4f24-93f2-764948e95014", "personId": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "workspaceMemberId": "20202020-0687-4c41-b707-ed1bfca972a7", "message": { "id": "20202020-04c8-4f24-93f2-764948e95014", "headerMessageId": "8f804a9a-04c8-4f24-93f2-764948e95014", "direction": "outgoing", "subject": "Inquiry Regarding Topic", "text": "Good Morning,\n I am writing to inquire about information. Could you please provide me with details regarding this topic? \n Your assistance in this matter would be greatly appreciated. Thank you in advance for your prompt response. \n Best regards,Tim", "receivedAt": "2024-07-08T16:08:50.022Z", "createdAt": "2024-07-08T16:08:50.022Z", "updatedAt": "2024-07-08T16:08:50.022Z", "messageThreadId": "20202020-634a-4fde-aa7c-28a0eaf203ca" }, "person": { "id": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "email": "[email protected]", "jobTitle": "", "phone": "+33789012345", "city": "Seattle", "avatarUrl": "", "position": 1, "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "companyId": "20202020-3ec3-4fe3-8997-b76aa0bfa408", "name": { "firstName": "Christoph", "lastName": "Callisto" }, "linkedinLink": { "label": "", "url": "" }, "xLink": { "label": "", "url": "" } }, "workspaceMember": { "id": "20202020-0687-4c41-b707-ed1bfca972a7", "colorScheme": "Light", "locale": "en", "avatarUrl": "", "userEmail": "[email protected]", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "name": { "firstName": "Tim", "lastName": "Apple" } } } ], "calendarEventParticipants": [ { "id": "da8f47c3-8055-49ad-b7e4-9c9d5bbc1ecc", "handle": "[email protected]", "displayName": "Christoph Calisto", "isOrganizer": true, "responseStatus": "ACCEPTED", "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "calendarEventId": "86083141-1c0e-494c-a1b6-85b1c6fefaa5", "personId": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "workspaceMemberId": null, "workspaceMember": null, "calendarEvent": { "id": "86083141-1c0e-494c-a1b6-85b1c6fefaa5", "title": "Meeting with Christoph", "isCanceled": false, "isFullDay": false, "startsAt": "2024-07-08T08:00:50.030Z", "endsAt": "2024-07-08T09:00:50.030Z", "externalCreatedAt": "2024-07-08T16:08:50.030Z", "externalUpdatedAt": "2024-…
author JarWarren <[email protected]> 1717255102 -0600 committer JarWarren <[email protected]> 1724031436 -0600 parent 65fc83a763516e66ba2820723636241c9cfbaa5c author JarWarren <[email protected]> 1717255102 -0600 committer JarWarren <[email protected]> 1724031405 -0600 parent 65fc83a763516e66ba2820723636241c9cfbaa5c author JarWarren <[email protected]> 1717255102 -0600 committer JarWarren <[email protected]> 1724031152 -0600 parent 65fc83a763516e66ba2820723636241c9cfbaa5c author JarWarren <[email protected]> 1717255102 -0600 committer JarWarren <[email protected]> 1724031075 -0600 parent 65fc83a763516e66ba2820723636241c9cfbaa5c author JarWarren <[email protected]> 1717255102 -0600 committer JarWarren <[email protected]> 1724031068 -0600 parent 65fc83a763516e66ba2820723636241c9cfbaa5c author JarWarren <[email protected]> 1717255102 -0600 committer JarWarren <[email protected]> 1724031065 -0600 parent 65fc83a763516e66ba2820723636241c9cfbaa5c author JarWarren <[email protected]> 1717255102 -0600 committer JarWarren <[email protected]> 1724031064 -0600 parent 65fc83a763516e66ba2820723636241c9cfbaa5c author JarWarren <[email protected]> 1717255102 -0600 committer JarWarren <[email protected]> 1724031020 -0600 parent 65fc83a763516e66ba2820723636241c9cfbaa5c author JarWarren <[email protected]> 1717255102 -0600 committer JarWarren <[email protected]> 1724030985 -0600 parent 65fc83a763516e66ba2820723636241c9cfbaa5c author JarWarren <[email protected]> 1717255102 -0600 committer JarWarren <[email protected]> 1724030960 -0600 parent 65fc83a763516e66ba2820723636241c9cfbaa5c author JarWarren <[email protected]> 1717255102 -0600 committer JarWarren <[email protected]> 1724030944 -0600 parent 65fc83a763516e66ba2820723636241c9cfbaa5c author JarWarren <[email protected]> 1717255102 -0600 committer JarWarren <[email protected]> 1724030935 -0600 parent 65fc83a763516e66ba2820723636241c9cfbaa5c author JarWarren <[email protected]> 1717255102 -0600 committer JarWarren <[email protected]> 1724030917 -0600 parent 65fc83a763516e66ba2820723636241c9cfbaa5c author JarWarren <[email protected]> 1717255102 -0600 committer JarWarren <[email protected]> 1724030889 -0600 parent 65fc83a763516e66ba2820723636241c9cfbaa5c author JarWarren <[email protected]> 1717255102 -0600 committer JarWarren <[email protected]> 1724030600 -0600 parent 65fc83a763516e66ba2820723636241c9cfbaa5c author JarWarren <[email protected]> 1717255102 -0600 committer JarWarren <[email protected]> 1724030586 -0600 parent 65fc83a763516e66ba2820723636241c9cfbaa5c author JarWarren <[email protected]> 1717255102 -0600 committer JarWarren <[email protected]> 1724030582 -0600 parent 65fc83a763516e66ba2820723636241c9cfbaa5c author JarWarren <[email protected]> 1717255102 -0600 committer JarWarren <[email protected]> 1724030563 -0600 parent 65fc83a763516e66ba2820723636241c9cfbaa5c author JarWarren <[email protected]> 1717255102 -0600 committer JarWarren <[email protected]> 1724030562 -0600 parent 65fc83a763516e66ba2820723636241c9cfbaa5c author JarWarren <[email protected]> 1717255102 -0600 committer JarWarren <[email protected]> 1724030548 -0600 parent 65fc83a763516e66ba2820723636241c9cfbaa5c author JarWarren <[email protected]> 1717255102 -0600 committer JarWarren <[email protected]> 1724030547 -0600 parent 65fc83a763516e66ba2820723636241c9cfbaa5c author JarWarren <[email protected]> 1717255102 -0600 committer JarWarren <[email protected]> 1724030546 -0600 parent 65fc83a763516e66ba2820723636241c9cfbaa5c author JarWarren <[email protected]> 1717255102 -0600 committer JarWarren <[email protected]> 1724030531 -0600 parent 65fc83a763516e66ba2820723636241c9cfbaa5c author JarWarren <[email protected]> 1717255102 -0600 committer JarWarren <[email protected]> 1724030524 -0600 parent 65fc83a763516e66ba2820723636241c9cfbaa5c author JarWarren <[email protected]> 1717255102 -0600 committer JarWarren <[email protected]> 1724030479 -0600 parent 65fc83a763516e66ba2820723636241c9cfbaa5c author JarWarren <[email protected]> 1717255102 -0600 committer JarWarren <[email protected]> 1724030475 -0600 parent 65fc83a763516e66ba2820723636241c9cfbaa5c author JarWarren <[email protected]> 1717255102 -0600 committer JarWarren <[email protected]> 1724030469 -0600 parent 65fc83a763516e66ba2820723636241c9cfbaa5c author JarWarren <[email protected]> 1717255102 -0600 committer JarWarren <[email protected]> 1724030461 -0600 parent 65fc83a763516e66ba2820723636241c9cfbaa5c author JarWarren <[email protected]> 1717255102 -0600 committer JarWarren <[email protected]> 1724030453 -0600 parent 65fc83a763516e66ba2820723636241c9cfbaa5c author JarWarren <[email protected]> 1717255102 -0600 committer JarWarren <[email protected]> 1724030443 -0600 parent 65fc83a763516e66ba2820723636241c9cfbaa5c author JarWarren <[email protected]> 1717255102 -0600 committer JarWarren <[email protected]> 1724030440 -0600 parent 65fc83a763516e66ba2820723636241c9cfbaa5c author JarWarren <[email protected]> 1717255102 -0600 committer JarWarren <[email protected]> 1724030437 -0600 parent 65fc83a763516e66ba2820723636241c9cfbaa5c author JarWarren <[email protected]> 1717255102 -0600 committer JarWarren <[email protected]> 1724030406 -0600 parent 65fc83a763516e66ba2820723636241c9cfbaa5c author JarWarren <[email protected]> 1717255102 -0600 committer JarWarren <[email protected]> 1724030386 -0600 parent 65fc83a763516e66ba2820723636241c9cfbaa5c author JarWarren <[email protected]> 1717255102 -0600 committer JarWarren <[email protected]> 1724030351 -0600 # This is a combination of 33 commits. # This is the 1st commit message: add funnelmink logo to twenty-front # This is the commit message #2: whitelabel strings # This is the commit message #3: change package name # This is the commit message #4: add logging to command.js # This is the commit message #5: disable some gh actions # This is the commit message #6: add to docker-compose environment # This is the commit message #7: add env vars for storage credentials # This is the commit message #8: add email server env vars # This is the commit message #9: hide integration requests for now # This is the commit message #10: more string replacement # This is the commit message #11: change asset url # This is the commit message #12: android launcher icons # This is the commit message #13: ios icons # This is the commit message #14: url changes # This is the commit message #15: change docker-compose images # This is the commit message #16: more string replacement # This is the commit message #17: replace base64 images # This is the commit message #18: update docker-compose.yml # This is the commit message #19: simplify readme # This is the commit message #20: switch readme to markdown # This is the commit message #21: sentry env vars # This is the commit message #22: update docker-compose.yml # This is the commit message #23: add google auth to docker-compose.yml # This is the commit message #24: add NODE_ENV to docker-compose.yml # This is the commit message #25: add cache storage type # This is the commit message #26: add redis info # This is the commit message #27: add redis # This is the commit message #28: fsm (#4) * Add label to mocked connections (#5858) <img width="865" alt="Capture d’écran 2024-06-13 à 17 48 03" src="https://github.com/twentyhq/twenty/assets/22936103/2d313448-fbd5-4ff1-a65b-afd4df86117a"> * fix timeline activity pagination overflow (#5861) ## Before <img width="250" alt="Screenshot 2024-06-13 at 18 51 56" src="https://github.com/twentyhq/twenty/assets/1834158/d6c7f5fa-3cc7-48bc-a711-29345e93af92"> ## After <img width="284" alt="Screenshot 2024-06-13 at 18 51 41" src="https://github.com/twentyhq/twenty/assets/1834158/25029e0a-c1b0-4458-b715-dbab217eeee0"> * Add log for errors on message import (#5863) As per title :) * Support orderBy as array (#5681) closes: #4301 --------- Co-authored-by: Félix Malfait <[email protected]> * fix: text field overflow beyond cell limits (#5834) - fixes #5775 https://github.com/twentyhq/twenty/assets/47355538/9e440018-ec1e-4faa-a9f3-7131615cf9f1 --------- Co-authored-by: Charles Bochet <[email protected]> Co-authored-by: Lucas Bordeau <[email protected]> * Collapsible menu (#5846) A mini PR to discuss with @Bonapara tomorrow Separating remote objects from others and making the menu collapsible (style to be changed) <img width="225" alt="Screenshot 2024-06-12 at 23 25 59" src="https://github.com/twentyhq/twenty/assets/6399865/b4b69d36-6770-43a2-a5e8-bfcdf0a629ea"> Biggest issue is we don't use local storage today so the collapsed state gets lost. I see we have localStorageEffect with recoil. Maybe store it there? Seems easy but don't want to introduce a bad pattern. Todo: - style update - collapsible favorites - persistent storage * Fix workspaceLogo in invite-email (#5865) ## Fixes wrong image url in email ![image](https://github.com/twentyhq/twenty/assets/29927851/5fb1524b-874d-4723-8450-0284382bbeb3) ## Done - duplicates and adapt `getImageAbsoluteURIOrBase64` from `twenty-front` in `twenty-email` - send `SERVER_URL` to email builder * Fix error log on message import (#5866) Modify #5863 to log the connected account id rather than the message channel id to be consistent with the other logs and stringify the error. * Fix sentry error (#5848) Fixes https://twenty-v7.sentry.io/issues/5363536663/?environment=prod&project=4507072499810304&query=is%3Aunresolved+issue.priority%3A%5Bhigh%2C+medium%5D&referrer=issue-stream&statsPeriod=7d&stream_index=0 - handle error properly in twenty-server - display backend error message * Fix overflow on notes (#5853) ##before ![image](https://github.com/twentyhq/twenty/assets/29927851/c1784340-0741-4701-b11f-d2cf50fab9fb) ##after ![image](https://github.com/twentyhq/twenty/assets/29927851/c095eaf1-15c4-4e68-8cff-c175f99856d0) * Record horizontal scrolling mobile (#5843) I have fixed the scrolling the record container page on mobile making it hidden. This PR aims to fix #5745 --------- Co-authored-by: Lucas Bordeau <[email protected]> * fix: 404 generate API key link (#5871) - update api key link in the docs * Wrote 0.20 changelog (#5870) Created the changelog for 0.2 * Fix website docs (#5873) There was a 500 on the playground and the switch between core and metadata * Added Thai Baht support (#5881) Hey, saw Thai Baht support was [requested](https://github.com/twentyhq/twenty/issues/5876) and thought it was a cool first issue to get to know the project a little bit. * feat: Enhancements to MessageQueue Module with Decorators (#5657) ### Overview This PR introduces significant enhancements to the MessageQueue module by integrating `@Processor`, `@Process`, and `@InjectMessageQueue` decorators. These changes streamline the process of defining and managing queue processors and job handlers, and also allow for request-scoped handlers, improving compatibility with services that rely on scoped providers like TwentyORM repositories. ### Key Features 1. **Decorator-based Job Handling**: Use `@Processor` and `@Process` decorators to define job handlers declaratively. 2. **Request Scope Support**: Job handlers can be scoped per request, enhancing integration with request-scoped services. ### Usage #### Defining Processors and Job Handlers The `@Processor` decorator is used to define a class that processes jobs for a specific queue. The `@Process` decorator is applied to methods within this class to define specific job handlers. ##### Example 1: Specific Job Handlers ```typescript import { Processor, Process, InjectMessageQueue } from 'src/engine/integrations/message-queue'; @Processor('taskQueue') export class TaskProcessor { @Process('taskA') async handleTaskA(job: { id: string, data: any }) { console.log(`Handling task A with data:`, job.data); // Logic for task A } @Process('taskB') async handleTaskB(job: { id: string, data: any }) { console.log(`Handling task B with data:`, job.data); // Logic for task B } } ``` In the example above, `TaskProcessor` is responsible for processing jobs in the `taskQueue`. The `handleTaskA` method will only be called for jobs with the name `taskA`, while `handleTaskB` will be called for `taskB` jobs. ##### Example 2: General Job Handler ```typescript import { Processor, Process, InjectMessageQueue } from 'src/engine/integrations/message-queue'; @Processor('generalQueue') export class GeneralProcessor { @Process() async handleAnyJob(job: { id: string, name: string, data: any }) { console.log(`Handling job ${job.name} with data:`, job.data); // Logic for any job } } ``` In this example, `GeneralProcessor` handles all jobs in the `generalQueue`, regardless of the job name. The `handleAnyJob` method will be invoked for every job added to the `generalQueue`. #### Adding Jobs to a Queue You can use the `@InjectMessageQueue` decorator to inject a queue into a service and add jobs to it. ##### Example: ```typescript import { Injectable } from '@nestjs/common'; import { InjectMessageQueue, MessageQueue } from 'src/engine/integrations/message-queue'; @Injectable() export class TaskService { constructor( @InjectMessageQueue('taskQueue') private readonly taskQueue: MessageQueue, ) {} async addTaskA(data: any) { await this.taskQueue.add('taskA', data); } async addTaskB(data: any) { await this.taskQueue.add('taskB', data); } } ``` In this example, `TaskService` adds jobs to the `taskQueue`. The `addTaskA` and `addTaskB` methods add jobs named `taskA` and `taskB`, respectively, to the queue. #### Using Scoped Job Handlers To utilize request-scoped job handlers, specify the scope in the `@Processor` decorator. This is particularly useful for services that use scoped repositories like those in TwentyORM. ##### Example: ```typescript import { Processor, Process, InjectMessageQueue, Scope } from 'src/engine/integrations/message-queue'; @Processor({ name: 'scopedQueue', scope: Scope.REQUEST }) export class ScopedTaskProcessor { @Process('scopedTask') async handleScopedTask(job: { id: string, data: any }) { console.log(`Handling scoped task with data:`, job.data); // Logic for scoped task, which might use request-scoped services } } ``` Here, the `ScopedTaskProcessor` is associated with `scopedQueue` and operates with request scope. This setup is essential when the job handler relies on services that need to be instantiated per request, such as scoped repositories. ### Migration Notes - **Decorators**: Refactor job handlers to use `@Processor` and `@Process` decorators. - **Request Scope**: Utilize the scope option in `@Processor` if your job handlers depend on request-scoped services. Fix #5628 --------- Co-authored-by: Weiko <[email protected]> * 5236 expandable list leave options when editing (#5890) Fixes https://github.com/twentyhq/twenty/issues/5236 ## After ![image](https://github.com/twentyhq/twenty/assets/29927851/5f0f910c-11b0-40ce-9c59-34e7ce0c2741) * 5581 get httpsapitwentycomrestmetadata relations not working (#5867) Filtering relations is not allowed (see`packages/twenty-server/src/engine/metadata-modules/relation-metadata/dtos/relation-metadata.dto.ts`) so we remove filtering for find many relation we also fixed some bug in result structure and metadata open-api schema * Fix verticale line timeline activity (#5894) Before <img width="400" alt="Capture d’écran 2024-06-17 à 10 23 17" src="https://github.com/twentyhq/twenty/assets/22936103/01408d7b-9a6c-4a21-9f08-c8cf304e2ea0"> After <img width="400" alt="Capture d’écran 2024-06-17 à 10 05 39" src="https://github.com/twentyhq/twenty/assets/22936103/df384726-bbf9-4828-ad47-d1c91724947d"> * Added and optimized missing RatingFieldDisplay component (#5904) The display for Rating field type was missing, I just added it based on RatingInput in readonly mode and optimized a bit for performance also. Fixes https://github.com/twentyhq/twenty/issues/5900 * Fix secondaryLinks field input (#5911) PR https://github.com/twentyhq/twenty/pull/5785/files broke links update. Also, dropdown "Add link" will be displayed only if a link is already added. Otherwise, it should be a normal input. * add multiple filters of same FieldMetadataType (#5892) fixes: #5378 * Add South Korean won to currency codes (#5914) Greetings from Seoul! I found this amazing project a few days ago, and trying to introduce it to my team. However there is a tiny but significant problem, that South Korean won is not available in twenty. So I added `KRW` to the enum `CurrencyCode` and the constant `SETTINGS_FIELD_CURRENCY_CODES`. I tested it locally and apparently works fine. * Upgrade pg graphql version to 1.5.6 (#5937) - update `pg_graphql` version doc - update `pg_graphql` version to 1.5.6 * Add loader and transition for details page tabs (#5935) Closes https://github.com/twentyhq/twenty/issues/5656 https://github.com/twentyhq/twenty/assets/22936103/3e4beea2-9aa9-4015-bb99-ee22adb53b63 * website / Fix broken links, slow loading, and prod errors (#5932) The code is in a bad state, this is just fixing it but not improving the structure * 5582 get httpsapitwentycomrestmetadata objects filters dont work (#5906) - Remove filters from metadata rest api - add limite before and after parameters for metadata - remove update from metadata relations - fix typing issue - fix naming - fix before parameter --------- Co-authored-by: Félix Malfait <[email protected]> * Add http status to graphql errors (#5896) Graphql errors are not properly filtered by our handler. We still receive errors like `NOT_FOUND` in sentry while they should be filtered. Example [here](https://twenty-v7.sentry.io/issues/5490383016/?environment=prod&project=4507072499810304&query=is%3Aunresolved+issue.priority%3A%5Bhigh%2C+medium%5D&referrer=issue-stream&statsPeriod=7d&stream_index=6). We associate statuses with errors in our map `graphQLPredefinedExceptions` but we cannot retrieve the status from the error. This PR lists the codes that should be filtered. To test: - call `findDuplicates` with an invalid id - before, server would breaks - now the error is simply returned * Handle no concurrency option (#5952) Fix error in local `teamConcurrency must be an integer between 1 and 1000` * Favicons are being re-rendered on hover (#5849) ### Description Favicons are being re-rendered on hover ### Refs #3523 ### Demo https://www.loom.com/share/e3944d940a014283af8c26baac1fed57?sid=e3e96a81-3a54-4969-8602-99c64bb3ffe7 Fixes #3523 --------- Co-authored-by: gitstart-twenty <[email protected]> Co-authored-by: v1b3m <[email protected]> Co-authored-by: Thiago Nascimbeni <[email protected]> Co-authored-by: Lucas Bordeau <[email protected]> * Add a ⏎ shortcut on Select options (#5641) fixes #5540 Added onkeyDown to 1. Create new option and 2. Move focus to it. [screen-capture (6).webm](https://github.com/twentyhq/twenty/assets/69167444/ede54ad8-22db-4b09-9617-4d999c6c08c7) --------- Co-authored-by: Lucas Bordeau <[email protected]> * Added a mechanism to reset error boundary on page change. (#5913) Previously the error boundary component was re-rendering with the same state as long as we stayed in the same router, so for page change inside an index container, it would stay on error state. The fix is to memorize the location the error page is on during its first render, and then to reset the error boundary if it gets re-rendered with a different location even in the same index container. Fixes : #3592 * fix(twenty-front): update DateTimeInput styles to apply top border radius to date picker (#5946) update DateTimeInput styled components to prevent the StyledInput from overflowing out of it's parent container <img width="860" alt="Screenshot 2024-06-19 at 9 55 04 AM" src="https://github.com/twentyhq/twenty/assets/19223383/8c5daf6a-9eb6-4ecd-a2e9-aa2ba8db3874"> Fixes #5940 * (5943) Match country selector button's background to phone number input's background (#5956) Fixes #5943 ### Before Light <img width="218" alt="Screenshot 2024-06-19 at 12 37 22 PM" src="https://github.com/twentyhq/twenty/assets/57673080/981d1877-be4e-4071-9a8d-9d0ed7e933ab"> Dark <img width="223" alt="Screenshot 2024-06-19 at 12 39 42 PM" src="https://github.com/twentyhq/twenty/assets/57673080/a3730ef5-21ba-4d90-998d-d330aec350ad"> ### After Light <img width="216" alt="Screenshot 2024-06-19 at 12 39 00 PM" src="https://github.com/twentyhq/twenty/assets/57673080/eef3b743-1b28-43a5-8c1c-bd944a4915c7"> Dark <img width="228" alt="Screenshot 2024-06-19 at 12 39 29 PM" src="https://github.com/twentyhq/twenty/assets/57673080/5bf10e51-5a07-4d55-99f1-734517b22781"> * [Bug] Put back subject is email right drawer (#5955) Fix https://github.com/twentyhq/twenty/issues/5903 * Data Skeleton Loading on Indexes (#5828) ### Description Data Skeleton Loading on Indexes ### Refs #4459 ### Demo https://github.com/twentyhq/twenty/assets/140154534/d9c9b0fa-2d8c-4b0d-8d48-cae09530622a Fixes #4459 --------- Co-authored-by: gitstart-twenty <[email protected]> Co-authored-by: v1b3m <[email protected]> Co-authored-by: Matheus <[email protected]> Co-authored-by: Lucas Bordeau <[email protected]> * 5934 create alert banner component (#5950) Closes #5934 --------- Co-authored-by: Lucas Bordeau <[email protected]> * Fix reconnect google account bug (#5905) Update syncStage to FULL_MESSAGE_LIST_FETCH_PENDING when reconnecting the account to trigger a full sync on the next cron iteration. * 5898 Create a cron to monitor messageChannelSyncStatus (#5933) Closes #5898 * Feat : Introduced Delay Options for Tooltip (#5766) Fixes https://github.com/twentyhq/twenty/issues/5727 --------- Co-authored-by: Rushikesh Tarapure <[email protected]> Co-authored-by: Lucas Bordeau <[email protected]> * add object id column to csv export (#5971) closes: #5893 --------- Co-authored-by: Félix Malfait <[email protected]> * fix: Column header menu Filter button (#5973) fixes: #5957 https://github.com/twentyhq/twenty/assets/13139771/51d42aa5-c774-4cbe-adca-b95ea6e17bbd * Fix date picker wrong on certain timezones (#5972) Timezone with a negative offset weren't working good with date pickers. I split the logic for display and parsing between date only and datetime. Date time is sending and displaying using timezone, and date only is sending and displaying by forcing the date to take its UTC day and month and 00:00:00 time. This way its consistent across all timezones. * Add the support of Empty and Non-Empty filter (#5773) * Fix(view): `Create` Button is not visible when creating `Kanban` View (#5969) Closes #5915 This issue occurs only when there is no select field. The user then creates a new one in settings and returns back to the view picker. And the bug arises, it because `viewPickerKanbanFieldMetadataId` is not being set correctly. When a user navigate to settings, the dirty state should be set to false. As a result, after re-rendering the view picker component, it triggers the effect to set `viewPickerKanbanFieldMetadataId` --------- Co-authored-by: Achsan <[email protected]> Co-authored-by: Lucas Bordeau <[email protected]> * Add disabled style on non-draggable menu items (#5974) Closes https://github.com/twentyhq/twenty/issues/5653 <img width="256" alt="Capture d’écran 2024-06-20 à 17 19 44" src="https://github.com/twentyhq/twenty/assets/22936103/c9d7e58f-818b-44f2-8aa4-4d85c8e1b6be"> <img width="231" alt="Capture d’écran 2024-06-20 à 17 20 03" src="https://github.com/twentyhq/twenty/assets/22936103/5e981e93-9d59-403a-bb6b-0ff75151ace2"> * Update LOGGER_DRIVER env var description (#5968) Update the docs to accurately reflect `LoggerDriverType`. Using `sentry` throws an error on startup. ``` export enum LoggerDriverType { Console = 'console', } ``` Happy to change the wording of course. * Fix: Selected Line Not Fully Highlighted in Blue (#5966) Fixes: #5942 <img width="1517" alt="Screenshot 2024-06-19 at 5 07 35 PM" src="https://github.com/twentyhq/twenty/assets/63531478/c88a98e9-7ce3-43fe-a496-1a5dfe796b81"> --------- Co-authored-by: Lucas Bordeau <[email protected]> * fix: background colors for record table (#5967) # Summary - Address issue #5959 - Update background color on hover & click for record table # Test Plan ![Kapture 2024-06-19 at 20 32 44](https://github.com/twentyhq/twenty/assets/10789158/18a58c09-040a-47e6-953d-aac6f3803486) * Fix links chip design (#5963) Fix https://github.com/twentyhq/twenty/issues/5938 and https://github.com/twentyhq/twenty/issues/5655 - Make sure chip count is displayed - Fix padding - Fix background colors, border - Add hover and active states --------- Co-authored-by: Lucas Bordeau <[email protected]> * Navigation Panel UI Sizing Changes (#5964) ## Fixes #5902 : - [x] Navigation items' height should be risen to 28px. > For clarity: - [x] Also increased the height of NavigationDrawerSectionTitle to 28px to match navigation item. - [x] The gap between sections should be reduced to 12px > Was already completed it seems. - [x] The workspace switcher should be aligned with the navigation items --------- Co-authored-by: Lucas Bordeau <[email protected]> * feat: add brazilian real currency (#5989) Added support to Brazilian Real currency code, added the new code on `CurrencyCode.ts` and on `SETTINGS_FIELD_CURRENCY_CODES` * feat: drop calendar repository (#5824) This PR is replacing and removing all the raw queries and repositories with the new `TwentyORM` and injection system using `@InjectWorkspaceRepository`. Some logic that was contained inside repositories has been moved to the services. In this PR we're only replacing repositories for calendar feature. --------- Co-authored-by: Weiko <[email protected]> Co-authored-by: bosiraphael <[email protected]> Co-authored-by: Charles Bochet <[email protected]> * [FlexibleSchema] Add IndexMetadata decorator (#5981) ## Context Our Flexible Schema engine dynamically generates entities/tables/APIs for us but was not flexible enough to build indexes in the DB. With more and more features involving heavy queries such as Messaging, we are now adding a new WorkspaceIndex() decorator for our standard objects (will come later for custom objects). This decorator will give enough information to the workspace sync metadata manager to generate the proper migrations that will create or drop indexes on demand. To be aligned with the rest of the engine, we are adding 2 new tables: IndexMetadata and IndexFieldMetadata, that will store the info of our indexes. ## Implementation ```typescript @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.person, namePlural: 'people', labelSingular: 'Person', labelPlural: 'People', description: 'A person', icon: 'IconUser', }) export class PersonWorkspaceEntity extends BaseWorkspaceEntity { @WorkspaceField({ standardId: PERSON_STANDARD_FIELD_IDS.email, type: FieldMetadataType.EMAIL, label: 'Email', description: 'Contact’s Email', icon: 'IconMail', }) @WorkspaceIndex() email: string; ``` By simply adding the WorkspaceIndex decorator, sync-metadata command will create a new index for that column. We can also add composite indexes, note that the order is important for PSQL. ```typescript @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.person, namePlural: 'people', labelSingular: 'Person', labelPlural: 'People', description: 'A person', icon: 'IconUser', }) @WorkspaceIndex(['phone', 'email']) export class PersonWorkspaceEntity extends BaseWorkspaceEntity { ``` Currently composite fields and relation fields are not handled by @WorkspaceIndex() and you will need to use this notation instead ```typescript @WorkspaceIndex(['companyId', 'nameFirstName']) export class PersonWorkspaceEntity extends BaseWorkspaceEntity { ``` <img width="700" alt="Screenshot 2024-06-21 at 15 15 45" src="https://github.com/twentyhq/twenty/assets/1834158/ac6da1d9-d315-40a4-9ba6-6ab9ae4709d4"> Next step: We might need to implement more complex index expressions, this is why we have an expression column in IndexMetadata. What I had in mind for the decorator, still open to discussion ```typescript @WorkspaceIndex(['nameFirstName', 'nameLastName'], { expression: "$1 || ' ' || $2"}) export class PersonWorkspaceEntity extends BaseWorkspaceEntity { ``` --------- Co-authored-by: Charles Bochet <[email protected]> * Improve tests (#5994) Our tests on FE are red, which is a threat to code quality. I'm adding a few unit tests to improve the coverage and lowering a bit the lines coverage threshold * Fix infinite scroll issue on table (#5996) We had an issue on infinite scroll on table view. The fetch more logic was modifying isTableLastRowVisible state (which is wrong, how could it know)? This was done to prevent loading too much data at once. This was causing some race condition on isTableLastRowVisible (as the table itself was also changing it depending on the real visibility of the line) I have remove this hacky usage of isTableLastRowVisible and replaced it by a setTimeout to let the user some time to scroll and introduce a throttle logic. * Remove Right-Edge Gap in Table Cell Display (#5992) fixes #5941 ![Screenshot from 2024-06-23 17-24-24](https://github.com/twentyhq/twenty/assets/59247136/ae67603a-824d-4e6b-b873-2d58e6296341) --------- Co-authored-by: Lucas Bordeau <[email protected]> * Refactor infiniteScoll to use debouncing (#5999) Same as https://github.com/twentyhq/twenty/pull/5996 but with useDebounced as asked in review * Create feature flag for calendar V2 (#5998) Create feature flag for calendar V2 * Turned on tooltip on kanban cards with shortDelay (#5991) fixes: #5982 Demo: https://github.com/twentyhq/twenty/assets/58113282/6593381c-c01a-4259-9caa-8612247a9e95 --------- Co-authored-by: Lucas Bordeau <[email protected]> * feat: add australian dollar currency (#5990) Hi Twenty team, I'd love to have Australian dollar as an option in Twenty! Please let me me know if I have missed anything I need to change to enable this. Thanks for a a great product --------- Co-authored-by: Lucas Bordeau <[email protected]> * Add update chevron (#5988) Fixes #5986 1. Added right chevron to Fields Menu Item <img width="735" alt="Screenshot 2024-06-21 at 5 59 46 PM" src="https://github.com/twentyhq/twenty/assets/63531478/1515aba0-6732-424d-a0b3-5cc826a35b16"> 2. Changed color of Hidden fields menu item chevron and stroke of left chevron <img width="735" alt="Screenshot 2024-06-21 at 6 21 30 PM" src="https://github.com/twentyhq/twenty/assets/63531478/20952197-2f09-486c-a3bb-5b6c285a6996"> --------- Co-authored-by: Lucas Bordeau <[email protected]> * Fix(view): Show Kanban View Creation (#5985) # This PR - Revise my previous work (PR #5969) Because it would break the current logic and cause unexpected behavior. (Issue #5979) - Solve (Issue #5915) with another way @lucasbordeau What do you think about my current approach? @JarWarren Please check it out—I'd love to get your feedback too! --------- Co-authored-by: Achsan <[email protected]> Co-authored-by: Lucas Bordeau <[email protected]> * Remove multi select usage (#6004) As per title! Also, I'm removing an incorrect logic in the enum migration runner that takes care of the case where we have no defaultValue but non nullable which is not a valid business case. * Create new sync statuses and stages for calendar (#5997) Create fields: - syncStatus - syncStage - syncStageStartedAt * 5951 create a command to trigger the import of a single message (#5962) Closes #5951 --------- Co-authored-by: Charles Bochet <[email protected]> * Add calendar cron command on self-hosting-var.mdx (#6009) To enable Google Calendar integration, you need to run `yarn command:prod cron:calendar:google-calendar-sync` in the worker container. However, currently, the self-hosting guide does not tell you how to do it. If you just follow the guide, only Gmail integration will be enabled. So I added the command for calendar sync cron on self-hosting-var.mdx. * Remove useless api position parameter (#6010) - remove buggy addition of position parameter - check created records are in first position by default * Fix sign up broken because of missing workspace schema (#6013) Allow workspace datasource factory to return null if the workspace schema has not been created yet * 5615 create messageongoingstalecron (#6005) Closes #5615 * feat: Dynamic hook registration for WorkspaceQueryHooks (#6008) #### Overview This PR introduces a new API for dynamically registering and executing pre and post query hooks in the Workspace Query Hook system using the `@WorkspaceQueryHook` decorator. This approach eliminates the need for manual provider registration, and fix the issue of `undefined` or `null` repository using `@InjectWorkspaceRepository`. #### New API **Define a Hook** Use the `@WorkspaceQueryHook` decorator to define pre or post hooks: ```typescript @WorkspaceQueryHook({ key: `calendarEvent.findMany`, scope: Scope.REQUEST, }) export class CalendarEventFindManyPreQueryHook implements WorkspaceQueryHookInstance { async execute(userId: string, workspaceId: string, payload: FindManyResolverArgs): Promise<void> { if (!payload?.filter?.id?.eq) { throw new BadRequestException('id filter is required'); } // Implement hook logic here } } ``` This API simplifies the registration and execution of query hooks, providing a more flexible and maintainable approach. --------- Co-authored-by: Weiko <[email protected]> * Fix billing signup when workspace does not exist (#6018) * Removed performance optimization and put back previous system with recoil states for edit mode and soft focus to avoid side effects. (#6019) Fixes https://github.com/twentyhq/twenty/issues/6016 This was another side effect of the optimization made on RecordTableCellContainer to avoid using recoil states, but which causes too many unpredictable side effects. I just put back the previous system which works well. We'll see how to optimize it again later. * Remove message-import cache when connectedAccount is removed (#6021) * Upsert endpoint and CSV import upsert (#5970) This PR introduces an `upsert` parameter (along the existing `data` param) for `createOne` and `createMany` mutations. When upsert is set to `true`, the function will look for records with the same id if an id was passed. If not id was passed, it will leverage the existing duplicate check mechanism to find a duplicate. If a record is found, then the function will perform an update instead of a create. Unfortunately I had to remove some nice tests that existing on the args factory. Those tests where mostly testing the duplication rule generation logic but through a GraphQL angle. Since I moved the duplication rule logic to a dedicated service, if I kept the tests but mocked the service we wouldn't really be testing anything useful. The right path would be to create new tests for this service that compare the JSON output and not the GraphQL output but I chose not to work on this as it's equivalent to rewriting the tests from scratch and I have other competing priorities. * Add mutationMaximumRecordAffected to clientConfig (#6039) We are exposing the server mutationMaximumRecordAffected value via clientConfig so it can be used by the FE. This is a first step for https://github.com/twentyhq/twenty/issues/6025 <img width="610" alt="Screenshot 2024-06-26 at 14 58 26" src="https://github.com/twentyhq/twenty/assets/1834158/9d192976-fd22-45d2-bdaa-a8ff6bb90ca2"> * Don't display unmatched columns in csv import (#6037) Adding a toggle so that, by default, we don't see dozens of fields but only the field we matched, during the data validation step in csv export <img width="785" alt="Screenshot 2024-06-26 at 13 25 36" src="https://github.com/twentyhq/twenty/assets/6399865/ae558eb5-7461-4bc8-a836-ecff8b6d0dff"> * Fix search in csv import (#6045) A mini quality of life improvements, the search was case-sensitive which was frustrating * Rename mutation maximum affected records (#6042) As per my last comment on https://github.com/twentyhq/twenty/pull/6039, we decided to rename this var * Basic import for select in CSV (#6047) Enables basic support for Select import and field matching in CSV. It's not pretty! But it's better than what we had before. We should iterate on that quickly <img width="591" alt="Screenshot 2024-06-26 at 18 41 16" src="https://github.com/twentyhq/twenty/assets/6399865/99f67f39-3f0f-4074-aac6-3200954be08a"> * Add boolean with toggle in csv import (#6050) Better UI when importing boolean via CSV (with a toggle) * Improve gmail error handling by catching and throttling for 400 failedPrecondition (#6044) Closes #5897 * Fix cache flush in messaging-channel-sync-status.service (#6024) Fix cache flush in messaging-channel-sync-status.service * hide delete button for selection over 100 - issue #6023 (#6030) hide the "Delete" Button when more than 100 records are Selected --------- Co-authored-by: Weiko <[email protected]> * Relations many in table view (#5842) Closes #5924. Adding the "many" side of relations in the table view, and fixing some issues (glitch in Multi record select, cache update after update). --------- Co-authored-by: Lucas Bordeau <[email protected]> * feat: manually implement joinColumn (#6022) This PR introduce a new decorator named `@WorkspaceJoinColumn`, the goal of this one is to manually declare the join columns inside the workspace entities, so we don't have to rely on `ObjectRecord` type. This decorator can be used that way: ```typescript @WorkspaceRelation({ standardId: ACTIVITY_TARGET_STANDARD_FIELD_IDS.company, type: RelationMetadataType.MANY_TO_ONE, label: 'Company', description: 'ActivityTarget company', icon: 'IconBuildingSkyscraper', inverseSideTarget: () => CompanyWorkspaceEntity, inverseSideFieldKey: 'activityTargets', }) @WorkspaceIsNullable() company: Relation<CompanyWorkspaceEntity> | null; // The argument is the name of the relation above @WorkspaceJoinColumn('company') companyId: string | null; ``` * Update create-workspace.mdx (#6053) Fix a dead link that was redirecting to a 400 * Manage isFocused state for table cells (#6058) as per title * Replace ObjectRecord<MessageChannelWorkspaceEntity> with MessageChannelWorkspaceEntity (#6059) Replace ObjectRecord<MessageChannelWorkspaceEntity> with MessageChannelWorkspaceEntity * Fixed board card field max width (#6061) Add a max-width to prevent overflow of board card fields * fix navigation panel workspace picker padding (#6062) ## Before <img width="223" alt="Screenshot 2024-06-27 at 15 23 26" src="https://github.com/twentyhq/twenty/assets/1834158/18cb5e15-352f-4e65-9cff-6e396abe4318"> ## After <img width="229" alt="Screenshot 2024-06-27 at 15 23 07" src="https://github.com/twentyhq/twenty/assets/1834158/53502c23-d9b4-4967-9e56-26e62e5e50ea"> <img width="225" alt="Screenshot 2024-06-27 at 15 25 23" src="https://github.com/twentyhq/twenty/assets/1834158/fbb751ba-2bde-44f0-9c70-a9091e9b9012"> * Create fields for calendar and messaging settings v2 (#6049) Create fields for calendar and messaging settings v2 * Change messaging batch size and cron pattern (#6063) Change messaging batch size and cron pattern to accelerate messages import * 5901 refactor email and calendar auto contact creation to create them by batch (#6038) Closes #5901 * Refactor messaging refresh access token (#6034) - Put error handling outside of `refreshAndSaveAccessToken` - return after failing to refresh access token in `processMessageBatchImport` - remove unnecessary token refresh in `processMessageListFetch` * 5095 move onboardingstatus computation from frontend to backend (#5954) - move front `onboardingStatus` computing to server side - add logic to `useSetNextOnboardingStatus` - update some missing redirections in `usePageChangeEffectNavigateLocation` - separate subscriptionStatus from onboardingStatus * 0.21 changelog (#6072) * Clarify storybook tests (#6073) In this PR, I'm simplifying storybook setup: 1) Remove build --test configuration that prevent autodocs. We are not using autodocs at all (the dev experience is not good enough), so I have completely disabled it. 2) Clarify `serve` vs `test` vs `serve-and-test` configurations After this PR: - you can serve storybook in two modes: `npx nx run twenty-front:storybook:serve:dev` and `npx nx run twenty-front:storybook:serve:static` - you can run tests agains an already served storybook (this is useful in dev so you don't have to rebuild everytime to run tests): `npx nx run twenty-front:storybook:test` - you can conbine both: `npx nx run twenty-front:storybook:serve-and-test:static` * Fix tests * Fix tests on RelationManyFieldDisplay * Improve use set next onboarding state (#6076) querying workspaceMembers may be slow leads to wrong setNextOnboardingStatus value. So we added a resolved field in workspace to get workspaceMemberCount directly * Allow s3 credentials via env (#6066) closes #5072 * Remove CSS modules (#6017) CSS modules were used as a first test for performance optimization. We later found out that Linaria was a better tradeoff. This PR removes what was implemented in CSS modules and also the CSS theme file that was created that was overlapping with the TS theme files. * feat: message cleaner drop repository (#6052) This PR use the new `TwentyORM` for the message-cleaner module by using the new injection system with `@InjectWorkspaceRepository`. * fix: message cleaner find operator (#6080) This PR fix an issue with the `IsNull()` find operator applied on one-to-many relation, this one is not supported by TypeORM. We can instead filter by an empty array to retrieve object with empty relations. * Fix: Tasks-List-page-Person-Switcher (#6077) Fixes #6007, adds context to the ObjectFilter DropdownRecordSelect * Add exceptions for metadata modules (#6070) Class exception for each metadata module + handler to map on graphql error TODO left : - find a way to call handler on auto-resolvers nestjs query (probably interceptors) - discuss what should be done for pre-hooks errors - discuss what should be done for Unauthorized exception * 5748 Create contacts for emails sent and received by email aliases (#5855) Closes #5748 - Create feature flag - Add scope `https://www.googleapis.com/auth/profile.emails.read` when connecting an account - Get email aliases with google people API, store them in connectedAccount and refresh them before each message-import - Update the contact creation logic accordingly - Refactor --------- Co-authored-by: Charles Bochet <[email protected]> * Change Messaging import frequency * Fix lint and used constant (#6082) - Fixed lint after merge of #6077 - Used constant for dropdown id * Fix demo seed script by using usage of deprecated sub status * Use invalid field input error for invalid object metadata input (#6083) As title * Fix Active Workspaces check (#6084) We have recently deprecated our subscriptionStatus on workspace to replace it by a check on existing subscription (+ freeAccess featureFlag) but the logic was not properly implemented * feature to reset value in select field (#6067) Fixes #6064 https://github.com/twentyhq/twenty/assets/55168611/8c553422-6ad2-4e6b-bd00-962dd81c0a93 --------- Co-authored-by: Lucas Bordeau <[email protected]> * Reorganise calendar module (#6089) Refactor Calendar into functional sub modules <img width="437" alt="image" src="https://github.com/twentyhq/twenty/assets/12035771/d9de3285-a226-4fe8-b3ef-2d8a21def2a5"> --------- Co-authored-by: bosiraphael <[email protected]> * Fix calendar import cron job (#6096) An error was introduced in the calendar cron job because we tried to inject the workspace context inside the calendarChannelRepository where we didn't have access to that context. * feat: refactor workspace sync fields (#6069) This PR was first here to fix the issue related to ticket #5004, after some testing it seems that changing the name of a relation is actually properly working, if we rename `ONE-TO-MANY` side, the only things that is going to be updated is the FieldMetadata as the `joinColumn` is stored on the opposite object. For `MANY-TO-ONE` relations, the `joinColumn` migration is properly generated. We need to take care that if we rename a side of a relation, sometimes the opposite side doesn't have `inverseSideFieldKey` implemented and used by default the name of the opposite object, so this is going to throw an error as the field can't be found in the object. --------- Co-authored-by: Marie <[email protected]> * Use return await to catch exceptions (#6109) So the exceptions are handled properly and filtered in sentry * Fix rating field not editable if null (#6110) ## Context Rating fields were not editable on the show page and kanban view when they were null, this is because we don't have a way to leave the empty state for fields that are editModeContentOnly. ~~This is actually an issue for bool fields (which is the other field type that has editModeContentOnly) as well but they have default values can't go be edited to NULL so it's not visible.~~ Actually let's fix bool, this could happen too Hovering over "Empty" will now show the RatingField edit mode. I'm not 100% sure about this solution though, we could also make this behaviour on click? I preferred over since this is the behaviour on the table view 🤔 ## Test https://github.com/twentyhq/twenty/assets/1834158/6825b5c3-2c62-41f2-8e03-343bc0e895e2 * Fix pg-boss worker not working with dynamic injection (#6119) * Fix workspace sync issue (#6121) Fixing an issue with typeORM not fetching existing metadata collection while syncing fields and relations * fix: small PR fixes workspace-sync-fields (#6107) Small fixes of PR #6069 * Decrease messaging import batch size * Improve performance/robustness of worker * Text-to-SQL proof of concept (#5788) Added: - An "Ask AI" command to the command menu. - A simple GraphQL resolver that converts the user's question into a relevant SQL query using an LLM, runs the query, and returns the result. <img width="428" alt="Screenshot 2024-06-09 at 20 53 09" src="https://github.com/twentyhq/twenty/assets/171685816/57127f37-d4a6-498d-b253-733ffa0d209f"> No security concerns have been addressed, this is only a proof-of-concept and not intended to be enabled in production. All changes are behind a feature flag called `IS_ASK_AI_ENABLED`. --------- Co-authored-by: Félix Malfait <[email protected]> * Hotfix tests after AI PR (#6124) I merged https://github.com/twentyhq/twenty/pull/5788 too quickly and didn't noticed it was broken with https://github.com/twentyhq/twenty/pull/6069 * fix: message queue injection issue (#6126) * Forbid names above 63 characters to comply with pg identifier limit (#6095) Fixes #6032. Pg has a char limit on identifiers (= table, columns, enum names) of 63 bytes. Let's limit the metadata names that will be converted to identifiers (objects names, fields names, relation names, enum values) to 63 chars. For the sake of simplicity in the FE we will limit the input length of labels. --------- Co-authored-by: Charles Bochet <[email protected]> * Fix website doc search (#6134) NEXT_PUBLIC environnement variable values are set at build time and not run time. Build is currently performed in Github actions so setting those vars at runtime has no effect. We can use a package to automatically pass those variables at runtime * Implement Settings Tabs (#6136) In this PR: - Renaming SettingsAccountsEmailBlocklist to SettingsAccountsEmailBlocklist as the blocklist is not tied to emails/messaging but is user level - Changing the UI settings UI by removing /emails/{id} page and adding tabs on /emails page <img width="1512" alt="image" src="https://github.com/twentyhq/twenty/assets/12035771/d215a891-fff9-477d-915d-0d7a697742e8"> * Add command to update boolean fields null values (#6113) We have recently decided that boolean fields should only accept truthy or falsy value, with users deciding of a default value at creation. This command helps cleaning the existing data, by 1. updating all boolean fields default values from null to false 2. updating all boolean fields values for records from null to false --------- Co-authored-by: Weiko <[email protected]> * Fix sort with Email and FullName field types and add sort/filter to labelIdentifier column (#6132) Fixes https://github.com/twentyhq/twenty/issues/5958 <img width="1088" alt="Screenshot 2024-07-04 at 16 23 25" src="https://github.com/twentyhq/twenty/assets/1834158/746c45a4-7112-4322-8c26-04f3e98add06"> <img width="1280" alt="Screenshot 2024-07-04 at 16 15 39" src="https://github.com/twentyhq/twenty/assets/1834158/9b9ecc60-9787-44a3-9ba7-0b33ec378e6f"> * 5421 box shadow on frozen header and first column (#6130) - Refactored components in table - Added a isTableRecordScrolledLeftState and isTableRecordScrolledTopState to subscribe to table scroll - Added a zIndex logic that subscribes to those new states in new tinier components --------- Co-authored-by: Charles Bochet <[email protected]> * Fix storybook tests (#6150) The PRs merged on Friday introduced regressions on our storybook tests suite * Refactor Calendar Settings into tabs (#6153) This PR migrates Calendar Settings into Tabs: <img width="1512" alt="image" src="https://github.com/twentyhq/twenty/assets/12035771/2531d0f1-ddfd-46c6-8678-bd76d78447b6"> * Add new Settings to front-end (#6154) <img width="1512" alt="image" src="https://github.com/twentyhq/twenty/assets/12035771/cfcc6ac9-feeb-4d91-aa68-bd0119780d6d"> * Small fixes on accounts settings (#6157) - Add keys in components map * Add message import granulary on non-pro emails, group emails and received contact creation (#6156) 1) Remove featureFlag 2) Base contactCreation on messageChannel.autoContactCreationPolicy 4) add excludeProfessionalEmails + excludeGroupEmails logic * Fix z-index issue on dropdown (#6160) Recently, we've forced all dropdown menu to be displayed in portal. This loses the z-index hieararchy structure and forces us to specify a higher z-index in order for dropdown menus to be displayed on top * Bump version to 0.21 (#6161) * Refactor calendar to use new sync statuses and stages (#6141) - Refactor calendar modules and some messaging modules to better organize them by business rules and decouple them - Work toward a common architecture for the different calendar providers by introducing interfaces for the drivers - Modify cron job to use the new sync statuses and stages * Navigate to field settings page on Go to Settings (#6128) Fixes #5661. Thanks @AdvaitChandorkar07 * Fix wrong email direction (#6163) Closes #6162 * Fix contactCreation ignoring connectedAccount mainHandle * Update render deploy configuration (#6167) * Add missing objectMetadataId column in auditLog (#6164) Insert inside AuditLog table are all failing due to objectMetadataId column missing. The FieldMetadata was sharing the same standard-id with another one (objectName) so it was skipped during the comparison step of the sync-metadata. Running a sync-metadata again should fix this issue. Note that this column is non-nullable so if the table contains existing records, it will fail. However, since the insert was failing I'm assuming the table is empty anyway. * Modify messaging message channel sync status monitoring cron pattern (#6173) Change from every hour to every 10 minutes, starting at 2 minutes past the hour * [Flexible Schema] Create indexes for join columns (#6165) ## Context We want to add an index on our foreign keys since PG does not do it for us. An index can sometimes be expensive and not always meaningful depending on different usages but in our case we decided to apply an index for every foreign keys. ```typescript @WorkspaceIndex() @WorkspaceJoinColumn('author') authorId: string; ``` This syntax is valid but since we want to apply it to every join column I've decided to update the code of WorkspaceJoinColumn so it properly registers a new index at the same time which is less error-prone. Note: We had a bug on index name generation since postgres index names are unique per schema and not table, the object metadata id (hashed) has been added to the formula that generates the name of the index ## Test Sync metadata. We have 45 join columns as of today per workspace, we should see 45 rows inside IndexMetadata table * Authorize 0 depth (#6171) Authorize depth 0 ![image](https://github.com/twentyhq/twenty/assets/29927851/2e82eaba-01b4-440f-8412-d2878007a3b1) ![image](https://github.com/twentyhq/twenty/assets/29927851/f0137671-20dc-4e44-97b8-7a8e4c583493) ## Edit ### Depth = 0 ``` { "data": { "people": [ { "id": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "email": "[email protected]", "jobTitle": "", "phone": "+33789012345", "city": "Seattle", "avatarUrl": "", "position": 1, "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "companyId": "20202020-3ec3-4fe3-8997-b76aa0bfa408", "name": { "firstName": "Christoph", "lastName": "Callisto" }, "linkedinLink": { "label": "", "url": "" }, "xLink": { "label": "", "url": "" } }, ... ]} ``` ### Depth = 1 ``` { "data": { "people": [ { "id": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "email": "[email protected]", "jobTitle": "", "phone": "+33789012345", "city": "Seattle", "avatarUrl": "", "position": 1, "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "companyId": "20202020-3ec3-4fe3-8997-b76aa0bfa408", "name": { "firstName": "Christoph", "lastName": "Callisto" }, "linkedinLink": { "label": "", "url": "" }, "xLink": { "label": "", "url": "" }, "activityTargets": [], "favorites": [], "attachments": [], "timelineActivities": [], "company": { "id": "20202020-3ec3-4fe3-8997-b76aa0bfa408", "name": "Linkedin", "domainName": "linkedin.com", "address": "", "employees": null, "idealCustomerProfile": false, "position": 1, "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "accountOwnerId": null, "linkedinLink": { "label": "", "url": "" }, "xLink": { "label": "", "url": "" }, "annualRecurringRevenue": { "amountMicros": null, "currencyCode": "" } }, "messageParticipants": [ { "id": "20202020-0f2a-49d8-8aa2-ec8786153a0b", "role": "from", "handle": "outgoing", "displayName": "Christoph", "createdAt": "2024-07-08T16:08:50.028Z", "updatedAt": "2024-07-08T16:08:50.028Z", "messageId": "20202020-2b8a-405d-8f42-e820ca921421", "personId": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "workspaceMemberId": "20202020-0687-4c41-b707-ed1bfca972a7" }, { "id": "20202020-fc7d-4ad8-9aea-b78bcbf79cdd", "role": "from", "handle": "outgoing", "displayName": "Christoph", "createdAt": "2024-07-08T16:08:50.028Z", "updatedAt": "2024-07-08T16:08:50.028Z", "messageId": "20202020-04c8-4f24-93f2-764948e95014", "personId": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "workspaceMemberId": "20202020-0687-4c41-b707-ed1bfca972a7" } ], "calendarEventParticipants": [ { "id": "da8f47c3-8055-49ad-b7e4-9c9d5bbc1ecc", "handle": "[email protected]", "displayName": "Christoph Calisto", "isOrganizer": true, "responseStatus": "ACCEPTED", "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "calendarEventId": "86083141-1c0e-494c-a1b6-85b1c6fefaa5", "personId": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "workspaceMemberId": null } ], "pointOfContactForOpportunities": [ { "id": "20202020-be10-412b-a663-16bd3c2228e1", "name": "Opportunity 1", "closeDate": "2024-07-08T16:08:50.018Z", "probability": "0.5", "stage": "NEW", "position": 1, "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "pointOfContactId": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "companyId": "20202020-3ec3-4fe3-8997-b76aa0bfa408", "amount": { "amountMicros": 100000, "currencyCode": "USD" } } ] }, ... ]} ``` ### Depth = 2 ``` { "data": { "people": [ { "id": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "email": "[email protected]", "jobTitle": "", "phone": "+33789012345", "city": "Seattle", "avatarUrl": "", "position": 1, "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "companyId": "20202020-3ec3-4fe3-8997-b76aa0bfa408", "name": { "firstName": "Christoph", "lastName": "Callisto" }, "linkedinLink": { "label": "", "url": "" }, "xLink": { "label": "", "url": "" }, "activityTargets": [], "favorites": [], "attachments": [], "timelineActivities": [], "company": { "id": "20202020-3ec3-4fe3-8997-b76aa0bfa408", "name": "Linkedin", "domainName": "linkedin.com", "address": "", "employees": null, "idealCustomerProfile": false, "position": 1, "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "accountOwnerId": null, "accountOwner": null, "linkedinLink": { "label": "", "url": "" }, "xLink": { "label": "", "url": "" }, "annualRecurringRevenue": { "amountMicros": null, "currencyCode": "" }, "activityTargets": [], "favorites": [], "attachments": [], "timelineActivities": [], "people": [ { "id": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "email": "[email protected]", "jobTitle": "", "phone": "+33789012345", "city": "Seattle", "avatarUrl": "", "position": 1, "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "companyId": "20202020-3ec3-4fe3-8997-b76aa0bfa408", "name": { "firstName": "Christoph", "lastName": "Callisto" }, "linkedinLink": { "label": "", "url": "" }, "xLink": { "label": "", "url": "" } }, { "id": "20202020-ac73-4797-824e-87a1f5aea9e0", "email": "[email protected]", "jobTitle": "", "phone": "+33780123456", "city": "Los Angeles", "avatarUrl": "", "position": 2, "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "companyId": "20202020-3ec3-4fe3-8997-b76aa0bfa408", "name": { "firstName": "Sylvie", "lastName": "Palmer" }, "linkedinLink": { "label": "", "url": "" }, "xLink": { "label": "", "url": "" } } ], "opportunities": [ { "id": "20202020-be10-412b-a663-16bd3c2228e1", "name": "Opportunity 1", "closeDate": "2024-07-08T16:08:50.018Z", "probability": "0.5", "stage": "NEW", "position": 1, "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "pointOfContactId": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "companyId": "20202020-3ec3-4fe3-8997-b76aa0bfa408", "amount": { "amountMicros": 100000, "currencyCode": "USD" } } ] }, "pointOfContactForOpportunities": [ { "id": "20202020-be10-412b-a663-16bd3c2228e1", "name": "Opportunity 1", "closeDate": "2024-07-08T16:08:50.018Z", "probability": "0.5", "stage": "NEW", "position": 1, "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "pointOfContactId": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "companyId": "20202020-3ec3-4fe3-8997-b76aa0bfa408", "amount": { "amountMicros": 100000, "currencyCode": "USD" }, "favorites": [], "activityTargets": [], "attachments": [], "timelineActivities": [], "pointOfContact": { "id": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "email": "[email protected]", "jobTitle": "", "phone": "+33789012345", "city": "Seattle", "avatarUrl": "", "position": 1, "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "companyId": "20202020-3ec3-4fe3-8997-b76aa0bfa408", "name": { "firstName": "Christoph", "lastName": "Callisto" }, "linkedinLink": { "label": "", "url": "" }, "xLink": { "label": "", "url": "" } }, "company": { "id": "20202020-3ec3-4fe3-8997-b76aa0bfa408", "name": "Linkedin", "domainName": "linkedin.com", "address": "", "employees": null, "idealCustomerProfile": false, "position": 1, "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "accountOwnerId": null, "linkedinLink": { "label": "", "url": "" }, "xLink": { "label": "", "url": "" }, "annualRecurringRevenue": { "amountMicros": null, "currencyCode": "" } } } ], "messageParticipants": [ { "id": "20202020-0f2a-49d8-8aa2-ec8786153a0b", "role": "from", "handle": "outgoing", "displayName": "Christoph", "createdAt": "2024-07-08T16:08:50.028Z", "updatedAt": "2024-07-08T16:08:50.028Z", "messageId": "20202020-2b8a-405d-8f42-e820ca921421", "personId": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "workspaceMemberId": "20202020-0687-4c41-b707-ed1bfca972a7", "message": { "id": "20202020-2b8a-405d-8f42-e820ca921421", "headerMessageId": "99ef24a8-2b8a-405d-8f42-e820ca921421", "direction": "outgoing", "subject": "Meeting Request", "text": "Hello, \n I hope this email finds you well. I am writing to request a meeting. I believe it would be beneficial for both parties to collaborate and explore potential opportunities. Would you be available for a meeting sometime next week? Please let me know your availability, and I will arrange a suitable time. \n Looking forward to your response.\n Best regards", "receivedAt": "2024-07-08T16:08:50.022Z", "createdAt": "2024-07-08T16:…
Enables basic support for Select import and field matching in CSV.
It's not pretty! But it's better than what we had before.
We should iterate on that quickly