feat: configure standard views and migrate attachment seeds to FILES field (#17958)

## Summary

- Add default visible view fields for `timelineActivity`, `attachment`,
`noteTarget`, `taskTarget`, and `workspaceMember` objects so they
display useful columns out of the box
- Standardize morph relation field labels to "Target" with
`IconArrowUpRight` for consistency across all pivot/junction tables
- Mark deprecated fields (`fullPath`, `fileCategory`,
`linkedRecordCachedName`, `linkedRecordId`, `linkedObjectMetadataId`) as
`isSystem` to hide them from the UI column picker
- Fix morph field deduplication logic (`pickMorphGroupSurvivor`) to
prefer active, non-system fields over auto-generated system fields from
custom objects
- Migrate attachment seeds from legacy `fullPath`/`fileCategory` to the
new `FILES` field type, creating proper `FileEntity` records in
`core.file` via `fileStorageService.writeFile()`
- Restore `customDomain` in the user query fragment


<img width="825" height="754" alt="Screenshot 2026-02-15 at 15 44 27"
src="https://github.com/user-attachments/assets/9596a3dd-8d3a-43c0-925a-0adef9ee68a8"
/>
<img width="736" height="731" alt="Screenshot 2026-02-15 at 15 44 13"
src="https://github.com/user-attachments/assets/cd1a66c5-731d-43e6-bbc3-703cbeda1652"
/>
<img width="722" height="757" alt="Screenshot 2026-02-15 at 15 44 03"
src="https://github.com/user-attachments/assets/b5210546-6a40-4940-8e4f-874818a614fb"
/>
<img width="907" height="757" alt="Screenshot 2026-02-15 at 15 43 52"
src="https://github.com/user-attachments/assets/ead5b9a8-1989-4d68-9640-583da6233711"
/>
<img width="1002" height="731" alt="Screenshot 2026-02-15 at 15 43 38"
src="https://github.com/user-attachments/assets/38accb8c-f5d5-4bfc-b245-06389849810b"
/>




<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Touches migration/upgrade commands that write to core metadata tables
and adjust field/view definitions, plus changes dev seeding to create
`core.file` records; mistakes could affect UI visibility or seed
integrity across workspaces.
> 
> **Overview**
> Adds a new `upgrade:1-18:backfill-standard-views-and-field-metadata`
command that, per workspace, marks specific fields as `isSystem`,
normalizes morph-relation field `label`/`icon` to
`Target`/`IconArrowUpRight`, and backfills missing standard
`view`/`viewField` rows for `attachment`, `noteTarget`, `taskTarget`,
`timelineActivity`, and `workspaceMember`, followed by cache
invalidation + metadata version bump.
> 
> Refactors morph-relation deduplication to pick a single survivor per
`morphId` using a new `pickMorphGroupSurvivor` rule (prefer active +
non-system, then smallest id), with new unit tests.
> 
> Updates standard metadata generators and snapshots to reflect the new
system flags and default view fields, and rewrites attachment dev
seeding to populate the new `file` (FILES field) JSON and create
corresponding `core.file` entries via `FileStorageService.writeFile`
with workspace-scoped file IDs.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
b1939bbf6f8cce294f9b4cdec06b19778daa205e. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
This commit is contained in:
Félix Malfait
2026-02-16 13:34:56 +01:00
committed by GitHub
parent b80146c890
commit c775d65952
29 changed files with 3153 additions and 1308 deletions
@@ -0,0 +1,103 @@
import { FieldMetadataType } from 'twenty-shared/types';
import { filterMorphRelationDuplicateFields } from 'src/engine/dataloaders/utils/filter-morph-relation-duplicate-fields.util';
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
const makeMorphField = (
overrides: Partial<FlatFieldMetadata<FieldMetadataType.MORPH_RELATION>> & {
id: string;
morphId: string;
},
): FlatFieldMetadata<FieldMetadataType.MORPH_RELATION> =>
({
type: FieldMetadataType.MORPH_RELATION,
isActive: true,
isSystem: false,
...overrides,
}) as FlatFieldMetadata<FieldMetadataType.MORPH_RELATION>;
const makeTextField = (id: string): FlatFieldMetadata<FieldMetadataType.TEXT> =>
({
id,
type: FieldMetadataType.TEXT,
}) as FlatFieldMetadata<FieldMetadataType.TEXT>;
describe('filterMorphRelationDuplicateFields', () => {
it('should return all fields when there are no morph fields', () => {
const fields = [makeTextField('t1'), makeTextField('t2')];
expect(filterMorphRelationDuplicateFields(fields)).toEqual(fields);
});
it('should return all fields when morph fields have distinct morphIds', () => {
const morph1 = makeMorphField({ id: 'a', morphId: 'morph-1' });
const morph2 = makeMorphField({ id: 'b', morphId: 'morph-2' });
const text = makeTextField('t1');
const result = filterMorphRelationDuplicateFields([morph1, text, morph2]);
expect(result).toHaveLength(3);
expect(result).toContain(text);
expect(result).toContain(morph1);
expect(result).toContain(morph2);
});
it('should deduplicate morph fields sharing the same morphId', () => {
const standard = makeMorphField({
id: 'b',
morphId: 'morph-1',
isSystem: false,
});
const system = makeMorphField({
id: 'a',
morphId: 'morph-1',
isSystem: true,
});
const text = makeTextField('t1');
const result = filterMorphRelationDuplicateFields([system, text, standard]);
expect(result).toHaveLength(2);
expect(result).toContain(text);
expect(result).toContain(standard);
expect(result).not.toContain(system);
});
it('should handle multiple morph groups independently', () => {
const group1Best = makeMorphField({
id: 'a',
morphId: 'morph-1',
isSystem: false,
});
const group1Dup = makeMorphField({
id: 'b',
morphId: 'morph-1',
isSystem: true,
});
const group2Best = makeMorphField({
id: 'c',
morphId: 'morph-2',
isSystem: false,
});
const group2Dup = makeMorphField({
id: 'd',
morphId: 'morph-2',
isSystem: true,
});
const result = filterMorphRelationDuplicateFields([
group1Dup,
group2Dup,
group1Best,
group2Best,
]);
expect(result).toHaveLength(2);
expect(result).toContain(group1Best);
expect(result).toContain(group2Best);
});
it('should return empty array for empty input', () => {
expect(filterMorphRelationDuplicateFields([])).toEqual([]);
});
});
@@ -0,0 +1,85 @@
import { FieldMetadataType } from 'twenty-shared/types';
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
import { pickMorphGroupSurvivor } from 'src/engine/dataloaders/utils/pick-morph-group-survivor.util';
const makeMorphField = (
overrides: Partial<FlatFieldMetadata<FieldMetadataType.MORPH_RELATION>> & {
id: string;
},
): FlatFieldMetadata<FieldMetadataType.MORPH_RELATION> =>
({
type: FieldMetadataType.MORPH_RELATION,
isActive: true,
isSystem: false,
morphId: 'morph-1',
...overrides,
}) as FlatFieldMetadata<FieldMetadataType.MORPH_RELATION>;
describe('pickMorphGroupSurvivor', () => {
it('should return the only field when group has one element', () => {
const field = makeMorphField({ id: 'a' });
expect(pickMorphGroupSurvivor([field])).toBe(field);
});
it('should prefer active non-system over active system', () => {
const standard = makeMorphField({
id: 'b',
isActive: true,
isSystem: false,
});
const system = makeMorphField({
id: 'a',
isActive: true,
isSystem: true,
});
expect(pickMorphGroupSurvivor([system, standard])).toBe(standard);
});
it('should prefer active over inactive', () => {
const active = makeMorphField({
id: 'b',
isActive: true,
isSystem: true,
});
const inactive = makeMorphField({
id: 'a',
isActive: false,
isSystem: false,
});
expect(pickMorphGroupSurvivor([inactive, active])).toBe(active);
});
it('should break ties by smallest id', () => {
const fieldA = makeMorphField({
id: 'aaa',
isActive: true,
isSystem: false,
});
const fieldB = makeMorphField({
id: 'bbb',
isActive: true,
isSystem: false,
});
expect(pickMorphGroupSurvivor([fieldB, fieldA])).toBe(fieldA);
});
it('should prefer active+non-system (score 3) over inactive+non-system (score 1)', () => {
const best = makeMorphField({
id: 'z',
isActive: true,
isSystem: false,
});
const worse = makeMorphField({
id: 'a',
isActive: false,
isSystem: false,
});
expect(pickMorphGroupSurvivor([worse, best])).toBe(best);
});
});
@@ -2,52 +2,42 @@ import { FieldMetadataType } from 'twenty-shared/types';
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
import { isFlatFieldMetadataOfType } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-flat-field-metadata-of-type.util';
import { pickMorphGroupSurvivor } from 'src/engine/dataloaders/utils/pick-morph-group-survivor.util';
export const filterMorphRelationDuplicateFields = (
flatFieldMetadatas: FlatFieldMetadata[],
): FlatFieldMetadata[] => {
const initialAccumulator: {
morphFlatFieldMetadatas: FlatFieldMetadata<FieldMetadataType.MORPH_RELATION>[];
otherFlatFieldMetadatas: FlatFieldMetadata[];
} = {
morphFlatFieldMetadatas: [],
otherFlatFieldMetadatas: [],
};
const { morphFlatFieldMetadatas, otherFlatFieldMetadatas } =
flatFieldMetadatas.reduce((acc, flatFieldMetadata) => {
if (
isFlatFieldMetadataOfType(
flatFieldMetadata,
FieldMetadataType.MORPH_RELATION,
)
) {
return {
...acc,
morphFlatFieldMetadatas: [
...acc.morphFlatFieldMetadatas,
flatFieldMetadata,
],
};
}
const otherFlatFieldMetadatas: FlatFieldMetadata[] = [];
const morphGroupsByMorphId = new Map<
string,
FlatFieldMetadata<FieldMetadataType.MORPH_RELATION>[]
>();
return {
...acc,
otherFlatFieldMetadatas: [
...acc.otherFlatFieldMetadatas,
flatFieldMetadata,
],
};
}, initialAccumulator);
for (const flatFieldMetadata of flatFieldMetadatas) {
if (
isFlatFieldMetadataOfType(
flatFieldMetadata,
FieldMetadataType.MORPH_RELATION,
)
) {
const existing =
morphGroupsByMorphId.get(flatFieldMetadata.morphId) ?? [];
const filteredMorphFlatFieldMetadatas = morphFlatFieldMetadatas.filter(
(currentField) =>
!morphFlatFieldMetadatas.some(
(otherField) =>
currentField.id !== otherField.id &&
otherField.morphId === currentField.morphId &&
otherField.id < currentField.id,
),
);
morphGroupsByMorphId.set(flatFieldMetadata.morphId, [
...existing,
flatFieldMetadata,
]);
} else {
otherFlatFieldMetadatas.push(flatFieldMetadata);
}
}
const filteredMorphFlatFieldMetadatas: FlatFieldMetadata<FieldMetadataType.MORPH_RELATION>[] =
[];
for (const group of morphGroupsByMorphId.values()) {
filteredMorphFlatFieldMetadatas.push(pickMorphGroupSurvivor(group));
}
return [...otherFlatFieldMetadatas, ...filteredMorphFlatFieldMetadatas];
};
@@ -0,0 +1,19 @@
import { type FieldMetadataType } from 'twenty-shared/types';
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
// Prefers active non-system fields (standard targets) over system ones
// (auto-created for custom objects). Smallest id breaks ties.
const scoreMorphField = (
field: FlatFieldMetadata<FieldMetadataType.MORPH_RELATION>,
): number => (field.isActive ? 2 : 0) + (field.isSystem ? 0 : 1);
export const pickMorphGroupSurvivor = (
group: FlatFieldMetadata<FieldMetadataType.MORPH_RELATION>[],
): FlatFieldMetadata<FieldMetadataType.MORPH_RELATION> => {
return group.reduce((best, current) => {
const diff = scoreMorphField(current) - scoreMorphField(best);
return diff > 0 || (diff === 0 && current.id < best.id) ? current : best;
});
};
@@ -6,6 +6,7 @@ import { z } from 'zod';
import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant';
import { formatValidationErrors } from 'src/engine/core-modules/tool-provider/utils/format-validation-errors.util';
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
import { buildObjectIdByNameMaps } from 'src/engine/metadata-modules/flat-object-metadata/utils/build-object-id-by-name-maps.util';
import { ViewType } from 'src/engine/metadata-modules/view/enums/view-type.enum';
import { ViewVisibility } from 'src/engine/metadata-modules/view/enums/view-visibility.enum';
import { ViewQueryParamsService } from 'src/engine/metadata-modules/view/services/view-query-params.service';
@@ -105,17 +106,19 @@ export class ViewToolsFactory {
},
);
const objectMetadata = Object.values(
flatObjectMetadataMaps.byUniversalIdentifier,
).find((obj) => obj?.nameSingular === objectNameSingular);
const { idByNameSingular } = buildObjectIdByNameMaps(
flatObjectMetadataMaps,
);
if (!objectMetadata) {
const objectMetadataId = idByNameSingular[objectNameSingular];
if (!objectMetadataId) {
throw new Error(
`Object "${objectNameSingular}" not found. Use get_object_metadata to list available objects.`,
);
}
return objectMetadata.id;
return objectMetadataId;
}
private async resolveFieldMetadataId(
@@ -10,8 +10,7 @@ import { WORKSPACE_MEMBER_DATA_SEED_IDS } from 'src/engine/workspace-manager/dev
type AttachmentDataSeed = {
id: string;
name: string;
fullPath: string;
fileCategory: string;
file: string;
createdBySource: string;
createdByWorkspaceMemberId: string;
createdByName: string;
@@ -28,8 +27,7 @@ type AttachmentDataSeed = {
export const ATTACHMENT_DATA_SEED_COLUMNS: (keyof AttachmentDataSeed)[] = [
'id',
'name',
'fullPath',
'fileCategory',
'file',
'createdBySource',
'createdByWorkspaceMemberId',
'createdByName',
@@ -58,203 +56,153 @@ const GENERATE_ATTACHMENT_IDS = (): Record<string, string> => {
export const ATTACHMENT_DATA_SEED_IDS = GENERATE_ATTACHMENT_IDS();
// Pool of 5 reusable file paths for attachments
const FILE_TEMPLATE_PATHS = [
'attachment/sample-contract.pdf',
'attachment/budget-2024.xlsx',
'attachment/presentation.pptx',
'attachment/screenshot.png',
'attachment/archive.zip',
// FileIds must be unique per workspace since core.file is a shared table.
// We use the first 12 hex chars of the workspaceId as a namespace suffix.
const deriveFileId = (attachmentIndex: number, workspaceId: string): string => {
const workspaceHex = workspaceId.replace(/-/g, '').slice(0, 12);
const hexIndex = attachmentIndex.toString(16).padStart(4, '0');
return `f11e0000-${hexIndex}-4a7c-8001-${workspaceHex}`;
};
export const ATTACHMENT_SAMPLE_FILES = [
{
filename: 'sample-contract.pdf',
mimeType: 'application/pdf',
extension: 'pdf',
},
{
filename: 'budget-2024.xlsx',
mimeType:
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
extension: 'xlsx',
},
{
filename: 'presentation.pptx',
mimeType:
'application/vnd.openxmlformats-officedocument.presentationml.presentation',
extension: 'pptx',
},
{
filename: 'screenshot.png',
mimeType: 'image/png',
extension: 'png',
},
{
filename: 'archive.zip',
mimeType: 'application/zip',
extension: 'zip',
},
];
// Additional name variations for more realistic variety
const FILE_NAME_VARIATIONS = [
// Documents
{
name: 'Service Agreement.pdf',
fileCategory: 'TEXT_DOCUMENT',
pathIndex: 0,
},
{
name: 'NDA Document.pdf',
fileCategory: 'TEXT_DOCUMENT',
pathIndex: 0,
},
{
name: 'Project Proposal.pdf',
fileCategory: 'TEXT_DOCUMENT',
pathIndex: 0,
},
{
name: 'Invoice Q1 2024.pdf',
fileCategory: 'TEXT_DOCUMENT',
pathIndex: 0,
},
{
name: 'Meeting Notes.pdf',
fileCategory: 'TEXT_DOCUMENT',
pathIndex: 0,
},
{
name: 'Report Final.pdf',
fileCategory: 'TEXT_DOCUMENT',
pathIndex: 0,
},
{
name: 'Contract Signed.pdf',
fileCategory: 'TEXT_DOCUMENT',
pathIndex: 0,
},
{ name: 'Service Agreement.pdf', sampleFileIndex: 0 },
{ name: 'NDA Document.pdf', sampleFileIndex: 0 },
{ name: 'Project Proposal.pdf', sampleFileIndex: 0 },
{ name: 'Invoice Q1 2024.pdf', sampleFileIndex: 0 },
{ name: 'Meeting Notes.pdf', sampleFileIndex: 0 },
{ name: 'Report Final.pdf', sampleFileIndex: 0 },
{ name: 'Contract Signed.pdf', sampleFileIndex: 0 },
// Spreadsheets
{
name: 'Financial Forecast.xlsx',
fileCategory: 'SPREADSHEET',
pathIndex: 1,
},
{
name: 'Sales Report Q4.xlsx',
fileCategory: 'SPREADSHEET',
pathIndex: 1,
},
{
name: 'Team Roster.xlsx',
fileCategory: 'SPREADSHEET',
pathIndex: 1,
},
{
name: 'Expense Report.xlsx',
fileCategory: 'SPREADSHEET',
pathIndex: 1,
},
{
name: 'Inventory List.xlsx',
fileCategory: 'SPREADSHEET',
pathIndex: 1,
},
{
name: 'Data Export.csv',
fileCategory: 'SPREADSHEET',
pathIndex: 1,
},
{ name: 'Financial Forecast.xlsx', sampleFileIndex: 1 },
{ name: 'Sales Report Q4.xlsx', sampleFileIndex: 1 },
{ name: 'Team Roster.xlsx', sampleFileIndex: 1 },
{ name: 'Expense Report.xlsx', sampleFileIndex: 1 },
{ name: 'Inventory List.xlsx', sampleFileIndex: 1 },
{ name: 'Data Export.csv', sampleFileIndex: 1 },
// Presentations
{
name: 'Pitch Deck.pptx',
fileCategory: 'PRESENTATION',
pathIndex: 2,
},
{
name: 'Q4 Results.pptx',
fileCategory: 'PRESENTATION',
pathIndex: 2,
},
{
name: 'Roadmap 2024.pptx',
fileCategory: 'PRESENTATION',
pathIndex: 2,
},
{
name: 'Company Overview.pptx',
fileCategory: 'PRESENTATION',
pathIndex: 2,
},
{
name: 'Training Materials.pptx',
fileCategory: 'PRESENTATION',
pathIndex: 2,
},
{ name: 'Pitch Deck.pptx', sampleFileIndex: 2 },
{ name: 'Q4 Results.pptx', sampleFileIndex: 2 },
{ name: 'Roadmap 2024.pptx', sampleFileIndex: 2 },
{ name: 'Company Overview.pptx', sampleFileIndex: 2 },
{ name: 'Training Materials.pptx', sampleFileIndex: 2 },
// Images
{
name: 'Company Logo.png',
fileCategory: 'IMAGE',
pathIndex: 3,
},
{
name: 'Product Photo.jpg',
fileCategory: 'IMAGE',
pathIndex: 3,
},
{ name: 'Diagram.png', fileCategory: 'IMAGE', pathIndex: 3 },
{ name: 'Wireframe.png', fileCategory: 'IMAGE', pathIndex: 3 },
{
name: 'Mockup Design.png',
fileCategory: 'IMAGE',
pathIndex: 3,
},
{ name: 'Headshot.jpg', fileCategory: 'IMAGE', pathIndex: 3 },
{ name: 'Company Logo.png', sampleFileIndex: 3 },
{ name: 'Product Photo.jpg', sampleFileIndex: 3 },
{ name: 'Diagram.png', sampleFileIndex: 3 },
{ name: 'Wireframe.png', sampleFileIndex: 3 },
{ name: 'Mockup Design.png', sampleFileIndex: 3 },
{ name: 'Headshot.jpg', sampleFileIndex: 3 },
// Archives
{
name: 'Project Files.zip',
fileCategory: 'ARCHIVE',
pathIndex: 4,
},
{
name: 'Backup Data.zip',
fileCategory: 'ARCHIVE',
pathIndex: 4,
},
{
name: 'Source Code.zip',
fileCategory: 'ARCHIVE',
pathIndex: 4,
},
{ name: 'Project Files.zip', sampleFileIndex: 4 },
{ name: 'Backup Data.zip', sampleFileIndex: 4 },
{ name: 'Source Code.zip', sampleFileIndex: 4 },
];
const GENERATE_ATTACHMENT_SEEDS = (): AttachmentDataSeed[] => {
const ATTACHMENT_SEEDS: AttachmentDataSeed[] = [];
export type AttachmentFileSeedMetadata = {
fileId: string;
label: string;
sampleFileIndex: number;
mimeType: string;
extension: string;
};
// Get available entity IDs
const PERSON_IDS = Object.values(PERSON_DATA_SEED_IDS).slice(0, 120); // Use first 120 persons
const COMPANY_IDS = Object.values(COMPANY_DATA_SEED_IDS).slice(0, 120); // Use first 120 companies
const NOTE_IDS = Object.values(NOTE_DATA_SEED_IDS).slice(0, 80); // Use first 80 notes
const TASK_IDS = Object.values(TASK_DATA_SEED_IDS).slice(0, 60); // Use first 60 tasks
const OPPORTUNITY_IDS = Object.values(OPPORTUNITY_DATA_SEED_IDS).slice(0, 20); // Use first 20 opportunities
export const generateAttachmentSeedsForWorkspace = (
workspaceId: string,
): {
seeds: AttachmentDataSeed[];
fileSeedMetadata: AttachmentFileSeedMetadata[];
} => {
const seeds: AttachmentDataSeed[] = [];
const fileSeedMetadata: AttachmentFileSeedMetadata[] = [];
const PERSON_IDS = Object.values(PERSON_DATA_SEED_IDS).slice(0, 120);
const COMPANY_IDS = Object.values(COMPANY_DATA_SEED_IDS).slice(0, 120);
const NOTE_IDS = Object.values(NOTE_DATA_SEED_IDS).slice(0, 80);
const TASK_IDS = Object.values(TASK_DATA_SEED_IDS).slice(0, 60);
const OPPORTUNITY_IDS = Object.values(OPPORTUNITY_DATA_SEED_IDS).slice(0, 20);
let entityIndex = 0;
for (let INDEX = 1; INDEX <= 400; INDEX++) {
// Cycle through file name variations
const NAME_VARIATION_INDEX = INDEX % FILE_NAME_VARIATIONS.length;
const NAME_VARIATION = FILE_NAME_VARIATIONS[NAME_VARIATION_INDEX];
const FILE_PATH = FILE_TEMPLATE_PATHS[NAME_VARIATION.pathIndex];
for (let index = 1; index <= 400; index++) {
const nameVariationIndex = index % FILE_NAME_VARIATIONS.length;
const nameVariation = FILE_NAME_VARIATIONS[nameVariationIndex];
const sampleFile = ATTACHMENT_SAMPLE_FILES[nameVariation.sampleFileIndex];
const attachmentId = ATTACHMENT_DATA_SEED_IDS[`ID_${index}`];
const fileId = deriveFileId(index, workspaceId);
// Determine which entity this attachment belongs to
// Distribution: ~30% person, ~30% company, ~20% note, ~15% task, ~5% opportunity
let targetPersonId: string | null = null;
let targetCompanyId: string | null = null;
let targetNoteId: string | null = null;
let targetTaskId: string | null = null;
let targetOpportunityId: string | null = null;
const DISTRIBUTION_VALUE = INDEX % 100;
const distributionValue = index % 100;
if (DISTRIBUTION_VALUE < 30) {
// 30% Person attachments
if (distributionValue < 30) {
targetPersonId = PERSON_IDS[entityIndex % PERSON_IDS.length];
entityIndex++;
} else if (DISTRIBUTION_VALUE < 60) {
// 30% Company attachments
} else if (distributionValue < 60) {
targetCompanyId = COMPANY_IDS[entityIndex % COMPANY_IDS.length];
entityIndex++;
} else if (DISTRIBUTION_VALUE < 80) {
// 20% Note attachments
} else if (distributionValue < 80) {
targetNoteId = NOTE_IDS[entityIndex % NOTE_IDS.length];
entityIndex++;
} else if (DISTRIBUTION_VALUE < 95) {
// 15% Task attachments
} else if (distributionValue < 95) {
targetTaskId = TASK_IDS[entityIndex % TASK_IDS.length];
entityIndex++;
} else {
// 5% Opportunity attachments
targetOpportunityId =
OPPORTUNITY_IDS[entityIndex % OPPORTUNITY_IDS.length];
entityIndex++;
}
ATTACHMENT_SEEDS.push({
id: ATTACHMENT_DATA_SEED_IDS[`ID_${INDEX}`],
name: NAME_VARIATION.name,
fullPath: FILE_PATH,
fileCategory: NAME_VARIATION.fileCategory,
fileSeedMetadata.push({
fileId,
label: nameVariation.name,
sampleFileIndex: nameVariation.sampleFileIndex,
mimeType: sampleFile.mimeType,
extension: sampleFile.extension,
});
seeds.push({
id: attachmentId,
name: nameVariation.name,
file: JSON.stringify([
{ fileId, label: nameVariation.name, extension: sampleFile.extension },
]),
createdBySource: FieldActorSource.MANUAL,
createdByWorkspaceMemberId: WORKSPACE_MEMBER_DATA_SEED_IDS.TIM,
createdByName: 'Tim A',
@@ -269,7 +217,5 @@ const GENERATE_ATTACHMENT_SEEDS = (): AttachmentDataSeed[] => {
});
}
return ATTACHMENT_SEEDS;
return { seeds, fileSeedMetadata };
};
export const ATTACHMENT_DATA_SEEDS = GENERATE_ATTACHMENT_SEEDS();
@@ -4,6 +4,8 @@ import { InjectDataSource } from '@nestjs/typeorm';
import { readFile } from 'fs/promises';
import { join } from 'path';
import { STANDARD_OBJECTS } from 'twenty-shared/metadata';
import { FileFolder } from 'twenty-shared/types';
import { DataSource } from 'typeorm';
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
@@ -15,7 +17,9 @@ import { type WorkspaceEntityManager } from 'src/engine/twenty-orm/entity-manage
import { computeTableName } from 'src/engine/utils/compute-table-name.util';
import {
ATTACHMENT_DATA_SEED_COLUMNS,
ATTACHMENT_DATA_SEEDS,
ATTACHMENT_SAMPLE_FILES,
type AttachmentFileSeedMetadata,
generateAttachmentSeedsForWorkspace,
} from 'src/engine/workspace-manager/dev-seeder/data/constants/attachment-data-seeds.constant';
import {
CALENDAR_CHANNEL_DATA_SEED_COLUMNS,
@@ -115,6 +119,7 @@ import {
} from 'src/engine/workspace-manager/dev-seeder/data/constants/workspace-member-data-seeds.constant';
import { TimelineActivitySeederService } from 'src/engine/workspace-manager/dev-seeder/data/services/timeline-activity-seeder.service';
import { prefillWorkflows } from 'src/engine/workspace-manager/standard-objects-prefill-data/prefill-workflows';
import { TWENTY_STANDARD_APPLICATION } from 'src/engine/workspace-manager/twenty-standard-application/constants/twenty-standard-applications';
type RecordSeedConfig = {
tableName: string;
@@ -125,6 +130,7 @@ type RecordSeedConfig = {
// Organize seeds into dependency batches for parallel insertion
const getRecordSeedsBatches = (
workspaceId: string,
attachmentSeeds: RecordSeedConfig['recordSeeds'],
_featureFlags?: Record<FeatureFlagKey, boolean>,
): RecordSeedConfig[][] => {
// Batch 1: No dependencies
@@ -273,7 +279,7 @@ const getRecordSeedsBatches = (
{
tableName: 'attachment',
pgColumns: ATTACHMENT_DATA_SEED_COLUMNS,
recordSeeds: ATTACHMENT_DATA_SEEDS,
recordSeeds: attachmentSeeds,
},
];
@@ -311,12 +317,16 @@ export class DevSeederDataService {
},
);
const { seeds: attachmentSeeds, fileSeedMetadata: attachmentFileMeta } =
generateAttachmentSeedsForWorkspace(workspaceId);
await this.coreDataSource.transaction(
async (entityManager: WorkspaceEntityManager) => {
await this.seedRecordsInBatches({
entityManager,
schemaName,
workspaceId,
attachmentSeeds,
featureFlags,
objectMetadataItems,
});
@@ -327,7 +337,11 @@ export class DevSeederDataService {
workspaceId,
});
await this.seedAttachmentFiles(workspaceId);
await this.seedAttachmentFiles(
workspaceId,
entityManager,
attachmentFileMeta,
);
await prefillWorkflows(
entityManager,
@@ -343,16 +357,22 @@ export class DevSeederDataService {
entityManager,
schemaName,
workspaceId,
attachmentSeeds,
featureFlags,
objectMetadataItems,
}: {
entityManager: WorkspaceEntityManager;
schemaName: string;
workspaceId: string;
attachmentSeeds: RecordSeedConfig['recordSeeds'];
featureFlags?: Record<FeatureFlagKey, boolean>;
objectMetadataItems: FlatObjectMetadata[];
}) {
const batches = getRecordSeedsBatches(workspaceId, featureFlags);
const batches = getRecordSeedsBatches(
workspaceId,
attachmentSeeds,
featureFlags,
);
// Process batches sequentially (respecting dependencies)
// but entities within each batch in parallel
@@ -406,9 +426,11 @@ export class DevSeederDataService {
.execute();
}
private async seedAttachmentFiles(workspaceId: string): Promise<void> {
// Files are copied to dist/assets during build via nest-cli.json
// The pattern **/dev-seeder/data/sample-files/** preserves the full path
private async seedAttachmentFiles(
workspaceId: string,
entityManager: WorkspaceEntityManager,
fileSeedMetadata: AttachmentFileSeedMetadata[],
): Promise<void> {
const IS_BUILT = __dirname.includes('/dist/');
const sampleFilesDir = IS_BUILT
? join(
@@ -417,37 +439,38 @@ export class DevSeederDataService {
)
: join(__dirname, '../sample-files');
const filesToCreate = [
'sample-contract.pdf',
'budget-2024.xlsx',
'presentation.pptx',
'screenshot.png',
'archive.zip',
];
// Read each sample file once and cache the buffer
const sampleFileBuffers: Buffer[] = [];
for (const filename of filesToCreate) {
const filePath = join(sampleFilesDir, filename);
const fileBuffer = await readFile(filePath);
for (const sampleFile of ATTACHMENT_SAMPLE_FILES) {
const filePath = join(sampleFilesDir, sampleFile.filename);
await this.fileStorageService.writeFileLegacy({
file: fileBuffer,
name: filename,
folder: `workspace-${workspaceId}/attachment`,
mimeType: this.getMimeType(filename),
sampleFileBuffers.push(await readFile(filePath));
}
const fieldUniversalIdentifier =
STANDARD_OBJECTS.attachment.fields.file.universalIdentifier;
const applicationUniversalIdentifier =
TWENTY_STANDARD_APPLICATION.universalIdentifier;
for (const metadata of fileSeedMetadata) {
const resourcePath = `${metadata.fileId}.${metadata.extension}`;
const sourceFile = sampleFileBuffers[metadata.sampleFileIndex];
await this.fileStorageService.writeFile({
sourceFile,
mimeType: metadata.mimeType,
fileFolder: FileFolder.FilesField,
applicationUniversalIdentifier,
workspaceId,
resourcePath: `${fieldUniversalIdentifier}/${resourcePath}`,
fileId: metadata.fileId,
settings: {
isTemporaryFile: false,
toDelete: false,
},
queryRunner: entityManager.queryRunner,
});
}
}
private getMimeType(filename: string): string {
const ext = filename.split('.').pop()?.toLowerCase();
const mimeTypes: Record<string, string> = {
pdf: 'application/pdf',
xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
png: 'image/png',
zip: 'application/zip',
};
return mimeTypes[ext || ''] || 'application/octet-stream';
}
}
@@ -156,6 +156,7 @@ export const buildAttachmentStandardFlatFieldMetadatas = ({
label: 'Full path',
description: 'Attachment full path',
icon: 'IconLink',
isSystem: true,
isNullable: true,
isUIReadOnly: true,
},
@@ -174,6 +175,7 @@ export const buildAttachmentStandardFlatFieldMetadatas = ({
label: 'File category',
description: 'Attachment file category',
icon: 'IconList',
isSystem: true,
isNullable: false,
isUIReadOnly: true,
defaultValue: "'OTHER'",
@@ -261,9 +263,9 @@ export const buildAttachmentStandardFlatFieldMetadatas = ({
type: FieldMetadataType.MORPH_RELATION,
morphId: STANDARD_OBJECTS.attachment.morphIds.targetMorphId.morphId,
fieldName: 'targetTask',
label: 'Task',
description: 'Attachment task',
icon: 'IconNotes',
label: 'Target',
description: 'Attachment target',
icon: 'IconArrowUpRight',
isNullable: true,
isUIReadOnly: true,
targetObjectName: 'task',
@@ -286,9 +288,9 @@ export const buildAttachmentStandardFlatFieldMetadatas = ({
type: FieldMetadataType.MORPH_RELATION,
morphId: STANDARD_OBJECTS.attachment.morphIds.targetMorphId.morphId,
fieldName: 'targetNote',
label: 'Note',
description: 'Attachment note',
icon: 'IconNotes',
label: 'Target',
description: 'Attachment target',
icon: 'IconArrowUpRight',
isNullable: true,
isUIReadOnly: true,
targetObjectName: 'note',
@@ -311,9 +313,9 @@ export const buildAttachmentStandardFlatFieldMetadatas = ({
type: FieldMetadataType.MORPH_RELATION,
morphId: STANDARD_OBJECTS.attachment.morphIds.targetMorphId.morphId,
fieldName: 'targetPerson',
label: 'Person',
description: 'Attachment person',
icon: 'IconUser',
label: 'Target',
description: 'Attachment target',
icon: 'IconArrowUpRight',
isNullable: true,
isUIReadOnly: true,
targetObjectName: 'person',
@@ -336,9 +338,9 @@ export const buildAttachmentStandardFlatFieldMetadatas = ({
type: FieldMetadataType.MORPH_RELATION,
morphId: STANDARD_OBJECTS.attachment.morphIds.targetMorphId.morphId,
fieldName: 'targetCompany',
label: 'Company',
description: 'Attachment company',
icon: 'IconBuildingSkyscraper',
label: 'Target',
description: 'Attachment target',
icon: 'IconArrowUpRight',
isNullable: true,
isUIReadOnly: true,
targetObjectName: 'company',
@@ -361,9 +363,9 @@ export const buildAttachmentStandardFlatFieldMetadatas = ({
type: FieldMetadataType.MORPH_RELATION,
morphId: STANDARD_OBJECTS.attachment.morphIds.targetMorphId.morphId,
fieldName: 'targetOpportunity',
label: 'Opportunity',
description: 'Attachment opportunity',
icon: 'IconBuildingSkyscraper',
label: 'Target',
description: 'Attachment target',
icon: 'IconArrowUpRight',
isNullable: true,
isUIReadOnly: true,
targetObjectName: 'opportunity',
@@ -386,9 +388,9 @@ export const buildAttachmentStandardFlatFieldMetadatas = ({
type: FieldMetadataType.MORPH_RELATION,
morphId: STANDARD_OBJECTS.attachment.morphIds.targetMorphId.morphId,
fieldName: 'targetDashboard',
label: 'Dashboard',
description: 'Attachment dashboard',
icon: 'IconLayout',
label: 'Target',
description: 'Attachment target',
icon: 'IconArrowUpRight',
isNullable: true,
isUIReadOnly: true,
targetObjectName: 'dashboard',
@@ -411,9 +413,9 @@ export const buildAttachmentStandardFlatFieldMetadatas = ({
type: FieldMetadataType.MORPH_RELATION,
morphId: STANDARD_OBJECTS.attachment.morphIds.targetMorphId.morphId,
fieldName: 'targetWorkflow',
label: 'Workflow',
description: 'Attachment workflow',
icon: 'IconSettingsAutomation',
label: 'Target',
description: 'Attachment target',
icon: 'IconArrowUpRight',
isNullable: true,
isUIReadOnly: true,
targetObjectName: 'workflow',
@@ -141,9 +141,9 @@ export const buildNoteTargetStandardFlatFieldMetadatas = ({
type: FieldMetadataType.MORPH_RELATION,
morphId: STANDARD_OBJECTS.noteTarget.morphIds.targetMorphId.morphId,
fieldName: 'targetPerson',
label: 'Person',
description: 'NoteTarget person',
icon: 'IconUser',
label: 'Target',
description: 'NoteTarget target',
icon: 'IconArrowUpRight',
isNullable: true,
isUIReadOnly: true,
targetObjectName: 'person',
@@ -166,9 +166,9 @@ export const buildNoteTargetStandardFlatFieldMetadatas = ({
type: FieldMetadataType.MORPH_RELATION,
morphId: STANDARD_OBJECTS.noteTarget.morphIds.targetMorphId.morphId,
fieldName: 'targetCompany',
label: 'Company',
description: 'NoteTarget company',
icon: 'IconBuildingSkyscraper',
label: 'Target',
description: 'NoteTarget target',
icon: 'IconArrowUpRight',
isNullable: true,
isUIReadOnly: true,
targetObjectName: 'company',
@@ -191,9 +191,9 @@ export const buildNoteTargetStandardFlatFieldMetadatas = ({
type: FieldMetadataType.MORPH_RELATION,
morphId: STANDARD_OBJECTS.noteTarget.morphIds.targetMorphId.morphId,
fieldName: 'targetOpportunity',
label: 'Opportunity',
description: 'NoteTarget opportunity',
icon: 'IconTargetArrow',
label: 'Target',
description: 'NoteTarget target',
icon: 'IconArrowUpRight',
isNullable: true,
isUIReadOnly: true,
targetObjectName: 'opportunity',
@@ -141,9 +141,9 @@ export const buildTaskTargetStandardFlatFieldMetadatas = ({
type: FieldMetadataType.MORPH_RELATION,
morphId: STANDARD_OBJECTS.taskTarget.morphIds.targetMorphId.morphId,
fieldName: 'targetPerson',
label: 'Person',
description: 'TaskTarget person',
icon: 'IconUser',
label: 'Target',
description: 'TaskTarget target',
icon: 'IconArrowUpRight',
isNullable: true,
isUIReadOnly: true,
targetObjectName: 'person',
@@ -166,9 +166,9 @@ export const buildTaskTargetStandardFlatFieldMetadatas = ({
type: FieldMetadataType.MORPH_RELATION,
morphId: STANDARD_OBJECTS.taskTarget.morphIds.targetMorphId.morphId,
fieldName: 'targetCompany',
label: 'Company',
description: 'TaskTarget company',
icon: 'IconBuildingSkyscraper',
label: 'Target',
description: 'TaskTarget target',
icon: 'IconArrowUpRight',
isNullable: true,
isUIReadOnly: true,
targetObjectName: 'company',
@@ -191,9 +191,9 @@ export const buildTaskTargetStandardFlatFieldMetadatas = ({
type: FieldMetadataType.MORPH_RELATION,
morphId: STANDARD_OBJECTS.taskTarget.morphIds.targetMorphId.morphId,
fieldName: 'targetOpportunity',
label: 'Opportunity',
description: 'TaskTarget opportunity',
icon: 'IconTargetArrow',
label: 'Target',
description: 'TaskTarget target',
icon: 'IconArrowUpRight',
isNullable: true,
isUIReadOnly: true,
targetObjectName: 'opportunity',
@@ -167,6 +167,7 @@ export const buildTimelineActivityStandardFlatFieldMetadatas = ({
label: 'Linked Record cached name',
description: 'Cached record name',
icon: 'IconAbc',
isSystem: true,
isNullable: true,
isUIReadOnly: true,
},
@@ -184,6 +185,7 @@ export const buildTimelineActivityStandardFlatFieldMetadatas = ({
label: 'Linked Record id',
description: 'Linked Record id',
icon: 'IconAbc',
isSystem: true,
isNullable: true,
isUIReadOnly: true,
},
@@ -201,6 +203,7 @@ export const buildTimelineActivityStandardFlatFieldMetadatas = ({
label: 'Linked Object Metadata Id',
description: 'Linked Object Metadata Id',
icon: 'IconAbc',
isSystem: true,
isNullable: true,
isUIReadOnly: true,
},
@@ -243,9 +246,9 @@ export const buildTimelineActivityStandardFlatFieldMetadatas = ({
type: FieldMetadataType.MORPH_RELATION,
morphId: STANDARD_OBJECTS.timelineActivity.morphIds.targetMorphId.morphId,
fieldName: 'targetPerson',
label: 'Person',
description: 'Event person',
icon: 'IconUser',
label: 'Target',
description: 'Event target',
icon: 'IconArrowUpRight',
isNullable: true,
isUIReadOnly: true,
targetObjectName: 'person',
@@ -268,9 +271,9 @@ export const buildTimelineActivityStandardFlatFieldMetadatas = ({
type: FieldMetadataType.MORPH_RELATION,
morphId: STANDARD_OBJECTS.timelineActivity.morphIds.targetMorphId.morphId,
fieldName: 'targetCompany',
label: 'Company',
description: 'Event company',
icon: 'IconBuildingSkyscraper',
label: 'Target',
description: 'Event target',
icon: 'IconArrowUpRight',
isNullable: true,
isUIReadOnly: true,
targetObjectName: 'company',
@@ -293,9 +296,9 @@ export const buildTimelineActivityStandardFlatFieldMetadatas = ({
type: FieldMetadataType.MORPH_RELATION,
morphId: STANDARD_OBJECTS.timelineActivity.morphIds.targetMorphId.morphId,
fieldName: 'targetOpportunity',
label: 'Opportunity',
description: 'Event opportunity',
icon: 'IconTargetArrow',
label: 'Target',
description: 'Event target',
icon: 'IconArrowUpRight',
isNullable: true,
isUIReadOnly: true,
targetObjectName: 'opportunity',
@@ -318,9 +321,9 @@ export const buildTimelineActivityStandardFlatFieldMetadatas = ({
type: FieldMetadataType.MORPH_RELATION,
morphId: STANDARD_OBJECTS.timelineActivity.morphIds.targetMorphId.morphId,
fieldName: 'targetNote',
label: 'Note',
description: 'Event note',
icon: 'IconTargetArrow',
label: 'Target',
description: 'Event target',
icon: 'IconArrowUpRight',
isNullable: true,
isUIReadOnly: true,
targetObjectName: 'note',
@@ -343,9 +346,9 @@ export const buildTimelineActivityStandardFlatFieldMetadatas = ({
type: FieldMetadataType.MORPH_RELATION,
morphId: STANDARD_OBJECTS.timelineActivity.morphIds.targetMorphId.morphId,
fieldName: 'targetTask',
label: 'Task',
description: 'Event task',
icon: 'IconTargetArrow',
label: 'Target',
description: 'Event target',
icon: 'IconArrowUpRight',
isNullable: true,
isUIReadOnly: true,
targetObjectName: 'task',
@@ -368,9 +371,9 @@ export const buildTimelineActivityStandardFlatFieldMetadatas = ({
type: FieldMetadataType.MORPH_RELATION,
morphId: STANDARD_OBJECTS.timelineActivity.morphIds.targetMorphId.morphId,
fieldName: 'targetWorkflow',
label: 'Workflow',
description: 'Event workflow',
icon: 'IconTargetArrow',
label: 'Target',
description: 'Event target',
icon: 'IconArrowUpRight',
isNullable: true,
isUIReadOnly: true,
targetObjectName: 'workflow',
@@ -393,9 +396,9 @@ export const buildTimelineActivityStandardFlatFieldMetadatas = ({
type: FieldMetadataType.MORPH_RELATION,
morphId: STANDARD_OBJECTS.timelineActivity.morphIds.targetMorphId.morphId,
fieldName: 'targetWorkflowVersion',
label: 'WorkflowVersion',
description: 'Event workflow version',
icon: 'IconTargetArrow',
label: 'Target',
description: 'Event target',
icon: 'IconArrowUpRight',
isNullable: true,
isUIReadOnly: true,
targetObjectName: 'workflowVersion',
@@ -418,9 +421,9 @@ export const buildTimelineActivityStandardFlatFieldMetadatas = ({
type: FieldMetadataType.MORPH_RELATION,
morphId: STANDARD_OBJECTS.timelineActivity.morphIds.targetMorphId.morphId,
fieldName: 'targetWorkflowRun',
label: 'Workflow Run',
description: 'Event workflow run',
icon: 'IconTargetArrow',
label: 'Target',
description: 'Event target',
icon: 'IconArrowUpRight',
isNullable: true,
isUIReadOnly: true,
targetObjectName: 'workflowRun',
@@ -443,9 +446,9 @@ export const buildTimelineActivityStandardFlatFieldMetadatas = ({
type: FieldMetadataType.MORPH_RELATION,
morphId: STANDARD_OBJECTS.timelineActivity.morphIds.targetMorphId.morphId,
fieldName: 'targetDashboard',
label: 'Dashboard',
description: 'Event dashboard',
icon: 'IconTargetArrow',
label: 'Target',
description: 'Event target',
icon: 'IconArrowUpRight',
isNullable: true,
isUIReadOnly: true,
targetObjectName: 'dashboard',
@@ -444,6 +444,7 @@ export const buildWorkspaceMemberStandardFlatFieldMetadatas = ({
label: 'Favorites',
description: 'Favorites linked to the workspace member',
icon: 'IconHeart',
isSystem: true,
isNullable: false,
isUIReadOnly: true,
targetObjectName: 'favorite',
@@ -467,6 +468,7 @@ export const buildWorkspaceMemberStandardFlatFieldMetadatas = ({
label: 'Account Owner For Companies',
description: 'Account owner for companies',
icon: 'IconBriefcase',
isSystem: true,
isNullable: false,
isUIReadOnly: true,
targetObjectName: 'company',
@@ -490,6 +492,7 @@ export const buildWorkspaceMemberStandardFlatFieldMetadatas = ({
label: 'Connected accounts',
description: 'Connected accounts',
icon: 'IconAt',
isSystem: true,
isNullable: false,
isUIReadOnly: true,
targetObjectName: 'connectedAccount',
@@ -513,6 +516,7 @@ export const buildWorkspaceMemberStandardFlatFieldMetadatas = ({
label: 'Message Participants',
description: 'Message Participants',
icon: 'IconUserCircle',
isSystem: true,
isNullable: false,
isUIReadOnly: true,
targetObjectName: 'messageParticipant',
@@ -536,6 +540,7 @@ export const buildWorkspaceMemberStandardFlatFieldMetadatas = ({
label: 'Blocklist',
description: 'Blocklisted handles',
icon: 'IconForbid2',
isSystem: true,
isNullable: false,
isUIReadOnly: true,
targetObjectName: 'blocklist',
@@ -559,6 +564,7 @@ export const buildWorkspaceMemberStandardFlatFieldMetadatas = ({
label: 'Calendar Event Participants',
description: 'Calendar Event Participants',
icon: 'IconCalendar',
isSystem: true,
isNullable: false,
isUIReadOnly: true,
targetObjectName: 'calendarEventParticipant',
@@ -5,18 +5,23 @@ import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/typ
import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-maps-or-throw.util';
import { type FlatViewField } from 'src/engine/metadata-modules/flat-view-field/types/flat-view-field.type';
import { type AllStandardObjectName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-name.type';
import { computeStandardAttachmentViewFields } from 'src/engine/workspace-manager/twenty-standard-application/utils/view-field/compute-standard-attachment-view-fields.util';
import { computeStandardCalendarEventViewFields } from 'src/engine/workspace-manager/twenty-standard-application/utils/view-field/compute-standard-calendar-event-view-fields.util';
import { computeStandardCompanyViewFields } from 'src/engine/workspace-manager/twenty-standard-application/utils/view-field/compute-standard-company-view-fields.util';
import { computeStandardDashboardViewFields } from 'src/engine/workspace-manager/twenty-standard-application/utils/view-field/compute-standard-dashboard-view-fields.util';
import { computeStandardMessageThreadViewFields } from 'src/engine/workspace-manager/twenty-standard-application/utils/view-field/compute-standard-message-thread-view-fields.util';
import { computeStandardMessageViewFields } from 'src/engine/workspace-manager/twenty-standard-application/utils/view-field/compute-standard-message-view-fields.util';
import { computeStandardNoteTargetViewFields } from 'src/engine/workspace-manager/twenty-standard-application/utils/view-field/compute-standard-note-target-view-fields.util';
import { computeStandardNoteViewFields } from 'src/engine/workspace-manager/twenty-standard-application/utils/view-field/compute-standard-note-view-fields.util';
import { computeStandardOpportunityViewFields } from 'src/engine/workspace-manager/twenty-standard-application/utils/view-field/compute-standard-opportunity-view-fields.util';
import { computeStandardPersonViewFields } from 'src/engine/workspace-manager/twenty-standard-application/utils/view-field/compute-standard-person-view-fields.util';
import { computeStandardTaskTargetViewFields } from 'src/engine/workspace-manager/twenty-standard-application/utils/view-field/compute-standard-task-target-view-fields.util';
import { computeStandardTaskViewFields } from 'src/engine/workspace-manager/twenty-standard-application/utils/view-field/compute-standard-task-view-fields.util';
import { computeStandardTimelineActivityViewFields } from 'src/engine/workspace-manager/twenty-standard-application/utils/view-field/compute-standard-timeline-activity-view-fields.util';
import { computeStandardWorkflowRunViewFields } from 'src/engine/workspace-manager/twenty-standard-application/utils/view-field/compute-standard-workflow-run-view-fields.util';
import { computeStandardWorkflowVersionViewFields } from 'src/engine/workspace-manager/twenty-standard-application/utils/view-field/compute-standard-workflow-version-view-fields.util';
import { computeStandardWorkflowViewFields } from 'src/engine/workspace-manager/twenty-standard-application/utils/view-field/compute-standard-workflow-view-fields.util';
import { computeStandardWorkspaceMemberViewFields } from 'src/engine/workspace-manager/twenty-standard-application/utils/view-field/compute-standard-workspace-member-view-fields.util';
import { type CreateStandardViewFieldArgs } from 'src/engine/workspace-manager/twenty-standard-application/utils/view-field/create-standard-view-field-flat-metadata.util';
type StandardViewFieldBuilder<P extends AllStandardObjectName> = (
@@ -24,18 +29,23 @@ type StandardViewFieldBuilder<P extends AllStandardObjectName> = (
) => Record<string, FlatViewField>;
const STANDARD_FLAT_VIEW_FIELD_METADATA_BUILDERS_BY_OBJECT_NAME = {
attachment: computeStandardAttachmentViewFields,
calendarEvent: computeStandardCalendarEventViewFields,
company: computeStandardCompanyViewFields,
dashboard: computeStandardDashboardViewFields,
message: computeStandardMessageViewFields,
messageThread: computeStandardMessageThreadViewFields,
note: computeStandardNoteViewFields,
noteTarget: computeStandardNoteTargetViewFields,
opportunity: computeStandardOpportunityViewFields,
person: computeStandardPersonViewFields,
task: computeStandardTaskViewFields,
taskTarget: computeStandardTaskTargetViewFields,
timelineActivity: computeStandardTimelineActivityViewFields,
workflow: computeStandardWorkflowViewFields,
workflowRun: computeStandardWorkflowRunViewFields,
workflowVersion: computeStandardWorkflowVersionViewFields,
workspaceMember: computeStandardWorkspaceMemberViewFields,
} as const satisfies {
[P in AllStandardObjectName]?: StandardViewFieldBuilder<P>;
};
@@ -0,0 +1,145 @@
import { type FlatViewField } from 'src/engine/metadata-modules/flat-view-field/types/flat-view-field.type';
import {
createStandardViewFieldFlatMetadata,
type CreateStandardViewFieldArgs,
} from 'src/engine/workspace-manager/twenty-standard-application/utils/view-field/create-standard-view-field-flat-metadata.util';
export const computeStandardAttachmentViewFields = (
args: Omit<CreateStandardViewFieldArgs<'attachment'>, 'context'>,
): Record<string, FlatViewField> => {
return {
allAttachmentsName: createStandardViewFieldFlatMetadata({
...args,
objectName: 'attachment',
context: {
viewName: 'allAttachments',
viewFieldName: 'name',
fieldName: 'name',
position: 0,
isVisible: true,
size: 210,
},
}),
allAttachmentsFile: createStandardViewFieldFlatMetadata({
...args,
objectName: 'attachment',
context: {
viewName: 'allAttachments',
viewFieldName: 'file',
fieldName: 'file',
position: 1,
isVisible: true,
size: 150,
},
}),
// All morph targets are included so the surviving field after dedup always has a viewField
allAttachmentsTargetPerson: createStandardViewFieldFlatMetadata({
...args,
objectName: 'attachment',
context: {
viewName: 'allAttachments',
viewFieldName: 'targetPerson',
fieldName: 'targetPerson',
position: 2,
isVisible: true,
size: 150,
},
}),
allAttachmentsTargetCompany: createStandardViewFieldFlatMetadata({
...args,
objectName: 'attachment',
context: {
viewName: 'allAttachments',
viewFieldName: 'targetCompany',
fieldName: 'targetCompany',
position: 3,
isVisible: true,
size: 150,
},
}),
allAttachmentsTargetOpportunity: createStandardViewFieldFlatMetadata({
...args,
objectName: 'attachment',
context: {
viewName: 'allAttachments',
viewFieldName: 'targetOpportunity',
fieldName: 'targetOpportunity',
position: 4,
isVisible: true,
size: 150,
},
}),
allAttachmentsTargetTask: createStandardViewFieldFlatMetadata({
...args,
objectName: 'attachment',
context: {
viewName: 'allAttachments',
viewFieldName: 'targetTask',
fieldName: 'targetTask',
position: 5,
isVisible: true,
size: 150,
},
}),
allAttachmentsTargetNote: createStandardViewFieldFlatMetadata({
...args,
objectName: 'attachment',
context: {
viewName: 'allAttachments',
viewFieldName: 'targetNote',
fieldName: 'targetNote',
position: 6,
isVisible: true,
size: 150,
},
}),
allAttachmentsTargetDashboard: createStandardViewFieldFlatMetadata({
...args,
objectName: 'attachment',
context: {
viewName: 'allAttachments',
viewFieldName: 'targetDashboard',
fieldName: 'targetDashboard',
position: 7,
isVisible: true,
size: 150,
},
}),
allAttachmentsTargetWorkflow: createStandardViewFieldFlatMetadata({
...args,
objectName: 'attachment',
context: {
viewName: 'allAttachments',
viewFieldName: 'targetWorkflow',
fieldName: 'targetWorkflow',
position: 8,
isVisible: true,
size: 150,
},
}),
allAttachmentsCreatedBy: createStandardViewFieldFlatMetadata({
...args,
objectName: 'attachment',
context: {
viewName: 'allAttachments',
viewFieldName: 'createdBy',
fieldName: 'createdBy',
position: 9,
isVisible: true,
size: 150,
},
}),
allAttachmentsCreatedAt: createStandardViewFieldFlatMetadata({
...args,
objectName: 'attachment',
context: {
viewName: 'allAttachments',
viewFieldName: 'createdAt',
fieldName: 'createdAt',
position: 10,
isVisible: true,
size: 150,
},
}),
};
};
@@ -0,0 +1,74 @@
import { type FlatViewField } from 'src/engine/metadata-modules/flat-view-field/types/flat-view-field.type';
import {
createStandardViewFieldFlatMetadata,
type CreateStandardViewFieldArgs,
} from 'src/engine/workspace-manager/twenty-standard-application/utils/view-field/create-standard-view-field-flat-metadata.util';
export const computeStandardNoteTargetViewFields = (
args: Omit<CreateStandardViewFieldArgs<'noteTarget'>, 'context'>,
): Record<string, FlatViewField> => {
return {
// Label identifier for junction tables
allNoteTargetsId: createStandardViewFieldFlatMetadata({
...args,
objectName: 'noteTarget',
context: {
viewName: 'allNoteTargets',
viewFieldName: 'id',
fieldName: 'id',
position: 0,
isVisible: true,
size: 210,
},
}),
allNoteTargetsNote: createStandardViewFieldFlatMetadata({
...args,
objectName: 'noteTarget',
context: {
viewName: 'allNoteTargets',
viewFieldName: 'note',
fieldName: 'note',
position: 1,
isVisible: true,
size: 150,
},
}),
// All morph targets are included so the surviving field after dedup always has a viewField
allNoteTargetsTargetPerson: createStandardViewFieldFlatMetadata({
...args,
objectName: 'noteTarget',
context: {
viewName: 'allNoteTargets',
viewFieldName: 'targetPerson',
fieldName: 'targetPerson',
position: 2,
isVisible: true,
size: 150,
},
}),
allNoteTargetsTargetCompany: createStandardViewFieldFlatMetadata({
...args,
objectName: 'noteTarget',
context: {
viewName: 'allNoteTargets',
viewFieldName: 'targetCompany',
fieldName: 'targetCompany',
position: 3,
isVisible: true,
size: 150,
},
}),
allNoteTargetsTargetOpportunity: createStandardViewFieldFlatMetadata({
...args,
objectName: 'noteTarget',
context: {
viewName: 'allNoteTargets',
viewFieldName: 'targetOpportunity',
fieldName: 'targetOpportunity',
position: 4,
isVisible: true,
size: 150,
},
}),
};
};
@@ -0,0 +1,74 @@
import { type FlatViewField } from 'src/engine/metadata-modules/flat-view-field/types/flat-view-field.type';
import {
createStandardViewFieldFlatMetadata,
type CreateStandardViewFieldArgs,
} from 'src/engine/workspace-manager/twenty-standard-application/utils/view-field/create-standard-view-field-flat-metadata.util';
export const computeStandardTaskTargetViewFields = (
args: Omit<CreateStandardViewFieldArgs<'taskTarget'>, 'context'>,
): Record<string, FlatViewField> => {
return {
// Label identifier for junction tables
allTaskTargetsId: createStandardViewFieldFlatMetadata({
...args,
objectName: 'taskTarget',
context: {
viewName: 'allTaskTargets',
viewFieldName: 'id',
fieldName: 'id',
position: 0,
isVisible: true,
size: 210,
},
}),
allTaskTargetsTask: createStandardViewFieldFlatMetadata({
...args,
objectName: 'taskTarget',
context: {
viewName: 'allTaskTargets',
viewFieldName: 'task',
fieldName: 'task',
position: 1,
isVisible: true,
size: 150,
},
}),
// All morph targets are included so the surviving field after dedup always has a viewField
allTaskTargetsTargetPerson: createStandardViewFieldFlatMetadata({
...args,
objectName: 'taskTarget',
context: {
viewName: 'allTaskTargets',
viewFieldName: 'targetPerson',
fieldName: 'targetPerson',
position: 2,
isVisible: true,
size: 150,
},
}),
allTaskTargetsTargetCompany: createStandardViewFieldFlatMetadata({
...args,
objectName: 'taskTarget',
context: {
viewName: 'allTaskTargets',
viewFieldName: 'targetCompany',
fieldName: 'targetCompany',
position: 3,
isVisible: true,
size: 150,
},
}),
allTaskTargetsTargetOpportunity: createStandardViewFieldFlatMetadata({
...args,
objectName: 'taskTarget',
context: {
viewName: 'allTaskTargets',
viewFieldName: 'targetOpportunity',
fieldName: 'targetOpportunity',
position: 4,
isVisible: true,
size: 150,
},
}),
};
};
@@ -0,0 +1,162 @@
import { type FlatViewField } from 'src/engine/metadata-modules/flat-view-field/types/flat-view-field.type';
import {
createStandardViewFieldFlatMetadata,
type CreateStandardViewFieldArgs,
} from 'src/engine/workspace-manager/twenty-standard-application/utils/view-field/create-standard-view-field-flat-metadata.util';
export const computeStandardTimelineActivityViewFields = (
args: Omit<CreateStandardViewFieldArgs<'timelineActivity'>, 'context'>,
): Record<string, FlatViewField> => {
return {
allTimelineActivitiesName: createStandardViewFieldFlatMetadata({
...args,
objectName: 'timelineActivity',
context: {
viewName: 'allTimelineActivities',
viewFieldName: 'name',
fieldName: 'name',
position: 0,
isVisible: true,
size: 210,
},
}),
allTimelineActivitiesHappensAt: createStandardViewFieldFlatMetadata({
...args,
objectName: 'timelineActivity',
context: {
viewName: 'allTimelineActivities',
viewFieldName: 'happensAt',
fieldName: 'happensAt',
position: 1,
isVisible: true,
size: 150,
},
}),
// All morph targets are included so the surviving field after dedup always has a viewField
allTimelineActivitiesTargetPerson: createStandardViewFieldFlatMetadata({
...args,
objectName: 'timelineActivity',
context: {
viewName: 'allTimelineActivities',
viewFieldName: 'targetPerson',
fieldName: 'targetPerson',
position: 2,
isVisible: true,
size: 150,
},
}),
allTimelineActivitiesTargetCompany: createStandardViewFieldFlatMetadata({
...args,
objectName: 'timelineActivity',
context: {
viewName: 'allTimelineActivities',
viewFieldName: 'targetCompany',
fieldName: 'targetCompany',
position: 3,
isVisible: true,
size: 150,
},
}),
allTimelineActivitiesTargetOpportunity: createStandardViewFieldFlatMetadata(
{
...args,
objectName: 'timelineActivity',
context: {
viewName: 'allTimelineActivities',
viewFieldName: 'targetOpportunity',
fieldName: 'targetOpportunity',
position: 4,
isVisible: true,
size: 150,
},
},
),
allTimelineActivitiesTargetTask: createStandardViewFieldFlatMetadata({
...args,
objectName: 'timelineActivity',
context: {
viewName: 'allTimelineActivities',
viewFieldName: 'targetTask',
fieldName: 'targetTask',
position: 5,
isVisible: true,
size: 150,
},
}),
allTimelineActivitiesTargetNote: createStandardViewFieldFlatMetadata({
...args,
objectName: 'timelineActivity',
context: {
viewName: 'allTimelineActivities',
viewFieldName: 'targetNote',
fieldName: 'targetNote',
position: 6,
isVisible: true,
size: 150,
},
}),
allTimelineActivitiesTargetWorkflow: createStandardViewFieldFlatMetadata({
...args,
objectName: 'timelineActivity',
context: {
viewName: 'allTimelineActivities',
viewFieldName: 'targetWorkflow',
fieldName: 'targetWorkflow',
position: 7,
isVisible: true,
size: 150,
},
}),
allTimelineActivitiesTargetWorkflowVersion:
createStandardViewFieldFlatMetadata({
...args,
objectName: 'timelineActivity',
context: {
viewName: 'allTimelineActivities',
viewFieldName: 'targetWorkflowVersion',
fieldName: 'targetWorkflowVersion',
position: 8,
isVisible: true,
size: 150,
},
}),
allTimelineActivitiesTargetWorkflowRun: createStandardViewFieldFlatMetadata(
{
...args,
objectName: 'timelineActivity',
context: {
viewName: 'allTimelineActivities',
viewFieldName: 'targetWorkflowRun',
fieldName: 'targetWorkflowRun',
position: 9,
isVisible: true,
size: 150,
},
},
),
allTimelineActivitiesTargetDashboard: createStandardViewFieldFlatMetadata({
...args,
objectName: 'timelineActivity',
context: {
viewName: 'allTimelineActivities',
viewFieldName: 'targetDashboard',
fieldName: 'targetDashboard',
position: 10,
isVisible: true,
size: 150,
},
}),
allTimelineActivitiesWorkspaceMember: createStandardViewFieldFlatMetadata({
...args,
objectName: 'timelineActivity',
context: {
viewName: 'allTimelineActivities',
viewFieldName: 'workspaceMember',
fieldName: 'workspaceMember',
position: 11,
isVisible: true,
size: 150,
},
}),
};
};
@@ -0,0 +1,60 @@
import { type FlatViewField } from 'src/engine/metadata-modules/flat-view-field/types/flat-view-field.type';
import {
createStandardViewFieldFlatMetadata,
type CreateStandardViewFieldArgs,
} from 'src/engine/workspace-manager/twenty-standard-application/utils/view-field/create-standard-view-field-flat-metadata.util';
export const computeStandardWorkspaceMemberViewFields = (
args: Omit<CreateStandardViewFieldArgs<'workspaceMember'>, 'context'>,
): Record<string, FlatViewField> => {
return {
allWorkspaceMembersName: createStandardViewFieldFlatMetadata({
...args,
objectName: 'workspaceMember',
context: {
viewName: 'allWorkspaceMembers',
viewFieldName: 'name',
fieldName: 'name',
position: 0,
isVisible: true,
size: 210,
},
}),
allWorkspaceMembersCreatedAt: createStandardViewFieldFlatMetadata({
...args,
objectName: 'workspaceMember',
context: {
viewName: 'allWorkspaceMembers',
viewFieldName: 'createdAt',
fieldName: 'createdAt',
position: 1,
isVisible: true,
size: 150,
},
}),
allWorkspaceMembersOwnedOpportunities: createStandardViewFieldFlatMetadata({
...args,
objectName: 'workspaceMember',
context: {
viewName: 'allWorkspaceMembers',
viewFieldName: 'ownedOpportunities',
fieldName: 'ownedOpportunities',
position: 2,
isVisible: true,
size: 150,
},
}),
allWorkspaceMembersAssignedTasks: createStandardViewFieldFlatMetadata({
...args,
objectName: 'workspaceMember',
context: {
viewName: 'allWorkspaceMembers',
viewFieldName: 'assignedTasks',
fieldName: 'assignedTasks',
position: 3,
isVisible: true,
size: 150,
},
}),
};
};
@@ -4,18 +4,23 @@ import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/metadata-module
import { type FlatView } from 'src/engine/metadata-modules/flat-view/types/flat-view.type';
import { ViewType } from 'src/engine/metadata-modules/view/enums/view-type.enum';
import { type AllStandardObjectName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-name.type';
import { computeStandardAttachmentViews } from 'src/engine/workspace-manager/twenty-standard-application/utils/view/compute-standard-attachment-views.util';
import { computeStandardCalendarEventViews } from 'src/engine/workspace-manager/twenty-standard-application/utils/view/compute-standard-calendar-event-views.util';
import { computeStandardCompanyViews } from 'src/engine/workspace-manager/twenty-standard-application/utils/view/compute-standard-company-views.util';
import { computeStandardDashboardViews } from 'src/engine/workspace-manager/twenty-standard-application/utils/view/compute-standard-dashboard-views.util';
import { computeStandardMessageThreadViews } from 'src/engine/workspace-manager/twenty-standard-application/utils/view/compute-standard-message-thread-views.util';
import { computeStandardMessageViews } from 'src/engine/workspace-manager/twenty-standard-application/utils/view/compute-standard-message-views.util';
import { computeStandardNoteTargetViews } from 'src/engine/workspace-manager/twenty-standard-application/utils/view/compute-standard-note-target-views.util';
import { computeStandardNoteViews } from 'src/engine/workspace-manager/twenty-standard-application/utils/view/compute-standard-note-views.util';
import { computeStandardOpportunityViews } from 'src/engine/workspace-manager/twenty-standard-application/utils/view/compute-standard-opportunity-views.util';
import { computeStandardPersonViews } from 'src/engine/workspace-manager/twenty-standard-application/utils/view/compute-standard-person-views.util';
import { computeStandardTaskTargetViews } from 'src/engine/workspace-manager/twenty-standard-application/utils/view/compute-standard-task-target-views.util';
import { computeStandardTaskViews } from 'src/engine/workspace-manager/twenty-standard-application/utils/view/compute-standard-task-views.util';
import { computeStandardTimelineActivityViews } from 'src/engine/workspace-manager/twenty-standard-application/utils/view/compute-standard-timeline-activity-views.util';
import { computeStandardWorkflowRunViews } from 'src/engine/workspace-manager/twenty-standard-application/utils/view/compute-standard-workflow-run-views.util';
import { computeStandardWorkflowVersionViews } from 'src/engine/workspace-manager/twenty-standard-application/utils/view/compute-standard-workflow-version-views.util';
import { computeStandardWorkflowViews } from 'src/engine/workspace-manager/twenty-standard-application/utils/view/compute-standard-workflow-views.util';
import { computeStandardWorkspaceMemberViews } from 'src/engine/workspace-manager/twenty-standard-application/utils/view/compute-standard-workspace-member-views.util';
import { type CreateStandardViewArgs } from 'src/engine/workspace-manager/twenty-standard-application/utils/view/create-standard-view-flat-metadata.util';
type StandardViewBuilder<P extends AllStandardObjectName> = (
@@ -23,18 +28,23 @@ type StandardViewBuilder<P extends AllStandardObjectName> = (
) => Record<string, FlatView>;
const STANDARD_FLAT_VIEW_METADATA_BUILDERS_BY_OBJECT_NAME = {
attachment: computeStandardAttachmentViews,
calendarEvent: computeStandardCalendarEventViews,
company: computeStandardCompanyViews,
dashboard: computeStandardDashboardViews,
message: computeStandardMessageViews,
messageThread: computeStandardMessageThreadViews,
note: computeStandardNoteViews,
noteTarget: computeStandardNoteTargetViews,
opportunity: computeStandardOpportunityViews,
person: computeStandardPersonViews,
task: computeStandardTaskViews,
taskTarget: computeStandardTaskTargetViews,
timelineActivity: computeStandardTimelineActivityViews,
workflow: computeStandardWorkflowViews,
workflowRun: computeStandardWorkflowRunViews,
workflowVersion: computeStandardWorkflowVersionViews,
workspaceMember: computeStandardWorkspaceMemberViews,
} as const satisfies {
[P in AllStandardObjectName]?: StandardViewBuilder<P>;
};
@@ -0,0 +1,26 @@
import { type FlatView } from 'src/engine/metadata-modules/flat-view/types/flat-view.type';
import { ViewKey } from 'src/engine/metadata-modules/view/enums/view-key.enum';
import { ViewType } from 'src/engine/metadata-modules/view/enums/view-type.enum';
import {
createStandardViewFlatMetadata,
type CreateStandardViewArgs,
} from 'src/engine/workspace-manager/twenty-standard-application/utils/view/create-standard-view-flat-metadata.util';
export const computeStandardAttachmentViews = (
args: Omit<CreateStandardViewArgs<'attachment'>, 'context'>,
): Record<string, FlatView> => {
return {
allAttachments: createStandardViewFlatMetadata({
...args,
objectName: 'attachment',
context: {
viewName: 'allAttachments',
name: 'All Attachments',
type: ViewType.TABLE,
key: ViewKey.INDEX,
position: 0,
icon: 'IconList',
},
}),
};
};
@@ -0,0 +1,26 @@
import { type FlatView } from 'src/engine/metadata-modules/flat-view/types/flat-view.type';
import { ViewKey } from 'src/engine/metadata-modules/view/enums/view-key.enum';
import { ViewType } from 'src/engine/metadata-modules/view/enums/view-type.enum';
import {
createStandardViewFlatMetadata,
type CreateStandardViewArgs,
} from 'src/engine/workspace-manager/twenty-standard-application/utils/view/create-standard-view-flat-metadata.util';
export const computeStandardNoteTargetViews = (
args: Omit<CreateStandardViewArgs<'noteTarget'>, 'context'>,
): Record<string, FlatView> => {
return {
allNoteTargets: createStandardViewFlatMetadata({
...args,
objectName: 'noteTarget',
context: {
viewName: 'allNoteTargets',
name: 'All Note Targets',
type: ViewType.TABLE,
key: ViewKey.INDEX,
position: 0,
icon: 'IconList',
},
}),
};
};
@@ -0,0 +1,26 @@
import { type FlatView } from 'src/engine/metadata-modules/flat-view/types/flat-view.type';
import { ViewKey } from 'src/engine/metadata-modules/view/enums/view-key.enum';
import { ViewType } from 'src/engine/metadata-modules/view/enums/view-type.enum';
import {
createStandardViewFlatMetadata,
type CreateStandardViewArgs,
} from 'src/engine/workspace-manager/twenty-standard-application/utils/view/create-standard-view-flat-metadata.util';
export const computeStandardTaskTargetViews = (
args: Omit<CreateStandardViewArgs<'taskTarget'>, 'context'>,
): Record<string, FlatView> => {
return {
allTaskTargets: createStandardViewFlatMetadata({
...args,
objectName: 'taskTarget',
context: {
viewName: 'allTaskTargets',
name: 'All Task Targets',
type: ViewType.TABLE,
key: ViewKey.INDEX,
position: 0,
icon: 'IconList',
},
}),
};
};
@@ -0,0 +1,26 @@
import { type FlatView } from 'src/engine/metadata-modules/flat-view/types/flat-view.type';
import { ViewKey } from 'src/engine/metadata-modules/view/enums/view-key.enum';
import { ViewType } from 'src/engine/metadata-modules/view/enums/view-type.enum';
import {
createStandardViewFlatMetadata,
type CreateStandardViewArgs,
} from 'src/engine/workspace-manager/twenty-standard-application/utils/view/create-standard-view-flat-metadata.util';
export const computeStandardTimelineActivityViews = (
args: Omit<CreateStandardViewArgs<'timelineActivity'>, 'context'>,
): Record<string, FlatView> => {
return {
allTimelineActivities: createStandardViewFlatMetadata({
...args,
objectName: 'timelineActivity',
context: {
viewName: 'allTimelineActivities',
name: 'All Timeline Activities',
type: ViewType.TABLE,
key: ViewKey.INDEX,
position: 0,
icon: 'IconList',
},
}),
};
};
@@ -0,0 +1,26 @@
import { type FlatView } from 'src/engine/metadata-modules/flat-view/types/flat-view.type';
import { ViewKey } from 'src/engine/metadata-modules/view/enums/view-key.enum';
import { ViewType } from 'src/engine/metadata-modules/view/enums/view-type.enum';
import {
createStandardViewFlatMetadata,
type CreateStandardViewArgs,
} from 'src/engine/workspace-manager/twenty-standard-application/utils/view/create-standard-view-flat-metadata.util';
export const computeStandardWorkspaceMemberViews = (
args: Omit<CreateStandardViewArgs<'workspaceMember'>, 'context'>,
): Record<string, FlatView> => {
return {
allWorkspaceMembers: createStandardViewFlatMetadata({
...args,
objectName: 'workspaceMember',
context: {
viewName: 'allWorkspaceMembers',
name: 'All Workspace Members',
type: ViewType.TABLE,
key: ViewKey.INDEX,
position: 0,
icon: 'IconList',
},
}),
};
};