8b4b9ef8da86196398db83df1591e44d9f130f87
27 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
8b4b9ef8da |
Change type import rule (#13751)
Forcing "type" to be explicit, works best will rollup on the frontend to exclude depdendencies |
||
|
|
46e43a62c4 |
[permissions] Handle fieldPermissions configuration for 1N relations (#13630)
When upserting a fieldPermission on a 1 <-> N relation field, we should upsert the same fieldPermission on the relationTargetFieldMetadata to avoid inconsistencies. |
||
|
|
a0a575fa0b |
Improve FieldMetadataEntity defaultValue, settings and options typing (#13320)
# Introduction Following https://github.com/twentyhq/twenty/pull/13264, this PR introduces several `fieldMetadataEntity` typing enhancement suggestions. Mainly any nullable field metadata entity properties are now either nullable or defined. Or never if field is dynamically required or not depending on the field metadata type This enhance DevX ## Standards - field enum ( `MULTI_SELECT`, `SELECT`, `RATING` ) will never have `options` set to `NULL` in db - field `RELATION` or `MORH_RELATION` won't ever have its relation fields set to `NULL` in db - field of any type `settings`, even if possibly defined, can still be `NULL` in db - field of any type `defaultValue`, even if possibly defined, can still be `NULL` in db It coud be interesting to guard these standards by adding dedicated pg constraints on each field ## TypesScript type tests added coverage for each `settings`, `defaultValue`, and `options` depending on the current `fieldMetadata` Honestly I don' know if this typescript assertions test file is not overkill, but regarding metadata staticness it might be very interesting to have this guard ## Possible improvements - We could type as `unknown` instead of "all" on `FieldMetadataType` inferrance - We still need to deprecate remaining duplicated entities such as `Index/Field/MetadataInterface` etc not a huge refactor neither urgent |
||
|
|
47b60bd49f |
Deprecate FieldMetadataInterface (#13264)
# Introduction
From the moment replaced the FieldMetadataInterface definition to:
```ts
import { FieldMetadataType } from 'twenty-shared/types';
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
export type FieldMetadataInterface<
T extends FieldMetadataType = FieldMetadataType,
> = FieldMetadataEntity<T>;
```
After this PR merge will create a new one removing the type and
replacing it to `FieldMetadataEntity`.
Did not renamed it here to avoid conflicts on naming + type issues fixs
within the same PR
## Field metadata entity RELATION or MORPH
Relations fields cannot be null for those field metadata entity instance
anymore, but are never for the others see
`packages/twenty-server/src/engine/metadata-modules/field-metadata/types/field-metadata-entity-test.type.ts`
( introduced TypeScript tests )
## Concerns
- TS_VECTOR is the most at risk with the `generatedType` and
`asExpression` removal from interface
## What's next
- `FielMetadataInterface` removal and rename ( see introduction )
- Depcrecating `ObjectMetadataInterface`
- Refactor `FieldMetadataEntity` optional fiels to be nullable only
- TO DIG `never` occurences on settings, defaultValue etc
- Some interfaces will be replaced by the `FlatFieldMetadata` when
deprecating the current sync and comparators tools
|
||
|
|
d5c974054d |
Improve performance on metadata computation (#12785)
In this PR: ## Improve recompute metadata cache performance. We are aiming for ~100ms Deleting relationMetadata table and FKs pointing on it Fetching indexMetadata and indexFieldMetadata in a separate query as typeorm is suboptimizing ## Remove caching lock As recomputing the metadata cache is lighter, we try to stop preventing multiple concurrent computations. This also simplifies interfaces ## Introduce self recovery mecanisms to recompute cache automatically if corrupted Aka getFreshObjectMetadataMaps ## custom object resolver performance improvement: 1sec to 200ms Double check queries and indexes used while creating a custom object Remove the queries to db to use the cached objectMetadataMap ## reduce objectMetadataMaps to 500kb <img width="222" alt="image" src="https://github.com/user-attachments/assets/2370dc80-49b6-4b63-8d5e-30c5ebdaa062" /> We used to stored 3 fieldMetadataMaps (byId, byName, byJoinColumnName). While this is great for devXP, this is not great for performances. Using the same mecanisme as for objectMetadataMap: we only keep byIdMap and introduce two otherMaps to idByName, idByJoinColumnName to make the bridge ## Add dataloader on IndexMetadata (aka indexMetadataList in the API) ## Improve field resolver performances too ## Deprecate ClientConfig |
||
|
|
a68895189c |
Deprecate old relations completely (#12482)
# What Fully deprecate old relations because we have one bug tied to it and it make the codebase complex # How I've made this PR: 1. remove metadata datasource (we only keep 'core') => this was causing extra complexity in the refactor + flaky reset 2. merge dev and demo datasets => as I needed to update the tests which is very painful, I don't want to do it twice 3. remove all code tied to RELATION_METADATA / relation-metadata.resolver, or anything tied to the old relation system 4. Remove ONE_TO_ONE and MANY_TO_MANY that are not supported 5. fix impacts on the different areas : see functional testing below # Functional testing ## Functional testing from the front-end: 1. Database Reset ✅ 2. Sign In ✅ 3. Workspace sign-up ✅ 5. Browsing table / kanban / show ✅ 6. Assigning a record in a one to many / in a many to one ✅ 7. Deleting a record involved in a relation ✅ => broken but not tied to this PR 8. "Add new" from relation picker ✅ => broken but not tied to this PR 9. Creating a Task / Note, Updating a Task / Note relations, Deleting a Task / Note (from table, show page, right drawer) ✅ => broken but not tied to this PR 10. creating a relation from settings (custom / standard x oneToMany / manyToOne) ✅ 11. updating a relation from settings should not be possible ✅ 12. deleting a relation from settings (custom / standard x oneToMany / manyToOne) ✅ 13. Make sure timeline activity still work (relation were involved there), espacially with Task / Note => to be double checked ✅ => Cannot convert undefined or null to object 14. Workspace deletion / User deletion ✅ 15. CSV Import should keep working ✅ 16. Permissions: I have tested without permissions V2 as it's still hard to test v2 work and it's not in prod yet ✅ 17. Workflows global test ✅ ## From the API: 1. Review open-api documentation (REST) ✅ 2. Make sure REST Api are still able to fetch relations ==> won't do, we have a coupling Get/Update/Create there, this requires refactoring 3. Make sure REST Api is still able to update / remove relation => won't do same ## Automated tests 1. lint + typescript ✅ 2. front unit tests: ✅ 3. server unit tests 2 ✅ 4. front stories: ✅ 5. server integration: ✅ 6. chromatic check : expected 0 7. e2e check : expected no more that current failures ## Remove // Todos 1. All are captured by functional tests above, nothing additional to do ## (Un)related regressions 1. Table loading state is not working anymore, we see the empty state before table content 2. Filtering by Creator Tim Ap return empty results 3. Not possible to add Tasks / Notes / Files from show page # Result ## New seeds that can be easily extended <img width="1920" alt="image" src="https://github.com/user-attachments/assets/d290d130-2a5f-44e6-b419-7e42a89eec4b" /> ## -5k lines of code ## No more 'metadata' dataSource (we only have 'core) ## No more relationMetadata (I haven't drop the table yet it's not referenced in the code anymore) ## We are ready to fix the 6 months lag between current API results and our mocked tests ## No more bug on relation creation / deletion --------- Co-authored-by: Weiko <corentin@twenty.com> Co-authored-by: Félix Malfait <felix@twenty.com> |
||
|
|
442f8dbe3c |
[QRQC_2] No implicitAny in twenty-server (#12075)
# Introduction Following https://github.com/twentyhq/twenty/pull/12068 Related with https://github.com/twentyhq/core-team-issues/issues/975 We're enabling `noImplicitAny` handled few use case manually, added a `ts-expect-error` to the others, we should plan to handle them in the future |
||
|
|
f40aafb89f |
fix: reflect on #10521 changes to order-by-input-factory.ts file (#10662)
# This PR
Fixes an error on the FindMany REST API
I was getting the following error:
```
{
"statusCode": 400,
"error": "TypeError",
"messages": [
"Cannot read properties of undefined (reading 'fields')"
]
}
```
Now, it's working as expected
Related to #10521
cc: @Weiko @ijreilly
---------
Co-authored-by: Weiko <corentin@twenty.com>
|
||
|
|
9ad8287dbc |
[REFACTOR] twenty-shared multi barrel and CJS/ESM build with preconstruct (#11083)
# Introduction In this PR we've migrated `twenty-shared` from a `vite` app [libary-mode](https://vite.dev/guide/build#library-mode) to a [preconstruct](https://preconstruct.tools/) "atomic" application ( in the future would like to introduce preconstruct to handle of all our atomic dependencies such as `twenty-emails` `twenty-ui` etc it will be integrated at the monorepo's root directly, would be to invasive in the first, starting incremental via `twenty-shared`) For more information regarding the motivations please refer to nor: - https://github.com/twentyhq/core-team-issues/issues/587 - https://github.com/twentyhq/core-team-issues/issues/281#issuecomment-2630949682 close https://github.com/twentyhq/core-team-issues/issues/589 close https://github.com/twentyhq/core-team-issues/issues/590 ## How to test In order to ease the review this PR will ship all the codegen at the very end, the actual meaning full diff is `+2,411 −114` In order to migrate existing dependent packages to `twenty-shared` multi barrel new arch you need to run in local: ```sh yarn tsx packages/twenty-shared/scripts/migrateFromSingleToMultiBarrelImport.ts && \ npx nx run-many -t lint --fix -p twenty-front twenty-ui twenty-server twenty-emails twenty-shared twenty-zapier ``` Note that `migrateFromSingleToMultiBarrelImport` is idempotent, it's atm included in the PR but should not be merged. ( such as codegen will be added before merging this script will be removed ) ## Misc - related opened issue preconstruct https://github.com/preconstruct/preconstruct/issues/617 ## Closed related PR - https://github.com/twentyhq/twenty/pull/11028 - https://github.com/twentyhq/twenty/pull/10993 - https://github.com/twentyhq/twenty/pull/10960 ## Upcoming enhancement: ( in others dedicated PRs ) - 1/ refactor generate barrel to export atomic module instead of `*` - 2/ generate barrel own package with several files and tests - 3/ Migration twenty-ui the same way - 4/ Use `preconstruct` at monorepo global level ## Conclusion As always any suggestions are welcomed ! |
||
|
|
71a4593ba4 |
Move FieldMetadataType to twenty-shared (#9482)
Co-authored-by: Charles Bochet <charles@twenty.com> |
||
|
|
360c34fd18 |
Phone country code unique (#9035)
fix #8775 |
||
|
|
ac1197afe1 |
Fix secondary links default value and types (#8532)
Fixes broken companies view |
||
|
|
a58236e6da |
Remove deprecated EMAIL, PHONE, LINK (#7551)
In this PR: - remove deprecated EMAIL, PHONE, LINK field types (except for Zapier package as there is another work ongoing) - remove composite currency filter on currencyCode, actor filter on name and workspaceMember as the UX is not great yet |
||
|
|
8208a3e976 |
Introduce ARRAY field type (#6862)
This PR was created by \[GitStart\](<https://gitstart.com/>) to address the requirements from this ticket: \[TWNTY-6447\](<https://clients.gitstart.com/twenty/5449/tickets/TWNTY-6447>). This ticket was imported from: <https://github.com/twentyhq/twenty/issues/6447> ### Description \- We added a new field type ### Refs #6447 ### Demo <https://jam.dev/c/2b4d7853-ea89-4e9d-a561-6edcb4fdb34b> Fixes #6447 --------- Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com> Co-authored-by: Charles Bochet <charles@twenty.com> |
||
|
|
846953b0f4 |
Support for multiple values in the Phone field (#6882)
### Description - This is the first PR on Phones field; - We are introducing new field type(Phones) - We are Forbidding creation of Phone field - We Added support for filtering and sorting on Phones field - We are using the same display mode as used on the Links field type (chips), check the Domain field of the Company object - We are also using the same logic of the link when editing the field **How to Test** 1. Checkout to TWNTY-6260 branch 2. Reset database using "npx nx database:reset twenty-server" command 3. Add custom field of type Phones in settings/data-model **Loom Video:**\ <https://www.loom.com/share/3c981260be254dcf851256d020a20ab0?sid=58507361-3a3b-452c-9de8-b5b1abda70ac> ### Refs #6260 Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com> |
||
|
|
c55dfbde6e |
Fix unauthorized error handling (#6835)
from @BOHEUS comments in #6640 - fix bad 500 error when authentication invalid - remove "id", "createdAt", "updatedAt", etc from creation and update paths schema - improve error message - remove "id" from test body - improve secondaryLink schema description - improve depth parameter description - remove required from response body - improve examples - improve error message formatting - fix filter by position - answered to negative float position @BOHEUS comment Also: - fix secondary field openapi field description - remove schema display in playground Screenshots   |
||
|
|
7a9a43b85c |
Add composite Emails field and forbid creation of Email field type (#6689)
### Description
1.
- We are introducing new field type(Emails)
- We are Forbiding creation of Email field
- We Added support for filtering and sorting on Emails field
- We are using the same display mode as used on the Links field type
(chips), check the Domain field of the Company object
- We are also using the same logic of the link when editing the field
\
How To Test\
Follow the below steps for testing locally:\
1. Checkout to TWENTY-6261\
2. Reset database using "npx nx database:reset twenty-server" command\
3. Run both the backend and frontend app\
4. Go to Settings/Data model and choose one of the standard objects like
people\
5. Click on Add Field button and choose Emails as the field type
\
### Refs
#6261\
\
### Demo
\
<https://www.loom.com/share/22979acac8134ed390fef93cc56fe07c?sid=adafba94-840d-4f01-872c-dc9ec256d987>
Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com>
|
||
|
|
ee6180a76f |
[Fix] Prevent fields name conflicts with composite subfields names (#6713)
At field creation we are checking the availability of the name by comparing it to the other fields' names' on the object; but for composite fields the fields' names' as indicated in the repository do not exactly match the column names' on the tables (e.g "createdBy" field is actually represented by columns createdByName, createdBySource etc.). In this PR we prevent the conflict with the standard composite fields' names. There is still room for errors with the custom composite fields: for example a custom composite field "address" of type address on a custom object "listing" will introduce the columns addressAddressStreet1, addressAddressStreet2 etc. while we won't prevent the user from later creating a custom field named "addressAddressStreet1". For now I decided not to tackle this as this seem extremely edgy + would impact performance on creation of all fields while never actually useful (I think). |
||
|
|
6432ad39b9 |
feat: add new ACTOR field type and createdBy standard fields (#6324)
This pull request introduces a new `FieldMetadataType` called `ACTOR`.
The primary objective of this new type is to add an extra column to the
following objects: `person`, `company`, `opportunity`, `note`, `task`,
and all custom objects.
This composite type contains three properties:
- `source`
```typescript
export enum FieldActorSource {
EMAIL = 'EMAIL',
CALENDAR = 'CALENDAR',
API = 'API',
IMPORT = 'IMPORT',
MANUAL = 'MANUAL',
}
```
- `workspaceMemberId`
- This property can be `undefined` in some cases and refers to the
member who created the record.
- `name`
- Serves as a fallback if the `workspaceMember` is deleted and is used
for other source types like `API`.
### Functionality
The pre-hook system has been updated to allow real-time argument
updates. When a record is created, a pre-hook can now compute and update
the arguments accordingly. This enhancement enables the `createdBy`
field to be populated with the correct values based on the
`authContext`.
The `authContext` now includes:
- An optional User entity
- An optional ApiKey entity
- The workspace entity
This provides access to the necessary data for the `createdBy` field.
In the GraphQL API, only the `source` can be specified in the
`createdBy` input. This allows the front-end to specify the source when
creating records from a CSV file.
### Front-End Handling
On the front-end, `orderBy` and `filter` are only applied to the name
property of the `ACTOR` composite type. Currently, we are unable to
apply these operations to the workspace member relation. This means that
if a workspace member changes their first name or last name, there may
be a mismatch because the name will differ from the new one. The name
displayed on the screen is based on the workspace member entity when
available.
### Missing Components
Currently, this PR does not include a `createdBy` value for the `MAIL`
and `CALENDAR` sources. These records are created in a job, and at
present, we only have access to the workspaceId within the job. To
address this, we should use a function similar to
`loadServiceWithContext`, which was recently removed from `TwentyORM`.
This function would allow us to pass the `authContext` to the jobs
without disrupting existing jobs.
Another PR will be created to handle these cases.
### Related Issues
Fixes issue #5155.
### Additional Notes
This PR doesn't include the migrations of the current records and views.
Everything works properly when the database is reset but this part is
still missing for now. We'll add that in another PR.
- There is a minor issue: front-end tests are broken since this commit:
[https://github.com/twentyhq/twenty/commit/80c0fc7ff108d61c0e8d89fd334da64bd224f7aa](https://github.com/twentyhq/twenty/commit/80c0fc7ff108d61c0e8d89fd334da64bd224f7aa).
---------
Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
|
||
|
|
80c0fc7ff1 |
Activity as standard object (#6219)
In this PR I layout the first steps to migrate Activity to a traditional Standard objects Since this is a big transition, I'd rather split it into several deployments / PRs <img width="1512" alt="image" src="https://github.com/user-attachments/assets/012e2bbf-9d1b-4723-aaf6-269ef588b050"> --------- Co-authored-by: Charles Bochet <charles@twenty.com> Co-authored-by: bosiraphael <71827178+bosiraphael@users.noreply.github.com> Co-authored-by: Weiko <corentin@twenty.com> Co-authored-by: Faisal-imtiyaz123 <142205282+Faisal-imtiyaz123@users.noreply.github.com> Co-authored-by: Prateek Jain <prateekj1171998@gmail.com> |
||
|
|
364caf0fdf |
fix: remove usage of probability field (#5877)
- fixes #5735 --------- Co-authored-by: Marie Stoppa <marie.stoppa@essec.edu> |
||
|
|
de51e653fc |
Authorize 0 depth (#6171)
Authorize depth 0   ## Edit ### Depth = 0 ``` { "data": { "people": [ { "id": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "email": "christoph.calisto@linkedin.com", "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": "christoph.calisto@linkedin.com", "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": "christoph.calisto@linkedin.com", "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": "christoph.calisto@linkedin.com", "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": "christoph.calisto@linkedin.com", "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": "sylvie.palmer@linkedin.com", "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": "christoph.calisto@linkedin.com", "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": "christoph.calisto@linkedin.com", "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": "tim@apple.dev", "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": "christoph.calisto@linkedin.com", "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": "tim@apple.dev", "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": "christoph.calisto@linkedin.com", "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-07-08T16:08:50.030Z", "description": "Discuss project progress", "location": "Seattle", "iCalUID": "event1@calendar.com", "conferenceSolution": "Zoom", "recurringEventExternalId": "recurring1", "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "conferenceLink": { "label": "https://zoom.us/j/1234567890", "url": "https://zoom.us/j/1234567890" } }, "person": { "id": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "email": "christoph.calisto@linkedin.com", "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": "" } } } ] }, ... ]} ``` |
||
|
|
5c15fcd249 |
5805 typing issue in rest api (#5818)
Fixed types for: - uuid - email - datetime - date - number - currency.amountMicros - select - multiSelect ## Before  ## After  |
||
|
|
01991fe717 |
4902 bug fix fix api filter for enum (#4909)
- Handle NUMERIC, SELECT, PROBABILITY, RATING FieldMetadataTypes Those filters now works: - http://localhost:3000/rest/opportunities?filter=stage[eq]:MEETING - http://localhost:3000/rest/opportunities?filter=stage[in]:[MEETING,NEW] When providing wrong enum values, the following error messages are returned: - http://localhost:3000/rest/opportunities?filter=stage[eq]:MEETINGG > BadRequestException: 'filter' enum value 'MEETINGG' not available in 'stage' enum. Available enum values are ['NEW', 'SCREENING', 'MEETING', 'PROPOSAL', 'CUSTOMER'] - http://localhost:3000/rest/opportunities?filter=stage[in]:[MEETING,NEWW] > BadRequestException: 'filter' enum value 'NEWW' not available in 'stage' enum. Available enum values are ['NEW', 'SCREENING', 'MEETING', 'PROPOSAL', 'CUSTOMER'] |
||
|
|
5019b5febc |
feat: drop target column map (#4670)
This PR is dropping the column `targetColumnMap` of fieldMetadata entities. The goal of this column was to properly map field to their respecting column in the table. We decide to drop it and instead compute the column name on the fly when we need it, as it's more easier to support. Some parts of the code has been refactored to try making implementation of composite type more easier to understand and maintain. Fix #3760 --------- Co-authored-by: Charles Bochet <charles@twenty.com> |
||
|
|
e5c1309e8c |
feat: wip server folder structure (#4573)
* feat: wip server folder structure * fix: merge * fix: wrong merge * fix: remove unused file * fix: comment * fix: lint * fix: merge * fix: remove console.log * fix: metadata graphql arguments broken |
||
|
|
2c09096edd |
Refactor backend folder structure (#4505)
* Refactor backend folder structure Co-authored-by: Charles Bochet <charles@twenty.com> * fix tests * fix * move yoga hooks --------- Co-authored-by: Charles Bochet <charles@twenty.com> |