Update standard fields (#6532)
In this PR: - adding Favorites to Tasks and Notes - fixing inconsistencies between custom object creation and sync of standard fields of custom objects - fixing workspaceCacheVersion not used to invalidate existing datasource
This commit is contained in:
@ -1,6 +1,6 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { Avatar } from 'twenty-ui';
|
||||
import { Avatar, isDefined } from 'twenty-ui';
|
||||
|
||||
import { FavoritesSkeletonLoader } from '@/favorites/components/FavoritesSkeletonLoader';
|
||||
import { useIsPrefetchLoading } from '@/prefetch/hooks/useIsPrefetchLoading';
|
||||
@ -11,6 +11,7 @@ import { NavigationDrawerSection } from '@/ui/navigation/navigation-drawer/compo
|
||||
import { NavigationDrawerSectionTitle } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSectionTitle';
|
||||
import { useNavigationSection } from '@/ui/navigation/navigation-drawer/hooks/useNavigationSection';
|
||||
|
||||
import { currentUserState } from '@/auth/states/currentUserState';
|
||||
import { useFavorites } from '../hooks/useFavorites';
|
||||
|
||||
const StyledContainer = styled(NavigationDrawerSection)`
|
||||
@ -34,6 +35,8 @@ const StyledNavigationDrawerItem = styled(NavigationDrawerItem)`
|
||||
`;
|
||||
|
||||
export const Favorites = () => {
|
||||
const currentUser = useRecoilValue(currentUserState);
|
||||
|
||||
const { favorites, handleReorderFavorite } = useFavorites();
|
||||
const loading = useIsPrefetchLoading();
|
||||
|
||||
@ -41,7 +44,7 @@ export const Favorites = () => {
|
||||
useNavigationSection('Favorites');
|
||||
const isNavigationSectionOpen = useRecoilValue(isNavigationSectionOpenState);
|
||||
|
||||
if (loading) {
|
||||
if (loading && isDefined(currentUser)) {
|
||||
return <FavoritesSkeletonLoader />;
|
||||
}
|
||||
|
||||
|
||||
@ -2,8 +2,9 @@ import React from 'react';
|
||||
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { useIcons } from 'twenty-ui';
|
||||
import { isDefined, useIcons } from 'twenty-ui';
|
||||
|
||||
import { currentUserState } from '@/auth/states/currentUserState';
|
||||
import { ObjectMetadataNavItemsSkeletonLoader } from '@/object-metadata/components/ObjectMetadataNavItemsSkeletonLoader';
|
||||
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
|
||||
import { useIsPrefetchLoading } from '@/prefetch/hooks/useIsPrefetchLoading';
|
||||
@ -18,6 +19,8 @@ import { View } from '@/views/types/View';
|
||||
import { getObjectMetadataItemViews } from '@/views/utils/getObjectMetadataItemViews';
|
||||
|
||||
export const ObjectMetadataNavItems = ({ isRemote }: { isRemote: boolean }) => {
|
||||
const currentUser = useRecoilValue(currentUserState);
|
||||
|
||||
const { toggleNavigationSection, isNavigationSectionOpenState } =
|
||||
useNavigationSection('Objects' + (isRemote ? 'Remote' : 'Workspace'));
|
||||
const isNavigationSectionOpen = useRecoilValue(isNavigationSectionOpenState);
|
||||
@ -33,7 +36,7 @@ export const ObjectMetadataNavItems = ({ isRemote }: { isRemote: boolean }) => {
|
||||
const { records: views } = usePrefetchedData<View>(PrefetchKey.AllViews);
|
||||
const loading = useIsPrefetchLoading();
|
||||
|
||||
if (loading) {
|
||||
if (loading && isDefined(currentUser)) {
|
||||
return <ObjectMetadataNavItemsSkeletonLoader />;
|
||||
}
|
||||
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { currentUserState } from '@/auth/states/currentUserState';
|
||||
import { useIsPrefetchLoading } from '@/prefetch/hooks/useIsPrefetchLoading';
|
||||
import { NavigationDrawerSectionTitleSkeletonLoader } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSectionTitleSkeletonLoader';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { isDefined } from 'twenty-ui';
|
||||
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
|
||||
|
||||
type NavigationDrawerSectionTitleProps = {
|
||||
@ -32,9 +35,10 @@ export const NavigationDrawerSectionTitle = ({
|
||||
onClick,
|
||||
label,
|
||||
}: NavigationDrawerSectionTitleProps) => {
|
||||
const currentUser = useRecoilValue(currentUserState);
|
||||
const loading = useIsPrefetchLoading();
|
||||
|
||||
if (loading) {
|
||||
if (loading && isDefined(currentUser)) {
|
||||
return <NavigationDrawerSectionTitleSkeletonLoader />;
|
||||
}
|
||||
return <StyledTitle onClick={onClick}>{label}</StyledTitle>;
|
||||
|
||||
@ -50,6 +50,7 @@ import {
|
||||
CUSTOM_OBJECT_STANDARD_FIELD_IDS,
|
||||
FAVORITE_STANDARD_FIELD_IDS,
|
||||
NOTE_TARGET_STANDARD_FIELD_IDS,
|
||||
TASK_TARGET_STANDARD_FIELD_IDS,
|
||||
TIMELINE_ACTIVITY_STANDARD_FIELD_IDS,
|
||||
} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
|
||||
import {
|
||||
@ -255,13 +256,13 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
standardId: BASE_OBJECT_STANDARD_FIELD_IDS.updatedAt,
|
||||
type: FieldMetadataType.DATE_TIME,
|
||||
name: 'updatedAt',
|
||||
label: 'Update date',
|
||||
icon: 'IconCalendar',
|
||||
description: 'Update date',
|
||||
label: 'Last update',
|
||||
icon: 'IconCalendarClock',
|
||||
description: 'Last time the record was changed',
|
||||
isNullable: false,
|
||||
isActive: true,
|
||||
isCustom: false,
|
||||
isSystem: true,
|
||||
isSystem: false,
|
||||
workspaceId: objectMetadataInput.workspaceId,
|
||||
defaultValue: 'now',
|
||||
},
|
||||
@ -269,7 +270,7 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
standardId: CUSTOM_OBJECT_STANDARD_FIELD_IDS.createdBy,
|
||||
type: FieldMetadataType.ACTOR,
|
||||
name: 'createdBy',
|
||||
label: 'Created By',
|
||||
label: 'Created by',
|
||||
icon: 'IconCreativeCommonsSa',
|
||||
description: 'The creator of the record',
|
||||
isNullable: false,
|
||||
@ -676,7 +677,7 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
name: 'noteTargets',
|
||||
label: 'Notes',
|
||||
description: `Notes tied to the ${createdObjectMetadata.labelSingular}`,
|
||||
icon: 'IconCheckbox',
|
||||
icon: 'IconNotes',
|
||||
isNullable: true,
|
||||
},
|
||||
// TO
|
||||
@ -746,7 +747,7 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
{
|
||||
standardId: createForeignKeyDeterministicUuid({
|
||||
objectId: createdObjectMetadata.id,
|
||||
standardId: NOTE_TARGET_STANDARD_FIELD_IDS.custom,
|
||||
standardId: TASK_TARGET_STANDARD_FIELD_IDS.custom,
|
||||
}),
|
||||
objectMetadataId: taskTargetObjectMetadata.id,
|
||||
workspaceId: workspaceId,
|
||||
@ -784,7 +785,7 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
{
|
||||
standardId: createRelationDeterministicUuid({
|
||||
objectId: createdObjectMetadata.id,
|
||||
standardId: NOTE_TARGET_STANDARD_FIELD_IDS.custom,
|
||||
standardId: TASK_TARGET_STANDARD_FIELD_IDS.custom,
|
||||
}),
|
||||
objectMetadataId: taskTargetObjectMetadata.id,
|
||||
workspaceId: workspaceId,
|
||||
@ -979,8 +980,9 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
name: 'timelineActivities',
|
||||
label: 'Timeline Activities',
|
||||
description: `Timeline Activities tied to the ${createdObjectMetadata.labelSingular}`,
|
||||
icon: 'IconTimeline',
|
||||
icon: 'IconIconTimelineEvent',
|
||||
isNullable: true,
|
||||
isSystem: true,
|
||||
},
|
||||
// TO
|
||||
{
|
||||
@ -996,7 +998,7 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
name: createdObjectMetadata.nameSingular,
|
||||
label: createdObjectMetadata.labelSingular,
|
||||
description: `Timeline Activity ${createdObjectMetadata.labelSingular}`,
|
||||
icon: 'IconBuildingSkyscraper',
|
||||
icon: 'IconTimeline',
|
||||
isNullable: true,
|
||||
},
|
||||
]);
|
||||
@ -1100,7 +1102,7 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
name: createdObjectMetadata.nameSingular,
|
||||
label: createdObjectMetadata.labelSingular,
|
||||
description: `Favorite ${createdObjectMetadata.labelSingular}`,
|
||||
icon: 'IconBuildingSkyscraper',
|
||||
icon: 'IconHeart',
|
||||
isNullable: true,
|
||||
},
|
||||
]);
|
||||
|
||||
@ -2,12 +2,12 @@ import { ObjectType } from 'typeorm';
|
||||
|
||||
import { WorkspaceDynamicRelationMetadataArgsFactory } from 'src/engine/twenty-orm/interfaces/workspace-dynamic-relation-metadata-args.interface';
|
||||
|
||||
import { TypedReflect } from 'src/utils/typed-reflect';
|
||||
import {
|
||||
RelationMetadataType,
|
||||
RelationOnDeleteAction,
|
||||
} from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity';
|
||||
import { metadataArgsStorage } from 'src/engine/twenty-orm/storage/metadata-args.storage';
|
||||
import { TypedReflect } from 'src/utils/typed-reflect';
|
||||
|
||||
interface WorkspaceBaseDynamicRelationOptions<TClass> {
|
||||
type: RelationMetadataType;
|
||||
@ -27,6 +27,7 @@ export function WorkspaceDynamicRelation<TClass extends object>(
|
||||
target,
|
||||
propertyKey.toString(),
|
||||
) ?? false;
|
||||
|
||||
const gate = TypedReflect.getMetadata(
|
||||
'workspace:gate-metadata-args',
|
||||
target,
|
||||
|
||||
@ -26,20 +26,20 @@ export class WorkspaceDatasourceFactory {
|
||||
|
||||
public async create(
|
||||
workspaceId: string,
|
||||
cacheVersion: string | null,
|
||||
workspaceSchemaVersion: string | null,
|
||||
): Promise<WorkspaceDataSource> {
|
||||
const desiredCacheVersion =
|
||||
cacheVersion ??
|
||||
const desiredWorkspaceSchemaVersion =
|
||||
workspaceSchemaVersion ??
|
||||
(await this.workspaceCacheVersionService.getVersion(workspaceId));
|
||||
|
||||
if (!desiredCacheVersion) {
|
||||
if (!desiredWorkspaceSchemaVersion) {
|
||||
throw new Error('Cache version not found');
|
||||
}
|
||||
|
||||
const latestCacheVersion =
|
||||
const latestWorkspaceSchemaVersion =
|
||||
await this.workspaceCacheVersionService.getVersion(workspaceId);
|
||||
|
||||
if (latestCacheVersion !== desiredCacheVersion) {
|
||||
if (latestWorkspaceSchemaVersion !== desiredWorkspaceSchemaVersion) {
|
||||
throw new Error('Cache version mismatch');
|
||||
}
|
||||
|
||||
@ -70,7 +70,7 @@ export class WorkspaceDatasourceFactory {
|
||||
}
|
||||
|
||||
const workspaceDataSource = await workspaceDataSourceCacheInstance.execute(
|
||||
`${workspaceId}-${cacheVersion}`,
|
||||
`${workspaceId}-${latestWorkspaceSchemaVersion}`,
|
||||
async () => {
|
||||
const dataSourceMetadata =
|
||||
await this.dataSourceService.getLastDataSourceMetadataFromWorkspaceId(
|
||||
|
||||
@ -12,7 +12,6 @@ export class CacheManager<T> {
|
||||
): Promise<T | null> {
|
||||
const [workspaceId] = cacheKey.split('-');
|
||||
|
||||
// If the cacheKey exists, return the cached value
|
||||
if (this.cache.has(cacheKey)) {
|
||||
return this.cache.get(cacheKey)!;
|
||||
}
|
||||
|
||||
@ -203,6 +203,8 @@ export const FAVORITE_STANDARD_FIELD_IDS = {
|
||||
company: '20202020-cff5-4682-8bf9-069169e08279',
|
||||
opportunity: '20202020-dabc-48e1-8318-2781a2b32aa2',
|
||||
workflow: '20202020-b11b-4dc8-999a-6bd0a947b463',
|
||||
task: '20202020-1b1b-4b3b-8b1b-7f8d6a1d7d5c',
|
||||
note: '20202020-1f25-43fe-8b00-af212fdde824',
|
||||
custom: '20202020-855a-4bc8-9861-79deef37011f',
|
||||
};
|
||||
|
||||
@ -272,6 +274,7 @@ export const NOTE_STANDARD_FIELD_IDS = {
|
||||
noteTargets: '20202020-1f25-43fe-8b00-af212fdde823',
|
||||
attachments: '20202020-4986-4c92-bf19-39934b149b16',
|
||||
timelineActivities: '20202020-7030-42f8-929c-1a57b25d6bce',
|
||||
favorites: '20202020-4d1d-41ac-b13b-621631298d67',
|
||||
};
|
||||
|
||||
export const NOTE_TARGET_STANDARD_FIELD_IDS = {
|
||||
@ -334,6 +337,7 @@ export const TASK_STANDARD_FIELD_IDS = {
|
||||
attachments: '20202020-794d-4783-a8ff-cecdb15be139',
|
||||
assignee: '20202020-065a-4f42-a906-e20422c1753f',
|
||||
timelineActivities: '20202020-c778-4278-99ee-23a2837aee64',
|
||||
favorites: '20202020-4d1d-41ac-b13b-621631298d65',
|
||||
};
|
||||
|
||||
export const TASK_TARGET_STANDARD_FIELD_IDS = {
|
||||
|
||||
@ -1,22 +1,22 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { WorkspaceSyncContext } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/workspace-sync-context.interface';
|
||||
import { FeatureFlagMap } from 'src/engine/core-modules/feature-flag/interfaces/feature-flag-map.interface';
|
||||
import { WorkspaceDynamicRelationMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-dynamic-relation-metadata-args.interface';
|
||||
import { WorkspaceEntityMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-entity-metadata-args.interface';
|
||||
import { WorkspaceFieldMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-field-metadata-args.interface';
|
||||
import { WorkspaceRelationMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-relation-metadata-args.interface';
|
||||
import {
|
||||
PartialComputedFieldMetadata,
|
||||
PartialFieldMetadata,
|
||||
} from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-field-metadata.interface';
|
||||
import { WorkspaceEntityMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-entity-metadata-args.interface';
|
||||
import { WorkspaceFieldMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-field-metadata-args.interface';
|
||||
import { WorkspaceDynamicRelationMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-dynamic-relation-metadata-args.interface';
|
||||
import { WorkspaceRelationMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-relation-metadata-args.interface';
|
||||
import { WorkspaceSyncContext } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/workspace-sync-context.interface';
|
||||
|
||||
import { isGatedAndNotEnabled } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/is-gate-and-not-enabled.util';
|
||||
import { metadataArgsStorage } from 'src/engine/twenty-orm/storage/metadata-args.storage';
|
||||
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
|
||||
import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { createDeterministicUuid } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/create-deterministic-uuid.util';
|
||||
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
|
||||
import { metadataArgsStorage } from 'src/engine/twenty-orm/storage/metadata-args.storage';
|
||||
import { getJoinColumn } from 'src/engine/twenty-orm/utils/get-join-column.util';
|
||||
import { createDeterministicUuid } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/create-deterministic-uuid.util';
|
||||
import { isGatedAndNotEnabled } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/is-gate-and-not-enabled.util';
|
||||
|
||||
@Injectable()
|
||||
export class StandardFieldFactory {
|
||||
@ -163,9 +163,7 @@ export class StandardFieldFactory {
|
||||
workspaceId: context.workspaceId,
|
||||
isNullable: workspaceFieldMetadataArgs.isNullable,
|
||||
isCustom: workspaceFieldMetadataArgs.isDeprecated ? true : false,
|
||||
isSystem:
|
||||
workspaceEntityMetadataArgs?.isSystem ||
|
||||
workspaceFieldMetadataArgs.isSystem,
|
||||
isSystem: workspaceFieldMetadataArgs.isSystem ?? false,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
@ -84,7 +84,7 @@ export class WorkspaceSyncMetadataService {
|
||||
workspaceFeatureFlagsMap,
|
||||
);
|
||||
|
||||
// 2 - Sync standard fields on custom objects
|
||||
// 2 - Sync standard fields on standard and custom objects
|
||||
const workspaceFieldMigrations =
|
||||
await this.workspaceSyncFieldMetadataService.synchronize(
|
||||
context,
|
||||
|
||||
@ -17,8 +17,10 @@ import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-re
|
||||
import { FAVORITE_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
|
||||
import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids';
|
||||
import { CompanyWorkspaceEntity } from 'src/modules/company/standard-objects/company.workspace-entity';
|
||||
import { NoteWorkspaceEntity } from 'src/modules/note/standard-objects/note.workspace-entity';
|
||||
import { OpportunityWorkspaceEntity } from 'src/modules/opportunity/standard-objects/opportunity.workspace-entity';
|
||||
import { PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity';
|
||||
import { TaskWorkspaceEntity } from 'src/modules/task/standard-objects/task.workspace-entity';
|
||||
import { WorkflowWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity';
|
||||
import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
|
||||
|
||||
@ -124,6 +126,36 @@ export class FavoriteWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
})
|
||||
workflowId: string;
|
||||
|
||||
@WorkspaceRelation({
|
||||
standardId: FAVORITE_STANDARD_FIELD_IDS.task,
|
||||
type: RelationMetadataType.MANY_TO_ONE,
|
||||
label: 'Task',
|
||||
description: 'Favorite task',
|
||||
icon: 'IconCheckbox',
|
||||
inverseSideTarget: () => TaskWorkspaceEntity,
|
||||
inverseSideFieldKey: 'favorites',
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
task: Relation<TaskWorkspaceEntity> | null;
|
||||
|
||||
@WorkspaceJoinColumn('task')
|
||||
taskId: string;
|
||||
|
||||
@WorkspaceRelation({
|
||||
standardId: FAVORITE_STANDARD_FIELD_IDS.note,
|
||||
type: RelationMetadataType.MANY_TO_ONE,
|
||||
label: 'Note',
|
||||
description: 'Favorite note',
|
||||
icon: 'IconNotes',
|
||||
inverseSideTarget: () => NoteWorkspaceEntity,
|
||||
inverseSideFieldKey: 'favorites',
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
note: Relation<NoteWorkspaceEntity> | null;
|
||||
|
||||
@WorkspaceJoinColumn('note')
|
||||
noteId: string;
|
||||
|
||||
@WorkspaceDynamicRelation({
|
||||
type: RelationMetadataType.MANY_TO_ONE,
|
||||
argsFactory: (oppositeObjectMetadata) => ({
|
||||
@ -132,7 +164,7 @@ export class FavoriteWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
label: oppositeObjectMetadata.labelSingular,
|
||||
description: `Favorite ${oppositeObjectMetadata.labelSingular}`,
|
||||
joinColumn: `${oppositeObjectMetadata.nameSingular}Id`,
|
||||
icon: 'IconBuildingSkyscraper',
|
||||
icon: 'IconHeart',
|
||||
}),
|
||||
inverseSideTarget: () => CustomWorkspaceEntity,
|
||||
inverseSideFieldKey: 'favorites',
|
||||
|
||||
@ -18,6 +18,7 @@ import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-re
|
||||
import { NOTE_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
|
||||
import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids';
|
||||
import { AttachmentWorkspaceEntity } from 'src/modules/attachment/standard-objects/attachment.workspace-entity';
|
||||
import { FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity';
|
||||
import { NoteTargetWorkspaceEntity } from 'src/modules/note/standard-objects/note-target.workspace-entity';
|
||||
import { TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-objects/timeline-activity.workspace-entity';
|
||||
|
||||
@ -110,4 +111,16 @@ export class NoteWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
timelineActivities: Relation<TimelineActivityWorkspaceEntity[]>;
|
||||
|
||||
@WorkspaceRelation({
|
||||
standardId: NOTE_STANDARD_FIELD_IDS.favorites,
|
||||
type: RelationMetadataType.ONE_TO_MANY,
|
||||
label: 'Favorites',
|
||||
description: 'Favorites linked to the note',
|
||||
icon: 'IconHeart',
|
||||
inverseSideTarget: () => FavoriteWorkspaceEntity,
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
@WorkspaceIsSystem()
|
||||
favorites: Relation<FavoriteWorkspaceEntity[]>;
|
||||
}
|
||||
|
||||
@ -19,6 +19,7 @@ import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-re
|
||||
import { TASK_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
|
||||
import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids';
|
||||
import { AttachmentWorkspaceEntity } from 'src/modules/attachment/standard-objects/attachment.workspace-entity';
|
||||
import { FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity';
|
||||
import { TaskTargetWorkspaceEntity } from 'src/modules/task/standard-objects/task-target.workspace-entity';
|
||||
import { TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-objects/timeline-activity.workspace-entity';
|
||||
import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
|
||||
@ -164,4 +165,16 @@ export class TaskWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
timelineActivities: Relation<TimelineActivityWorkspaceEntity[]>;
|
||||
|
||||
@WorkspaceRelation({
|
||||
standardId: TASK_STANDARD_FIELD_IDS.favorites,
|
||||
type: RelationMetadataType.ONE_TO_MANY,
|
||||
label: 'Favorites',
|
||||
description: 'Favorites linked to the task',
|
||||
icon: 'IconHeart',
|
||||
inverseSideTarget: () => FavoriteWorkspaceEntity,
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
@WorkspaceIsSystem()
|
||||
favorites: Relation<FavoriteWorkspaceEntity[]>;
|
||||
}
|
||||
|
||||
@ -212,7 +212,7 @@ export class TimelineActivityWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
standardId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.custom,
|
||||
name: oppositeObjectMetadata.nameSingular,
|
||||
label: oppositeObjectMetadata.labelSingular,
|
||||
description: `Event ${oppositeObjectMetadata.labelSingular}`,
|
||||
description: `Timeline Activity ${oppositeObjectMetadata.labelSingular}`,
|
||||
joinColumn: `${oppositeObjectMetadata.nameSingular}Id`,
|
||||
icon: 'IconTimeline',
|
||||
}),
|
||||
|
||||
Reference in New Issue
Block a user