fix(server): preserve kanban/calendar fields in view manifest sync (#19946)
## Summary The `fromViewManifestToUniversalFlatView` converter hardcoded five view fields to `null` instead of reading them from the manifest: - `mainGroupByFieldMetadataUniversalIdentifier` - `kanbanAggregateOperation` - `kanbanAggregateOperationFieldMetadataUniversalIdentifier` - `calendarLayout` - `calendarFieldMetadataUniversalIdentifier` As a result **any** Kanban view in an app manifest is rejected by `validateFlatViewCreation` with `"Kanban view must have a main group by field"`, and any Calendar view would trip the `view.entity.ts` check constraint requiring `calendarLayout` + `calendarFieldMetadataId` to be non-null. Discovered while trying to install [`twenty-crm-meeting-baas`](https://github.com/Meeting-BaaS/twenty-crm-meeting-baas) which ships a Kanban view. ## Changes - **Server converter**: read all five fields from the manifest (with `?? null` fallback). - **`ViewManifest` type** (`twenty-shared`): add the five fields so SDK users can set them type-safely. - **Move `ViewCalendarLayout`** from `twenty-server` to `twenty-shared` so the manifest type can reference it. Seven import sites updated; the front-end imports via generated GraphQL types and is unaffected. - **Unit tests**: extend `from-view-manifest-to-universal-flat-view.util.spec.ts` with preservation + null-default cases for both Kanban and Calendar (5 tests total). - **Regression coverage**: add a Kanban view (`post-cards-by-status.view.ts`) to the `rich-app` fixture grouped by the existing `status` SELECT field. The existing `applications-install-delete-reinstall` e2e test now exercises the Kanban path end-to-end — a future regression here would fail CI. Note: `expected-manifest.ts` and the `views.length` assertion in `manifest.tests.ts` were updated to reflect the new fixture view. ## Test plan - [x] `nx test twenty-server -- from-view-manifest-to-universal-flat-view` → 5/5 pass - [x] `nx typecheck twenty-shared` / `twenty-sdk` / `twenty-server` → no new errors (one pre-existing unrelated error in `admin-panel.module-factory.ts`) - [x] `nx lint twenty-shared` / `twenty-sdk` → clean - [x] Manual install of the Meeting BaaS app on a dev workspace succeeds with the Kanban view after this fix - [ ] CI: SDK e2e `applications-install-delete-reinstall` passes against the new fixture view - [ ] CI: integration test `calendar-field-deactivation-deletes-views` still passes after the enum move 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
This commit is contained in:
@@ -13,6 +13,13 @@ export const POST_CARD_UNIVERSAL_IDENTIFIER =
|
||||
|
||||
export const CONTENT_FIELD_UNIVERSAL_IDENTIFIER =
|
||||
'58a0a314-d7ea-4865-9850-7fb84e72f30b';
|
||||
|
||||
export const STATUS_FIELD_UNIVERSAL_IDENTIFIER =
|
||||
'87b675b8-dd8c-4448-b4ca-20e5a2234a1e';
|
||||
|
||||
export const DELIVERED_AT_FIELD_UNIVERSAL_IDENTIFIER =
|
||||
'e06abe72-5b44-4e7f-93be-afc185a3c433';
|
||||
|
||||
export default defineObject({
|
||||
universalIdentifier: POST_CARD_UNIVERSAL_IDENTIFIER,
|
||||
nameSingular: 'postCard',
|
||||
@@ -47,7 +54,7 @@ export default defineObject({
|
||||
name: 'recipientAddress',
|
||||
},
|
||||
{
|
||||
universalIdentifier: '87b675b8-dd8c-4448-b4ca-20e5a2234a1e',
|
||||
universalIdentifier: STATUS_FIELD_UNIVERSAL_IDENTIFIER,
|
||||
type: FieldType.SELECT,
|
||||
label: 'Status',
|
||||
icon: 'IconSend',
|
||||
@@ -92,7 +99,7 @@ export default defineObject({
|
||||
name: 'status',
|
||||
},
|
||||
{
|
||||
universalIdentifier: 'e06abe72-5b44-4e7f-93be-afc185a3c433',
|
||||
universalIdentifier: DELIVERED_AT_FIELD_UNIVERSAL_IDENTIFIER,
|
||||
type: FieldType.DATE_TIME,
|
||||
label: 'Delivered at',
|
||||
icon: 'IconCheck',
|
||||
|
||||
@@ -2,6 +2,7 @@ import { defineView } from 'twenty-sdk/define';
|
||||
import {
|
||||
CONTENT_FIELD_UNIVERSAL_IDENTIFIER,
|
||||
POST_CARD_UNIVERSAL_IDENTIFIER,
|
||||
STATUS_FIELD_UNIVERSAL_IDENTIFIER,
|
||||
} from '../objects/post-card.object';
|
||||
import { ViewType } from 'twenty-shared/types';
|
||||
|
||||
@@ -24,7 +25,7 @@ export default defineView({
|
||||
},
|
||||
{
|
||||
universalIdentifier: 'bf1a2b3c-0002-4a7b-8c9d-0e1f2a3b4c5d',
|
||||
fieldMetadataUniversalIdentifier: '87b675b8-dd8c-4448-b4ca-20e5a2234a1e',
|
||||
fieldMetadataUniversalIdentifier: STATUS_FIELD_UNIVERSAL_IDENTIFIER,
|
||||
position: 1,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
import { defineView } from 'twenty-sdk/define';
|
||||
import { ViewCalendarLayout, ViewType } from 'twenty-shared/types';
|
||||
|
||||
import {
|
||||
CONTENT_FIELD_UNIVERSAL_IDENTIFIER,
|
||||
DELIVERED_AT_FIELD_UNIVERSAL_IDENTIFIER,
|
||||
POST_CARD_UNIVERSAL_IDENTIFIER,
|
||||
} from '../objects/post-card.object';
|
||||
|
||||
export const POST_CARDS_BY_DELIVERY_DATE_VIEW_ID =
|
||||
'b1a2b3c4-0005-4a7b-8c9d-0e1f2a3b4c5d';
|
||||
|
||||
export default defineView({
|
||||
universalIdentifier: POST_CARDS_BY_DELIVERY_DATE_VIEW_ID,
|
||||
name: 'By Delivery Date',
|
||||
objectUniversalIdentifier: POST_CARD_UNIVERSAL_IDENTIFIER,
|
||||
type: ViewType.CALENDAR,
|
||||
icon: 'IconCalendarEvent',
|
||||
position: 2,
|
||||
calendarLayout: ViewCalendarLayout.MONTH,
|
||||
calendarFieldMetadataUniversalIdentifier:
|
||||
DELIVERED_AT_FIELD_UNIVERSAL_IDENTIFIER,
|
||||
fields: [
|
||||
{
|
||||
universalIdentifier: 'bf1a2b3c-0006-4a7b-8c9d-0e1f2a3b4c5d',
|
||||
fieldMetadataUniversalIdentifier: CONTENT_FIELD_UNIVERSAL_IDENTIFIER,
|
||||
position: 0,
|
||||
isVisible: true,
|
||||
size: 200,
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -0,0 +1,63 @@
|
||||
import { defineView } from 'twenty-sdk/define';
|
||||
import { ViewType } from 'twenty-shared/types';
|
||||
|
||||
import {
|
||||
CONTENT_FIELD_UNIVERSAL_IDENTIFIER,
|
||||
POST_CARD_UNIVERSAL_IDENTIFIER,
|
||||
STATUS_FIELD_UNIVERSAL_IDENTIFIER,
|
||||
} from '../objects/post-card.object';
|
||||
|
||||
export const POST_CARDS_BY_STATUS_VIEW_ID =
|
||||
'b1a2b3c4-0004-4a7b-8c9d-0e1f2a3b4c5d';
|
||||
|
||||
export default defineView({
|
||||
universalIdentifier: POST_CARDS_BY_STATUS_VIEW_ID,
|
||||
name: 'By Status',
|
||||
objectUniversalIdentifier: POST_CARD_UNIVERSAL_IDENTIFIER,
|
||||
type: ViewType.KANBAN,
|
||||
icon: 'IconLayoutKanban',
|
||||
position: 1,
|
||||
mainGroupByFieldMetadataUniversalIdentifier:
|
||||
STATUS_FIELD_UNIVERSAL_IDENTIFIER,
|
||||
fields: [
|
||||
{
|
||||
universalIdentifier: 'bf1a2b3c-0005-4a7b-8c9d-0e1f2a3b4c5d',
|
||||
fieldMetadataUniversalIdentifier: CONTENT_FIELD_UNIVERSAL_IDENTIFIER,
|
||||
position: 0,
|
||||
isVisible: true,
|
||||
size: 200,
|
||||
},
|
||||
],
|
||||
groups: [
|
||||
{
|
||||
universalIdentifier: 'bg1a2b3c-0001-4a7b-8c9d-0e1f2a3b4c5d',
|
||||
fieldValue: 'DRAFT',
|
||||
position: 0,
|
||||
isVisible: true,
|
||||
},
|
||||
{
|
||||
universalIdentifier: 'bg1a2b3c-0002-4a7b-8c9d-0e1f2a3b4c5d',
|
||||
fieldValue: 'SENT',
|
||||
position: 1,
|
||||
isVisible: true,
|
||||
},
|
||||
{
|
||||
universalIdentifier: 'bg1a2b3c-0003-4a7b-8c9d-0e1f2a3b4c5d',
|
||||
fieldValue: 'DELIVERED',
|
||||
position: 2,
|
||||
isVisible: true,
|
||||
},
|
||||
{
|
||||
universalIdentifier: 'bg1a2b3c-0004-4a7b-8c9d-0e1f2a3b4c5d',
|
||||
fieldValue: 'RETURNED',
|
||||
position: 3,
|
||||
isVisible: true,
|
||||
},
|
||||
{
|
||||
universalIdentifier: 'bg1a2b3c-0005-4a7b-8c9d-0e1f2a3b4c5d',
|
||||
fieldValue: 'LOST',
|
||||
position: 4,
|
||||
isVisible: true,
|
||||
},
|
||||
],
|
||||
});
|
||||
+74
@@ -6,6 +6,7 @@ import {
|
||||
NavigationMenuItemType,
|
||||
RelationOnDeleteAction,
|
||||
RelationType,
|
||||
ViewCalendarLayout,
|
||||
ViewType,
|
||||
} from 'twenty-shared/types';
|
||||
|
||||
@@ -1473,6 +1474,79 @@ export const EXPECTED_MANIFEST: Manifest = {
|
||||
type: ViewType.TABLE,
|
||||
universalIdentifier: 'b1a2b3c4-0002-4a7b-8c9d-0e1f2a3b4c5d',
|
||||
},
|
||||
{
|
||||
fields: [
|
||||
{
|
||||
fieldMetadataUniversalIdentifier:
|
||||
'58a0a314-d7ea-4865-9850-7fb84e72f30b',
|
||||
isVisible: true,
|
||||
position: 0,
|
||||
size: 200,
|
||||
universalIdentifier: 'bf1a2b3c-0005-4a7b-8c9d-0e1f2a3b4c5d',
|
||||
},
|
||||
],
|
||||
groups: [
|
||||
{
|
||||
fieldValue: 'DRAFT',
|
||||
isVisible: true,
|
||||
position: 0,
|
||||
universalIdentifier: 'bg1a2b3c-0001-4a7b-8c9d-0e1f2a3b4c5d',
|
||||
},
|
||||
{
|
||||
fieldValue: 'SENT',
|
||||
isVisible: true,
|
||||
position: 1,
|
||||
universalIdentifier: 'bg1a2b3c-0002-4a7b-8c9d-0e1f2a3b4c5d',
|
||||
},
|
||||
{
|
||||
fieldValue: 'DELIVERED',
|
||||
isVisible: true,
|
||||
position: 2,
|
||||
universalIdentifier: 'bg1a2b3c-0003-4a7b-8c9d-0e1f2a3b4c5d',
|
||||
},
|
||||
{
|
||||
fieldValue: 'RETURNED',
|
||||
isVisible: true,
|
||||
position: 3,
|
||||
universalIdentifier: 'bg1a2b3c-0004-4a7b-8c9d-0e1f2a3b4c5d',
|
||||
},
|
||||
{
|
||||
fieldValue: 'LOST',
|
||||
isVisible: true,
|
||||
position: 4,
|
||||
universalIdentifier: 'bg1a2b3c-0005-4a7b-8c9d-0e1f2a3b4c5d',
|
||||
},
|
||||
],
|
||||
icon: 'IconLayoutKanban',
|
||||
mainGroupByFieldMetadataUniversalIdentifier:
|
||||
'87b675b8-dd8c-4448-b4ca-20e5a2234a1e',
|
||||
name: 'By Status',
|
||||
objectUniversalIdentifier: '54b589ca-eeed-4950-a176-358418b85c05',
|
||||
position: 1,
|
||||
type: ViewType.KANBAN,
|
||||
universalIdentifier: 'b1a2b3c4-0004-4a7b-8c9d-0e1f2a3b4c5d',
|
||||
},
|
||||
{
|
||||
calendarFieldMetadataUniversalIdentifier:
|
||||
'e06abe72-5b44-4e7f-93be-afc185a3c433',
|
||||
calendarLayout: ViewCalendarLayout.MONTH,
|
||||
fields: [
|
||||
{
|
||||
fieldMetadataUniversalIdentifier:
|
||||
'58a0a314-d7ea-4865-9850-7fb84e72f30b',
|
||||
isVisible: true,
|
||||
position: 0,
|
||||
size: 200,
|
||||
universalIdentifier: 'bf1a2b3c-0006-4a7b-8c9d-0e1f2a3b4c5d',
|
||||
},
|
||||
],
|
||||
icon: 'IconCalendarEvent',
|
||||
name: 'By Delivery Date',
|
||||
objectUniversalIdentifier: '54b589ca-eeed-4950-a176-358418b85c05',
|
||||
position: 2,
|
||||
type: ViewType.CALENDAR,
|
||||
universalIdentifier: 'b1a2b3c4-0005-4a7b-8c9d-0e1f2a3b4c5d',
|
||||
},
|
||||
],
|
||||
navigationMenuItems: [
|
||||
{
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ export const defineManifestTests = (appPath: string): void => {
|
||||
expect(manifest.frontComponents).toHaveLength(4);
|
||||
expect(manifest.roles).toHaveLength(2);
|
||||
expect(manifest.fields).toHaveLength(23);
|
||||
expect(manifest.views).toHaveLength(3);
|
||||
expect(manifest.views).toHaveLength(5);
|
||||
expect(manifest.navigationMenuItems).toHaveLength(3);
|
||||
|
||||
expect(normalizeManifestForComparison(manifest)).toEqual(
|
||||
|
||||
+67
@@ -1,4 +1,6 @@
|
||||
import {
|
||||
AggregateOperations,
|
||||
ViewCalendarLayout,
|
||||
ViewOpenRecordIn,
|
||||
ViewType,
|
||||
ViewVisibility,
|
||||
@@ -65,4 +67,69 @@ describe('fromViewManifestToUniversalFlatView', () => {
|
||||
expect(result.visibility).toBe(ViewVisibility.UNLISTED);
|
||||
expect(result.openRecordIn).toBe(ViewOpenRecordIn.RECORD_PAGE);
|
||||
});
|
||||
|
||||
it('should preserve kanban fields from the manifest', () => {
|
||||
const result = fromViewManifestToUniversalFlatView({
|
||||
viewManifest: {
|
||||
universalIdentifier: 'view-uuid-3',
|
||||
name: 'Kanban Board',
|
||||
objectUniversalIdentifier: 'object-uuid-1',
|
||||
type: ViewType.KANBAN,
|
||||
mainGroupByFieldMetadataUniversalIdentifier: 'field-uuid-status',
|
||||
kanbanAggregateOperation: AggregateOperations.COUNT,
|
||||
kanbanAggregateOperationFieldMetadataUniversalIdentifier:
|
||||
'field-uuid-amount',
|
||||
},
|
||||
applicationUniversalIdentifier,
|
||||
now,
|
||||
});
|
||||
|
||||
expect(result.mainGroupByFieldMetadataUniversalIdentifier).toBe(
|
||||
'field-uuid-status',
|
||||
);
|
||||
expect(result.kanbanAggregateOperation).toBe(AggregateOperations.COUNT);
|
||||
expect(
|
||||
result.kanbanAggregateOperationFieldMetadataUniversalIdentifier,
|
||||
).toBe('field-uuid-amount');
|
||||
});
|
||||
|
||||
it('should default kanban and calendar fields to null when omitted', () => {
|
||||
const result = fromViewManifestToUniversalFlatView({
|
||||
viewManifest: {
|
||||
universalIdentifier: 'view-uuid-4',
|
||||
name: 'All Records',
|
||||
objectUniversalIdentifier: 'object-uuid-1',
|
||||
},
|
||||
applicationUniversalIdentifier,
|
||||
now,
|
||||
});
|
||||
|
||||
expect(result.mainGroupByFieldMetadataUniversalIdentifier).toBeNull();
|
||||
expect(result.kanbanAggregateOperation).toBeNull();
|
||||
expect(
|
||||
result.kanbanAggregateOperationFieldMetadataUniversalIdentifier,
|
||||
).toBeNull();
|
||||
expect(result.calendarLayout).toBeNull();
|
||||
expect(result.calendarFieldMetadataUniversalIdentifier).toBeNull();
|
||||
});
|
||||
|
||||
it('should preserve calendar fields from the manifest', () => {
|
||||
const result = fromViewManifestToUniversalFlatView({
|
||||
viewManifest: {
|
||||
universalIdentifier: 'view-uuid-5',
|
||||
name: 'Calendar View',
|
||||
objectUniversalIdentifier: 'object-uuid-1',
|
||||
type: ViewType.CALENDAR,
|
||||
calendarLayout: ViewCalendarLayout.WEEK,
|
||||
calendarFieldMetadataUniversalIdentifier: 'field-uuid-date',
|
||||
},
|
||||
applicationUniversalIdentifier,
|
||||
now,
|
||||
});
|
||||
|
||||
expect(result.calendarLayout).toBe(ViewCalendarLayout.WEEK);
|
||||
expect(result.calendarFieldMetadataUniversalIdentifier).toBe(
|
||||
'field-uuid-date',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
+9
-5
@@ -29,11 +29,15 @@ export const fromViewManifestToUniversalFlatView = ({
|
||||
visibility: viewManifest.visibility ?? ViewVisibility.WORKSPACE,
|
||||
openRecordIn: viewManifest.openRecordIn ?? ViewOpenRecordIn.SIDE_PANEL,
|
||||
key: viewManifest.key ?? null,
|
||||
kanbanAggregateOperation: null,
|
||||
kanbanAggregateOperationFieldMetadataUniversalIdentifier: null,
|
||||
calendarLayout: null,
|
||||
calendarFieldMetadataUniversalIdentifier: null,
|
||||
mainGroupByFieldMetadataUniversalIdentifier: null,
|
||||
kanbanAggregateOperation: viewManifest.kanbanAggregateOperation ?? null,
|
||||
kanbanAggregateOperationFieldMetadataUniversalIdentifier:
|
||||
viewManifest.kanbanAggregateOperationFieldMetadataUniversalIdentifier ??
|
||||
null,
|
||||
calendarLayout: viewManifest.calendarLayout ?? null,
|
||||
calendarFieldMetadataUniversalIdentifier:
|
||||
viewManifest.calendarFieldMetadataUniversalIdentifier ?? null,
|
||||
mainGroupByFieldMetadataUniversalIdentifier:
|
||||
viewManifest.mainGroupByFieldMetadataUniversalIdentifier ?? null,
|
||||
shouldHideEmptyGroups: false,
|
||||
anyFieldFilterValue: null,
|
||||
createdByUserWorkspaceId: null,
|
||||
|
||||
+1
-1
@@ -11,6 +11,7 @@ import {
|
||||
} from 'class-validator';
|
||||
import {
|
||||
AggregateOperations,
|
||||
ViewCalendarLayout,
|
||||
ViewOpenRecordIn,
|
||||
ViewKey,
|
||||
ViewType,
|
||||
@@ -19,7 +20,6 @@ import {
|
||||
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
import { IsValidMetadataName } from 'src/engine/decorators/metadata/is-valid-metadata-name.decorator';
|
||||
import { ViewCalendarLayout } from 'src/engine/metadata-modules/view/enums/view-calendar-layout.enum';
|
||||
|
||||
@InputType()
|
||||
export class CreateViewInput {
|
||||
|
||||
+1
-1
@@ -10,6 +10,7 @@ import {
|
||||
} from 'class-validator';
|
||||
import {
|
||||
AggregateOperations,
|
||||
ViewCalendarLayout,
|
||||
ViewOpenRecordIn,
|
||||
ViewType,
|
||||
ViewVisibility,
|
||||
@@ -17,7 +18,6 @@ import {
|
||||
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
import { IsValidMetadataName } from 'src/engine/decorators/metadata/is-valid-metadata-name.decorator';
|
||||
import { ViewCalendarLayout } from 'src/engine/metadata-modules/view/enums/view-calendar-layout.enum';
|
||||
|
||||
// TODO: this should be refactored like for view-field.input.ts
|
||||
// This is a temporary fix as we were extending the CreateViewInput class which was adding default values for the non filled fields
|
||||
|
||||
@@ -3,6 +3,7 @@ import { Field, ObjectType, registerEnumType } from '@nestjs/graphql';
|
||||
import { IDField } from '@ptc-org/nestjs-query-graphql';
|
||||
import {
|
||||
AggregateOperations,
|
||||
ViewCalendarLayout,
|
||||
ViewOpenRecordIn,
|
||||
ViewType,
|
||||
ViewVisibility,
|
||||
@@ -16,7 +17,6 @@ import { ViewFilterGroupDTO } from 'src/engine/metadata-modules/view-filter-grou
|
||||
import { ViewFilterDTO } from 'src/engine/metadata-modules/view-filter/dtos/view-filter.dto';
|
||||
import { ViewGroupDTO } from 'src/engine/metadata-modules/view-group/dtos/view-group.dto';
|
||||
import { ViewSortDTO } from 'src/engine/metadata-modules/view-sort/dtos/view-sort.dto';
|
||||
import { ViewCalendarLayout } from 'src/engine/metadata-modules/view/enums/view-calendar-layout.enum';
|
||||
|
||||
registerEnumType(ViewOpenRecordIn, { name: 'ViewOpenRecordIn' });
|
||||
registerEnumType(ViewType, { name: 'ViewType' });
|
||||
|
||||
@@ -14,9 +14,10 @@ import {
|
||||
} from 'typeorm';
|
||||
import {
|
||||
AggregateOperations,
|
||||
ViewCalendarLayout,
|
||||
ViewKey,
|
||||
ViewOpenRecordIn,
|
||||
ViewType,
|
||||
ViewKey,
|
||||
ViewVisibility,
|
||||
} from 'twenty-shared/types';
|
||||
|
||||
@@ -29,7 +30,6 @@ import { ViewFilterGroupEntity } from 'src/engine/metadata-modules/view-filter-g
|
||||
import { ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entities/view-filter.entity';
|
||||
import { ViewGroupEntity } from 'src/engine/metadata-modules/view-group/entities/view-group.entity';
|
||||
import { ViewSortEntity } from 'src/engine/metadata-modules/view-sort/entities/view-sort.entity';
|
||||
import { ViewCalendarLayout } from 'src/engine/metadata-modules/view/enums/view-calendar-layout.enum';
|
||||
import { SyncableEntity } from 'src/engine/workspace-manager/types/syncable-entity.interface';
|
||||
|
||||
// We could refactor this type to be dynamic to view type
|
||||
|
||||
+1
-2
@@ -3,12 +3,11 @@ import { Test, type TestingModule } from '@nestjs/testing';
|
||||
import {
|
||||
FieldMetadataType,
|
||||
OrderByDirection,
|
||||
ViewCalendarLayout,
|
||||
ViewType,
|
||||
ViewVisibility,
|
||||
} from 'twenty-shared/types';
|
||||
|
||||
import { ViewCalendarLayout } from 'src/engine/metadata-modules/view/enums/view-calendar-layout.enum';
|
||||
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { ViewFieldService } from 'src/engine/metadata-modules/view-field/services/view-field.service';
|
||||
import { ViewQueryParamsService } from 'src/engine/metadata-modules/view/services/view-query-params.service';
|
||||
|
||||
@@ -4,6 +4,7 @@ import { type ToolSet } from 'ai';
|
||||
import {
|
||||
AggregateOperations,
|
||||
FieldMetadataType,
|
||||
ViewCalendarLayout,
|
||||
ViewType,
|
||||
ViewVisibility,
|
||||
} from 'twenty-shared/types';
|
||||
@@ -14,7 +15,6 @@ import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadat
|
||||
import { buildObjectIdByNameMaps } from 'src/engine/metadata-modules/flat-object-metadata/utils/build-object-id-by-name-maps.util';
|
||||
import { ViewFieldService } from 'src/engine/metadata-modules/view-field/services/view-field.service';
|
||||
|
||||
import { ViewCalendarLayout } from 'src/engine/metadata-modules/view/enums/view-calendar-layout.enum';
|
||||
import { ViewQueryParamsService } from 'src/engine/metadata-modules/view/services/view-query-params.service';
|
||||
import { ViewService } from 'src/engine/metadata-modules/view/services/view.service';
|
||||
import { WorkspaceMigrationBuilderException } from 'src/engine/workspace-manager/workspace-migration/exceptions/workspace-migration-builder-exception';
|
||||
|
||||
+5
-3
@@ -7,11 +7,13 @@ import { updateOneObjectMetadata } from 'test/integration/metadata/suites/object
|
||||
import { createOneView } from 'test/integration/metadata/suites/view/utils/create-one-view.util';
|
||||
import { findOneView } from 'test/integration/metadata/suites/view/utils/find-one-view.util';
|
||||
import { generateRecordName } from 'test/integration/utils/generate-record-name';
|
||||
import { FieldMetadataType, ViewType } from 'twenty-shared/types';
|
||||
import {
|
||||
FieldMetadataType,
|
||||
ViewCalendarLayout,
|
||||
ViewType,
|
||||
} from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { ViewCalendarLayout } from 'src/engine/metadata-modules/view/enums/view-calendar-layout.enum';
|
||||
|
||||
const VIEW_WITH_CALENDAR_FIELDS = `
|
||||
id
|
||||
name
|
||||
|
||||
@@ -2,6 +2,7 @@ import { type SyncableEntityOptions } from '@/application/syncableEntityOptionsT
|
||||
import {
|
||||
type ViewKey,
|
||||
type AggregateOperations,
|
||||
type ViewCalendarLayout,
|
||||
type ViewFilterGroupLogicalOperator,
|
||||
type ViewFilterOperand,
|
||||
type ViewOpenRecordIn,
|
||||
@@ -68,6 +69,11 @@ export type ViewManifest = SyncableEntityOptions & {
|
||||
isCompact?: boolean;
|
||||
visibility?: ViewVisibility;
|
||||
openRecordIn?: ViewOpenRecordIn;
|
||||
mainGroupByFieldMetadataUniversalIdentifier?: string;
|
||||
kanbanAggregateOperation?: AggregateOperations;
|
||||
kanbanAggregateOperationFieldMetadataUniversalIdentifier?: string;
|
||||
calendarLayout?: ViewCalendarLayout;
|
||||
calendarFieldMetadataUniversalIdentifier?: string;
|
||||
fields?: ViewFieldManifest[];
|
||||
filters?: ViewFilterManifest[];
|
||||
filterGroups?: ViewFilterGroupManifest[];
|
||||
|
||||
@@ -279,6 +279,7 @@ export type {
|
||||
export { StepLogicalOperator } from './StepFilters';
|
||||
export { TwoFactorAuthenticationStrategy } from './TwoFactorAuthenticationStrategy';
|
||||
export { IsValidGraphQLEnumName } from './validators/is-valid-graphql-enum-name.validator';
|
||||
export { ViewCalendarLayout } from './ViewCalendarLayout';
|
||||
export { ViewFilterGroupLogicalOperator } from './ViewFilterGroupLogicalOperator';
|
||||
export { ViewFilterOperand } from './ViewFilterOperand';
|
||||
export { ViewFilterOperandDeprecated } from './ViewFilterOperandDeprecated';
|
||||
|
||||
Reference in New Issue
Block a user