[WIP] Feat/marketing emails (#21173)
Marketing/campaign emails on top of the emailing-domain (SES) feature:
send a broadcast to a hand-picked list, with per-customer-domain
unsubscribe links and opt-out-only **unsubscribe topics**.
## Model
Standard objects (workspace schema, flat-metadata):
- `messageCampaign` — a campaign send (subject, body template, from
address, status, list, optional unsubscribe topic).
- `messageList` + `messageListMember` — the hand-picked audience (person
↔ list join). A campaign's recipients are its list's members; everyone
is sendable unless suppressed.
Core entities (`core` schema, workspace-scoped — readable by the public
unsubscribe flow without a workspace context):
- `unsubscribeTopic` — an opt-out-only category (name, description,
visibility). There is no opt-in subscription state.
- `messageSuppression` — the single consent store: a row with
`unsubscribeTopicId` NULL is a global block; a row with an
`unsubscribeTopicId` and reason `UNSUBSCRIBE` is a per-topic opt-out.
Two partial unique indexes dedupe global vs per-topic rows (Postgres
treats NULLs as distinct).
- `emailingDomain` — the workspace's SES sending domain,
auto-provisioned when an email channel is added (and cleaned up when its
last channel is removed), with verification status + DNS records.
Campaign messages reuse the existing `message` / `messageThread` /
`messageParticipant` model — one outbound `message` per recipient with a
`deliveryStatus` state machine.
## Sending
- `sendMessageCampaign` resolves the audience **under the caller's
permissions**, creates the campaign, and enqueues a single fan-out job
(the request never materializes per-recipient rows or jobs).
- The fan-out job materializes one QUEUED message per recipient
(deterministic ids → idempotent re-runs, reconciles crash-orphaned rows)
and fans out per-recipient send jobs carrying **only ids**.
- Each send job renders per-recipient `{{variable}}` merge fields and
sends via `EmailingDomainSenderService`, which applies suppression
(global + per-topic) and the unsubscribe footer/headers. Suppressed
recipients are recorded `SKIPPED`.
- The campaign finalizes `SENT`, or `SENT_WITH_ERRORS` if any recipient
terminally failed.
- `previewMessageCampaignAudience` returns a pre-send breakdown (total /
without-email / duplicate / globally-unsubscribed / topic-unsubscribed /
sendable), shown as a hint under the composer pickers.
## Unsubscribe
- Encrypted (AES-256-GCM) token carrying workspaceId, address, optional
`unsubscribeTopicId`, `issuedAt`, and a `preview` flag.
- One-click POST (RFC 8058) + `mailto:` — topic-scoped when the token
carries a topic, global otherwise.
- Preferences page: a checkbox per visible topic (checked = still
receiving); submitting creates per-topic opt-outs for unchecked topics
and lifts re-checked ones (UNSUBSCRIBE only — never
`BOUNCE`/`COMPLAINT`, never a global block).
- A **Preview** action in settings opens the live page via a
preview-claim token; opt-out POSTs are no-ops for preview tokens, so
previewing never mutates state.
- SES webhooks: inbound unsubscribe + outbound bounce/complaint →
suppression (race-safe against at-least-once delivery, with reason
escalation that never downgrades).
- Per-customer unsubscribe hostname (Cloudflare DNS); sends are gated on
it being active, except in LOG/demo mode.
## Architecture
Campaign orchestration, suppression, the sender, the unsubscribe
controller, and the SES webhook handlers live in `src/modules/emailing`
+ `src/modules/messaging-webhooks` (the workspace-feature layer).
`core-modules/emailing-domain` keeps the SES driver, domain
provisioning, the `unsubscribeTopic` / `messageSuppression` core
entities, and the unsubscribe token/hostname plumbing. Domain creation
is validated (`CreateEmailingDomainInput` — domain-format regex,
lowercased) before any value reaches SES or the unsubscribe hostname.
## Frontend
- Campaign composer side panel (from / list / unsubscribe topic /
subject / body) with a live audience-preview hint.
- Email settings: email channels each showing their auto-provisioned
sending domain in a single section (status + DNS records + a "Check
verification" action), plus an **Unsubscribe Topics** section to
create/manage topics and preview the recipient page. A demo-mode banner
is shown when the LOG driver is active.
---------
Co-authored-by: Félix Malfait <felix@twenty.com>
Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
This commit is contained in:
+2
@@ -5,4 +5,6 @@ export const MESSAGE_CHANNEL_DATA_SEED_IDS = {
|
||||
JANE: '20202020-8c4d-4e71-a672-2e6a8c9f1b3d',
|
||||
SUPPORT: '20202020-e2f1-49b5-85d2-5d3a3386990d',
|
||||
SALES: '20202020-e2f1-49b5-85d2-5d3a3386990e',
|
||||
SUPPORT_GROUP: '20202020-5a1e-4b2c-9d3e-200000000001',
|
||||
CONTACT_GROUP: '20202020-5a1e-4b2c-9d3e-200000000002',
|
||||
} as const;
|
||||
|
||||
+31
-3
@@ -7,6 +7,15 @@ const tableName = 'emailingDomain';
|
||||
|
||||
const DEV_EMAILING_DOMAIN = 'dev.twenty.local';
|
||||
|
||||
export const getSeededEmailGroupDomains = (workspaceId: string) => {
|
||||
const prefix = workspaceId.slice(0, 8);
|
||||
|
||||
return {
|
||||
verified: `${prefix}.${DEV_EMAILING_DOMAIN}`,
|
||||
pending: `${prefix}.pending.${DEV_EMAILING_DOMAIN}`,
|
||||
};
|
||||
};
|
||||
|
||||
type SeedEmailingDomainsArgs = {
|
||||
queryRunner: QueryRunner;
|
||||
schemaName: string;
|
||||
@@ -18,7 +27,7 @@ export const seedEmailingDomains = async ({
|
||||
schemaName,
|
||||
workspaceId,
|
||||
}: SeedEmailingDomainsArgs) => {
|
||||
const domain = `${workspaceId.slice(0, 8)}.${DEV_EMAILING_DOMAIN}`;
|
||||
const { verified, pending } = getSeededEmailGroupDomains(workspaceId);
|
||||
|
||||
await queryRunner.manager
|
||||
.createQueryBuilder()
|
||||
@@ -35,12 +44,31 @@ export const seedEmailingDomains = async ({
|
||||
.values([
|
||||
{
|
||||
workspaceId,
|
||||
domain,
|
||||
domain: verified,
|
||||
status: EmailingDomainStatus.VERIFIED,
|
||||
verificationRecords: JSON.stringify([]),
|
||||
verificationRecords: [],
|
||||
verifiedAt: new Date(),
|
||||
tenantStatus: EmailingDomainTenantStatus.ACTIVE,
|
||||
},
|
||||
{
|
||||
workspaceId,
|
||||
domain: pending,
|
||||
status: EmailingDomainStatus.PENDING,
|
||||
verificationRecords: [
|
||||
{
|
||||
type: 'TXT',
|
||||
key: `_amazonses.${pending}`,
|
||||
value: 'seed-verification-token',
|
||||
},
|
||||
{
|
||||
type: 'CNAME',
|
||||
key: `seed1._domainkey.${pending}`,
|
||||
value: 'seed1.dkim.amazonses.com',
|
||||
},
|
||||
],
|
||||
verifiedAt: null,
|
||||
tenantStatus: EmailingDomainTenantStatus.ACTIVE,
|
||||
},
|
||||
])
|
||||
.execute();
|
||||
};
|
||||
|
||||
+114
@@ -16,6 +16,8 @@ import { USER_WORKSPACE_DATA_SEED_IDS } from 'src/engine/workspace-manager/dev-s
|
||||
import { CALENDAR_CHANNEL_DATA_SEED_IDS } from 'src/engine/workspace-manager/dev-seeder/core/constants/calendar-channel-seed-ids.constant';
|
||||
import { MESSAGE_CHANNEL_DATA_SEED_IDS } from 'src/engine/workspace-manager/dev-seeder/core/constants/message-channel-seed-ids.constant';
|
||||
import { MESSAGE_FOLDER_DATA_SEED_IDS } from 'src/engine/workspace-manager/dev-seeder/core/constants/message-folder-seed-ids.constant';
|
||||
import { UnsubscribeTopicVisibility } from 'src/engine/core-modules/emailing-domain/types/unsubscribe-topic-visibility.type';
|
||||
import { getSeededEmailGroupDomains } from 'src/engine/workspace-manager/dev-seeder/core/utils/seed-emailing-domains.util';
|
||||
import { CONNECTED_ACCOUNT_DATA_SEED_IDS } from 'src/engine/workspace-manager/dev-seeder/data/constants/connected-account-data-seeds.constant';
|
||||
|
||||
type SeedMetadataEntitiesArgs = {
|
||||
@@ -31,6 +33,8 @@ const YC_CONNECTED_ACCOUNT_IDS = {
|
||||
PHIL: '30303030-cafc-4323-908d-e5b42ad69fdf',
|
||||
JANE: '30303030-b5c7-46f0-bf5c-3f4e4b3f7c1a',
|
||||
JANE_DELETABLE: '30303030-d1e5-4a8f-9c3b-7f6d5e4c3b2a',
|
||||
SUPPORT_GROUP: '30303030-5a1e-4b2c-9d3e-100000000001',
|
||||
CONTACT_GROUP: '30303030-5a1e-4b2c-9d3e-100000000002',
|
||||
};
|
||||
|
||||
const YC_MESSAGE_CHANNEL_IDS = {
|
||||
@@ -40,6 +44,8 @@ const YC_MESSAGE_CHANNEL_IDS = {
|
||||
JANE: '30303030-8c4d-4e71-a672-2e6a8c9f1b3d',
|
||||
SUPPORT: '30303030-e2f1-49b5-85d2-5d3a3386990d',
|
||||
SALES: '30303030-e2f1-49b5-85d2-5d3a3386990e',
|
||||
SUPPORT_GROUP: '30303030-5a1e-4b2c-9d3e-200000000001',
|
||||
CONTACT_GROUP: '30303030-5a1e-4b2c-9d3e-200000000002',
|
||||
} as const;
|
||||
|
||||
const YC_CALENDAR_CHANNEL_IDS = {
|
||||
@@ -59,6 +65,18 @@ const YC_MESSAGE_FOLDER_IDS = {
|
||||
JANE_SENT: '30303030-1234-4567-8901-abcdef012348',
|
||||
} as const;
|
||||
|
||||
const APPLE_UNSUBSCRIBE_TOPIC_IDS = {
|
||||
PRODUCT_UPDATES: '20202020-7b1c-4a2d-8e3f-300000000001',
|
||||
NEWSLETTER: '20202020-7b1c-4a2d-8e3f-300000000002',
|
||||
TRANSACTIONAL: '20202020-7b1c-4a2d-8e3f-300000000003',
|
||||
} as const;
|
||||
|
||||
const YC_UNSUBSCRIBE_TOPIC_IDS = {
|
||||
PRODUCT_UPDATES: '30303030-7b1c-4a2d-8e3f-300000000001',
|
||||
NEWSLETTER: '30303030-7b1c-4a2d-8e3f-300000000002',
|
||||
TRANSACTIONAL: '30303030-7b1c-4a2d-8e3f-300000000003',
|
||||
} as const;
|
||||
|
||||
const getSeedIds = (workspaceId: string) => {
|
||||
if (workspaceId === SEED_YCOMBINATOR_WORKSPACE_ID) {
|
||||
return {
|
||||
@@ -72,6 +90,7 @@ const getSeedIds = (workspaceId: string) => {
|
||||
messageChannelIds: YC_MESSAGE_CHANNEL_IDS,
|
||||
calendarChannelIds: YC_CALENDAR_CHANNEL_IDS,
|
||||
messageFolderIds: YC_MESSAGE_FOLDER_IDS,
|
||||
unsubscribeTopicIds: YC_UNSUBSCRIBE_TOPIC_IDS,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -86,6 +105,7 @@ const getSeedIds = (workspaceId: string) => {
|
||||
messageChannelIds: MESSAGE_CHANNEL_DATA_SEED_IDS,
|
||||
calendarChannelIds: CALENDAR_CHANNEL_DATA_SEED_IDS,
|
||||
messageFolderIds: MESSAGE_FOLDER_DATA_SEED_IDS,
|
||||
unsubscribeTopicIds: APPLE_UNSUBSCRIBE_TOPIC_IDS,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -103,6 +123,7 @@ export const seedMetadataEntities = async ({
|
||||
|
||||
await seedConnectedAccounts({ queryRunner, schemaName, workspaceId });
|
||||
await seedMessageChannels({ queryRunner, schemaName, workspaceId });
|
||||
await seedUnsubscribeTopics({ queryRunner, schemaName, workspaceId });
|
||||
await seedCalendarChannels({ queryRunner, schemaName, workspaceId });
|
||||
await seedMessageFolders({ queryRunner, schemaName, workspaceId });
|
||||
};
|
||||
@@ -113,6 +134,7 @@ const seedConnectedAccounts = async ({
|
||||
workspaceId,
|
||||
}: SeedMetadataEntitiesArgs) => {
|
||||
const ids = getSeedIds(workspaceId);
|
||||
const emailGroupDomains = getSeededEmailGroupDomains(workspaceId);
|
||||
|
||||
const connectedAccounts = [
|
||||
{
|
||||
@@ -150,6 +172,20 @@ const seedConnectedAccounts = async ({
|
||||
userWorkspaceId: ids.userWorkspaceIds.JANE,
|
||||
workspaceId,
|
||||
},
|
||||
{
|
||||
id: ids.connectedAccountIds.SUPPORT_GROUP,
|
||||
handle: `support@${emailGroupDomains.verified}`,
|
||||
provider: 'email_group',
|
||||
userWorkspaceId: ids.userWorkspaceIds.TIM,
|
||||
workspaceId,
|
||||
},
|
||||
{
|
||||
id: ids.connectedAccountIds.CONTACT_GROUP,
|
||||
handle: `contact@${emailGroupDomains.pending}`,
|
||||
provider: 'email_group',
|
||||
userWorkspaceId: ids.userWorkspaceIds.TIM,
|
||||
workspaceId,
|
||||
},
|
||||
];
|
||||
|
||||
await queryRunner.manager
|
||||
@@ -271,6 +307,38 @@ const seedMessageChannels = async ({
|
||||
connectedAccountId: ids.connectedAccountIds.TIM,
|
||||
workspaceId,
|
||||
},
|
||||
{
|
||||
id: ids.messageChannelIds.SUPPORT_GROUP,
|
||||
handle: 'emailgroup-support@demo.invalid',
|
||||
visibility: MessageChannelVisibility.SHARE_EVERYTHING,
|
||||
type: MessageChannelType.EMAIL_GROUP,
|
||||
syncStage: MessageChannelSyncStage.MESSAGE_LIST_FETCH_PENDING,
|
||||
isContactAutoCreationEnabled: true,
|
||||
contactAutoCreationPolicy: 'SENT_AND_RECEIVED',
|
||||
messageFolderImportPolicy: 'ALL_FOLDERS',
|
||||
excludeNonProfessionalEmails: false,
|
||||
excludeGroupEmails: false,
|
||||
pendingGroupEmailsAction: 'NONE',
|
||||
isSyncEnabled: true,
|
||||
connectedAccountId: ids.connectedAccountIds.SUPPORT_GROUP,
|
||||
workspaceId,
|
||||
},
|
||||
{
|
||||
id: ids.messageChannelIds.CONTACT_GROUP,
|
||||
handle: 'emailgroup-contact@demo.invalid',
|
||||
visibility: MessageChannelVisibility.SHARE_EVERYTHING,
|
||||
type: MessageChannelType.EMAIL_GROUP,
|
||||
syncStage: MessageChannelSyncStage.MESSAGE_LIST_FETCH_PENDING,
|
||||
isContactAutoCreationEnabled: true,
|
||||
contactAutoCreationPolicy: 'SENT_AND_RECEIVED',
|
||||
messageFolderImportPolicy: 'ALL_FOLDERS',
|
||||
excludeNonProfessionalEmails: false,
|
||||
excludeGroupEmails: false,
|
||||
pendingGroupEmailsAction: 'NONE',
|
||||
isSyncEnabled: true,
|
||||
connectedAccountId: ids.connectedAccountIds.CONTACT_GROUP,
|
||||
workspaceId,
|
||||
},
|
||||
];
|
||||
|
||||
await queryRunner.manager
|
||||
@@ -297,6 +365,52 @@ const seedMessageChannels = async ({
|
||||
.execute();
|
||||
};
|
||||
|
||||
const seedUnsubscribeTopics = async ({
|
||||
queryRunner,
|
||||
schemaName,
|
||||
workspaceId,
|
||||
}: SeedMetadataEntitiesArgs) => {
|
||||
const ids = getSeedIds(workspaceId);
|
||||
|
||||
const unsubscribeTopics = [
|
||||
{
|
||||
id: ids.unsubscribeTopicIds.PRODUCT_UPDATES,
|
||||
name: 'Product updates',
|
||||
description: 'New features and product announcements.',
|
||||
visibility: UnsubscribeTopicVisibility.PUBLIC,
|
||||
workspaceId,
|
||||
},
|
||||
{
|
||||
id: ids.unsubscribeTopicIds.NEWSLETTER,
|
||||
name: 'Newsletter',
|
||||
description: 'Our periodic company newsletter.',
|
||||
visibility: UnsubscribeTopicVisibility.PUBLIC,
|
||||
workspaceId,
|
||||
},
|
||||
{
|
||||
id: ids.unsubscribeTopicIds.TRANSACTIONAL,
|
||||
name: 'Transactional',
|
||||
description: 'Internal-only category, hidden from the preferences page.',
|
||||
visibility: UnsubscribeTopicVisibility.PRIVATE,
|
||||
workspaceId,
|
||||
},
|
||||
];
|
||||
|
||||
await queryRunner.manager
|
||||
.createQueryBuilder()
|
||||
.insert()
|
||||
.into(`${schemaName}.unsubscribeTopic`, [
|
||||
'id',
|
||||
'name',
|
||||
'description',
|
||||
'visibility',
|
||||
'workspaceId',
|
||||
])
|
||||
.orIgnore()
|
||||
.values(unsubscribeTopics)
|
||||
.execute();
|
||||
};
|
||||
|
||||
const seedCalendarChannels = async ({
|
||||
queryRunner,
|
||||
schemaName,
|
||||
|
||||
+2
@@ -33,6 +33,8 @@ export const CONNECTED_ACCOUNT_DATA_SEED_IDS = {
|
||||
PHIL: '20202020-cafc-4323-908d-e5b42ad69fdf',
|
||||
JANE: '20202020-b5c7-46f0-bf5c-3f4e4b3f7c1a',
|
||||
JANE_DELETABLE: '20202020-d1e5-4a8f-9c3b-7f6d5e4c3b2a',
|
||||
SUPPORT_GROUP: '20202020-5a1e-4b2c-9d3e-100000000001',
|
||||
CONTACT_GROUP: '20202020-5a1e-4b2c-9d3e-100000000002',
|
||||
};
|
||||
|
||||
export const CONNECTED_ACCOUNT_DATA_SEEDS: ConnectedAccountDataSeed[] = [
|
||||
|
||||
+30
@@ -709,6 +709,36 @@ export const STANDARD_COMMAND_MENU_ITEMS = {
|
||||
engineComponentKey: EngineComponentKey.COMPOSE_EMAIL,
|
||||
hotKeys: null,
|
||||
},
|
||||
composeCampaign: {
|
||||
universalIdentifier: '30473656-e7cb-42e0-b198-6c4e8b906106',
|
||||
label: 'Compose Campaign',
|
||||
icon: 'IconSend',
|
||||
isPinned: false,
|
||||
position: 66,
|
||||
shortLabel: 'Campaign',
|
||||
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
|
||||
conditionalAvailabilityExpression: 'featureFlags.IS_EMAIL_GROUP_ENABLED',
|
||||
availabilityObjectMetadataUniversalIdentifier: null,
|
||||
frontComponentUniversalIdentifier: null,
|
||||
engineComponentKey: EngineComponentKey.COMPOSE_CAMPAIGN,
|
||||
hotKeys: null,
|
||||
},
|
||||
composeCampaignPinned: {
|
||||
universalIdentifier: '7ad6f0c7-ac02-4062-b5cf-1f36e1664bc8',
|
||||
label: 'Compose Campaign',
|
||||
icon: 'IconSend',
|
||||
isPinned: true,
|
||||
position: 67,
|
||||
shortLabel: 'Campaign',
|
||||
availabilityType: CommandMenuItemAvailabilityType.GLOBAL_OBJECT_CONTEXT,
|
||||
conditionalAvailabilityExpression:
|
||||
'pageType == "INDEX_PAGE" and featureFlags.IS_EMAIL_GROUP_ENABLED',
|
||||
availabilityObjectMetadataUniversalIdentifier:
|
||||
STANDARD_OBJECTS.messageCampaign.universalIdentifier,
|
||||
frontComponentUniversalIdentifier: null,
|
||||
engineComponentKey: EngineComponentKey.COMPOSE_CAMPAIGN,
|
||||
hotKeys: null,
|
||||
},
|
||||
goToSettings: {
|
||||
universalIdentifier: 'ef9aba44-0068-453e-930a-f8c182af18ee',
|
||||
label: 'Go to Settings',
|
||||
|
||||
+4
@@ -85,6 +85,10 @@ export const VERTICAL_LIST_LAYOUT_POSITIONS = {
|
||||
layoutMode: PageLayoutTabLayoutMode.VERTICAL_LIST,
|
||||
index: 3,
|
||||
},
|
||||
FIFTH: {
|
||||
layoutMode: PageLayoutTabLayoutMode.VERTICAL_LIST,
|
||||
index: 4,
|
||||
},
|
||||
} as const satisfies Record<string, PageLayoutWidgetVerticalListPosition>;
|
||||
|
||||
export const CANVAS_LAYOUT_POSITIONS = {
|
||||
|
||||
+4
@@ -5,9 +5,11 @@ import {
|
||||
STANDARD_CALL_RECORDING_PAGE_LAYOUT_CONFIG,
|
||||
STANDARD_COMPANY_PAGE_LAYOUT_CONFIG,
|
||||
STANDARD_DASHBOARD_PAGE_LAYOUT_CONFIG,
|
||||
STANDARD_MESSAGE_CAMPAIGN_PAGE_LAYOUT_CONFIG,
|
||||
STANDARD_MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_MESSAGE_FOLDER_PAGE_LAYOUT_CONFIG,
|
||||
STANDARD_MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_PAGE_LAYOUT_CONFIG,
|
||||
STANDARD_MESSAGE_PARTICIPANT_PAGE_LAYOUT_CONFIG,
|
||||
STANDARD_MESSAGE_LIST_PAGE_LAYOUT_CONFIG,
|
||||
STANDARD_MESSAGE_THREAD_PAGE_LAYOUT_CONFIG,
|
||||
STANDARD_NOTE_PAGE_LAYOUT_CONFIG,
|
||||
STANDARD_OPPORTUNITY_PAGE_LAYOUT_CONFIG,
|
||||
@@ -29,11 +31,13 @@ export const STANDARD_PAGE_LAYOUTS = {
|
||||
STANDARD_CALENDAR_EVENT_PARTICIPANT_PAGE_LAYOUT_CONFIG,
|
||||
callRecordingRecordPage: STANDARD_CALL_RECORDING_PAGE_LAYOUT_CONFIG,
|
||||
companyRecordPage: STANDARD_COMPANY_PAGE_LAYOUT_CONFIG,
|
||||
messageCampaignRecordPage: STANDARD_MESSAGE_CAMPAIGN_PAGE_LAYOUT_CONFIG,
|
||||
messageChannelMessageAssociationRecordPage:
|
||||
STANDARD_MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_PAGE_LAYOUT_CONFIG,
|
||||
messageChannelMessageAssociationMessageFolderRecordPage:
|
||||
STANDARD_MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_MESSAGE_FOLDER_PAGE_LAYOUT_CONFIG,
|
||||
messageParticipantRecordPage: STANDARD_MESSAGE_PARTICIPANT_PAGE_LAYOUT_CONFIG,
|
||||
messageListRecordPage: STANDARD_MESSAGE_LIST_PAGE_LAYOUT_CONFIG,
|
||||
messageThreadRecordPage: STANDARD_MESSAGE_THREAD_PAGE_LAYOUT_CONFIG,
|
||||
noteRecordPage: STANDARD_NOTE_PAGE_LAYOUT_CONFIG,
|
||||
opportunityRecordPage: STANDARD_OPPORTUNITY_PAGE_LAYOUT_CONFIG,
|
||||
|
||||
+734
-578
File diff suppressed because it is too large
Load Diff
+233
-192
@@ -153,28 +153,7 @@ exports[`getStandardPageLayoutMetadataRelatedEntityIds should return standard pa
|
||||
},
|
||||
},
|
||||
},
|
||||
"messageChannelMessageAssociationMessageFolderRecordPage": {
|
||||
"id": "00000000-0000-0000-0000-000000000053",
|
||||
"tabs": {
|
||||
"home": {
|
||||
"id": "00000000-0000-0000-0000-000000000054",
|
||||
"widgets": {
|
||||
"fields": {
|
||||
"id": "00000000-0000-0000-0000-000000000055",
|
||||
},
|
||||
},
|
||||
},
|
||||
"timeline": {
|
||||
"id": "00000000-0000-0000-0000-000000000056",
|
||||
"widgets": {
|
||||
"timeline": {
|
||||
"id": "00000000-0000-0000-0000-000000000057",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"messageChannelMessageAssociationRecordPage": {
|
||||
"messageCampaignRecordPage": {
|
||||
"id": "00000000-0000-0000-0000-000000000048",
|
||||
"tabs": {
|
||||
"home": {
|
||||
@@ -183,47 +162,106 @@ exports[`getStandardPageLayoutMetadataRelatedEntityIds should return standard pa
|
||||
"fields": {
|
||||
"id": "00000000-0000-0000-0000-000000000050",
|
||||
},
|
||||
},
|
||||
},
|
||||
"timeline": {
|
||||
"id": "00000000-0000-0000-0000-000000000051",
|
||||
"widgets": {
|
||||
"timeline": {
|
||||
"list": {
|
||||
"id": "00000000-0000-0000-0000-000000000051",
|
||||
},
|
||||
"messages": {
|
||||
"id": "00000000-0000-0000-0000-000000000053",
|
||||
},
|
||||
"recipients": {
|
||||
"id": "00000000-0000-0000-0000-000000000052",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"messageParticipantRecordPage": {
|
||||
"id": "00000000-0000-0000-0000-000000000058",
|
||||
"messageChannelMessageAssociationMessageFolderRecordPage": {
|
||||
"id": "00000000-0000-0000-0000-000000000059",
|
||||
"tabs": {
|
||||
"home": {
|
||||
"id": "00000000-0000-0000-0000-000000000059",
|
||||
"id": "00000000-0000-0000-0000-000000000060",
|
||||
"widgets": {
|
||||
"fields": {
|
||||
"id": "00000000-0000-0000-0000-000000000060",
|
||||
"id": "00000000-0000-0000-0000-000000000061",
|
||||
},
|
||||
},
|
||||
},
|
||||
"timeline": {
|
||||
"id": "00000000-0000-0000-0000-000000000061",
|
||||
"id": "00000000-0000-0000-0000-000000000062",
|
||||
"widgets": {
|
||||
"timeline": {
|
||||
"id": "00000000-0000-0000-0000-000000000062",
|
||||
"id": "00000000-0000-0000-0000-000000000063",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"messageChannelMessageAssociationRecordPage": {
|
||||
"id": "00000000-0000-0000-0000-000000000054",
|
||||
"tabs": {
|
||||
"home": {
|
||||
"id": "00000000-0000-0000-0000-000000000055",
|
||||
"widgets": {
|
||||
"fields": {
|
||||
"id": "00000000-0000-0000-0000-000000000056",
|
||||
},
|
||||
},
|
||||
},
|
||||
"timeline": {
|
||||
"id": "00000000-0000-0000-0000-000000000057",
|
||||
"widgets": {
|
||||
"timeline": {
|
||||
"id": "00000000-0000-0000-0000-000000000058",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"messageListRecordPage": {
|
||||
"id": "00000000-0000-0000-0000-000000000069",
|
||||
"tabs": {
|
||||
"home": {
|
||||
"id": "00000000-0000-0000-0000-000000000070",
|
||||
"widgets": {
|
||||
"fields": {
|
||||
"id": "00000000-0000-0000-0000-000000000071",
|
||||
},
|
||||
"members": {
|
||||
"id": "00000000-0000-0000-0000-000000000072",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"messageParticipantRecordPage": {
|
||||
"id": "00000000-0000-0000-0000-000000000064",
|
||||
"tabs": {
|
||||
"home": {
|
||||
"id": "00000000-0000-0000-0000-000000000065",
|
||||
"widgets": {
|
||||
"fields": {
|
||||
"id": "00000000-0000-0000-0000-000000000066",
|
||||
},
|
||||
},
|
||||
},
|
||||
"timeline": {
|
||||
"id": "00000000-0000-0000-0000-000000000067",
|
||||
"widgets": {
|
||||
"timeline": {
|
||||
"id": "00000000-0000-0000-0000-000000000068",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"messageThreadRecordPage": {
|
||||
"id": "00000000-0000-0000-0000-000000000063",
|
||||
"id": "00000000-0000-0000-0000-000000000073",
|
||||
"tabs": {
|
||||
"home": {
|
||||
"id": "00000000-0000-0000-0000-000000000064",
|
||||
"id": "00000000-0000-0000-0000-000000000074",
|
||||
"widgets": {
|
||||
"emailThread": {
|
||||
"id": "00000000-0000-0000-0000-000000000065",
|
||||
"id": "00000000-0000-0000-0000-000000000075",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -264,102 +302,32 @@ exports[`getStandardPageLayoutMetadataRelatedEntityIds should return standard pa
|
||||
},
|
||||
},
|
||||
"noteRecordPage": {
|
||||
"id": "00000000-0000-0000-0000-000000000066",
|
||||
"tabs": {
|
||||
"files": {
|
||||
"id": "00000000-0000-0000-0000-000000000074",
|
||||
"widgets": {
|
||||
"files": {
|
||||
"id": "00000000-0000-0000-0000-000000000075",
|
||||
},
|
||||
},
|
||||
},
|
||||
"home": {
|
||||
"id": "00000000-0000-0000-0000-000000000067",
|
||||
"widgets": {
|
||||
"fields": {
|
||||
"id": "00000000-0000-0000-0000-000000000068",
|
||||
},
|
||||
"noteRichText": {
|
||||
"id": "00000000-0000-0000-0000-000000000069",
|
||||
},
|
||||
},
|
||||
},
|
||||
"note": {
|
||||
"id": "00000000-0000-0000-0000-000000000070",
|
||||
"widgets": {
|
||||
"noteRichText": {
|
||||
"id": "00000000-0000-0000-0000-000000000071",
|
||||
},
|
||||
},
|
||||
},
|
||||
"timeline": {
|
||||
"id": "00000000-0000-0000-0000-000000000072",
|
||||
"widgets": {
|
||||
"timeline": {
|
||||
"id": "00000000-0000-0000-0000-000000000073",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"opportunityRecordPage": {
|
||||
"id": "00000000-0000-0000-0000-000000000076",
|
||||
"tabs": {
|
||||
"calendar": {
|
||||
"id": "00000000-0000-0000-0000-000000000092",
|
||||
"widgets": {
|
||||
"calendar": {
|
||||
"id": "00000000-0000-0000-0000-000000000093",
|
||||
},
|
||||
},
|
||||
},
|
||||
"emails": {
|
||||
"id": "00000000-0000-0000-0000-000000000090",
|
||||
"widgets": {
|
||||
"emails": {
|
||||
"id": "00000000-0000-0000-0000-000000000091",
|
||||
},
|
||||
},
|
||||
},
|
||||
"files": {
|
||||
"id": "00000000-0000-0000-0000-000000000088",
|
||||
"id": "00000000-0000-0000-0000-000000000084",
|
||||
"widgets": {
|
||||
"files": {
|
||||
"id": "00000000-0000-0000-0000-000000000089",
|
||||
"id": "00000000-0000-0000-0000-000000000085",
|
||||
},
|
||||
},
|
||||
},
|
||||
"home": {
|
||||
"id": "00000000-0000-0000-0000-000000000077",
|
||||
"widgets": {
|
||||
"company": {
|
||||
"id": "00000000-0000-0000-0000-000000000080",
|
||||
},
|
||||
"fields": {
|
||||
"id": "00000000-0000-0000-0000-000000000078",
|
||||
},
|
||||
"owner": {
|
||||
"id": "00000000-0000-0000-0000-000000000081",
|
||||
},
|
||||
"pointOfContact": {
|
||||
"noteRichText": {
|
||||
"id": "00000000-0000-0000-0000-000000000079",
|
||||
},
|
||||
},
|
||||
},
|
||||
"notes": {
|
||||
"id": "00000000-0000-0000-0000-000000000086",
|
||||
"note": {
|
||||
"id": "00000000-0000-0000-0000-000000000080",
|
||||
"widgets": {
|
||||
"notes": {
|
||||
"id": "00000000-0000-0000-0000-000000000087",
|
||||
},
|
||||
},
|
||||
},
|
||||
"tasks": {
|
||||
"id": "00000000-0000-0000-0000-000000000084",
|
||||
"widgets": {
|
||||
"tasks": {
|
||||
"id": "00000000-0000-0000-0000-000000000085",
|
||||
"noteRichText": {
|
||||
"id": "00000000-0000-0000-0000-000000000081",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -373,190 +341,263 @@ exports[`getStandardPageLayoutMetadataRelatedEntityIds should return standard pa
|
||||
},
|
||||
},
|
||||
},
|
||||
"personRecordPage": {
|
||||
"id": "00000000-0000-0000-0000-000000000094",
|
||||
"opportunityRecordPage": {
|
||||
"id": "00000000-0000-0000-0000-000000000086",
|
||||
"tabs": {
|
||||
"calendar": {
|
||||
"id": "00000000-0000-0000-0000-000000000109",
|
||||
"id": "00000000-0000-0000-0000-000000000102",
|
||||
"widgets": {
|
||||
"calendar": {
|
||||
"id": "00000000-0000-0000-0000-000000000110",
|
||||
"id": "00000000-0000-0000-0000-000000000103",
|
||||
},
|
||||
},
|
||||
},
|
||||
"emails": {
|
||||
"id": "00000000-0000-0000-0000-000000000107",
|
||||
"id": "00000000-0000-0000-0000-000000000100",
|
||||
"widgets": {
|
||||
"emails": {
|
||||
"id": "00000000-0000-0000-0000-000000000108",
|
||||
"id": "00000000-0000-0000-0000-000000000101",
|
||||
},
|
||||
},
|
||||
},
|
||||
"files": {
|
||||
"id": "00000000-0000-0000-0000-000000000105",
|
||||
"id": "00000000-0000-0000-0000-000000000098",
|
||||
"widgets": {
|
||||
"files": {
|
||||
"id": "00000000-0000-0000-0000-000000000106",
|
||||
"id": "00000000-0000-0000-0000-000000000099",
|
||||
},
|
||||
},
|
||||
},
|
||||
"home": {
|
||||
"id": "00000000-0000-0000-0000-000000000095",
|
||||
"id": "00000000-0000-0000-0000-000000000087",
|
||||
"widgets": {
|
||||
"company": {
|
||||
"id": "00000000-0000-0000-0000-000000000097",
|
||||
"id": "00000000-0000-0000-0000-000000000090",
|
||||
},
|
||||
"fields": {
|
||||
"id": "00000000-0000-0000-0000-000000000096",
|
||||
"id": "00000000-0000-0000-0000-000000000088",
|
||||
},
|
||||
"pointOfContactForOpportunities": {
|
||||
"id": "00000000-0000-0000-0000-000000000098",
|
||||
"owner": {
|
||||
"id": "00000000-0000-0000-0000-000000000091",
|
||||
},
|
||||
"pointOfContact": {
|
||||
"id": "00000000-0000-0000-0000-000000000089",
|
||||
},
|
||||
},
|
||||
},
|
||||
"notes": {
|
||||
"id": "00000000-0000-0000-0000-000000000103",
|
||||
"id": "00000000-0000-0000-0000-000000000096",
|
||||
"widgets": {
|
||||
"notes": {
|
||||
"id": "00000000-0000-0000-0000-000000000104",
|
||||
"id": "00000000-0000-0000-0000-000000000097",
|
||||
},
|
||||
},
|
||||
},
|
||||
"tasks": {
|
||||
"id": "00000000-0000-0000-0000-000000000101",
|
||||
"id": "00000000-0000-0000-0000-000000000094",
|
||||
"widgets": {
|
||||
"tasks": {
|
||||
"id": "00000000-0000-0000-0000-000000000102",
|
||||
"id": "00000000-0000-0000-0000-000000000095",
|
||||
},
|
||||
},
|
||||
},
|
||||
"timeline": {
|
||||
"id": "00000000-0000-0000-0000-000000000099",
|
||||
"id": "00000000-0000-0000-0000-000000000092",
|
||||
"widgets": {
|
||||
"timeline": {
|
||||
"id": "00000000-0000-0000-0000-000000000100",
|
||||
"id": "00000000-0000-0000-0000-000000000093",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"personRecordPage": {
|
||||
"id": "00000000-0000-0000-0000-000000000104",
|
||||
"tabs": {
|
||||
"calendar": {
|
||||
"id": "00000000-0000-0000-0000-000000000120",
|
||||
"widgets": {
|
||||
"calendar": {
|
||||
"id": "00000000-0000-0000-0000-000000000121",
|
||||
},
|
||||
},
|
||||
},
|
||||
"emails": {
|
||||
"id": "00000000-0000-0000-0000-000000000118",
|
||||
"widgets": {
|
||||
"emails": {
|
||||
"id": "00000000-0000-0000-0000-000000000119",
|
||||
},
|
||||
},
|
||||
},
|
||||
"files": {
|
||||
"id": "00000000-0000-0000-0000-000000000116",
|
||||
"widgets": {
|
||||
"files": {
|
||||
"id": "00000000-0000-0000-0000-000000000117",
|
||||
},
|
||||
},
|
||||
},
|
||||
"home": {
|
||||
"id": "00000000-0000-0000-0000-000000000105",
|
||||
"widgets": {
|
||||
"company": {
|
||||
"id": "00000000-0000-0000-0000-000000000107",
|
||||
},
|
||||
"fields": {
|
||||
"id": "00000000-0000-0000-0000-000000000106",
|
||||
},
|
||||
"listMemberships": {
|
||||
"id": "00000000-0000-0000-0000-000000000109",
|
||||
},
|
||||
"pointOfContactForOpportunities": {
|
||||
"id": "00000000-0000-0000-0000-000000000108",
|
||||
},
|
||||
},
|
||||
},
|
||||
"notes": {
|
||||
"id": "00000000-0000-0000-0000-000000000114",
|
||||
"widgets": {
|
||||
"notes": {
|
||||
"id": "00000000-0000-0000-0000-000000000115",
|
||||
},
|
||||
},
|
||||
},
|
||||
"tasks": {
|
||||
"id": "00000000-0000-0000-0000-000000000112",
|
||||
"widgets": {
|
||||
"tasks": {
|
||||
"id": "00000000-0000-0000-0000-000000000113",
|
||||
},
|
||||
},
|
||||
},
|
||||
"timeline": {
|
||||
"id": "00000000-0000-0000-0000-000000000110",
|
||||
"widgets": {
|
||||
"timeline": {
|
||||
"id": "00000000-0000-0000-0000-000000000111",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"taskRecordPage": {
|
||||
"id": "00000000-0000-0000-0000-000000000111",
|
||||
"id": "00000000-0000-0000-0000-000000000122",
|
||||
"tabs": {
|
||||
"files": {
|
||||
"id": "00000000-0000-0000-0000-000000000119",
|
||||
"id": "00000000-0000-0000-0000-000000000130",
|
||||
"widgets": {
|
||||
"files": {
|
||||
"id": "00000000-0000-0000-0000-000000000120",
|
||||
"id": "00000000-0000-0000-0000-000000000131",
|
||||
},
|
||||
},
|
||||
},
|
||||
"home": {
|
||||
"id": "00000000-0000-0000-0000-000000000112",
|
||||
"id": "00000000-0000-0000-0000-000000000123",
|
||||
"widgets": {
|
||||
"fields": {
|
||||
"id": "00000000-0000-0000-0000-000000000113",
|
||||
"id": "00000000-0000-0000-0000-000000000124",
|
||||
},
|
||||
"taskRichText": {
|
||||
"id": "00000000-0000-0000-0000-000000000114",
|
||||
"id": "00000000-0000-0000-0000-000000000125",
|
||||
},
|
||||
},
|
||||
},
|
||||
"note": {
|
||||
"id": "00000000-0000-0000-0000-000000000115",
|
||||
"id": "00000000-0000-0000-0000-000000000126",
|
||||
"widgets": {
|
||||
"taskRichText": {
|
||||
"id": "00000000-0000-0000-0000-000000000116",
|
||||
"id": "00000000-0000-0000-0000-000000000127",
|
||||
},
|
||||
},
|
||||
},
|
||||
"timeline": {
|
||||
"id": "00000000-0000-0000-0000-000000000117",
|
||||
"id": "00000000-0000-0000-0000-000000000128",
|
||||
"widgets": {
|
||||
"timeline": {
|
||||
"id": "00000000-0000-0000-0000-000000000118",
|
||||
"id": "00000000-0000-0000-0000-000000000129",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"workflowAutomatedTriggerRecordPage": {
|
||||
"id": "00000000-0000-0000-0000-000000000124",
|
||||
"tabs": {
|
||||
"home": {
|
||||
"id": "00000000-0000-0000-0000-000000000125",
|
||||
"widgets": {
|
||||
"fields": {
|
||||
"id": "00000000-0000-0000-0000-000000000126",
|
||||
},
|
||||
},
|
||||
},
|
||||
"timeline": {
|
||||
"id": "00000000-0000-0000-0000-000000000127",
|
||||
"widgets": {
|
||||
"timeline": {
|
||||
"id": "00000000-0000-0000-0000-000000000128",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"workflowRecordPage": {
|
||||
"id": "00000000-0000-0000-0000-000000000121",
|
||||
"tabs": {
|
||||
"flow": {
|
||||
"id": "00000000-0000-0000-0000-000000000122",
|
||||
"widgets": {
|
||||
"workflow": {
|
||||
"id": "00000000-0000-0000-0000-000000000123",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"workflowRunRecordPage": {
|
||||
"id": "00000000-0000-0000-0000-000000000135",
|
||||
"tabs": {
|
||||
"flow": {
|
||||
"id": "00000000-0000-0000-0000-000000000139",
|
||||
"widgets": {
|
||||
"workflowRun": {
|
||||
"id": "00000000-0000-0000-0000-000000000140",
|
||||
},
|
||||
},
|
||||
},
|
||||
"home": {
|
||||
"id": "00000000-0000-0000-0000-000000000136",
|
||||
"widgets": {
|
||||
"fields": {
|
||||
"id": "00000000-0000-0000-0000-000000000137",
|
||||
},
|
||||
},
|
||||
},
|
||||
"timeline": {
|
||||
"id": "00000000-0000-0000-0000-000000000138",
|
||||
"widgets": {
|
||||
"timeline": {
|
||||
"id": "00000000-0000-0000-0000-000000000139",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"workflowRecordPage": {
|
||||
"id": "00000000-0000-0000-0000-000000000132",
|
||||
"tabs": {
|
||||
"flow": {
|
||||
"id": "00000000-0000-0000-0000-000000000133",
|
||||
"widgets": {
|
||||
"workflow": {
|
||||
"id": "00000000-0000-0000-0000-000000000138",
|
||||
"id": "00000000-0000-0000-0000-000000000134",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"workflowRunRecordPage": {
|
||||
"id": "00000000-0000-0000-0000-000000000146",
|
||||
"tabs": {
|
||||
"flow": {
|
||||
"id": "00000000-0000-0000-0000-000000000150",
|
||||
"widgets": {
|
||||
"workflowRun": {
|
||||
"id": "00000000-0000-0000-0000-000000000151",
|
||||
},
|
||||
},
|
||||
},
|
||||
"home": {
|
||||
"id": "00000000-0000-0000-0000-000000000147",
|
||||
"widgets": {
|
||||
"fields": {
|
||||
"id": "00000000-0000-0000-0000-000000000148",
|
||||
},
|
||||
"workflow": {
|
||||
"id": "00000000-0000-0000-0000-000000000149",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"workflowVersionRecordPage": {
|
||||
"id": "00000000-0000-0000-0000-000000000129",
|
||||
"id": "00000000-0000-0000-0000-000000000140",
|
||||
"tabs": {
|
||||
"flow": {
|
||||
"id": "00000000-0000-0000-0000-000000000133",
|
||||
"id": "00000000-0000-0000-0000-000000000144",
|
||||
"widgets": {
|
||||
"workflowVersion": {
|
||||
"id": "00000000-0000-0000-0000-000000000134",
|
||||
"id": "00000000-0000-0000-0000-000000000145",
|
||||
},
|
||||
},
|
||||
},
|
||||
"home": {
|
||||
"id": "00000000-0000-0000-0000-000000000130",
|
||||
"id": "00000000-0000-0000-0000-000000000141",
|
||||
"widgets": {
|
||||
"fields": {
|
||||
"id": "00000000-0000-0000-0000-000000000131",
|
||||
"id": "00000000-0000-0000-0000-000000000142",
|
||||
},
|
||||
"workflow": {
|
||||
"id": "00000000-0000-0000-0000-000000000132",
|
||||
"id": "00000000-0000-0000-0000-000000000143",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
+6
@@ -13,6 +13,9 @@ import { buildCalendarEventStandardFlatFieldMetadatas } from 'src/engine/workspa
|
||||
import { buildCallRecordingStandardFlatFieldMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-call-recording-standard-flat-field-metadata.util';
|
||||
import { buildCompanyStandardFlatFieldMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-company-standard-flat-field-metadata.util';
|
||||
import { buildDashboardStandardFlatFieldMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-dashboard-standard-flat-field-metadata.util';
|
||||
import { buildMessageCampaignStandardFlatFieldMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-campaign-standard-flat-field-metadata.util';
|
||||
import { buildMessageListStandardFlatFieldMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-list-standard-flat-field-metadata.util';
|
||||
import { buildMessageListMemberStandardFlatFieldMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-list-member-standard-flat-field-metadata.util';
|
||||
import { buildMessageChannelMessageAssociationMessageFolderStandardFlatFieldMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-channel-message-association-message-folder-standard-flat-field-metadata.util';
|
||||
import { buildMessageChannelMessageAssociationStandardFlatFieldMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-channel-message-association-standard-flat-field-metadata.util';
|
||||
import { buildMessageParticipantStandardFlatFieldMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-participant-standard-flat-field-metadata.util';
|
||||
@@ -47,6 +50,9 @@ const STANDARD_FLAT_FIELD_METADATA_BUILDERS_BY_OBJECT_NAME = {
|
||||
callRecording: buildCallRecordingStandardFlatFieldMetadatas,
|
||||
company: buildCompanyStandardFlatFieldMetadatas,
|
||||
dashboard: buildDashboardStandardFlatFieldMetadatas,
|
||||
messageCampaign: buildMessageCampaignStandardFlatFieldMetadatas,
|
||||
messageList: buildMessageListStandardFlatFieldMetadatas,
|
||||
messageListMember: buildMessageListMemberStandardFlatFieldMetadatas,
|
||||
message: buildMessageStandardFlatFieldMetadatas,
|
||||
messageChannelMessageAssociation:
|
||||
buildMessageChannelMessageAssociationStandardFlatFieldMetadatas,
|
||||
|
||||
+361
@@ -0,0 +1,361 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { i18nLabel } from 'src/engine/workspace-manager/twenty-standard-application/utils/i18n-label.util';
|
||||
import {
|
||||
DateDisplayFormat,
|
||||
FieldMetadataType,
|
||||
RelationOnDeleteAction,
|
||||
RelationType,
|
||||
} from 'twenty-shared/types';
|
||||
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { type AllStandardObjectFieldName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type';
|
||||
import {
|
||||
type CreateStandardFieldArgs,
|
||||
createStandardFieldFlatMetadata,
|
||||
} from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-field-flat-metadata.util';
|
||||
import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-relation-field-flat-metadata.util';
|
||||
import { getTsVectorColumnExpressionFromFields } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
|
||||
import { SEARCH_FIELDS_FOR_MESSAGE_CAMPAIGN } from 'src/modules/emailing/standard-objects/message-campaign.workspace-entity';
|
||||
|
||||
export const buildMessageCampaignStandardFlatFieldMetadatas = ({
|
||||
now,
|
||||
objectName,
|
||||
workspaceId,
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
}: Omit<
|
||||
CreateStandardFieldArgs<'messageCampaign', FieldMetadataType>,
|
||||
'context'
|
||||
>): Record<
|
||||
AllStandardObjectFieldName<'messageCampaign'>,
|
||||
FlatFieldMetadata
|
||||
> => {
|
||||
const base = {
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
objectName,
|
||||
workspaceId,
|
||||
};
|
||||
|
||||
return {
|
||||
id: createStandardFieldFlatMetadata({
|
||||
...base,
|
||||
context: {
|
||||
fieldName: 'id',
|
||||
type: FieldMetadataType.UUID,
|
||||
label: i18nLabel(msg`Id`),
|
||||
description: i18nLabel(msg`Id`),
|
||||
icon: 'Icon123',
|
||||
isSystem: true,
|
||||
isNullable: false,
|
||||
isUIEditable: false,
|
||||
defaultValue: 'uuid',
|
||||
},
|
||||
}),
|
||||
createdAt: createStandardFieldFlatMetadata({
|
||||
...base,
|
||||
context: {
|
||||
fieldName: 'createdAt',
|
||||
type: FieldMetadataType.DATE_TIME,
|
||||
label: i18nLabel(msg`Creation date`),
|
||||
description: i18nLabel(msg`Creation date`),
|
||||
icon: 'IconCalendar',
|
||||
isSystem: true,
|
||||
isNullable: false,
|
||||
isUIEditable: false,
|
||||
defaultValue: 'now',
|
||||
settings: { displayFormat: DateDisplayFormat.RELATIVE },
|
||||
},
|
||||
}),
|
||||
updatedAt: createStandardFieldFlatMetadata({
|
||||
...base,
|
||||
context: {
|
||||
fieldName: 'updatedAt',
|
||||
type: FieldMetadataType.DATE_TIME,
|
||||
label: i18nLabel(msg`Last update`),
|
||||
description: i18nLabel(msg`Last time the record was changed`),
|
||||
icon: 'IconCalendarClock',
|
||||
isSystem: true,
|
||||
isNullable: false,
|
||||
isUIEditable: false,
|
||||
defaultValue: 'now',
|
||||
settings: { displayFormat: DateDisplayFormat.RELATIVE },
|
||||
},
|
||||
}),
|
||||
deletedAt: createStandardFieldFlatMetadata({
|
||||
...base,
|
||||
context: {
|
||||
fieldName: 'deletedAt',
|
||||
type: FieldMetadataType.DATE_TIME,
|
||||
label: i18nLabel(msg`Deleted at`),
|
||||
description: i18nLabel(msg`Date when the record was deleted`),
|
||||
icon: 'IconCalendarMinus',
|
||||
isSystem: true,
|
||||
isNullable: true,
|
||||
isUIEditable: false,
|
||||
settings: { displayFormat: DateDisplayFormat.RELATIVE },
|
||||
},
|
||||
}),
|
||||
createdBy: createStandardFieldFlatMetadata({
|
||||
...base,
|
||||
context: {
|
||||
fieldName: 'createdBy',
|
||||
type: FieldMetadataType.ACTOR,
|
||||
label: i18nLabel(msg`Created by`),
|
||||
description: i18nLabel(msg`The creator of the record`),
|
||||
icon: 'IconCreativeCommonsSa',
|
||||
isSystem: true,
|
||||
isUIEditable: false,
|
||||
isNullable: false,
|
||||
defaultValue: {
|
||||
source: "'MANUAL'",
|
||||
name: "'System'",
|
||||
workspaceMemberId: null,
|
||||
},
|
||||
},
|
||||
}),
|
||||
updatedBy: createStandardFieldFlatMetadata({
|
||||
...base,
|
||||
context: {
|
||||
fieldName: 'updatedBy',
|
||||
type: FieldMetadataType.ACTOR,
|
||||
label: i18nLabel(msg`Updated by`),
|
||||
description: i18nLabel(
|
||||
msg`The workspace member who last updated the record`,
|
||||
),
|
||||
icon: 'IconUserCircle',
|
||||
isSystem: true,
|
||||
isUIEditable: false,
|
||||
isNullable: false,
|
||||
defaultValue: {
|
||||
source: "'MANUAL'",
|
||||
name: "'System'",
|
||||
workspaceMemberId: null,
|
||||
},
|
||||
},
|
||||
}),
|
||||
position: createStandardFieldFlatMetadata({
|
||||
...base,
|
||||
context: {
|
||||
fieldName: 'position',
|
||||
type: FieldMetadataType.POSITION,
|
||||
label: i18nLabel(msg`Position`),
|
||||
description: i18nLabel(msg`Email campaign record position`),
|
||||
icon: 'IconHierarchy2',
|
||||
isSystem: true,
|
||||
isNullable: false,
|
||||
defaultValue: 0,
|
||||
},
|
||||
}),
|
||||
searchVector: createStandardFieldFlatMetadata({
|
||||
...base,
|
||||
context: {
|
||||
fieldName: 'searchVector',
|
||||
type: FieldMetadataType.TS_VECTOR,
|
||||
label: i18nLabel(msg`Search vector`),
|
||||
description: i18nLabel(msg`Field used for full-text search`),
|
||||
icon: 'IconSend',
|
||||
isSystem: true,
|
||||
isNullable: true,
|
||||
settings: {
|
||||
generatedType: 'STORED',
|
||||
asExpression: getTsVectorColumnExpressionFromFields(
|
||||
SEARCH_FIELDS_FOR_MESSAGE_CAMPAIGN,
|
||||
),
|
||||
},
|
||||
},
|
||||
}),
|
||||
subject: createStandardFieldFlatMetadata({
|
||||
...base,
|
||||
context: {
|
||||
fieldName: 'subject',
|
||||
type: FieldMetadataType.TEXT,
|
||||
label: i18nLabel(msg`Subject`),
|
||||
description: i18nLabel(msg`Email subject line`),
|
||||
icon: 'IconMail',
|
||||
isNullable: true,
|
||||
isUIEditable: false,
|
||||
},
|
||||
}),
|
||||
bodyTemplate: createStandardFieldFlatMetadata({
|
||||
...base,
|
||||
context: {
|
||||
fieldName: 'bodyTemplate',
|
||||
type: FieldMetadataType.TEXT,
|
||||
label: i18nLabel(msg`Body`),
|
||||
description: i18nLabel(msg`Email body sent to recipients`),
|
||||
icon: 'IconFileText',
|
||||
isNullable: true,
|
||||
isUIEditable: false,
|
||||
},
|
||||
}),
|
||||
fromAddress: createStandardFieldFlatMetadata({
|
||||
...base,
|
||||
context: {
|
||||
fieldName: 'fromAddress',
|
||||
type: FieldMetadataType.EMAILS,
|
||||
label: i18nLabel(msg`From address`),
|
||||
description: i18nLabel(msg`Sender address for the campaign`),
|
||||
icon: 'IconAt',
|
||||
isNullable: true,
|
||||
isUIEditable: false,
|
||||
settings: {
|
||||
maxNumberOfValues: 1,
|
||||
},
|
||||
},
|
||||
}),
|
||||
status: createStandardFieldFlatMetadata({
|
||||
...base,
|
||||
context: {
|
||||
fieldName: 'status',
|
||||
type: FieldMetadataType.SELECT,
|
||||
label: i18nLabel(msg`Status`),
|
||||
description: i18nLabel(msg`Campaign lifecycle status`),
|
||||
icon: 'IconProgress',
|
||||
isNullable: false,
|
||||
isUIEditable: false,
|
||||
defaultValue: "'DRAFT'",
|
||||
options: [
|
||||
{
|
||||
id: '2bebe786-69e0-4673-8781-a85588b77c44',
|
||||
value: 'DRAFT',
|
||||
label: i18nLabel(msg`Draft`),
|
||||
position: 0,
|
||||
color: 'gray',
|
||||
},
|
||||
{
|
||||
id: 'dba0c513-d1dc-4c6a-980a-40795bdb0759',
|
||||
value: 'SCHEDULED',
|
||||
label: i18nLabel(msg`Scheduled`),
|
||||
position: 1,
|
||||
color: 'blue',
|
||||
},
|
||||
{
|
||||
id: '575b9ed5-1123-480c-9821-c73410841347',
|
||||
value: 'SENDING',
|
||||
label: i18nLabel(msg`Sending`),
|
||||
position: 2,
|
||||
color: 'yellow',
|
||||
},
|
||||
{
|
||||
id: '0c311eae-0892-4319-84e6-b30e921dc01a',
|
||||
value: 'SENT',
|
||||
label: i18nLabel(msg`Sent`),
|
||||
position: 3,
|
||||
color: 'green',
|
||||
},
|
||||
{
|
||||
id: 'c309536c-ceb7-4510-8481-c2cbd88ffe96',
|
||||
value: 'SENT_WITH_ERRORS',
|
||||
label: i18nLabel(msg`Sent with errors`),
|
||||
position: 4,
|
||||
color: 'orange',
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
sentAt: createStandardFieldFlatMetadata({
|
||||
...base,
|
||||
context: {
|
||||
fieldName: 'sentAt',
|
||||
type: FieldMetadataType.DATE_TIME,
|
||||
label: i18nLabel(msg`Sent at`),
|
||||
description: i18nLabel(msg`When the campaign finished sending`),
|
||||
icon: 'IconSend',
|
||||
isNullable: true,
|
||||
isUIEditable: false,
|
||||
settings: { displayFormat: DateDisplayFormat.RELATIVE },
|
||||
},
|
||||
}),
|
||||
unsubscribeTopicId: createStandardFieldFlatMetadata({
|
||||
...base,
|
||||
context: {
|
||||
fieldName: 'unsubscribeTopicId',
|
||||
type: FieldMetadataType.UUID,
|
||||
label: i18nLabel(msg`Unsubscribe topic id`),
|
||||
description: i18nLabel(
|
||||
msg`The unsubscribe topic this campaign was sent under`,
|
||||
),
|
||||
icon: 'IconMailbox',
|
||||
isNullable: true,
|
||||
isUIEditable: false,
|
||||
},
|
||||
}),
|
||||
list: createStandardRelationFieldFlatMetadata({
|
||||
...base,
|
||||
context: {
|
||||
type: FieldMetadataType.RELATION,
|
||||
morphId: null,
|
||||
fieldName: 'list',
|
||||
label: i18nLabel(msg`List`),
|
||||
description: i18nLabel(msg`The list this campaign was sent to`),
|
||||
icon: 'IconUsersGroup',
|
||||
isNullable: true,
|
||||
isUIEditable: false,
|
||||
targetObjectName: 'messageList',
|
||||
targetFieldName: 'campaigns',
|
||||
settings: {
|
||||
relationType: RelationType.MANY_TO_ONE,
|
||||
onDelete: RelationOnDeleteAction.SET_NULL,
|
||||
joinColumnName: 'listId',
|
||||
},
|
||||
},
|
||||
}),
|
||||
timelineActivities: createStandardRelationFieldFlatMetadata({
|
||||
...base,
|
||||
context: {
|
||||
type: FieldMetadataType.RELATION,
|
||||
morphId: null,
|
||||
fieldName: 'timelineActivities',
|
||||
label: i18nLabel(msg`Events`),
|
||||
description: i18nLabel(msg`Events linked to the campaign`),
|
||||
icon: 'IconTimelineEvent',
|
||||
isNullable: true,
|
||||
targetObjectName: 'timelineActivity',
|
||||
targetFieldName: 'targetMessageCampaign',
|
||||
settings: {
|
||||
relationType: RelationType.ONE_TO_MANY,
|
||||
},
|
||||
},
|
||||
}),
|
||||
messages: createStandardRelationFieldFlatMetadata({
|
||||
...base,
|
||||
context: {
|
||||
type: FieldMetadataType.RELATION,
|
||||
morphId: null,
|
||||
fieldName: 'messages',
|
||||
label: i18nLabel(msg`Messages`),
|
||||
description: i18nLabel(msg`Messages sent as part of this campaign`),
|
||||
icon: 'IconMessage',
|
||||
isNullable: true,
|
||||
isUIEditable: false,
|
||||
targetObjectName: 'message',
|
||||
targetFieldName: 'messageCampaign',
|
||||
settings: {
|
||||
relationType: RelationType.ONE_TO_MANY,
|
||||
},
|
||||
},
|
||||
}),
|
||||
recipients: createStandardRelationFieldFlatMetadata({
|
||||
...base,
|
||||
context: {
|
||||
type: FieldMetadataType.RELATION,
|
||||
morphId: null,
|
||||
fieldName: 'recipients',
|
||||
label: i18nLabel(msg`Recipients`),
|
||||
description: i18nLabel(msg`The people this campaign was sent to`),
|
||||
icon: 'IconUsers',
|
||||
isNullable: true,
|
||||
isUIEditable: false,
|
||||
targetObjectName: 'messageParticipant',
|
||||
targetFieldName: 'messageCampaign',
|
||||
settings: {
|
||||
relationType: RelationType.ONE_TO_MANY,
|
||||
},
|
||||
},
|
||||
}),
|
||||
};
|
||||
};
|
||||
+248
@@ -0,0 +1,248 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { i18nLabel } from 'src/engine/workspace-manager/twenty-standard-application/utils/i18n-label.util';
|
||||
import {
|
||||
DateDisplayFormat,
|
||||
FieldMetadataType,
|
||||
RelationOnDeleteAction,
|
||||
RelationType,
|
||||
} from 'twenty-shared/types';
|
||||
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { type AllStandardObjectFieldName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type';
|
||||
import {
|
||||
type CreateStandardFieldArgs,
|
||||
createStandardFieldFlatMetadata,
|
||||
} from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-field-flat-metadata.util';
|
||||
import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-relation-field-flat-metadata.util';
|
||||
import { getTsVectorColumnExpressionFromFields } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
|
||||
|
||||
export const buildMessageListMemberStandardFlatFieldMetadatas = ({
|
||||
now,
|
||||
objectName,
|
||||
workspaceId,
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
}: Omit<
|
||||
CreateStandardFieldArgs<'messageListMember', FieldMetadataType>,
|
||||
'context'
|
||||
>): Record<
|
||||
AllStandardObjectFieldName<'messageListMember'>,
|
||||
FlatFieldMetadata
|
||||
> => ({
|
||||
id: createStandardFieldFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
fieldName: 'id',
|
||||
type: FieldMetadataType.UUID,
|
||||
label: i18nLabel(msg`Id`),
|
||||
description: i18nLabel(msg`Id`),
|
||||
icon: 'Icon123',
|
||||
isSystem: true,
|
||||
isNullable: false,
|
||||
isUIEditable: false,
|
||||
defaultValue: 'uuid',
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
createdAt: createStandardFieldFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
fieldName: 'createdAt',
|
||||
type: FieldMetadataType.DATE_TIME,
|
||||
label: i18nLabel(msg`Creation date`),
|
||||
description: i18nLabel(msg`Creation date`),
|
||||
icon: 'IconCalendar',
|
||||
isSystem: true,
|
||||
isNullable: false,
|
||||
isUIEditable: false,
|
||||
defaultValue: 'now',
|
||||
settings: { displayFormat: DateDisplayFormat.RELATIVE },
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
updatedAt: createStandardFieldFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
fieldName: 'updatedAt',
|
||||
type: FieldMetadataType.DATE_TIME,
|
||||
label: i18nLabel(msg`Last update`),
|
||||
description: i18nLabel(msg`Last time the record was changed`),
|
||||
icon: 'IconCalendarClock',
|
||||
isSystem: true,
|
||||
isNullable: false,
|
||||
isUIEditable: false,
|
||||
defaultValue: 'now',
|
||||
settings: { displayFormat: DateDisplayFormat.RELATIVE },
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
deletedAt: createStandardFieldFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
fieldName: 'deletedAt',
|
||||
type: FieldMetadataType.DATE_TIME,
|
||||
label: i18nLabel(msg`Deleted at`),
|
||||
description: i18nLabel(msg`Date when the record was deleted`),
|
||||
icon: 'IconCalendarMinus',
|
||||
isSystem: true,
|
||||
isNullable: true,
|
||||
isUIEditable: false,
|
||||
settings: { displayFormat: DateDisplayFormat.RELATIVE },
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
createdBy: createStandardFieldFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
fieldName: 'createdBy',
|
||||
type: FieldMetadataType.ACTOR,
|
||||
label: i18nLabel(msg`Created by`),
|
||||
description: i18nLabel(msg`The creator of the record`),
|
||||
icon: 'IconCreativeCommonsSa',
|
||||
isSystem: true,
|
||||
isUIEditable: false,
|
||||
isNullable: false,
|
||||
defaultValue: {
|
||||
source: "'MANUAL'",
|
||||
name: "'System'",
|
||||
workspaceMemberId: null,
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
updatedBy: createStandardFieldFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
fieldName: 'updatedBy',
|
||||
type: FieldMetadataType.ACTOR,
|
||||
label: i18nLabel(msg`Updated by`),
|
||||
description: i18nLabel(
|
||||
msg`The workspace member who last updated the record`,
|
||||
),
|
||||
icon: 'IconUserCircle',
|
||||
isSystem: true,
|
||||
isUIEditable: false,
|
||||
isNullable: false,
|
||||
defaultValue: {
|
||||
source: "'MANUAL'",
|
||||
name: "'System'",
|
||||
workspaceMemberId: null,
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
position: createStandardFieldFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
fieldName: 'position',
|
||||
type: FieldMetadataType.POSITION,
|
||||
label: i18nLabel(msg`Position`),
|
||||
description: i18nLabel(msg`List member record position`),
|
||||
icon: 'IconHierarchy2',
|
||||
isSystem: true,
|
||||
isNullable: false,
|
||||
defaultValue: 0,
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
list: createStandardRelationFieldFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
type: FieldMetadataType.RELATION,
|
||||
morphId: null,
|
||||
fieldName: 'list',
|
||||
label: i18nLabel(msg`List`),
|
||||
description: i18nLabel(msg`The list the person belongs to`),
|
||||
icon: 'IconUsersGroup',
|
||||
isNullable: false,
|
||||
targetObjectName: 'messageList',
|
||||
targetFieldName: 'members',
|
||||
settings: {
|
||||
relationType: RelationType.MANY_TO_ONE,
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
joinColumnName: 'listId',
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
person: createStandardRelationFieldFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
type: FieldMetadataType.RELATION,
|
||||
morphId: null,
|
||||
fieldName: 'person',
|
||||
label: i18nLabel(msg`Person`),
|
||||
description: i18nLabel(msg`The person in the list`),
|
||||
icon: 'IconUser',
|
||||
isNullable: false,
|
||||
targetObjectName: 'person',
|
||||
targetFieldName: 'listMemberships',
|
||||
settings: {
|
||||
relationType: RelationType.MANY_TO_ONE,
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
joinColumnName: 'personId',
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
searchVector: createStandardFieldFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
fieldName: 'searchVector',
|
||||
type: FieldMetadataType.TS_VECTOR,
|
||||
label: i18nLabel(msg`Search vector`),
|
||||
description: i18nLabel(msg`Field used for full-text search`),
|
||||
icon: 'IconUser',
|
||||
isSystem: true,
|
||||
isNullable: true,
|
||||
settings: {
|
||||
generatedType: 'STORED',
|
||||
asExpression: getTsVectorColumnExpressionFromFields([
|
||||
{ name: 'id', type: FieldMetadataType.UUID },
|
||||
]),
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
});
|
||||
+284
@@ -0,0 +1,284 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { STANDARD_OBJECTS } from 'twenty-shared/metadata';
|
||||
|
||||
import { i18nLabel } from 'src/engine/workspace-manager/twenty-standard-application/utils/i18n-label.util';
|
||||
import {
|
||||
DateDisplayFormat,
|
||||
FieldMetadataType,
|
||||
RelationType,
|
||||
} from 'twenty-shared/types';
|
||||
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { type AllStandardObjectFieldName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type';
|
||||
import {
|
||||
type CreateStandardFieldArgs,
|
||||
createStandardFieldFlatMetadata,
|
||||
} from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-field-flat-metadata.util';
|
||||
import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-relation-field-flat-metadata.util';
|
||||
import { getTsVectorColumnExpressionFromFields } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
|
||||
import { SEARCH_FIELDS_FOR_MESSAGE_LIST } from 'src/modules/emailing/standard-objects/message-list.workspace-entity';
|
||||
|
||||
export const buildMessageListStandardFlatFieldMetadatas = ({
|
||||
now,
|
||||
objectName,
|
||||
workspaceId,
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
}: Omit<
|
||||
CreateStandardFieldArgs<'messageList', FieldMetadataType>,
|
||||
'context'
|
||||
>): Record<AllStandardObjectFieldName<'messageList'>, FlatFieldMetadata> => ({
|
||||
id: createStandardFieldFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
fieldName: 'id',
|
||||
type: FieldMetadataType.UUID,
|
||||
label: i18nLabel(msg`Id`),
|
||||
description: i18nLabel(msg`Id`),
|
||||
icon: 'Icon123',
|
||||
isSystem: true,
|
||||
isNullable: false,
|
||||
isUIEditable: false,
|
||||
defaultValue: 'uuid',
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
createdAt: createStandardFieldFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
fieldName: 'createdAt',
|
||||
type: FieldMetadataType.DATE_TIME,
|
||||
label: i18nLabel(msg`Creation date`),
|
||||
description: i18nLabel(msg`Creation date`),
|
||||
icon: 'IconCalendar',
|
||||
isSystem: true,
|
||||
isNullable: false,
|
||||
isUIEditable: false,
|
||||
defaultValue: 'now',
|
||||
settings: { displayFormat: DateDisplayFormat.RELATIVE },
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
updatedAt: createStandardFieldFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
fieldName: 'updatedAt',
|
||||
type: FieldMetadataType.DATE_TIME,
|
||||
label: i18nLabel(msg`Last update`),
|
||||
description: i18nLabel(msg`Last time the record was changed`),
|
||||
icon: 'IconCalendarClock',
|
||||
isSystem: true,
|
||||
isNullable: false,
|
||||
isUIEditable: false,
|
||||
defaultValue: 'now',
|
||||
settings: { displayFormat: DateDisplayFormat.RELATIVE },
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
deletedAt: createStandardFieldFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
fieldName: 'deletedAt',
|
||||
type: FieldMetadataType.DATE_TIME,
|
||||
label: i18nLabel(msg`Deleted at`),
|
||||
description: i18nLabel(msg`Date when the record was deleted`),
|
||||
icon: 'IconCalendarMinus',
|
||||
isSystem: true,
|
||||
isNullable: true,
|
||||
isUIEditable: false,
|
||||
settings: { displayFormat: DateDisplayFormat.RELATIVE },
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
createdBy: createStandardFieldFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
fieldName: 'createdBy',
|
||||
type: FieldMetadataType.ACTOR,
|
||||
label: i18nLabel(msg`Created by`),
|
||||
description: i18nLabel(msg`The creator of the record`),
|
||||
icon: 'IconCreativeCommonsSa',
|
||||
isSystem: true,
|
||||
isUIEditable: false,
|
||||
isNullable: false,
|
||||
defaultValue: {
|
||||
source: "'MANUAL'",
|
||||
name: "'System'",
|
||||
workspaceMemberId: null,
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
updatedBy: createStandardFieldFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
fieldName: 'updatedBy',
|
||||
type: FieldMetadataType.ACTOR,
|
||||
label: i18nLabel(msg`Updated by`),
|
||||
description: i18nLabel(
|
||||
msg`The workspace member who last updated the record`,
|
||||
),
|
||||
icon: 'IconUserCircle',
|
||||
isSystem: true,
|
||||
isUIEditable: false,
|
||||
isNullable: false,
|
||||
defaultValue: {
|
||||
source: "'MANUAL'",
|
||||
name: "'System'",
|
||||
workspaceMemberId: null,
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
position: createStandardFieldFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
fieldName: 'position',
|
||||
type: FieldMetadataType.POSITION,
|
||||
label: i18nLabel(msg`Position`),
|
||||
description: i18nLabel(msg`List record position`),
|
||||
icon: 'IconHierarchy2',
|
||||
isSystem: true,
|
||||
isNullable: false,
|
||||
defaultValue: 0,
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
name: createStandardFieldFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
fieldName: 'name',
|
||||
type: FieldMetadataType.TEXT,
|
||||
label: i18nLabel(msg`Name`),
|
||||
description: i18nLabel(msg`The list name`),
|
||||
icon: 'IconUsersGroup',
|
||||
isNullable: true,
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
members: createStandardRelationFieldFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
type: FieldMetadataType.RELATION,
|
||||
morphId: null,
|
||||
fieldName: 'members',
|
||||
label: i18nLabel(msg`Members`),
|
||||
description: i18nLabel(msg`People in this list`),
|
||||
icon: 'IconUser',
|
||||
isNullable: true,
|
||||
targetObjectName: 'messageListMember',
|
||||
targetFieldName: 'list',
|
||||
settings: {
|
||||
relationType: RelationType.ONE_TO_MANY,
|
||||
},
|
||||
junctionTargetFieldUniversalIdentifier:
|
||||
STANDARD_OBJECTS.messageListMember.fields.person.universalIdentifier,
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
campaigns: createStandardRelationFieldFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
type: FieldMetadataType.RELATION,
|
||||
morphId: null,
|
||||
fieldName: 'campaigns',
|
||||
label: i18nLabel(msg`Campaigns`),
|
||||
description: i18nLabel(msg`Campaigns sent to this list`),
|
||||
icon: 'IconSend',
|
||||
isUIEditable: false,
|
||||
isNullable: true,
|
||||
targetObjectName: 'messageCampaign',
|
||||
targetFieldName: 'list',
|
||||
settings: {
|
||||
relationType: RelationType.ONE_TO_MANY,
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
timelineActivities: createStandardRelationFieldFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
type: FieldMetadataType.RELATION,
|
||||
morphId: null,
|
||||
fieldName: 'timelineActivities',
|
||||
label: i18nLabel(msg`Events`),
|
||||
description: i18nLabel(msg`Events linked to the list`),
|
||||
icon: 'IconTimelineEvent',
|
||||
isNullable: true,
|
||||
targetObjectName: 'timelineActivity',
|
||||
targetFieldName: 'targetMessageList',
|
||||
settings: {
|
||||
relationType: RelationType.ONE_TO_MANY,
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
searchVector: createStandardFieldFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
fieldName: 'searchVector',
|
||||
type: FieldMetadataType.TS_VECTOR,
|
||||
label: i18nLabel(msg`Search vector`),
|
||||
description: i18nLabel(msg`Field used for full-text search`),
|
||||
icon: 'IconUsersGroup',
|
||||
isSystem: true,
|
||||
isNullable: true,
|
||||
settings: {
|
||||
generatedType: 'STORED',
|
||||
asExpression: getTsVectorColumnExpressionFromFields(
|
||||
SEARCH_FIELDS_FOR_MESSAGE_LIST,
|
||||
),
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
});
|
||||
+27
@@ -356,4 +356,31 @@ export const buildMessageParticipantStandardFlatFieldMetadatas = ({
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
messageCampaign: createStandardRelationFieldFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
type: FieldMetadataType.RELATION,
|
||||
morphId: null,
|
||||
fieldName: 'messageCampaign',
|
||||
label: i18nLabel(msg`Campaign`),
|
||||
description: i18nLabel(
|
||||
msg`The campaign this participant was a recipient of`,
|
||||
),
|
||||
icon: 'IconSend',
|
||||
isNullable: true,
|
||||
isUIEditable: false,
|
||||
targetObjectName: 'messageCampaign',
|
||||
targetFieldName: 'recipients',
|
||||
settings: {
|
||||
relationType: RelationType.MANY_TO_ONE,
|
||||
onDelete: RelationOnDeleteAction.SET_NULL,
|
||||
joinColumnName: 'messageCampaignId',
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
});
|
||||
|
||||
+90
@@ -334,4 +334,94 @@ export const buildMessageStandardFlatFieldMetadatas = ({
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
messageCampaign: createStandardRelationFieldFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
type: FieldMetadataType.RELATION,
|
||||
morphId: null,
|
||||
fieldName: 'messageCampaign',
|
||||
label: i18nLabel(msg`Campaign`),
|
||||
description: i18nLabel(
|
||||
msg`The campaign this message was sent as part of`,
|
||||
),
|
||||
icon: 'IconSend',
|
||||
isNullable: true,
|
||||
isUIEditable: false,
|
||||
targetObjectName: 'messageCampaign',
|
||||
targetFieldName: 'messages',
|
||||
settings: {
|
||||
relationType: RelationType.MANY_TO_ONE,
|
||||
onDelete: RelationOnDeleteAction.SET_NULL,
|
||||
joinColumnName: 'messageCampaignId',
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
deliveryStatus: createStandardFieldFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
fieldName: 'deliveryStatus',
|
||||
type: FieldMetadataType.SELECT,
|
||||
label: i18nLabel(msg`Delivery status`),
|
||||
description: i18nLabel(
|
||||
msg`Per-recipient delivery status for campaign sends`,
|
||||
),
|
||||
icon: 'IconMailFast',
|
||||
isNullable: true,
|
||||
isUIEditable: false,
|
||||
options: [
|
||||
{
|
||||
id: '6b189ac2-5054-45c0-a95b-25764e978d81',
|
||||
value: 'QUEUED',
|
||||
label: i18nLabel(msg`Queued`),
|
||||
position: 0,
|
||||
color: 'gray',
|
||||
},
|
||||
{
|
||||
id: 'af7390a3-bd35-480b-9bc2-6f7d8589b3d2',
|
||||
value: 'SENT',
|
||||
label: i18nLabel(msg`Sent`),
|
||||
position: 1,
|
||||
color: 'green',
|
||||
},
|
||||
{
|
||||
id: '39c934fc-01d7-48fa-9b79-8e19f75dab03',
|
||||
value: 'FAILED',
|
||||
label: i18nLabel(msg`Failed`),
|
||||
position: 2,
|
||||
color: 'red',
|
||||
},
|
||||
{
|
||||
id: 'ade2b01f-8f10-43c6-ab3d-63b0d98ce40c',
|
||||
value: 'BOUNCED',
|
||||
label: i18nLabel(msg`Bounced`),
|
||||
position: 3,
|
||||
color: 'orange',
|
||||
},
|
||||
{
|
||||
id: 'ae79b7bc-b416-4fd2-a366-ab8d91cb22da',
|
||||
value: 'COMPLAINED',
|
||||
label: i18nLabel(msg`Complained`),
|
||||
position: 4,
|
||||
color: 'purple',
|
||||
},
|
||||
{
|
||||
id: 'c0d3f2a1-7e64-4b9a-8f21-1d5e6a7b8c90',
|
||||
value: 'SKIPPED',
|
||||
label: i18nLabel(msg`Skipped`),
|
||||
position: 5,
|
||||
color: 'yellow',
|
||||
},
|
||||
],
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
});
|
||||
|
||||
+27
@@ -1,4 +1,6 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { STANDARD_OBJECTS } from 'twenty-shared/metadata';
|
||||
|
||||
import { i18nLabel } from 'src/engine/workspace-manager/twenty-standard-application/utils/i18n-label.util';
|
||||
import {
|
||||
DateDisplayFormat,
|
||||
@@ -490,6 +492,31 @@ export const buildPersonStandardFlatFieldMetadatas = ({
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
listMemberships: createStandardRelationFieldFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
type: FieldMetadataType.RELATION,
|
||||
morphId: null,
|
||||
fieldName: 'listMemberships',
|
||||
label: i18nLabel(msg`Lists`),
|
||||
description: i18nLabel(msg`Lists the contact belongs to`),
|
||||
icon: 'IconUsersGroup',
|
||||
isUIEditable: true,
|
||||
isNullable: true,
|
||||
targetObjectName: 'messageListMember',
|
||||
targetFieldName: 'person',
|
||||
settings: {
|
||||
relationType: RelationType.ONE_TO_MANY,
|
||||
},
|
||||
junctionTargetFieldUniversalIdentifier:
|
||||
STANDARD_OBJECTS.messageListMember.fields.list.universalIdentifier,
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
searchVector: createStandardFieldFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
|
||||
+50
@@ -536,6 +536,56 @@ export const buildTimelineActivityStandardFlatFieldMetadatas = ({
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
targetMessageList: createStandardRelationFieldFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
type: FieldMetadataType.MORPH_RELATION,
|
||||
morphId: STANDARD_OBJECTS.timelineActivity.morphIds.targetMorphId.morphId,
|
||||
fieldName: 'targetMessageList',
|
||||
label: i18nLabel(msg`Target`),
|
||||
description: i18nLabel(msg`Event target`),
|
||||
icon: 'IconArrowUpRight',
|
||||
isNullable: true,
|
||||
isUIEditable: false,
|
||||
targetObjectName: 'messageList',
|
||||
targetFieldName: 'timelineActivities',
|
||||
settings: {
|
||||
relationType: RelationType.MANY_TO_ONE,
|
||||
onDelete: RelationOnDeleteAction.SET_NULL,
|
||||
joinColumnName: 'targetMessageListId',
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
targetMessageCampaign: createStandardRelationFieldFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
type: FieldMetadataType.MORPH_RELATION,
|
||||
morphId: STANDARD_OBJECTS.timelineActivity.morphIds.targetMorphId.morphId,
|
||||
fieldName: 'targetMessageCampaign',
|
||||
label: i18nLabel(msg`Target`),
|
||||
description: i18nLabel(msg`Event target`),
|
||||
icon: 'IconArrowUpRight',
|
||||
isNullable: true,
|
||||
isUIEditable: false,
|
||||
targetObjectName: 'messageCampaign',
|
||||
targetFieldName: 'timelineActivities',
|
||||
settings: {
|
||||
relationType: RelationType.MANY_TO_ONE,
|
||||
onDelete: RelationOnDeleteAction.SET_NULL,
|
||||
joinColumnName: 'targetMessageCampaignId',
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
searchVector: createStandardFieldFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
|
||||
+8
-1
@@ -40,6 +40,7 @@ export type CreateStandardMorphOrRelationFieldContext<
|
||||
settings: FieldMetadataSettings<F>;
|
||||
options?: FieldMetadataDefaultOption[] | FieldMetadataComplexOption[] | null;
|
||||
morphId: F extends FieldMetadataType.MORPH_RELATION ? string : null;
|
||||
junctionTargetFieldUniversalIdentifier?: string;
|
||||
};
|
||||
|
||||
export type CreateStandardRelationFieldArgs<
|
||||
@@ -70,6 +71,7 @@ export const createStandardRelationFieldFlatMetadata = <
|
||||
options: fieldOptions = null,
|
||||
morphId,
|
||||
type,
|
||||
junctionTargetFieldUniversalIdentifier,
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
twentyStandardApplicationId,
|
||||
@@ -135,6 +137,11 @@ export const createStandardRelationFieldFlatMetadata = <
|
||||
mainGroupByFieldMetadataViewUniversalIdentifiers: [],
|
||||
viewSortIds: [],
|
||||
viewSortUniversalIdentifiers: [],
|
||||
universalSettings: settings,
|
||||
universalSettings: {
|
||||
...settings,
|
||||
...(junctionTargetFieldUniversalIdentifier && {
|
||||
junctionTargetFieldUniversalIdentifier,
|
||||
}),
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ const computeStandardViewObjectIds = <O extends AllStandardObjectName>({
|
||||
}): StandardObjectViewIds<O> | undefined => {
|
||||
const objectDefinition = STANDARD_OBJECTS[objectName];
|
||||
|
||||
if (!Object.prototype.hasOwnProperty.call(objectDefinition, 'views')) {
|
||||
if (!('views' in objectDefinition)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
||||
+6
@@ -10,6 +10,9 @@ import { buildCalendarEventParticipantStandardFlatIndexMetadatas } from 'src/eng
|
||||
import { buildCallRecordingStandardFlatIndexMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/index/compute-call-recording-standard-flat-index-metadata.util';
|
||||
import { buildCompanyStandardFlatIndexMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/index/compute-company-standard-flat-index-metadata.util';
|
||||
import { buildDashboardStandardFlatIndexMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/index/compute-dashboard-standard-flat-index-metadata.util';
|
||||
import { buildMessageCampaignStandardFlatIndexMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/index/compute-message-campaign-standard-flat-index-metadata.util';
|
||||
import { buildMessageListStandardFlatIndexMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/index/compute-message-list-standard-flat-index-metadata.util';
|
||||
import { buildMessageListMemberStandardFlatIndexMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/index/compute-message-list-member-standard-flat-index-metadata.util';
|
||||
import { buildMessageChannelMessageAssociationMessageFolderStandardFlatIndexMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/index/compute-message-channel-message-association-message-folder-standard-flat-index-metadata.util';
|
||||
import { buildMessageChannelMessageAssociationStandardFlatIndexMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/index/compute-message-channel-message-association-standard-flat-index-metadata.util';
|
||||
import { buildMessageParticipantStandardFlatIndexMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/index/compute-message-participant-standard-flat-index-metadata.util';
|
||||
@@ -42,6 +45,9 @@ const STANDARD_FLAT_INDEX_METADATA_BUILDERS_BY_OBJECT_NAME = {
|
||||
callRecording: buildCallRecordingStandardFlatIndexMetadatas,
|
||||
company: buildCompanyStandardFlatIndexMetadatas,
|
||||
dashboard: buildDashboardStandardFlatIndexMetadatas,
|
||||
messageCampaign: buildMessageCampaignStandardFlatIndexMetadatas,
|
||||
messageList: buildMessageListStandardFlatIndexMetadatas,
|
||||
messageListMember: buildMessageListMemberStandardFlatIndexMetadatas,
|
||||
message: buildMessageStandardFlatIndexMetadatas,
|
||||
messageChannelMessageAssociation:
|
||||
buildMessageChannelMessageAssociationStandardFlatIndexMetadatas,
|
||||
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
import { type FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/types/flat-index-metadata.type';
|
||||
import { IndexType } from 'src/engine/metadata-modules/index-metadata/types/indexType.types';
|
||||
import { type AllStandardObjectIndexName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-index-name.type';
|
||||
import {
|
||||
type CreateStandardIndexArgs,
|
||||
createStandardIndexFlatMetadata,
|
||||
} from 'src/engine/workspace-manager/twenty-standard-application/utils/index/create-standard-index-flat-metadata.util';
|
||||
|
||||
export const buildMessageCampaignStandardFlatIndexMetadatas = ({
|
||||
now,
|
||||
objectName,
|
||||
workspaceId,
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
}: Omit<CreateStandardIndexArgs<'messageCampaign'>, 'context'>): Record<
|
||||
AllStandardObjectIndexName<'messageCampaign'>,
|
||||
FlatIndexMetadata
|
||||
> => ({
|
||||
unsubscribeTopicIdIndex: createStandardIndexFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
indexName: 'unsubscribeTopicIdIndex',
|
||||
relatedFieldNames: ['unsubscribeTopicId'],
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
listIdIndex: createStandardIndexFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
indexName: 'listIdIndex',
|
||||
relatedFieldNames: ['list'],
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
searchVectorGinIndex: createStandardIndexFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
indexName: 'searchVectorGinIndex',
|
||||
relatedFieldNames: ['searchVector'],
|
||||
indexType: IndexType.GIN,
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
});
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
import { type FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/types/flat-index-metadata.type';
|
||||
import { type AllStandardObjectIndexName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-index-name.type';
|
||||
import {
|
||||
type CreateStandardIndexArgs,
|
||||
createStandardIndexFlatMetadata,
|
||||
} from 'src/engine/workspace-manager/twenty-standard-application/utils/index/create-standard-index-flat-metadata.util';
|
||||
|
||||
export const buildMessageListMemberStandardFlatIndexMetadatas = ({
|
||||
now,
|
||||
objectName,
|
||||
workspaceId,
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
}: Omit<CreateStandardIndexArgs<'messageListMember'>, 'context'>): Record<
|
||||
AllStandardObjectIndexName<'messageListMember'>,
|
||||
FlatIndexMetadata
|
||||
> => ({
|
||||
listIdIndex: createStandardIndexFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
indexName: 'listIdIndex',
|
||||
relatedFieldNames: ['list'],
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
personListUniqueIndex: createStandardIndexFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
indexName: 'personListUniqueIndex',
|
||||
relatedFieldNames: ['person', 'list'],
|
||||
isUnique: true,
|
||||
indexWhereClause: '"deletedAt" IS NULL',
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
});
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
import { type FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/types/flat-index-metadata.type';
|
||||
import { IndexType } from 'src/engine/metadata-modules/index-metadata/types/indexType.types';
|
||||
import { type AllStandardObjectIndexName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-index-name.type';
|
||||
import {
|
||||
type CreateStandardIndexArgs,
|
||||
createStandardIndexFlatMetadata,
|
||||
} from 'src/engine/workspace-manager/twenty-standard-application/utils/index/create-standard-index-flat-metadata.util';
|
||||
|
||||
export const buildMessageListStandardFlatIndexMetadatas = ({
|
||||
now,
|
||||
objectName,
|
||||
workspaceId,
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
}: Omit<CreateStandardIndexArgs<'messageList'>, 'context'>): Record<
|
||||
AllStandardObjectIndexName<'messageList'>,
|
||||
FlatIndexMetadata
|
||||
> => ({
|
||||
searchVectorGinIndex: createStandardIndexFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
indexName: 'searchVectorGinIndex',
|
||||
relatedFieldNames: ['searchVector'],
|
||||
indexType: IndexType.GIN,
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
});
|
||||
+12
@@ -52,4 +52,16 @@ export const buildMessageParticipantStandardFlatIndexMetadatas = ({
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
messageCampaignIdIndex: createStandardIndexFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
indexName: 'messageCampaignIdIndex',
|
||||
relatedFieldNames: ['messageCampaign'],
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
});
|
||||
|
||||
+12
@@ -28,4 +28,16 @@ export const buildMessageStandardFlatIndexMetadatas = ({
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
messageCampaignIdIndex: createStandardIndexFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
indexName: 'messageCampaignIdIndex',
|
||||
relatedFieldNames: ['messageCampaign'],
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
});
|
||||
|
||||
+90
@@ -245,6 +245,96 @@ export const STANDARD_FLAT_OBJECT_METADATA_BUILDERS_BY_OBJECT_NAME = {
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
messageCampaign: ({
|
||||
now,
|
||||
workspaceId,
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
twentyStandardApplicationId,
|
||||
dependencyFlatEntityMaps,
|
||||
}: Omit<
|
||||
CreateStandardObjectArgs<'messageCampaign'>,
|
||||
'context' | 'objectName'
|
||||
>) =>
|
||||
createStandardObjectFlatMetadata({
|
||||
objectName: 'messageCampaign',
|
||||
dependencyFlatEntityMaps,
|
||||
context: {
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.messageCampaign.universalIdentifier,
|
||||
nameSingular: 'messageCampaign',
|
||||
namePlural: 'messageCampaigns',
|
||||
labelSingular: i18nLabel(msg`Campaign`),
|
||||
labelPlural: i18nLabel(msg`Campaigns`),
|
||||
description: i18nLabel(
|
||||
msg`A bulk email send to an audience, with delivery stats`,
|
||||
),
|
||||
icon: 'IconSend',
|
||||
isSystem: true,
|
||||
isUICreatable: false,
|
||||
labelIdentifierFieldMetadataName: 'subject',
|
||||
},
|
||||
workspaceId,
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
messageList: ({
|
||||
now,
|
||||
workspaceId,
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
twentyStandardApplicationId,
|
||||
dependencyFlatEntityMaps,
|
||||
}: Omit<CreateStandardObjectArgs<'messageList'>, 'context' | 'objectName'>) =>
|
||||
createStandardObjectFlatMetadata({
|
||||
objectName: 'messageList',
|
||||
dependencyFlatEntityMaps,
|
||||
context: {
|
||||
universalIdentifier: STANDARD_OBJECTS.messageList.universalIdentifier,
|
||||
nameSingular: 'messageList',
|
||||
namePlural: 'messageLists',
|
||||
labelSingular: i18nLabel(msg`List`),
|
||||
labelPlural: i18nLabel(msg`Lists`),
|
||||
description: i18nLabel(msg`A hand-picked audience of people`),
|
||||
icon: 'IconUsersGroup',
|
||||
isSystem: true,
|
||||
isSearchable: true,
|
||||
labelIdentifierFieldMetadataName: 'name',
|
||||
},
|
||||
workspaceId,
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
messageListMember: ({
|
||||
now,
|
||||
workspaceId,
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
twentyStandardApplicationId,
|
||||
dependencyFlatEntityMaps,
|
||||
}: Omit<
|
||||
CreateStandardObjectArgs<'messageListMember'>,
|
||||
'context' | 'objectName'
|
||||
>) =>
|
||||
createStandardObjectFlatMetadata({
|
||||
objectName: 'messageListMember',
|
||||
dependencyFlatEntityMaps,
|
||||
context: {
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.messageListMember.universalIdentifier,
|
||||
nameSingular: 'messageListMember',
|
||||
namePlural: 'messageListMembers',
|
||||
labelSingular: i18nLabel(msg`List Member`),
|
||||
labelPlural: i18nLabel(msg`List Members`),
|
||||
description: i18nLabel(msg`A person's membership in a list`),
|
||||
icon: 'IconUser',
|
||||
isSystem: true,
|
||||
labelIdentifierFieldMetadataName: 'id',
|
||||
},
|
||||
workspaceId,
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
messageChannelMessageAssociation: ({
|
||||
now,
|
||||
workspaceId,
|
||||
|
||||
+2
@@ -4,9 +4,11 @@ export { STANDARD_CALENDAR_EVENT_PARTICIPANT_PAGE_LAYOUT_CONFIG } from './standa
|
||||
export { STANDARD_CALL_RECORDING_PAGE_LAYOUT_CONFIG } from './standard-call-recording-page-layout.config';
|
||||
export { STANDARD_COMPANY_PAGE_LAYOUT_CONFIG } from './standard-company-page-layout.config';
|
||||
export { STANDARD_DASHBOARD_PAGE_LAYOUT_CONFIG } from './standard-dashboard-page-layout.config';
|
||||
export { STANDARD_MESSAGE_CAMPAIGN_PAGE_LAYOUT_CONFIG } from './standard-message-campaign-page-layout.config';
|
||||
export { STANDARD_MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_MESSAGE_FOLDER_PAGE_LAYOUT_CONFIG } from './standard-message-channel-message-association-message-folder-page-layout.config';
|
||||
export { STANDARD_MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_PAGE_LAYOUT_CONFIG } from './standard-message-channel-message-association-page-layout.config';
|
||||
export { STANDARD_MESSAGE_PARTICIPANT_PAGE_LAYOUT_CONFIG } from './standard-message-participant-page-layout.config';
|
||||
export { STANDARD_MESSAGE_LIST_PAGE_LAYOUT_CONFIG } from './standard-message-list-page-layout.config';
|
||||
export { STANDARD_MESSAGE_THREAD_PAGE_LAYOUT_CONFIG } from './standard-message-thread-page-layout.config';
|
||||
export { STANDARD_NOTE_PAGE_LAYOUT_CONFIG } from './standard-note-page-layout.config';
|
||||
export { STANDARD_OPPORTUNITY_PAGE_LAYOUT_CONFIG } from './standard-opportunity-page-layout.config';
|
||||
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
import {
|
||||
STANDARD_OBJECTS,
|
||||
STANDARD_PAGE_LAYOUT_UNIVERSAL_IDENTIFIERS,
|
||||
} from 'twenty-shared/metadata';
|
||||
|
||||
import { WidgetType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-type.enum';
|
||||
import { PageLayoutType } from 'src/engine/metadata-modules/page-layout/enums/page-layout-type.enum';
|
||||
import {
|
||||
GRID_POSITIONS,
|
||||
TAB_PROPS,
|
||||
VERTICAL_LIST_LAYOUT_POSITIONS,
|
||||
WIDGET_PROPS,
|
||||
} from 'src/engine/workspace-manager/twenty-standard-application/constants/standard-page-layout-tabs.template';
|
||||
import {
|
||||
type StandardPageLayoutConfig,
|
||||
type StandardPageLayoutTabConfig,
|
||||
} from 'src/engine/workspace-manager/twenty-standard-application/utils/page-layout-config/standard-page-layout-config.type';
|
||||
|
||||
const MESSAGE_CAMPAIGN_PAGE_TABS = {
|
||||
home: {
|
||||
universalIdentifier:
|
||||
STANDARD_PAGE_LAYOUT_UNIVERSAL_IDENTIFIERS.messageCampaignRecordPage.tabs
|
||||
.home.universalIdentifier,
|
||||
...TAB_PROPS.home,
|
||||
widgets: {
|
||||
fields: {
|
||||
universalIdentifier:
|
||||
STANDARD_PAGE_LAYOUT_UNIVERSAL_IDENTIFIERS.messageCampaignRecordPage
|
||||
.tabs.home.widgets.fields.universalIdentifier,
|
||||
...WIDGET_PROPS.fields,
|
||||
},
|
||||
list: {
|
||||
universalIdentifier:
|
||||
STANDARD_PAGE_LAYOUT_UNIVERSAL_IDENTIFIERS.messageCampaignRecordPage
|
||||
.tabs.home.widgets.list.universalIdentifier,
|
||||
title: 'List',
|
||||
type: WidgetType.FIELD,
|
||||
gridPosition: GRID_POSITIONS.FULL_WIDTH,
|
||||
position: VERTICAL_LIST_LAYOUT_POSITIONS.THIRD,
|
||||
fieldUniversalIdentifier:
|
||||
STANDARD_OBJECTS.messageCampaign.fields.list.universalIdentifier,
|
||||
},
|
||||
recipients: {
|
||||
universalIdentifier:
|
||||
STANDARD_PAGE_LAYOUT_UNIVERSAL_IDENTIFIERS.messageCampaignRecordPage
|
||||
.tabs.home.widgets.recipients.universalIdentifier,
|
||||
title: 'Recipients',
|
||||
type: WidgetType.FIELD,
|
||||
gridPosition: GRID_POSITIONS.FULL_WIDTH,
|
||||
position: VERTICAL_LIST_LAYOUT_POSITIONS.FOURTH,
|
||||
fieldUniversalIdentifier:
|
||||
STANDARD_OBJECTS.messageCampaign.fields.recipients
|
||||
.universalIdentifier,
|
||||
},
|
||||
messages: {
|
||||
universalIdentifier:
|
||||
STANDARD_PAGE_LAYOUT_UNIVERSAL_IDENTIFIERS.messageCampaignRecordPage
|
||||
.tabs.home.widgets.messages.universalIdentifier,
|
||||
title: 'Sent Messages',
|
||||
type: WidgetType.FIELD,
|
||||
gridPosition: GRID_POSITIONS.FULL_WIDTH,
|
||||
position: VERTICAL_LIST_LAYOUT_POSITIONS.FIFTH,
|
||||
fieldUniversalIdentifier:
|
||||
STANDARD_OBJECTS.messageCampaign.fields.messages.universalIdentifier,
|
||||
},
|
||||
},
|
||||
},
|
||||
} as const satisfies Record<string, StandardPageLayoutTabConfig>;
|
||||
|
||||
export const STANDARD_MESSAGE_CAMPAIGN_PAGE_LAYOUT_CONFIG = {
|
||||
name: 'Default Campaign Layout',
|
||||
type: PageLayoutType.RECORD_PAGE,
|
||||
objectUniversalIdentifier:
|
||||
STANDARD_OBJECTS.messageCampaign.universalIdentifier,
|
||||
universalIdentifier:
|
||||
STANDARD_PAGE_LAYOUT_UNIVERSAL_IDENTIFIERS.messageCampaignRecordPage
|
||||
.universalIdentifier,
|
||||
defaultTabUniversalIdentifier: null,
|
||||
tabs: MESSAGE_CAMPAIGN_PAGE_TABS,
|
||||
} as const satisfies StandardPageLayoutConfig;
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
import {
|
||||
STANDARD_OBJECTS,
|
||||
STANDARD_PAGE_LAYOUT_UNIVERSAL_IDENTIFIERS,
|
||||
} from 'twenty-shared/metadata';
|
||||
|
||||
import { WidgetType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-type.enum';
|
||||
import { PageLayoutType } from 'src/engine/metadata-modules/page-layout/enums/page-layout-type.enum';
|
||||
import {
|
||||
GRID_POSITIONS,
|
||||
TAB_PROPS,
|
||||
VERTICAL_LIST_LAYOUT_POSITIONS,
|
||||
WIDGET_PROPS,
|
||||
} from 'src/engine/workspace-manager/twenty-standard-application/constants/standard-page-layout-tabs.template';
|
||||
import {
|
||||
type StandardPageLayoutConfig,
|
||||
type StandardPageLayoutTabConfig,
|
||||
} from 'src/engine/workspace-manager/twenty-standard-application/utils/page-layout-config/standard-page-layout-config.type';
|
||||
|
||||
const MESSAGE_LIST_PAGE_TABS = {
|
||||
home: {
|
||||
universalIdentifier:
|
||||
STANDARD_PAGE_LAYOUT_UNIVERSAL_IDENTIFIERS.messageListRecordPage.tabs.home
|
||||
.universalIdentifier,
|
||||
...TAB_PROPS.home,
|
||||
widgets: {
|
||||
fields: {
|
||||
universalIdentifier:
|
||||
STANDARD_PAGE_LAYOUT_UNIVERSAL_IDENTIFIERS.messageListRecordPage.tabs
|
||||
.home.widgets.fields.universalIdentifier,
|
||||
...WIDGET_PROPS.fields,
|
||||
},
|
||||
members: {
|
||||
universalIdentifier:
|
||||
STANDARD_PAGE_LAYOUT_UNIVERSAL_IDENTIFIERS.messageListRecordPage.tabs
|
||||
.home.widgets.members.universalIdentifier,
|
||||
title: 'Members',
|
||||
type: WidgetType.FIELD,
|
||||
gridPosition: GRID_POSITIONS.FULL_WIDTH,
|
||||
position: VERTICAL_LIST_LAYOUT_POSITIONS.SECOND,
|
||||
fieldUniversalIdentifier:
|
||||
STANDARD_OBJECTS.messageList.fields.members.universalIdentifier,
|
||||
},
|
||||
},
|
||||
},
|
||||
} as const satisfies Record<string, StandardPageLayoutTabConfig>;
|
||||
|
||||
export const STANDARD_MESSAGE_LIST_PAGE_LAYOUT_CONFIG = {
|
||||
name: 'Default List Layout',
|
||||
type: PageLayoutType.RECORD_PAGE,
|
||||
objectUniversalIdentifier: STANDARD_OBJECTS.messageList.universalIdentifier,
|
||||
universalIdentifier:
|
||||
STANDARD_PAGE_LAYOUT_UNIVERSAL_IDENTIFIERS.messageListRecordPage
|
||||
.universalIdentifier,
|
||||
defaultTabUniversalIdentifier: null,
|
||||
tabs: MESSAGE_LIST_PAGE_TABS,
|
||||
} as const satisfies StandardPageLayoutConfig;
|
||||
+11
@@ -52,6 +52,17 @@ const PERSON_PAGE_TABS = {
|
||||
STANDARD_OBJECTS.person.fields.pointOfContactForOpportunities
|
||||
.universalIdentifier,
|
||||
},
|
||||
listMemberships: {
|
||||
universalIdentifier:
|
||||
STANDARD_PAGE_LAYOUT_UNIVERSAL_IDENTIFIERS.personRecordPage.tabs.home
|
||||
.widgets.listMemberships.universalIdentifier,
|
||||
title: 'Lists',
|
||||
type: WidgetType.FIELD,
|
||||
gridPosition: GRID_POSITIONS.FULL_WIDTH,
|
||||
position: VERTICAL_LIST_LAYOUT_POSITIONS.FIFTH,
|
||||
fieldUniversalIdentifier:
|
||||
STANDARD_OBJECTS.person.fields.listMemberships.universalIdentifier,
|
||||
},
|
||||
},
|
||||
},
|
||||
timeline: {
|
||||
|
||||
Reference in New Issue
Block a user