Setup relations for remote objects (#5149)
New strategy: - add settings field on FieldMetadata. Contains a boolean isIdField and for numbers, a precision - if idField, the graphql scalar returned will be a GraphQL id. This will allow the app to work even for ids that are not uuid - remove globals dateScalar and numberScalar modes. These were not used - set limit as Integer - check manually in query runner mutations that we send a valid id Todo left: - remove WorkspaceBuildSchemaOptions since this is not used anymore. Will do in another PR --------- Co-authored-by: Thomas Trompette <thomast@twenty.com> Co-authored-by: Weiko <corentin@twenty.com>
This commit is contained in:
@ -51,7 +51,7 @@ const mocks: MockedResponse[] = [
|
||||
$filter: ActivityTargetFilterInput
|
||||
$orderBy: ActivityTargetOrderByInput
|
||||
$lastCursor: String
|
||||
$limit: Float
|
||||
$limit: Int
|
||||
) {
|
||||
activityTargets(
|
||||
filter: $filter
|
||||
@ -105,7 +105,7 @@ const mocks: MockedResponse[] = [
|
||||
$filter: ActivityFilterInput
|
||||
$orderBy: ActivityOrderByInput
|
||||
$lastCursor: String
|
||||
$limit: Float
|
||||
$limit: Int
|
||||
) {
|
||||
activities(
|
||||
filter: $filter
|
||||
|
||||
@ -36,7 +36,7 @@ const mocks: MockedResponse[] = [
|
||||
$filter: ActivityTargetFilterInput
|
||||
$orderBy: ActivityTargetOrderByInput
|
||||
$lastCursor: String
|
||||
$limit: Float
|
||||
$limit: Int
|
||||
) {
|
||||
activityTargets(
|
||||
filter: $filter
|
||||
|
||||
@ -16,7 +16,7 @@ const mocks: MockedResponse[] = [
|
||||
{
|
||||
request: {
|
||||
query: gql`
|
||||
query FindOneWorkspaceMember($objectRecordId: UUID!) {
|
||||
query FindOneWorkspaceMember($objectRecordId: ID!) {
|
||||
workspaceMember(filter: { id: { eq: $objectRecordId } }) {
|
||||
__typename
|
||||
colorScheme
|
||||
|
||||
@ -17,7 +17,7 @@ const mocks: MockedResponse[] = [
|
||||
request: {
|
||||
query: gql`
|
||||
mutation UpdateOneActivity(
|
||||
$idToUpdate: UUID!
|
||||
$idToUpdate: ID!
|
||||
$input: ActivityUpdateInput!
|
||||
) {
|
||||
updateActivity(id: $idToUpdate, data: $input) {
|
||||
|
||||
@ -177,7 +177,7 @@ export const mocks = [
|
||||
{
|
||||
request: {
|
||||
query: gql`
|
||||
mutation DeleteOneFavorite($idToDelete: UUID!) {
|
||||
mutation DeleteOneFavorite($idToDelete: ID!) {
|
||||
deleteFavorite(id: $idToDelete) {
|
||||
id
|
||||
}
|
||||
@ -197,7 +197,7 @@ export const mocks = [
|
||||
request: {
|
||||
query: gql`
|
||||
mutation UpdateOneFavorite(
|
||||
$idToUpdate: UUID!
|
||||
$idToUpdate: ID!
|
||||
$input: FavoriteUpdateInput!
|
||||
) {
|
||||
updateFavorite(id: $idToUpdate, data: $input) {
|
||||
|
||||
@ -48,6 +48,7 @@ export const FIND_MANY_OBJECT_METADATA_ITEMS = gql`
|
||||
nameSingular
|
||||
namePlural
|
||||
isSystem
|
||||
isRemote
|
||||
}
|
||||
toFieldMetadataId
|
||||
}
|
||||
@ -60,6 +61,7 @@ export const FIND_MANY_OBJECT_METADATA_ITEMS = gql`
|
||||
nameSingular
|
||||
namePlural
|
||||
isSystem
|
||||
isRemote
|
||||
}
|
||||
fromFieldMetadataId
|
||||
}
|
||||
|
||||
@ -26,7 +26,7 @@ export const findManyViewsQuery = gql`
|
||||
$filter: ViewFilterInput
|
||||
$orderBy: ViewOrderByInput
|
||||
$lastCursor: String
|
||||
$limit: Float
|
||||
$limit: Int
|
||||
) {
|
||||
views(
|
||||
filter: $filter
|
||||
|
||||
@ -21,6 +21,7 @@ export type FieldMetadataItem = Omit<
|
||||
| 'toRelationMetadata'
|
||||
| 'defaultValue'
|
||||
| 'options'
|
||||
| 'settings'
|
||||
| 'relationDefinition'
|
||||
> & {
|
||||
__typename?: string;
|
||||
@ -28,7 +29,7 @@ export type FieldMetadataItem = Omit<
|
||||
| (Pick<Relation, 'id' | 'toFieldMetadataId' | 'relationType'> & {
|
||||
toObjectMetadata: Pick<
|
||||
Relation['toObjectMetadata'],
|
||||
'id' | 'nameSingular' | 'namePlural' | 'isSystem'
|
||||
'id' | 'nameSingular' | 'namePlural' | 'isSystem' | 'isRemote'
|
||||
>;
|
||||
})
|
||||
| null;
|
||||
@ -36,7 +37,7 @@ export type FieldMetadataItem = Omit<
|
||||
| (Pick<Relation, 'id' | 'fromFieldMetadataId' | 'relationType'> & {
|
||||
fromObjectMetadata: Pick<
|
||||
Relation['fromObjectMetadata'],
|
||||
'id' | 'nameSingular' | 'namePlural' | 'isSystem'
|
||||
'id' | 'nameSingular' | 'namePlural' | 'isSystem' | 'isRemote'
|
||||
>;
|
||||
})
|
||||
| null;
|
||||
|
||||
@ -2,10 +2,15 @@ import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSi
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
|
||||
export const isObjectMetadataAvailableForRelation = (
|
||||
objectMetadataItem: Pick<ObjectMetadataItem, 'isSystem' | 'nameSingular'>,
|
||||
objectMetadataItem: Pick<
|
||||
ObjectMetadataItem,
|
||||
'isSystem' | 'nameSingular' | 'isRemote'
|
||||
>,
|
||||
) => {
|
||||
return (
|
||||
!objectMetadataItem.isSystem ||
|
||||
objectMetadataItem.nameSingular === CoreObjectNameSingular.WorkspaceMember
|
||||
(!objectMetadataItem.isSystem ||
|
||||
objectMetadataItem.nameSingular ===
|
||||
CoreObjectNameSingular.WorkspaceMember) &&
|
||||
!objectMetadataItem.isRemote
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
import { useContext } from 'react';
|
||||
import { EntityChip, EntityChipVariant } from 'twenty-ui';
|
||||
|
||||
import { useMapToObjectRecordIdentifier } from '@/object-metadata/hooks/useMapToObjectRecordIdentifier';
|
||||
import { RecordTableRowContext } from '@/object-record/record-table/contexts/RecordTableRowContext';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { getImageAbsoluteURIOrBase64 } from '~/utils/image/getImageAbsoluteURIOrBase64';
|
||||
|
||||
@ -25,16 +23,8 @@ export const RecordChip = ({
|
||||
objectNameSingular,
|
||||
});
|
||||
|
||||
// Will only exists if the chip is inside a record table.
|
||||
// This is temporary until we have the show page for remote objects.
|
||||
const { isReadOnly } = useContext(RecordTableRowContext);
|
||||
|
||||
const objectRecordIdentifier = mapToObjectRecordIdentifier(record);
|
||||
|
||||
const linkToEntity = isReadOnly
|
||||
? undefined
|
||||
: objectRecordIdentifier.linkToShowPage;
|
||||
|
||||
return (
|
||||
<EntityChip
|
||||
entityId={record.id}
|
||||
@ -43,7 +33,7 @@ export const RecordChip = ({
|
||||
avatarUrl={
|
||||
getImageAbsoluteURIOrBase64(objectRecordIdentifier.avatarUrl) || ''
|
||||
}
|
||||
linkToEntity={linkToEntity}
|
||||
linkToEntity={objectRecordIdentifier.linkToShowPage}
|
||||
maxWidth={maxWidth}
|
||||
className={className}
|
||||
variant={variant}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const query = gql`
|
||||
mutation DeleteOnePerson($idToDelete: UUID!) {
|
||||
mutation DeleteOnePerson($idToDelete: ID!) {
|
||||
deletePerson(id: $idToDelete) {
|
||||
id
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@ import { gql } from '@apollo/client';
|
||||
export { responseData } from './useUpdateOneRecord';
|
||||
|
||||
export const query = gql`
|
||||
mutation ExecuteQuickActionOnOnePerson($idToExecuteQuickActionOn: UUID!) {
|
||||
mutation ExecuteQuickActionOnOnePerson($idToExecuteQuickActionOn: ID!) {
|
||||
executeQuickActionOnPerson(id: $idToExecuteQuickActionOn) {
|
||||
__typename
|
||||
xLink {
|
||||
|
||||
@ -5,7 +5,7 @@ export const query = gql`
|
||||
$filter: PersonFilterInput
|
||||
$orderBy: PersonOrderByInput
|
||||
$lastCursor: String
|
||||
$limit: Float
|
||||
$limit: Int
|
||||
) {
|
||||
people(
|
||||
filter: $filter
|
||||
|
||||
@ -3,7 +3,7 @@ import { gql } from '@apollo/client';
|
||||
import { responseData as person } from './useUpdateOneRecord';
|
||||
|
||||
export const query = gql`
|
||||
query FindOnePerson($objectRecordId: UUID!) {
|
||||
query FindOnePerson($objectRecordId: ID!) {
|
||||
person(filter: { id: { eq: $objectRecordId } }) {
|
||||
__typename
|
||||
xLink {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const query = gql`
|
||||
mutation UpdateOnePerson($idToUpdate: UUID!, $input: PersonUpdateInput!) {
|
||||
mutation UpdateOnePerson($idToUpdate: ID!, $input: PersonUpdateInput!) {
|
||||
updatePerson(id: $idToUpdate, data: $input) {
|
||||
__typename
|
||||
xLink {
|
||||
|
||||
@ -26,7 +26,7 @@ export const useDeleteOneRecordMutation = ({
|
||||
);
|
||||
|
||||
const deleteOneRecordMutation = gql`
|
||||
mutation DeleteOne${capitalizedObjectName}($idToDelete: UUID!) {
|
||||
mutation DeleteOne${capitalizedObjectName}($idToDelete: ID!) {
|
||||
${mutationResponseField}(id: $idToDelete) {
|
||||
id
|
||||
}
|
||||
|
||||
@ -39,7 +39,7 @@ export const useExecuteQuickActionOnOneRecordMutation = ({
|
||||
});
|
||||
|
||||
const executeQuickActionOnOneRecordMutation = gql`
|
||||
mutation ExecuteQuickActionOnOne${capitalizedObjectName}($idToExecuteQuickActionOn: UUID!) {
|
||||
mutation ExecuteQuickActionOnOne${capitalizedObjectName}($idToExecuteQuickActionOn: ID!) {
|
||||
${graphQLFieldForExecuteQuickActionOnOneRecordMutation}(id: $idToExecuteQuickActionOn) ${mapObjectMetadataToGraphQLQuery(
|
||||
{
|
||||
objectMetadataItems,
|
||||
|
||||
@ -23,7 +23,7 @@ export const useFindDuplicateRecordsQuery = ({
|
||||
const findDuplicateRecordsQuery = gql`
|
||||
query FindDuplicate${capitalize(
|
||||
objectMetadataItem.nameSingular,
|
||||
)}($id: UUID) {
|
||||
)}($id: ID!) {
|
||||
${getFindDuplicateRecordsQueryResponseField(
|
||||
objectMetadataItem.nameSingular,
|
||||
)}(id: $id) {
|
||||
|
||||
@ -22,7 +22,7 @@ export const useFindOneRecordQuery = ({
|
||||
const findOneRecordQuery = gql`
|
||||
query FindOne${capitalize(
|
||||
objectMetadataItem.nameSingular,
|
||||
)}($objectRecordId: UUID!) {
|
||||
)}($objectRecordId: ID!) {
|
||||
${objectMetadataItem.nameSingular}(filter: {
|
||||
id: {
|
||||
eq: $objectRecordId
|
||||
@ -32,7 +32,7 @@ export const useFindOneRecordQuery = ({
|
||||
objectMetadataItem,
|
||||
depth,
|
||||
})}
|
||||
}
|
||||
},
|
||||
`;
|
||||
|
||||
return {
|
||||
|
||||
@ -35,7 +35,7 @@ export const useUpdateOneRecordMutation = ({
|
||||
);
|
||||
|
||||
const updateOneRecordMutation = gql`
|
||||
mutation UpdateOne${capitalizedObjectName}($idToUpdate: UUID!, $input: ${capitalizedObjectName}UpdateInput!) {
|
||||
mutation UpdateOne${capitalizedObjectName}($idToUpdate: ID!, $input: ${capitalizedObjectName}UpdateInput!) {
|
||||
${mutationResponseField}(id: $idToUpdate, data: $input) ${mapObjectMetadataToGraphQLQuery(
|
||||
{
|
||||
objectMetadataItems,
|
||||
|
||||
@ -47,7 +47,7 @@ export const useGenerateFindManyRecordsForMultipleMetadataItemsQuery = ({
|
||||
const limitPerMetadataItemArray = capitalizedObjectNameSingulars
|
||||
.map(
|
||||
(capitalizedObjectNameSingular) =>
|
||||
`$limit${capitalizedObjectNameSingular}: Float`,
|
||||
`$limit${capitalizedObjectNameSingular}: Int`,
|
||||
)
|
||||
.join(', ');
|
||||
|
||||
|
||||
@ -21,7 +21,7 @@ import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata'
|
||||
import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector';
|
||||
|
||||
const query = gql`
|
||||
mutation UpdateOnePerson($idToUpdate: UUID!, $input: PersonUpdateInput!) {
|
||||
mutation UpdateOnePerson($idToUpdate: ID!, $input: PersonUpdateInput!) {
|
||||
updatePerson(id: $idToUpdate, data: $input) {
|
||||
__typename
|
||||
xLink {
|
||||
|
||||
@ -21,7 +21,7 @@ const mocks: MockedResponse[] = [
|
||||
request: {
|
||||
query: gql`
|
||||
mutation UpdateOneCompany(
|
||||
$idToUpdate: UUID!
|
||||
$idToUpdate: ID!
|
||||
$input: CompanyUpdateInput!
|
||||
) {
|
||||
updateCompany(id: $idToUpdate, data: $input) {
|
||||
|
||||
@ -8,7 +8,7 @@ import { isFieldDateValue } from '@/object-record/record-field/types/guards/isFi
|
||||
import { isFieldFullName } from '@/object-record/record-field/types/guards/isFieldFullName';
|
||||
import { isFieldFullNameValue } from '@/object-record/record-field/types/guards/isFieldFullNameValue';
|
||||
import { isFieldMultiSelect } from '@/object-record/record-field/types/guards/isFieldMultiSelect';
|
||||
import { isFieldMultiSelectValue } from '@/object-record/record-field/types/guards/isFieldMultiSelectValue';
|
||||
import { isFieldMultiSelectValue } from '@/object-record/record-field/types/guards/isFieldMultiSelectValue.ts';
|
||||
import { isFieldRawJson } from '@/object-record/record-field/types/guards/isFieldRawJson';
|
||||
import { isFieldRawJsonValue } from '@/object-record/record-field/types/guards/isFieldRawJsonValue';
|
||||
import { isFieldSelect } from '@/object-record/record-field/types/guards/isFieldSelect';
|
||||
|
||||
@ -13,7 +13,7 @@ const query = gql`
|
||||
$filterNameSingular: NameSingularFilterInput
|
||||
$orderByNameSingular: NameSingularOrderByInput
|
||||
$lastCursorNameSingular: String
|
||||
$limitNameSingular: Float
|
||||
$limitNameSingular: Int
|
||||
) {
|
||||
namePlural(
|
||||
filter: $filterNameSingular
|
||||
|
||||
@ -24,7 +24,7 @@ query FindMany${capitalize(
|
||||
objectMetadataItem.nameSingular,
|
||||
)}FilterInput, $orderBy: ${capitalize(
|
||||
objectMetadataItem.nameSingular,
|
||||
)}OrderByInput, $lastCursor: String, $limit: Float) {
|
||||
)}OrderByInput, $lastCursor: String, $limit: Int) {
|
||||
${
|
||||
objectMetadataItem.namePlural
|
||||
}(filter: $filter, orderBy: $orderBy, first: $limit, after: $lastCursor){
|
||||
|
||||
@ -5,7 +5,7 @@ export const query = gql`
|
||||
$filter: PersonFilterInput
|
||||
$orderBy: PersonOrderByInput
|
||||
$lastCursor: String
|
||||
$limit: Float = 60
|
||||
$limit: Int = 60
|
||||
) {
|
||||
people(
|
||||
filter: $filter
|
||||
|
||||
@ -65,7 +65,12 @@ export const ShowPageRightContainer = ({
|
||||
const { activeTabIdState } = useTabList(TAB_LIST_COMPONENT_ID);
|
||||
const activeTabId = useRecoilValue(activeTabIdState);
|
||||
|
||||
const shouldDisplayCalendarTab = useIsFeatureEnabled('IS_CALENDAR_ENABLED');
|
||||
const shouldDisplayCalendarTab =
|
||||
useIsFeatureEnabled('IS_CALENDAR_ENABLED') &&
|
||||
(targetableObject.targetObjectNameSingular ===
|
||||
CoreObjectNameSingular.Company ||
|
||||
targetableObject.targetObjectNameSingular ===
|
||||
CoreObjectNameSingular.Person);
|
||||
const shouldDisplayLogTab = useIsFeatureEnabled('IS_EVENT_OBJECT_ENABLED');
|
||||
|
||||
const shouldDisplayEmailsTab =
|
||||
|
||||
Reference in New Issue
Block a user