Revert 21949 (#22081)
#21949 introduced deterministic uuid utils with usage in the same PR. Usage was not uniform and expected a backfill command as well. Since we want to release I'm reverting all the changes from that PR that concerns twenty-server and only keeping the unused utils in twenty-shared and I'll introduce usages within the same PR as backfill command
This commit is contained in:
-1
@@ -202,7 +202,6 @@ export class RefactorNavigationCommandsCommand extends ActiveOrSuspendedWorkspac
|
||||
workspaceId,
|
||||
position: nextPosition++,
|
||||
now,
|
||||
universalIdentifier,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
+21
-12
@@ -13,6 +13,8 @@ import { type FlatPageLayoutTab } from 'src/engine/metadata-modules/flat-page-la
|
||||
import { type FlatPageLayoutWidget } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget.type';
|
||||
import { type FlatPageLayout } from 'src/engine/metadata-modules/flat-page-layout/types/flat-page-layout.type';
|
||||
import { computeFlatDefaultRecordPageLayoutToCreate } from 'src/engine/metadata-modules/object-metadata/utils/compute-flat-default-record-page-layout-to-create.util';
|
||||
import { computeFlatRecordPageFieldsViewToCreate } from 'src/engine/metadata-modules/object-metadata/utils/compute-flat-record-page-fields-view-to-create.util';
|
||||
import { computeFlatViewFieldsToCreate } from 'src/engine/metadata-modules/object-metadata/utils/compute-flat-view-fields-to-create.util';
|
||||
import { WidgetConfigurationType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-configuration-type.type';
|
||||
import { PageLayoutType } from 'src/engine/metadata-modules/page-layout/enums/page-layout-type.enum';
|
||||
import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service';
|
||||
@@ -506,32 +508,39 @@ export class BackfillRecordPageLayoutsCommand extends ActiveOrSuspendedWorkspace
|
||||
const allViewFields: UniversalFlatViewField[] = [];
|
||||
|
||||
for (const customObject of customObjectsWithoutPageLayout) {
|
||||
const fieldsView = computeFlatRecordPageFieldsViewToCreate({
|
||||
objectMetadata: customObject,
|
||||
flatApplication: twentyStandardFlatApplication,
|
||||
});
|
||||
|
||||
const objectFieldMetadatas = Object.values(
|
||||
flatFieldMetadataMaps.byUniversalIdentifier,
|
||||
)
|
||||
.filter(isDefined)
|
||||
.filter((field) => field.objectMetadataId === customObject.id);
|
||||
|
||||
const {
|
||||
pageLayouts,
|
||||
pageLayoutTabs,
|
||||
pageLayoutWidgets,
|
||||
recordPageFieldsView,
|
||||
recordPageFieldsViewFields,
|
||||
} = computeFlatDefaultRecordPageLayoutToCreate({
|
||||
objectMetadata: customObject,
|
||||
flatApplication: twentyStandardFlatApplication,
|
||||
const viewFields = computeFlatViewFieldsToCreate({
|
||||
objectFlatFieldMetadatas: objectFieldMetadatas,
|
||||
viewUniversalIdentifier: fieldsView.universalIdentifier,
|
||||
flatApplication: twentyStandardFlatApplication,
|
||||
labelIdentifierFieldMetadataUniversalIdentifier:
|
||||
customObject.labelIdentifierFieldMetadataUniversalIdentifier,
|
||||
workspaceId,
|
||||
excludeLabelIdentifier: true,
|
||||
});
|
||||
|
||||
const { pageLayouts, pageLayoutTabs, pageLayoutWidgets } =
|
||||
computeFlatDefaultRecordPageLayoutToCreate({
|
||||
objectMetadata: customObject,
|
||||
flatApplication: twentyStandardFlatApplication,
|
||||
recordPageFieldsView: fieldsView,
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
allPageLayouts.push(...pageLayouts);
|
||||
allTabs.push(...pageLayoutTabs);
|
||||
allWidgets.push(...pageLayoutWidgets);
|
||||
allViews.push(recordPageFieldsView);
|
||||
allViewFields.push(...recordPageFieldsViewFields);
|
||||
allViews.push(fieldsView);
|
||||
allViewFields.push(...viewFields);
|
||||
}
|
||||
|
||||
const result =
|
||||
|
||||
-4
@@ -57,10 +57,6 @@ const buildExistingNavigationItem = ({
|
||||
workspaceId: WORKSPACE_ID,
|
||||
position,
|
||||
now: NOW,
|
||||
universalIdentifier: v5(
|
||||
objectUniversalIdentifier,
|
||||
NAVIGATION_COMMAND_UUID_NAMESPACE,
|
||||
),
|
||||
});
|
||||
|
||||
describe('buildNavigationCommandMenuItemOperationsOrThrow', () => {
|
||||
|
||||
-1
@@ -69,7 +69,6 @@ export const buildNavigationCommandMenuItemOperationsOrThrow = ({
|
||||
workspaceId,
|
||||
position: nextPosition++,
|
||||
now,
|
||||
universalIdentifier: commandMenuItemUniversalIdentifier,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
+11
-3
@@ -1,4 +1,5 @@
|
||||
import { STANDARD_OBJECTS } from 'twenty-shared/metadata';
|
||||
import { v5 } from 'uuid';
|
||||
|
||||
import { CommandMenuItemAvailabilityType } from 'src/engine/metadata-modules/command-menu-item/enums/command-menu-item-availability-type.enum';
|
||||
import { EngineComponentKey } from 'src/engine/metadata-modules/command-menu-item/enums/engine-component-key.enum';
|
||||
@@ -10,6 +11,9 @@ import {
|
||||
NAVIGATION_INTERPOLATED_SHORT_LABEL,
|
||||
} from 'src/engine/metadata-modules/flat-command-menu-item/utils/build-navigation-flat-command-menu-item.util';
|
||||
|
||||
const NAVIGATION_COMMAND_UUID_NAMESPACE =
|
||||
'b31830da-2ae0-48eb-a915-12fa4ab96dd3';
|
||||
|
||||
const baseObjectMetadata = {
|
||||
id: 'obj-id-1',
|
||||
universalIdentifier: 'obj-universal-1',
|
||||
@@ -25,14 +29,18 @@ const baseArgs = {
|
||||
workspaceId: 'ws-id-1',
|
||||
position: 5,
|
||||
now: '2026-01-01T00:00:00.000Z',
|
||||
universalIdentifier: 'nav-universal-1',
|
||||
};
|
||||
|
||||
describe('buildNavigationFlatCommandMenuItem', () => {
|
||||
it('should use the provided universalIdentifier', () => {
|
||||
it('should produce a deterministic universalIdentifier via UUID v5', () => {
|
||||
const result = buildNavigationFlatCommandMenuItem(baseArgs);
|
||||
|
||||
expect(result.universalIdentifier).toBe('nav-universal-1');
|
||||
const expectedUniversalIdentifier = v5(
|
||||
baseObjectMetadata.universalIdentifier,
|
||||
NAVIGATION_COMMAND_UUID_NAMESPACE,
|
||||
);
|
||||
|
||||
expect(result.universalIdentifier).toBe(expectedUniversalIdentifier);
|
||||
});
|
||||
|
||||
it('should set label and shortLabel as interpolation templates', () => {
|
||||
|
||||
+6
-2
@@ -1,6 +1,7 @@
|
||||
import { STANDARD_OBJECTS } from 'twenty-shared/metadata';
|
||||
import { FeatureFlagKey } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { v5 } from 'uuid';
|
||||
|
||||
import { CommandMenuItemAvailabilityType } from 'src/engine/metadata-modules/command-menu-item/enums/command-menu-item-availability-type.enum';
|
||||
import { EngineComponentKey } from 'src/engine/metadata-modules/command-menu-item/enums/engine-component-key.enum';
|
||||
@@ -53,7 +54,6 @@ export const buildNavigationFlatCommandMenuItem = ({
|
||||
workspaceId,
|
||||
position,
|
||||
now,
|
||||
universalIdentifier,
|
||||
}: {
|
||||
objectMetadata: {
|
||||
id: string;
|
||||
@@ -67,8 +67,12 @@ export const buildNavigationFlatCommandMenuItem = ({
|
||||
workspaceId: string;
|
||||
position: number;
|
||||
now: string;
|
||||
universalIdentifier: string;
|
||||
}): FlatCommandMenuItem => {
|
||||
const universalIdentifier = v5(
|
||||
objectMetadata.universalIdentifier,
|
||||
NAVIGATION_COMMAND_UUID_NAMESPACE,
|
||||
);
|
||||
|
||||
const conditionalAvailabilityExpression =
|
||||
buildNavigationConditionalAvailabilityExpression({
|
||||
universalIdentifier: objectMetadata.universalIdentifier,
|
||||
|
||||
-101
@@ -1,101 +0,0 @@
|
||||
import { compositeTypeDefinitions, RelationType } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { computeCompositeColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-column-name.util';
|
||||
import { computeMorphOrRelationFieldJoinColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-morph-or-relation-field-join-column-name.util';
|
||||
import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util';
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { isMorphOrRelationUniversalFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-morph-or-relation-flat-field-metadata.util';
|
||||
import { generateDeterministicIndexNameV2 } from 'src/engine/metadata-modules/index-metadata/utils/generate-deterministic-index-name-v2';
|
||||
import { type UniversalFlatFieldMetadata } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-field-metadata.type';
|
||||
import { type UniversalFlatObjectMetadata } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-object-metadata.type';
|
||||
|
||||
type FlatIndexFieldForName = {
|
||||
fieldMetadataUniversalIdentifier: string;
|
||||
order: number;
|
||||
subFieldName: string | null;
|
||||
};
|
||||
|
||||
export const computeFlatIndexNameOrThrow = ({
|
||||
flatObjectMetadata,
|
||||
objectFlatFieldMetadatas,
|
||||
universalFlatIndexFieldMetadatas,
|
||||
isUnique,
|
||||
indexWhereClause,
|
||||
}: {
|
||||
flatObjectMetadata: UniversalFlatObjectMetadata;
|
||||
objectFlatFieldMetadatas: UniversalFlatFieldMetadata[];
|
||||
universalFlatIndexFieldMetadatas: FlatIndexFieldForName[];
|
||||
isUnique: boolean;
|
||||
indexWhereClause: string | null;
|
||||
}): string => {
|
||||
const orderedIndexColumnNames = [...universalFlatIndexFieldMetadatas]
|
||||
.sort((a, b) => a.order - b.order)
|
||||
.map((flatIndexField) => {
|
||||
const relatedFlatFieldMetadata = objectFlatFieldMetadatas.find(
|
||||
(flatFieldMetadata) =>
|
||||
flatFieldMetadata.universalIdentifier ===
|
||||
flatIndexField.fieldMetadataUniversalIdentifier,
|
||||
);
|
||||
|
||||
if (!isDefined(relatedFlatFieldMetadata)) {
|
||||
throw new FlatEntityMapsException(
|
||||
'Could not find flat index field related field in cache',
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
// Composite parent with an explicit sub-field → single sub-column.
|
||||
// Composite parent without sub-field falls through to the legacy
|
||||
// scalar branch below, which produces a deterministic name based on
|
||||
// the parent name (the runner handles the multi-column SQL expansion
|
||||
// via isIncludedInUniqueConstraint).
|
||||
if (
|
||||
isCompositeFieldMetadataType(relatedFlatFieldMetadata.type) &&
|
||||
isDefined(flatIndexField.subFieldName)
|
||||
) {
|
||||
const property = compositeTypeDefinitions
|
||||
.get(relatedFlatFieldMetadata.type)
|
||||
?.properties.find(
|
||||
(compositeProperty) =>
|
||||
compositeProperty.name === flatIndexField.subFieldName,
|
||||
);
|
||||
|
||||
if (!isDefined(property)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Composite sub-field "${flatIndexField.subFieldName}" not found on ${relatedFlatFieldMetadata.name}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
return computeCompositeColumnName(
|
||||
{
|
||||
name: relatedFlatFieldMetadata.name,
|
||||
type: relatedFlatFieldMetadata.type,
|
||||
},
|
||||
property,
|
||||
);
|
||||
}
|
||||
|
||||
const isManyToOneRelation =
|
||||
isMorphOrRelationUniversalFlatFieldMetadata(relatedFlatFieldMetadata) &&
|
||||
relatedFlatFieldMetadata.universalSettings?.relationType ===
|
||||
RelationType.MANY_TO_ONE;
|
||||
|
||||
return isManyToOneRelation
|
||||
? computeMorphOrRelationFieldJoinColumnName({
|
||||
name: relatedFlatFieldMetadata.name,
|
||||
})
|
||||
: relatedFlatFieldMetadata.name;
|
||||
});
|
||||
|
||||
return generateDeterministicIndexNameV2({
|
||||
flatObjectMetadata,
|
||||
orderedIndexColumnNames,
|
||||
isUnique,
|
||||
indexWhereClause,
|
||||
});
|
||||
};
|
||||
-63
@@ -1,63 +0,0 @@
|
||||
import { getIndexUniversalIdentifier } from 'twenty-shared/application';
|
||||
|
||||
import { computeFlatIndexNameOrThrow } from 'src/engine/metadata-modules/index-metadata/utils/compute-flat-index-name-or-throw.util';
|
||||
import { type UniversalFlatFieldMetadata } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-field-metadata.type';
|
||||
import { type UniversalFlatIndexMetadata } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-index-metadata.type';
|
||||
import { type UniversalFlatObjectMetadata } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-object-metadata.type';
|
||||
|
||||
type FlatIndexWithoutDeterministicIdentifiers = Omit<
|
||||
UniversalFlatIndexMetadata,
|
||||
| 'name'
|
||||
| 'universalIdentifier'
|
||||
| 'objectMetadataUniversalIdentifier'
|
||||
| 'applicationUniversalIdentifier'
|
||||
| 'universalFlatIndexFieldMetadatas'
|
||||
> & {
|
||||
universalFlatIndexFieldMetadatas: Array<
|
||||
Omit<
|
||||
UniversalFlatIndexMetadata['universalFlatIndexFieldMetadatas'][number],
|
||||
'indexMetadataUniversalIdentifier'
|
||||
>
|
||||
>;
|
||||
};
|
||||
|
||||
export const generateFlatIndexMetadataWithDeterministicUniversalIdentifierOrThrow =
|
||||
({
|
||||
flatObjectMetadata,
|
||||
objectFlatFieldMetadatas,
|
||||
flatIndex,
|
||||
}: {
|
||||
flatObjectMetadata: UniversalFlatObjectMetadata;
|
||||
objectFlatFieldMetadatas: UniversalFlatFieldMetadata[];
|
||||
flatIndex: FlatIndexWithoutDeterministicIdentifiers;
|
||||
}): UniversalFlatIndexMetadata => {
|
||||
const name = computeFlatIndexNameOrThrow({
|
||||
flatObjectMetadata,
|
||||
objectFlatFieldMetadatas,
|
||||
universalFlatIndexFieldMetadatas:
|
||||
flatIndex.universalFlatIndexFieldMetadatas,
|
||||
isUnique: flatIndex.isUnique,
|
||||
indexWhereClause: flatIndex.indexWhereClause,
|
||||
});
|
||||
|
||||
const universalIdentifier = getIndexUniversalIdentifier({
|
||||
applicationUniversalIdentifier:
|
||||
flatObjectMetadata.applicationUniversalIdentifier,
|
||||
objectUniversalIdentifier: flatObjectMetadata.universalIdentifier,
|
||||
name,
|
||||
});
|
||||
|
||||
return {
|
||||
...flatIndex,
|
||||
name,
|
||||
universalIdentifier,
|
||||
objectMetadataUniversalIdentifier: flatObjectMetadata.universalIdentifier,
|
||||
applicationUniversalIdentifier:
|
||||
flatObjectMetadata.applicationUniversalIdentifier,
|
||||
universalFlatIndexFieldMetadatas:
|
||||
flatIndex.universalFlatIndexFieldMetadatas.map((indexField) => ({
|
||||
...indexField,
|
||||
indexMetadataUniversalIdentifier: universalIdentifier,
|
||||
})),
|
||||
};
|
||||
};
|
||||
+74
-5
@@ -1,4 +1,15 @@
|
||||
import { computeFlatIndexNameOrThrow } from 'src/engine/metadata-modules/index-metadata/utils/compute-flat-index-name-or-throw.util';
|
||||
import { compositeTypeDefinitions, RelationType } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { computeCompositeColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-column-name.util';
|
||||
import { computeMorphOrRelationFieldJoinColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-morph-or-relation-field-join-column-name.util';
|
||||
import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util';
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { isMorphOrRelationUniversalFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-morph-or-relation-flat-field-metadata.util';
|
||||
import { generateDeterministicIndexNameV2 } from 'src/engine/metadata-modules/index-metadata/utils/generate-deterministic-index-name-v2';
|
||||
import { type UniversalFlatFieldMetadata } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-field-metadata.type';
|
||||
import { type UniversalFlatIndexMetadata } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-index-metadata.type';
|
||||
import { type UniversalFlatObjectMetadata } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-object-metadata.type';
|
||||
@@ -14,11 +25,69 @@ export const generateFlatIndexMetadataWithNameOrThrow = ({
|
||||
objectFlatFieldMetadatas,
|
||||
flatIndex,
|
||||
}: GenerateFlatIndexArgs): UniversalFlatIndexMetadata => {
|
||||
const name = computeFlatIndexNameOrThrow({
|
||||
const orderedIndexColumnNames = flatIndex.universalFlatIndexFieldMetadatas
|
||||
.sort((a, b) => a.order - b.order)
|
||||
.map((flatIndexField) => {
|
||||
const relatedFlatFieldMetadata = objectFlatFieldMetadatas.find(
|
||||
(flatFieldMetadata) =>
|
||||
flatFieldMetadata.universalIdentifier ===
|
||||
flatIndexField.fieldMetadataUniversalIdentifier,
|
||||
);
|
||||
|
||||
if (!isDefined(relatedFlatFieldMetadata)) {
|
||||
throw new FlatEntityMapsException(
|
||||
'Could not find flat index field related field in cache',
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
// Composite parent with an explicit sub-field → single sub-column.
|
||||
// Composite parent without sub-field falls through to the legacy
|
||||
// scalar branch below, which produces a deterministic name based on
|
||||
// the parent name (the runner handles the multi-column SQL expansion
|
||||
// via isIncludedInUniqueConstraint).
|
||||
if (
|
||||
isCompositeFieldMetadataType(relatedFlatFieldMetadata.type) &&
|
||||
isDefined(flatIndexField.subFieldName)
|
||||
) {
|
||||
const property = compositeTypeDefinitions
|
||||
.get(relatedFlatFieldMetadata.type)
|
||||
?.properties.find(
|
||||
(compositeProperty) =>
|
||||
compositeProperty.name === flatIndexField.subFieldName,
|
||||
);
|
||||
|
||||
if (!isDefined(property)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Composite sub-field "${flatIndexField.subFieldName}" not found on ${relatedFlatFieldMetadata.name}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
return computeCompositeColumnName(
|
||||
{
|
||||
name: relatedFlatFieldMetadata.name,
|
||||
type: relatedFlatFieldMetadata.type,
|
||||
},
|
||||
property,
|
||||
);
|
||||
}
|
||||
|
||||
const isManyToOneRelation =
|
||||
isMorphOrRelationUniversalFlatFieldMetadata(relatedFlatFieldMetadata) &&
|
||||
relatedFlatFieldMetadata.universalSettings?.relationType ===
|
||||
RelationType.MANY_TO_ONE;
|
||||
|
||||
return isManyToOneRelation
|
||||
? computeMorphOrRelationFieldJoinColumnName({
|
||||
name: relatedFlatFieldMetadata.name,
|
||||
})
|
||||
: relatedFlatFieldMetadata.name;
|
||||
});
|
||||
|
||||
const name = generateDeterministicIndexNameV2({
|
||||
flatObjectMetadata,
|
||||
objectFlatFieldMetadatas,
|
||||
universalFlatIndexFieldMetadatas:
|
||||
flatIndex.universalFlatIndexFieldMetadatas,
|
||||
orderedIndexColumnNames,
|
||||
isUnique: flatIndex.isUnique,
|
||||
indexWhereClause: flatIndex.indexWhereClause,
|
||||
});
|
||||
|
||||
+69
-31
@@ -2,10 +2,6 @@ import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm';
|
||||
import {
|
||||
getIndexViewUniversalIdentifier,
|
||||
getNavigationCommandUniversalIdentifier,
|
||||
} from 'twenty-shared/application';
|
||||
import {
|
||||
ViewKey,
|
||||
ViewOpenRecordIn,
|
||||
@@ -14,12 +10,15 @@ import {
|
||||
} from 'twenty-shared/types';
|
||||
import { fromArrayToUniqueKeyRecord, isDefined } from 'twenty-shared/utils';
|
||||
import { FindManyOptions, FindOneOptions, Repository } from 'typeorm';
|
||||
import { v4 } from 'uuid';
|
||||
import { v4, v5 } from 'uuid';
|
||||
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { type FlatCommandMenuItem } from 'src/engine/metadata-modules/flat-command-menu-item/types/flat-command-menu-item.type';
|
||||
import { buildNavigationFlatCommandMenuItem } from 'src/engine/metadata-modules/flat-command-menu-item/utils/build-navigation-flat-command-menu-item.util';
|
||||
import {
|
||||
buildNavigationFlatCommandMenuItem,
|
||||
NAVIGATION_COMMAND_UUID_NAMESPACE,
|
||||
} from 'src/engine/metadata-modules/flat-command-menu-item/utils/build-navigation-flat-command-menu-item.util';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { findFlatEntityByUniversalIdentifierOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier-or-throw.util';
|
||||
@@ -31,6 +30,9 @@ import { FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-meta
|
||||
import { fromCreateObjectInputToFlatObjectMetadataAndFlatFieldMetadatasToCreate } from 'src/engine/metadata-modules/flat-object-metadata/utils/from-create-object-input-to-flat-object-metadata-and-flat-field-metadatas-to-create.util';
|
||||
import { fromDeleteObjectInputToFlatFieldMetadatasToDelete } from 'src/engine/metadata-modules/flat-object-metadata/utils/from-delete-object-input-to-flat-field-metadatas-to-delete.util';
|
||||
import { fromUpdateObjectInputToFlatObjectMetadataAndRelatedFlatEntities } from 'src/engine/metadata-modules/flat-object-metadata/utils/from-update-object-input-to-flat-object-metadata-and-related-flat-entities.util';
|
||||
import { type FlatPageLayoutTab } from 'src/engine/metadata-modules/flat-page-layout-tab/types/flat-page-layout-tab.type';
|
||||
import { type FlatPageLayoutWidget } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget.type';
|
||||
import { type FlatPageLayout } from 'src/engine/metadata-modules/flat-page-layout/types/flat-page-layout.type';
|
||||
import { NavigationMenuItemType } from 'src/engine/metadata-modules/navigation-menu-item/enums/navigation-menu-item-type.enum';
|
||||
import { CreateObjectInput } from 'src/engine/metadata-modules/object-metadata/dtos/create-object.input';
|
||||
import { DeleteOneObjectInput } from 'src/engine/metadata-modules/object-metadata/dtos/delete-object.input';
|
||||
@@ -41,6 +43,7 @@ import {
|
||||
ObjectMetadataExceptionCode,
|
||||
} from 'src/engine/metadata-modules/object-metadata/object-metadata.exception';
|
||||
import { computeFlatDefaultRecordPageLayoutToCreate } from 'src/engine/metadata-modules/object-metadata/utils/compute-flat-default-record-page-layout-to-create.util';
|
||||
import { computeFlatRecordPageFieldsViewToCreate } from 'src/engine/metadata-modules/object-metadata/utils/compute-flat-record-page-fields-view-to-create.util';
|
||||
import { computeFlatViewFieldsToCreate } from 'src/engine/metadata-modules/object-metadata/utils/compute-flat-view-fields-to-create.util';
|
||||
import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service';
|
||||
import { WorkspaceMigrationBuilderException } from 'src/engine/workspace-manager/workspace-migration/exceptions/workspace-migration-builder-exception';
|
||||
@@ -417,8 +420,6 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
this.findNavigationCommandMenuItemForObject({
|
||||
objectUniversalIdentifier:
|
||||
flatObjectMetadataToDelete.universalIdentifier,
|
||||
applicationUniversalIdentifier:
|
||||
flatObjectMetadataToDelete.applicationUniversalIdentifier,
|
||||
flatCommandMenuItemMaps,
|
||||
}),
|
||||
)
|
||||
@@ -543,13 +544,28 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
},
|
||||
);
|
||||
|
||||
const flatDefaultRecordPageLayoutsToCreate =
|
||||
computeFlatDefaultRecordPageLayoutToCreate({
|
||||
const flatRecordPageFieldsViewToCreate =
|
||||
this.computeFlatRecordPageFieldsViewToCreate({
|
||||
objectMetadata: flatObjectMetadataToCreate,
|
||||
flatApplication: resolvedOwnerFlatApplication,
|
||||
});
|
||||
|
||||
const flatRecordPageFieldsViewFieldsToCreate =
|
||||
computeFlatViewFieldsToCreate({
|
||||
flatApplication: resolvedOwnerFlatApplication,
|
||||
objectFlatFieldMetadatas: flatFieldMetadataToCreateOnObject,
|
||||
labelIdentifierFieldMetadataUniversalIdentifier:
|
||||
flatObjectMetadataToCreate.labelIdentifierFieldMetadataUniversalIdentifier,
|
||||
viewUniversalIdentifier:
|
||||
flatRecordPageFieldsViewToCreate.universalIdentifier,
|
||||
excludeLabelIdentifier: true,
|
||||
});
|
||||
|
||||
const flatDefaultRecordPageLayoutsToCreate =
|
||||
this.computeFlatDefaultRecordPageLayoutToCreate({
|
||||
objectMetadata: flatObjectMetadataToCreate,
|
||||
flatApplication: resolvedOwnerFlatApplication,
|
||||
recordPageFieldsView: flatRecordPageFieldsViewToCreate,
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
@@ -565,7 +581,7 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
view: {
|
||||
flatEntityToCreate: [
|
||||
flatDefaultViewToCreate,
|
||||
flatDefaultRecordPageLayoutsToCreate.recordPageFieldsView,
|
||||
flatRecordPageFieldsViewToCreate,
|
||||
],
|
||||
flatEntityToDelete: [],
|
||||
flatEntityToUpdate: [],
|
||||
@@ -573,7 +589,7 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
viewField: {
|
||||
flatEntityToCreate: [
|
||||
...flatDefaultViewFieldsToCreate,
|
||||
...flatDefaultRecordPageLayoutsToCreate.recordPageFieldsViewFields,
|
||||
...flatRecordPageFieldsViewFieldsToCreate,
|
||||
],
|
||||
flatEntityToDelete: [],
|
||||
flatEntityToUpdate: [],
|
||||
@@ -697,10 +713,7 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
mainGroupByFieldMetadataUniversalIdentifier: null,
|
||||
openRecordIn: ViewOpenRecordIn.SIDE_PANEL,
|
||||
position: 0,
|
||||
universalIdentifier: getIndexViewUniversalIdentifier({
|
||||
applicationUniversalIdentifier: flatApplication.universalIdentifier,
|
||||
objectUniversalIdentifier: objectMetadata.universalIdentifier,
|
||||
}),
|
||||
universalIdentifier: v4(),
|
||||
visibility: ViewVisibility.WORKSPACE,
|
||||
createdByUserWorkspaceId: null,
|
||||
isActive: true,
|
||||
@@ -716,6 +729,42 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
};
|
||||
}
|
||||
|
||||
private computeFlatRecordPageFieldsViewToCreate({
|
||||
objectMetadata,
|
||||
flatApplication,
|
||||
}: {
|
||||
flatApplication: FlatApplication;
|
||||
objectMetadata: UniversalFlatObjectMetadata & { id: string };
|
||||
}): UniversalFlatView & { id: string } {
|
||||
return computeFlatRecordPageFieldsViewToCreate({
|
||||
objectMetadata,
|
||||
flatApplication,
|
||||
});
|
||||
}
|
||||
|
||||
private computeFlatDefaultRecordPageLayoutToCreate({
|
||||
objectMetadata,
|
||||
flatApplication,
|
||||
recordPageFieldsView,
|
||||
workspaceId,
|
||||
}: {
|
||||
flatApplication: FlatApplication;
|
||||
objectMetadata: UniversalFlatObjectMetadata & { id: string };
|
||||
recordPageFieldsView: UniversalFlatView & { id: string };
|
||||
workspaceId: string;
|
||||
}): {
|
||||
pageLayouts: FlatPageLayout[];
|
||||
pageLayoutTabs: FlatPageLayoutTab[];
|
||||
pageLayoutWidgets: FlatPageLayoutWidget[];
|
||||
} {
|
||||
return computeFlatDefaultRecordPageLayoutToCreate({
|
||||
objectMetadata,
|
||||
flatApplication,
|
||||
recordPageFieldsView,
|
||||
workspaceId,
|
||||
});
|
||||
}
|
||||
|
||||
private async computeFlatNavigationMenuItemToCreate({
|
||||
objectMetadata,
|
||||
workspaceId,
|
||||
@@ -814,29 +863,22 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
workspaceId,
|
||||
position: nextPosition,
|
||||
now: new Date().toISOString(),
|
||||
universalIdentifier: getNavigationCommandUniversalIdentifier({
|
||||
applicationUniversalIdentifier,
|
||||
objectUniversalIdentifier: objectMetadata.universalIdentifier,
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
private findNavigationCommandMenuItemForObject({
|
||||
objectUniversalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
flatCommandMenuItemMaps,
|
||||
}: {
|
||||
objectUniversalIdentifier: string;
|
||||
applicationUniversalIdentifier: string;
|
||||
flatCommandMenuItemMaps: {
|
||||
byUniversalIdentifier: Record<string, FlatCommandMenuItem | undefined>;
|
||||
};
|
||||
}): FlatCommandMenuItem | undefined {
|
||||
const commandMenuItemUniversalIdentifier =
|
||||
getNavigationCommandUniversalIdentifier({
|
||||
applicationUniversalIdentifier,
|
||||
objectUniversalIdentifier,
|
||||
});
|
||||
const commandMenuItemUniversalIdentifier = v5(
|
||||
objectUniversalIdentifier,
|
||||
NAVIGATION_COMMAND_UUID_NAMESPACE,
|
||||
);
|
||||
|
||||
return findFlatEntityByUniversalIdentifier({
|
||||
flatEntityMaps: flatCommandMenuItemMaps,
|
||||
@@ -877,8 +919,6 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
this.findNavigationCommandMenuItemForObject({
|
||||
objectUniversalIdentifier:
|
||||
existingFlatObjectMetadata.universalIdentifier,
|
||||
applicationUniversalIdentifier:
|
||||
existingFlatObjectMetadata.applicationUniversalIdentifier,
|
||||
flatCommandMenuItemMaps,
|
||||
});
|
||||
|
||||
@@ -912,8 +952,6 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
this.findNavigationCommandMenuItemForObject({
|
||||
objectUniversalIdentifier:
|
||||
existingFlatObjectMetadata.universalIdentifier,
|
||||
applicationUniversalIdentifier:
|
||||
existingFlatObjectMetadata.applicationUniversalIdentifier,
|
||||
flatCommandMenuItemMaps,
|
||||
});
|
||||
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@ const makeFieldMetadata = (
|
||||
};
|
||||
|
||||
const flatApplication = {
|
||||
universalIdentifier: '20202020-1111-4111-8111-111111111111',
|
||||
universalIdentifier: 'app-uid',
|
||||
id: 'app-id',
|
||||
} as never;
|
||||
|
||||
|
||||
+10
-21
@@ -1,5 +1,5 @@
|
||||
import { getFieldUniversalIdentifier } from 'twenty-shared/application';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { PARTIAL_SYSTEM_FLAT_FIELD_METADATAS } from 'src/engine/metadata-modules/object-metadata/constants/partial-system-flat-field-metadatas.constant';
|
||||
import { getTsVectorColumnExpressionFromFields } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
|
||||
@@ -40,17 +40,10 @@ const buildObjectSystemFlatFieldMetadatas = ({
|
||||
updatedBy,
|
||||
} = PARTIAL_SYSTEM_FLAT_FIELD_METADATAS;
|
||||
|
||||
const getSystemFieldUniversalIdentifier = (fieldName: string) =>
|
||||
getFieldUniversalIdentifier({
|
||||
applicationUniversalIdentifier,
|
||||
objectUniversalIdentifier: objectMetadataUniversalIdentifier,
|
||||
name: fieldName,
|
||||
});
|
||||
|
||||
return {
|
||||
id: {
|
||||
...id,
|
||||
universalIdentifier: getSystemFieldUniversalIdentifier(id.name),
|
||||
universalIdentifier: v4(),
|
||||
applicationUniversalIdentifier,
|
||||
objectMetadataUniversalIdentifier,
|
||||
createdAt: now,
|
||||
@@ -58,7 +51,7 @@ const buildObjectSystemFlatFieldMetadatas = ({
|
||||
},
|
||||
createdAt: {
|
||||
...createdAt,
|
||||
universalIdentifier: getSystemFieldUniversalIdentifier(createdAt.name),
|
||||
universalIdentifier: v4(),
|
||||
applicationUniversalIdentifier,
|
||||
objectMetadataUniversalIdentifier,
|
||||
createdAt: now,
|
||||
@@ -66,7 +59,7 @@ const buildObjectSystemFlatFieldMetadatas = ({
|
||||
},
|
||||
createdBy: {
|
||||
...createdBy,
|
||||
universalIdentifier: getSystemFieldUniversalIdentifier(createdBy.name),
|
||||
universalIdentifier: v4(),
|
||||
applicationUniversalIdentifier,
|
||||
objectMetadataUniversalIdentifier,
|
||||
createdAt: now,
|
||||
@@ -74,7 +67,7 @@ const buildObjectSystemFlatFieldMetadatas = ({
|
||||
},
|
||||
deletedAt: {
|
||||
...deletedAt,
|
||||
universalIdentifier: getSystemFieldUniversalIdentifier(deletedAt.name),
|
||||
universalIdentifier: v4(),
|
||||
applicationUniversalIdentifier,
|
||||
objectMetadataUniversalIdentifier,
|
||||
createdAt: now,
|
||||
@@ -82,7 +75,7 @@ const buildObjectSystemFlatFieldMetadatas = ({
|
||||
},
|
||||
position: {
|
||||
...position,
|
||||
universalIdentifier: getSystemFieldUniversalIdentifier(position.name),
|
||||
universalIdentifier: v4(),
|
||||
applicationUniversalIdentifier,
|
||||
objectMetadataUniversalIdentifier,
|
||||
createdAt: now,
|
||||
@@ -90,7 +83,7 @@ const buildObjectSystemFlatFieldMetadatas = ({
|
||||
},
|
||||
searchVector: {
|
||||
...searchVector,
|
||||
universalIdentifier: getSystemFieldUniversalIdentifier(searchVector.name),
|
||||
universalIdentifier: v4(),
|
||||
applicationUniversalIdentifier,
|
||||
objectMetadataUniversalIdentifier,
|
||||
createdAt: now,
|
||||
@@ -99,7 +92,7 @@ const buildObjectSystemFlatFieldMetadatas = ({
|
||||
},
|
||||
updatedAt: {
|
||||
...updatedAt,
|
||||
universalIdentifier: getSystemFieldUniversalIdentifier(updatedAt.name),
|
||||
universalIdentifier: v4(),
|
||||
applicationUniversalIdentifier,
|
||||
objectMetadataUniversalIdentifier,
|
||||
createdAt: now,
|
||||
@@ -107,7 +100,7 @@ const buildObjectSystemFlatFieldMetadatas = ({
|
||||
},
|
||||
updatedBy: {
|
||||
...updatedBy,
|
||||
universalIdentifier: getSystemFieldUniversalIdentifier(updatedBy.name),
|
||||
universalIdentifier: v4(),
|
||||
applicationUniversalIdentifier,
|
||||
objectMetadataUniversalIdentifier,
|
||||
createdAt: now,
|
||||
@@ -133,11 +126,7 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
||||
type: FieldMetadataType.TEXT,
|
||||
isLabelSyncedWithName: false,
|
||||
isUnique: false,
|
||||
universalIdentifier: getFieldUniversalIdentifier({
|
||||
applicationUniversalIdentifier,
|
||||
objectUniversalIdentifier: objectMetadataUniversalIdentifier,
|
||||
name: 'name',
|
||||
}),
|
||||
universalIdentifier: v4(),
|
||||
name: 'name',
|
||||
label: 'Name',
|
||||
icon: 'IconAbc',
|
||||
|
||||
+35
-27
@@ -1,5 +1,7 @@
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { IndexType } from 'src/engine/metadata-modules/index-metadata/types/indexType.types';
|
||||
import { generateFlatIndexMetadataWithDeterministicUniversalIdentifierOrThrow } from 'src/engine/metadata-modules/index-metadata/utils/generate-flat-index-metadata-with-deterministic-universal-identifier.util';
|
||||
import { generateFlatIndexMetadataWithNameOrThrow } from 'src/engine/metadata-modules/index-metadata/utils/generate-flat-index.util';
|
||||
import { type DefaultFlatFieldForCustomObjectMaps } from 'src/engine/metadata-modules/object-metadata/utils/build-default-flat-field-metadatas-for-custom-object.util';
|
||||
import { type UniversalFlatFieldMetadata } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-field-metadata.type';
|
||||
import { type UniversalFlatIndexMetadata } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-index-metadata.type';
|
||||
@@ -14,33 +16,39 @@ export const buildDefaultIndexesForCustomObject = ({
|
||||
objectFlatFieldMetadatas: UniversalFlatFieldMetadata[];
|
||||
defaultFlatFieldForCustomObjectMaps: DefaultFlatFieldForCustomObjectMaps;
|
||||
}) => {
|
||||
const createdAt = new Date().toISOString();
|
||||
const tsFlatVectorIndexUniversalIdentifier = v4();
|
||||
const createdAt = new Date();
|
||||
const tsVectorFlatIndex = generateFlatIndexMetadataWithNameOrThrow({
|
||||
objectFlatFieldMetadatas,
|
||||
flatIndex: {
|
||||
createdAt: createdAt.toISOString(),
|
||||
universalFlatIndexFieldMetadatas: [
|
||||
{
|
||||
createdAt: createdAt.toISOString(),
|
||||
fieldMetadataUniversalIdentifier:
|
||||
defaultFlatFieldForCustomObjectMaps.fields.searchVector
|
||||
.universalIdentifier,
|
||||
indexMetadataUniversalIdentifier:
|
||||
tsFlatVectorIndexUniversalIdentifier,
|
||||
order: 0,
|
||||
subFieldName: null,
|
||||
updatedAt: createdAt.toISOString(),
|
||||
},
|
||||
],
|
||||
|
||||
const tsVectorFlatIndex =
|
||||
generateFlatIndexMetadataWithDeterministicUniversalIdentifierOrThrow({
|
||||
flatObjectMetadata,
|
||||
objectFlatFieldMetadatas,
|
||||
flatIndex: {
|
||||
createdAt,
|
||||
updatedAt: createdAt,
|
||||
universalFlatIndexFieldMetadatas: [
|
||||
{
|
||||
createdAt,
|
||||
updatedAt: createdAt,
|
||||
fieldMetadataUniversalIdentifier:
|
||||
defaultFlatFieldForCustomObjectMaps.fields.searchVector
|
||||
.universalIdentifier,
|
||||
order: 0,
|
||||
subFieldName: null,
|
||||
},
|
||||
],
|
||||
indexType: IndexType.GIN,
|
||||
indexWhereClause: null,
|
||||
isCustom: false,
|
||||
isUnique: false,
|
||||
isSystemSideEffect: true,
|
||||
},
|
||||
});
|
||||
indexType: IndexType.GIN,
|
||||
indexWhereClause: null,
|
||||
isCustom: false,
|
||||
isUnique: false,
|
||||
isSystemSideEffect: true,
|
||||
objectMetadataUniversalIdentifier: flatObjectMetadata.universalIdentifier,
|
||||
universalIdentifier: tsFlatVectorIndexUniversalIdentifier,
|
||||
updatedAt: createdAt.toISOString(),
|
||||
applicationUniversalIdentifier:
|
||||
flatObjectMetadata.applicationUniversalIdentifier,
|
||||
},
|
||||
flatObjectMetadata,
|
||||
});
|
||||
|
||||
return {
|
||||
indexes: {
|
||||
|
||||
+30
-85
@@ -1,52 +1,36 @@
|
||||
import {
|
||||
getPageLayoutTabUniversalIdentifier,
|
||||
getPageLayoutWidgetUniversalIdentifier,
|
||||
getRecordPageLayoutUniversalIdentifier,
|
||||
} from 'twenty-shared/application';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { type FlatPageLayoutTab } from 'src/engine/metadata-modules/flat-page-layout-tab/types/flat-page-layout-tab.type';
|
||||
import { type FlatPageLayoutWidget } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget.type';
|
||||
import { type FlatPageLayout } from 'src/engine/metadata-modules/flat-page-layout/types/flat-page-layout.type';
|
||||
import { computeFlatRecordPageFieldsViewToCreate } from 'src/engine/metadata-modules/object-metadata/utils/compute-flat-record-page-fields-view-to-create.util';
|
||||
import { computeFlatViewFieldsToCreate } from 'src/engine/metadata-modules/object-metadata/utils/compute-flat-view-fields-to-create.util';
|
||||
import { WidgetConfigurationType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-configuration-type.type';
|
||||
import { PageLayoutType } from 'src/engine/metadata-modules/page-layout/enums/page-layout-type.enum';
|
||||
import {
|
||||
TAB_PROPS,
|
||||
WIDGET_PROPS,
|
||||
} from 'src/engine/workspace-manager/twenty-standard-application/constants/standard-page-layout-tabs.template';
|
||||
import { type UniversalFlatFieldMetadata } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-field-metadata.type';
|
||||
import { type UniversalFlatObjectMetadata } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-object-metadata.type';
|
||||
import { type UniversalFlatView } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-view.type';
|
||||
import { type UniversalFlatViewField } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-view-field.type';
|
||||
|
||||
export const computeFlatDefaultRecordPageLayoutToCreate = ({
|
||||
objectMetadata,
|
||||
flatApplication,
|
||||
objectFlatFieldMetadatas,
|
||||
labelIdentifierFieldMetadataUniversalIdentifier,
|
||||
recordPageFieldsView,
|
||||
workspaceId,
|
||||
}: {
|
||||
flatApplication: FlatApplication;
|
||||
objectMetadata: UniversalFlatObjectMetadata & { id: string };
|
||||
objectFlatFieldMetadatas: UniversalFlatFieldMetadata[];
|
||||
labelIdentifierFieldMetadataUniversalIdentifier: string | null;
|
||||
recordPageFieldsView: UniversalFlatView & { id: string };
|
||||
workspaceId: string;
|
||||
}): {
|
||||
pageLayouts: FlatPageLayout[];
|
||||
pageLayoutTabs: FlatPageLayoutTab[];
|
||||
pageLayoutWidgets: FlatPageLayoutWidget[];
|
||||
recordPageFieldsView: UniversalFlatView & { id: string };
|
||||
recordPageFieldsViewFields: UniversalFlatViewField[];
|
||||
} => {
|
||||
const now = new Date().toISOString();
|
||||
const pageLayoutId = v4();
|
||||
const pageLayoutUniversalIdentifier = getRecordPageLayoutUniversalIdentifier({
|
||||
applicationUniversalIdentifier: flatApplication.universalIdentifier,
|
||||
objectUniversalIdentifier: objectMetadata.universalIdentifier,
|
||||
});
|
||||
const pageLayoutUniversalIdentifier = v4();
|
||||
|
||||
const tabDefinitions = [
|
||||
{ key: 'home' as const, widgetKey: 'fields' as const },
|
||||
@@ -58,24 +42,14 @@ export const computeFlatDefaultRecordPageLayoutToCreate = ({
|
||||
|
||||
const pageLayoutTabs: FlatPageLayoutTab[] = [];
|
||||
const pageLayoutWidgets: FlatPageLayoutWidget[] = [];
|
||||
let recordPageFieldsView: (UniversalFlatView & { id: string }) | undefined;
|
||||
let recordPageFieldsViewFields: UniversalFlatViewField[] = [];
|
||||
|
||||
for (const { key, widgetKey } of tabDefinitions) {
|
||||
const tabProps = TAB_PROPS[key];
|
||||
const widgetProps = WIDGET_PROPS[widgetKey];
|
||||
const tabId = v4();
|
||||
const tabUniversalIdentifier = getPageLayoutTabUniversalIdentifier({
|
||||
applicationUniversalIdentifier: flatApplication.universalIdentifier,
|
||||
pageLayoutUniversalIdentifier,
|
||||
title: tabProps.title,
|
||||
});
|
||||
const tabUniversalIdentifier = v4();
|
||||
const widgetId = v4();
|
||||
const widgetUniversalIdentifier = getPageLayoutWidgetUniversalIdentifier({
|
||||
applicationUniversalIdentifier: flatApplication.universalIdentifier,
|
||||
pageLayoutTabUniversalIdentifier: tabUniversalIdentifier,
|
||||
title: widgetProps.title,
|
||||
});
|
||||
const widgetUniversalIdentifier = v4();
|
||||
|
||||
pageLayoutTabs.push({
|
||||
id: tabId,
|
||||
@@ -101,48 +75,31 @@ export const computeFlatDefaultRecordPageLayoutToCreate = ({
|
||||
|
||||
const isFieldsWidget = widgetKey === 'fields';
|
||||
|
||||
if (isFieldsWidget) {
|
||||
recordPageFieldsView = computeFlatRecordPageFieldsViewToCreate({
|
||||
objectMetadata,
|
||||
flatApplication,
|
||||
pageLayoutWidgetUniversalIdentifier: widgetUniversalIdentifier,
|
||||
});
|
||||
recordPageFieldsViewFields = computeFlatViewFieldsToCreate({
|
||||
flatApplication,
|
||||
objectFlatFieldMetadatas,
|
||||
labelIdentifierFieldMetadataUniversalIdentifier,
|
||||
viewUniversalIdentifier: recordPageFieldsView.universalIdentifier,
|
||||
excludeLabelIdentifier: true,
|
||||
});
|
||||
}
|
||||
const configuration = isFieldsWidget
|
||||
? {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: recordPageFieldsView.id,
|
||||
newFieldDefaultVisibility: true,
|
||||
}
|
||||
: {
|
||||
configurationType:
|
||||
WidgetConfigurationType[
|
||||
widgetKey.toUpperCase() as keyof typeof WidgetConfigurationType
|
||||
],
|
||||
};
|
||||
|
||||
const configuration =
|
||||
isFieldsWidget && recordPageFieldsView
|
||||
? {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: recordPageFieldsView.id,
|
||||
newFieldDefaultVisibility: true,
|
||||
}
|
||||
: {
|
||||
configurationType:
|
||||
WidgetConfigurationType[
|
||||
widgetKey.toUpperCase() as keyof typeof WidgetConfigurationType
|
||||
],
|
||||
};
|
||||
|
||||
const universalConfiguration =
|
||||
isFieldsWidget && recordPageFieldsView
|
||||
? {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewUniversalIdentifier: recordPageFieldsView.universalIdentifier,
|
||||
newFieldDefaultVisibility: true,
|
||||
}
|
||||
: {
|
||||
configurationType:
|
||||
WidgetConfigurationType[
|
||||
widgetKey.toUpperCase() as keyof typeof WidgetConfigurationType
|
||||
],
|
||||
};
|
||||
const universalConfiguration = isFieldsWidget
|
||||
? {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewUniversalIdentifier: recordPageFieldsView.universalIdentifier,
|
||||
newFieldDefaultVisibility: true,
|
||||
}
|
||||
: {
|
||||
configurationType:
|
||||
WidgetConfigurationType[
|
||||
widgetKey.toUpperCase() as keyof typeof WidgetConfigurationType
|
||||
],
|
||||
};
|
||||
|
||||
pageLayoutWidgets.push({
|
||||
id: widgetId,
|
||||
@@ -172,12 +129,6 @@ export const computeFlatDefaultRecordPageLayoutToCreate = ({
|
||||
});
|
||||
}
|
||||
|
||||
if (!recordPageFieldsView) {
|
||||
throw new Error(
|
||||
'Record page fields widget is missing from the default record page layout',
|
||||
);
|
||||
}
|
||||
|
||||
const pageLayout: FlatPageLayout = {
|
||||
id: pageLayoutId,
|
||||
universalIdentifier: pageLayoutUniversalIdentifier,
|
||||
@@ -200,11 +151,5 @@ export const computeFlatDefaultRecordPageLayoutToCreate = ({
|
||||
defaultTabToFocusOnMobileAndSidePanelUniversalIdentifier: null,
|
||||
};
|
||||
|
||||
return {
|
||||
pageLayouts: [pageLayout],
|
||||
pageLayoutTabs,
|
||||
pageLayoutWidgets,
|
||||
recordPageFieldsView,
|
||||
recordPageFieldsViewFields,
|
||||
};
|
||||
return { pageLayouts: [pageLayout], pageLayoutTabs, pageLayoutWidgets };
|
||||
};
|
||||
|
||||
+1
-7
@@ -1,4 +1,3 @@
|
||||
import { getFieldsWidgetViewUniversalIdentifier } from 'twenty-shared/application';
|
||||
import {
|
||||
ViewOpenRecordIn,
|
||||
ViewType,
|
||||
@@ -13,11 +12,9 @@ import { type UniversalFlatView } from 'src/engine/workspace-manager/workspace-m
|
||||
export const computeFlatRecordPageFieldsViewToCreate = ({
|
||||
objectMetadata,
|
||||
flatApplication,
|
||||
pageLayoutWidgetUniversalIdentifier,
|
||||
}: {
|
||||
flatApplication: FlatApplication;
|
||||
objectMetadata: UniversalFlatObjectMetadata & { id: string };
|
||||
pageLayoutWidgetUniversalIdentifier: string;
|
||||
}): UniversalFlatView & { id: string } => {
|
||||
const createdAt = new Date().toISOString();
|
||||
|
||||
@@ -43,10 +40,7 @@ export const computeFlatRecordPageFieldsViewToCreate = ({
|
||||
mainGroupByFieldMetadataUniversalIdentifier: null,
|
||||
openRecordIn: ViewOpenRecordIn.SIDE_PANEL,
|
||||
position: 0,
|
||||
universalIdentifier: getFieldsWidgetViewUniversalIdentifier({
|
||||
applicationUniversalIdentifier: flatApplication.universalIdentifier,
|
||||
pageLayoutWidgetUniversalIdentifier,
|
||||
}),
|
||||
universalIdentifier: v4(),
|
||||
visibility: ViewVisibility.WORKSPACE,
|
||||
createdByUserWorkspaceId: null,
|
||||
isActive: true,
|
||||
|
||||
+2
-6
@@ -1,4 +1,4 @@
|
||||
import { getViewFieldUniversalIdentifier } from 'twenty-shared/application';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { DEFAULT_VIEW_FIELD_SIZE } from 'src/engine/metadata-modules/flat-view-field/constants/default-view-field-size.constant';
|
||||
@@ -59,11 +59,7 @@ export const computeFlatViewFieldsToCreate = ({
|
||||
createdAt,
|
||||
updatedAt: createdAt,
|
||||
deletedAt: null,
|
||||
universalIdentifier: getViewFieldUniversalIdentifier({
|
||||
applicationUniversalIdentifier: flatApplication.universalIdentifier,
|
||||
viewUniversalIdentifier,
|
||||
fieldMetadataUniversalIdentifier: field.universalIdentifier,
|
||||
}),
|
||||
universalIdentifier: v4(),
|
||||
isVisible: true,
|
||||
size: DEFAULT_VIEW_FIELD_SIZE,
|
||||
position: index,
|
||||
|
||||
+1
-9
@@ -1,7 +1,4 @@
|
||||
import {
|
||||
getNavigationCommandUniversalIdentifier,
|
||||
TWENTY_STANDARD_APPLICATION_UNIVERSAL_IDENTIFIER,
|
||||
} from 'twenty-shared/application';
|
||||
import { TWENTY_STANDARD_APPLICATION_UNIVERSAL_IDENTIFIER } from 'twenty-shared/application';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
@@ -81,11 +78,6 @@ export const buildStandardFlatCommandMenuItemMaps = ({
|
||||
workspaceId,
|
||||
position,
|
||||
now,
|
||||
universalIdentifier: getNavigationCommandUniversalIdentifier({
|
||||
applicationUniversalIdentifier:
|
||||
TWENTY_STANDARD_APPLICATION_UNIVERSAL_IDENTIFIER,
|
||||
objectUniversalIdentifier: flatObject.universalIdentifier,
|
||||
}),
|
||||
});
|
||||
|
||||
addFlatEntityToFlatEntityMapsThroughMutationOrThrow({
|
||||
|
||||
+40
-6
@@ -1,19 +1,53 @@
|
||||
import {
|
||||
getCommandMenuItemUniversalIdentifier,
|
||||
getGlobalCommandMenuItemUniversalIdentifier,
|
||||
getGlobalObjectContextCommandMenuItemUniversalIdentifier,
|
||||
getNavigationCommandUniversalIdentifier,
|
||||
getRecordSelectionCommandMenuItemUniversalIdentifier,
|
||||
} from '@/application/deterministic-identifier/get-command-menu-item-universal-identifier.util';
|
||||
|
||||
const APP = '11111111-1111-4111-8111-111111111111';
|
||||
const OBJECT = '22222222-2222-4222-8222-222222222222';
|
||||
|
||||
describe('getCommandMenuItemUniversalIdentifier', () => {
|
||||
it('derives a deterministic id from the command label within its application', () => {
|
||||
describe('getGlobalCommandMenuItemUniversalIdentifier', () => {
|
||||
it('derives a deterministic id from the engineComponentKey within GLOBAL', () => {
|
||||
expect(
|
||||
getCommandMenuItemUniversalIdentifier({
|
||||
getGlobalCommandMenuItemUniversalIdentifier({
|
||||
applicationUniversalIdentifier: APP,
|
||||
label: 'Create Record',
|
||||
engineComponentKey: 'EXPORT_RECORDS',
|
||||
}),
|
||||
).toBe('e284adf7-5332-5253-9c94-9e6b3c57237f');
|
||||
).toBe('bba78a2e-c117-52af-b25d-126702e8cf57');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getGlobalObjectContextCommandMenuItemUniversalIdentifier', () => {
|
||||
it('derives a deterministic id from the engineComponentKey within GLOBAL_OBJECT_CONTEXT', () => {
|
||||
expect(
|
||||
getGlobalObjectContextCommandMenuItemUniversalIdentifier({
|
||||
applicationUniversalIdentifier: APP,
|
||||
engineComponentKey: 'CREATE_NEW_RECORD',
|
||||
}),
|
||||
).toBe('77fb3fcd-ee35-50ea-9c3c-ab95cef5e0e2');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getRecordSelectionCommandMenuItemUniversalIdentifier', () => {
|
||||
it('includes the target object when scoped to one', () => {
|
||||
expect(
|
||||
getRecordSelectionCommandMenuItemUniversalIdentifier({
|
||||
applicationUniversalIdentifier: APP,
|
||||
engineComponentKey: 'COMPOSE_EMAIL',
|
||||
objectUniversalIdentifier: OBJECT,
|
||||
}),
|
||||
).toBe('dd10a2b1-229b-572a-a887-ea20e487cfd3');
|
||||
});
|
||||
|
||||
it('omits the object for object-agnostic record-selection commands', () => {
|
||||
expect(
|
||||
getRecordSelectionCommandMenuItemUniversalIdentifier({
|
||||
applicationUniversalIdentifier: APP,
|
||||
engineComponentKey: 'DELETE_RECORDS',
|
||||
}),
|
||||
).toBe('36b20ed1-6172-5da5-9a21-58de9c8acb22');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
+46
-6
@@ -1,14 +1,54 @@
|
||||
import { getNavigationMenuItemUniversalIdentifier } from '@/application/deterministic-identifier/get-navigation-menu-item-universal-identifier.util';
|
||||
import {
|
||||
getFolderNavigationMenuItemUniversalIdentifier,
|
||||
getLinkNavigationMenuItemUniversalIdentifier,
|
||||
getObjectNavigationMenuItemUniversalIdentifier,
|
||||
getViewNavigationMenuItemUniversalIdentifier,
|
||||
} from '@/application/deterministic-identifier/get-navigation-menu-item-universal-identifier.util';
|
||||
|
||||
const APP = '11111111-1111-4111-8111-111111111111';
|
||||
const OBJECT = '22222222-2222-4222-8222-222222222222';
|
||||
const VIEW = '44444444-4444-4444-8444-444444444444';
|
||||
|
||||
describe('getNavigationMenuItemUniversalIdentifier', () => {
|
||||
it('derives a deterministic id from the item name within its application', () => {
|
||||
describe('getFolderNavigationMenuItemUniversalIdentifier', () => {
|
||||
it('derives a deterministic id from the folder name within its application', () => {
|
||||
expect(
|
||||
getNavigationMenuItemUniversalIdentifier({
|
||||
getFolderNavigationMenuItemUniversalIdentifier({
|
||||
applicationUniversalIdentifier: APP,
|
||||
name: 'Home',
|
||||
name: 'Workflows',
|
||||
}),
|
||||
).toBe('dc0ca522-7f09-567d-a7f7-d33824495fc4');
|
||||
).toBe('ca043c51-ac75-515d-902b-dd836626bba4');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getObjectNavigationMenuItemUniversalIdentifier', () => {
|
||||
it('derives a deterministic id from the object it targets', () => {
|
||||
expect(
|
||||
getObjectNavigationMenuItemUniversalIdentifier({
|
||||
applicationUniversalIdentifier: APP,
|
||||
objectUniversalIdentifier: OBJECT,
|
||||
}),
|
||||
).toBe('071361bd-47c8-5513-be33-998dd287f8c7');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getViewNavigationMenuItemUniversalIdentifier', () => {
|
||||
it('derives a deterministic id from the view it targets', () => {
|
||||
expect(
|
||||
getViewNavigationMenuItemUniversalIdentifier({
|
||||
applicationUniversalIdentifier: APP,
|
||||
viewUniversalIdentifier: VIEW,
|
||||
}),
|
||||
).toBe('6504fd6d-ed38-5f34-87fc-26025130260f');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getLinkNavigationMenuItemUniversalIdentifier', () => {
|
||||
it('derives a deterministic id from its target URL', () => {
|
||||
expect(
|
||||
getLinkNavigationMenuItemUniversalIdentifier({
|
||||
applicationUniversalIdentifier: APP,
|
||||
link: 'https://example.com',
|
||||
}),
|
||||
).toBe('635cef97-cc61-53a3-873e-38fecf3ecbd7');
|
||||
});
|
||||
});
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
import { getSearchFieldUniversalIdentifier } from '@/application/deterministic-identifier/get-search-field-universal-identifier.util';
|
||||
|
||||
const APP = '11111111-1111-4111-8111-111111111111';
|
||||
const FIELD = '33333333-3333-4333-8333-333333333333';
|
||||
|
||||
describe('getSearchFieldUniversalIdentifier', () => {
|
||||
it('derives a deterministic id from the field it makes searchable', () => {
|
||||
expect(
|
||||
getSearchFieldUniversalIdentifier({
|
||||
applicationUniversalIdentifier: APP,
|
||||
fieldMetadataUniversalIdentifier: FIELD,
|
||||
}),
|
||||
).toBe('db4e5b93-15b6-5c83-a0b3-6c031e0ca072');
|
||||
});
|
||||
});
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
import { getViewFieldGroupUniversalIdentifier } from '@/application/deterministic-identifier/get-view-field-group-universal-identifier.util';
|
||||
|
||||
const APP = '11111111-1111-4111-8111-111111111111';
|
||||
const VIEW = '44444444-4444-4444-8444-444444444444';
|
||||
|
||||
describe('getViewFieldGroupUniversalIdentifier', () => {
|
||||
it('derives a deterministic id from the group name within its view', () => {
|
||||
expect(
|
||||
getViewFieldGroupUniversalIdentifier({
|
||||
applicationUniversalIdentifier: APP,
|
||||
viewUniversalIdentifier: VIEW,
|
||||
name: 'General',
|
||||
}),
|
||||
).toBe('26350cf1-bec3-5617-b525-c0115811963e');
|
||||
});
|
||||
});
|
||||
+43
-6
@@ -2,18 +2,55 @@ import { computeDeterministicUuid } from '@/application/deterministic-identifier
|
||||
|
||||
const NAVIGATION_COMMAND_DISCRIMINATOR = 'navigation';
|
||||
|
||||
// A command menu item is identified by its label within its application
|
||||
// (not every command is backed by a front component).
|
||||
export const getCommandMenuItemUniversalIdentifier = ({
|
||||
// A command menu item is identified by its availabilityType + engineComponentKey
|
||||
// (the same engineComponentKey is reused across availability types and, for
|
||||
// RECORD_SELECTION, across objects). One util per availabilityType, prefixed by
|
||||
// the type, with the target object added only for RECORD_SELECTION.
|
||||
|
||||
// GLOBAL: a command available everywhere, identified by its engineComponentKey.
|
||||
export const getGlobalCommandMenuItemUniversalIdentifier = ({
|
||||
applicationUniversalIdentifier,
|
||||
label,
|
||||
engineComponentKey,
|
||||
}: {
|
||||
applicationUniversalIdentifier: string;
|
||||
label: string;
|
||||
engineComponentKey: string;
|
||||
}): string =>
|
||||
computeDeterministicUuid({
|
||||
entityNamespace: 'commandMenuItem',
|
||||
value: label,
|
||||
value: `GLOBAL:${engineComponentKey}`,
|
||||
applicationUniversalIdentifier,
|
||||
});
|
||||
|
||||
// GLOBAL_OBJECT_CONTEXT: a command whose object is resolved at runtime (not stored),
|
||||
// identified by its engineComponentKey.
|
||||
export const getGlobalObjectContextCommandMenuItemUniversalIdentifier = ({
|
||||
applicationUniversalIdentifier,
|
||||
engineComponentKey,
|
||||
}: {
|
||||
applicationUniversalIdentifier: string;
|
||||
engineComponentKey: string;
|
||||
}): string =>
|
||||
computeDeterministicUuid({
|
||||
entityNamespace: 'commandMenuItem',
|
||||
value: `GLOBAL_OBJECT_CONTEXT:${engineComponentKey}`,
|
||||
applicationUniversalIdentifier,
|
||||
});
|
||||
|
||||
// RECORD_SELECTION: a command acting on selected records; the same engineComponentKey
|
||||
// is replicated per object, so the target object is part of the identity
|
||||
// (null/absent for the object-agnostic record-selection commands).
|
||||
export const getRecordSelectionCommandMenuItemUniversalIdentifier = ({
|
||||
applicationUniversalIdentifier,
|
||||
engineComponentKey,
|
||||
objectUniversalIdentifier,
|
||||
}: {
|
||||
applicationUniversalIdentifier: string;
|
||||
engineComponentKey: string;
|
||||
objectUniversalIdentifier?: string | null;
|
||||
}): string =>
|
||||
computeDeterministicUuid({
|
||||
entityNamespace: 'commandMenuItem',
|
||||
value: `RECORD_SELECTION:${engineComponentKey}:${objectUniversalIdentifier ?? ''}`,
|
||||
applicationUniversalIdentifier,
|
||||
});
|
||||
|
||||
|
||||
+50
-3
@@ -1,7 +1,12 @@
|
||||
import { computeDeterministicUuid } from '@/application/deterministic-identifier/compute-deterministic-uuid.util';
|
||||
|
||||
// A navigation menu item is identified by its name within its application.
|
||||
export const getNavigationMenuItemUniversalIdentifier = ({
|
||||
// NavigationMenuItem is a single polymorphic entity: every variant shares
|
||||
// name/icon/color/position/folder, but each type is identified by a different
|
||||
// target, so each variant has its own discriminator (prefixed by the type to
|
||||
// keep the shared `navigationMenuItem` namespace collision-free).
|
||||
|
||||
// A FOLDER navigation item is identified by its name within its application.
|
||||
export const getFolderNavigationMenuItemUniversalIdentifier = ({
|
||||
applicationUniversalIdentifier,
|
||||
name,
|
||||
}: {
|
||||
@@ -10,6 +15,48 @@ export const getNavigationMenuItemUniversalIdentifier = ({
|
||||
}): string =>
|
||||
computeDeterministicUuid({
|
||||
entityNamespace: 'navigationMenuItem',
|
||||
value: name,
|
||||
value: `FOLDER:${name}`,
|
||||
applicationUniversalIdentifier,
|
||||
});
|
||||
|
||||
// An OBJECT navigation item is identified by the object it targets.
|
||||
export const getObjectNavigationMenuItemUniversalIdentifier = ({
|
||||
applicationUniversalIdentifier,
|
||||
objectUniversalIdentifier,
|
||||
}: {
|
||||
applicationUniversalIdentifier: string;
|
||||
objectUniversalIdentifier: string;
|
||||
}): string =>
|
||||
computeDeterministicUuid({
|
||||
entityNamespace: 'navigationMenuItem',
|
||||
value: `OBJECT:${objectUniversalIdentifier}`,
|
||||
applicationUniversalIdentifier,
|
||||
});
|
||||
|
||||
// A VIEW navigation item is identified by the view it targets.
|
||||
export const getViewNavigationMenuItemUniversalIdentifier = ({
|
||||
applicationUniversalIdentifier,
|
||||
viewUniversalIdentifier,
|
||||
}: {
|
||||
applicationUniversalIdentifier: string;
|
||||
viewUniversalIdentifier: string;
|
||||
}): string =>
|
||||
computeDeterministicUuid({
|
||||
entityNamespace: 'navigationMenuItem',
|
||||
value: `VIEW:${viewUniversalIdentifier}`,
|
||||
applicationUniversalIdentifier,
|
||||
});
|
||||
|
||||
// A LINK navigation item is identified by its target URL.
|
||||
export const getLinkNavigationMenuItemUniversalIdentifier = ({
|
||||
applicationUniversalIdentifier,
|
||||
link,
|
||||
}: {
|
||||
applicationUniversalIdentifier: string;
|
||||
link: string;
|
||||
}): string =>
|
||||
computeDeterministicUuid({
|
||||
entityNamespace: 'navigationMenuItem',
|
||||
value: `LINK:${link}`,
|
||||
applicationUniversalIdentifier,
|
||||
});
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
import { computeDeterministicUuid } from '@/application/deterministic-identifier/compute-deterministic-uuid.util';
|
||||
|
||||
// A search field is 1:1 with the field it makes searchable, so it is keyed by that field.
|
||||
export const getSearchFieldUniversalIdentifier = ({
|
||||
applicationUniversalIdentifier,
|
||||
fieldMetadataUniversalIdentifier,
|
||||
}: {
|
||||
applicationUniversalIdentifier: string;
|
||||
fieldMetadataUniversalIdentifier: string;
|
||||
}): string =>
|
||||
computeDeterministicUuid({
|
||||
entityNamespace: 'searchFieldMetadata',
|
||||
value: fieldMetadataUniversalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
});
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import { computeDeterministicUuid } from '@/application/deterministic-identifier/compute-deterministic-uuid.util';
|
||||
|
||||
// A view field group is identified by its name within its view.
|
||||
export const getViewFieldGroupUniversalIdentifier = ({
|
||||
applicationUniversalIdentifier,
|
||||
viewUniversalIdentifier,
|
||||
name,
|
||||
}: {
|
||||
applicationUniversalIdentifier: string;
|
||||
viewUniversalIdentifier: string;
|
||||
name: string;
|
||||
}): string =>
|
||||
computeDeterministicUuid({
|
||||
entityNamespace: 'viewFieldGroup',
|
||||
value: `${viewUniversalIdentifier}:${name}`,
|
||||
applicationUniversalIdentifier,
|
||||
});
|
||||
@@ -31,7 +31,9 @@ export type { DeterministicEntityNamespace } from './deterministic-identifier/de
|
||||
export { getAgentUniversalIdentifier } from './deterministic-identifier/get-agent-universal-identifier.util';
|
||||
export { getApplicationVariableUniversalIdentifier } from './deterministic-identifier/get-application-variable-universal-identifier.util';
|
||||
export {
|
||||
getCommandMenuItemUniversalIdentifier,
|
||||
getGlobalCommandMenuItemUniversalIdentifier,
|
||||
getGlobalObjectContextCommandMenuItemUniversalIdentifier,
|
||||
getRecordSelectionCommandMenuItemUniversalIdentifier,
|
||||
getNavigationCommandUniversalIdentifier,
|
||||
} from './deterministic-identifier/get-command-menu-item-universal-identifier.util';
|
||||
export { getConnectionProviderUniversalIdentifier } from './deterministic-identifier/get-connection-provider-universal-identifier.util';
|
||||
@@ -40,7 +42,12 @@ export { getFieldUniversalIdentifier } from './deterministic-identifier/get-fiel
|
||||
export { getFrontComponentUniversalIdentifier } from './deterministic-identifier/get-front-component-universal-identifier.util';
|
||||
export { getIndexUniversalIdentifier } from './deterministic-identifier/get-index-universal-identifier.util';
|
||||
export { getLogicFunctionUniversalIdentifier } from './deterministic-identifier/get-logic-function-universal-identifier.util';
|
||||
export { getNavigationMenuItemUniversalIdentifier } from './deterministic-identifier/get-navigation-menu-item-universal-identifier.util';
|
||||
export {
|
||||
getFolderNavigationMenuItemUniversalIdentifier,
|
||||
getObjectNavigationMenuItemUniversalIdentifier,
|
||||
getViewNavigationMenuItemUniversalIdentifier,
|
||||
getLinkNavigationMenuItemUniversalIdentifier,
|
||||
} from './deterministic-identifier/get-navigation-menu-item-universal-identifier.util';
|
||||
export { getObjectPermissionUniversalIdentifier } from './deterministic-identifier/get-object-permission-universal-identifier.util';
|
||||
export { getObjectUniversalIdentifier } from './deterministic-identifier/get-object-universal-identifier.util';
|
||||
export { getPageLayoutTabUniversalIdentifier } from './deterministic-identifier/get-page-layout-tab-universal-identifier.util';
|
||||
@@ -52,8 +59,10 @@ export { getPageLayoutWidgetUniversalIdentifier } from './deterministic-identifi
|
||||
export { getPermissionFlagUniversalIdentifier } from './deterministic-identifier/get-permission-flag-universal-identifier.util';
|
||||
export { getRolePermissionFlagUniversalIdentifier } from './deterministic-identifier/get-role-permission-flag-universal-identifier.util';
|
||||
export { getRoleUniversalIdentifier } from './deterministic-identifier/get-role-universal-identifier.util';
|
||||
export { getSearchFieldUniversalIdentifier } from './deterministic-identifier/get-search-field-universal-identifier.util';
|
||||
export { getSelectOptionUniversalIdentifier } from './deterministic-identifier/get-select-option-universal-identifier.util';
|
||||
export { getSkillUniversalIdentifier } from './deterministic-identifier/get-skill-universal-identifier.util';
|
||||
export { getViewFieldGroupUniversalIdentifier } from './deterministic-identifier/get-view-field-group-universal-identifier.util';
|
||||
export { getViewFieldUniversalIdentifier } from './deterministic-identifier/get-view-field-universal-identifier.util';
|
||||
export { getViewFilterUniversalIdentifier } from './deterministic-identifier/get-view-filter-universal-identifier.util';
|
||||
export { getViewGroupUniversalIdentifier } from './deterministic-identifier/get-view-group-universal-identifier.util';
|
||||
|
||||
Reference in New Issue
Block a user