Skip to content

Commit

Permalink
Config for unsubscribe page (#117)
Browse files Browse the repository at this point in the history
  • Loading branch information
juliawegmayr authored Jan 21, 2025
1 parent 2f9f03b commit ea503b9
Show file tree
Hide file tree
Showing 12 changed files with 69 additions and 2 deletions.
6 changes: 6 additions & 0 deletions .changeset/weak-points-tan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@comet/brevo-admin": minor
"@comet/brevo-api": minor
---

Add a brevo configuration field for `unsubscriptionPageId`
3 changes: 3 additions & 0 deletions demo/api/schema.gql
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,7 @@ type BrevoConfig implements DocumentInterface {
doubleOptInTemplateId: Int!
folderId: Int!
allowedRedirectionUrl: String!
unsubscriptionPageId: String!
createdAt: DateTime!
scope: EmailCampaignContentScope!
}
Expand Down Expand Up @@ -1036,6 +1037,7 @@ input BrevoConfigInput {
doubleOptInTemplateId: Int!
folderId: Int!
allowedRedirectionUrl: String!
unsubscriptionPageId: String!
}

input BrevoConfigUpdateInput {
Expand All @@ -1044,4 +1046,5 @@ input BrevoConfigUpdateInput {
doubleOptInTemplateId: Int
folderId: Int
allowedRedirectionUrl: String
unsubscriptionPageId: String
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export const brevoConfigFormFragment = gql`
doubleOptInTemplateId
folderId
allowedRedirectionUrl
unsubscriptionPageId
}
`;

Expand Down
31 changes: 30 additions & 1 deletion packages/admin/src/brevoConfiguration/BrevoConfigForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ type FormValues = {
doubleOptInTemplate: Option;
folderId: number;
allowedRedirectionUrl: string;
unsubscriptionPageId: string;
};

interface FormProps {
Expand Down Expand Up @@ -128,6 +129,7 @@ export function BrevoConfigForm({ scope }: FormProps): React.ReactElement {
: undefined,
allowedRedirectionUrl: data?.brevoConfig?.allowedRedirectionUrl ?? "",
folderId: data?.brevoConfig?.folderId ?? 1,
unsubscriptionPageId: data?.brevoConfig?.unsubscriptionPageId ?? "",
};
}, [
data?.brevoConfig?.folderId,
Expand All @@ -137,6 +139,7 @@ export function BrevoConfigForm({ scope }: FormProps): React.ReactElement {
data?.brevoConfig?.senderMail,
data?.brevoConfig?.senderName,
doubleOptInTemplatesData?.doubleOptInTemplates,
data?.brevoConfig?.unsubscriptionPageId,
sendersData?.senders,
]);

Expand Down Expand Up @@ -170,7 +173,7 @@ export function BrevoConfigForm({ scope }: FormProps): React.ReactElement {

const sender = sendersData?.senders?.find((s) => s.email === state.sender.value);

if (!sender || !state.doubleOptInTemplate || !state.allowedRedirectionUrl) {
if (!sender || !state.doubleOptInTemplate || !state.allowedRedirectionUrl || !state.unsubscriptionPageId) {
throw new Error("Not all required fields are set");
}

Expand All @@ -180,6 +183,7 @@ export function BrevoConfigForm({ scope }: FormProps): React.ReactElement {
doubleOptInTemplateId: Number(state.doubleOptInTemplate.value),
folderId: state.folderId ?? 1,
allowedRedirectionUrl: state?.allowedRedirectionUrl ?? "",
unsubscriptionPageId: state.unsubscriptionPageId,
};

if (mode === "edit") {
Expand Down Expand Up @@ -215,6 +219,19 @@ export function BrevoConfigForm({ scope }: FormProps): React.ReactElement {
return <Loading behavior="fillPageHeight" />;
}

const validateUnsubscriptionPageId = (value: string) => {
const validUnsubscriptionPageId = /^[a-zA-Z0-9]{24}$/;
if (!validUnsubscriptionPageId.test(value)) {
return (
<FormattedMessage
id="cometBrevoModule.brevoConfig.unsubscriptionPageId.validation"
defaultMessage="Must be a 24-digit alphanumeric ID"
/>
);
}
return undefined;
};

return (
<FinalForm<FormValues> apiRef={formApiRef} onSubmit={handleSubmit} mode={mode} initialValues={initialValues}>
{({ values }) => {
Expand Down Expand Up @@ -303,6 +320,18 @@ export function BrevoConfigForm({ scope }: FormProps): React.ReactElement {
}
validate={validateUrl}
/>
<TextField
fullWidth
name="unsubscriptionPageId"
required
label={
<FormattedMessage
id="cometBrevoModule.brevoConfig.unsubscriptionPageId"
defaultMessage="Unsubscription Page ID"
/>
}
validate={validateUnsubscriptionPageId}
/>
</MainContent>
</>
);
Expand Down
3 changes: 3 additions & 0 deletions packages/api/schema.gql
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ type BrevoConfig implements DocumentInterface {
doubleOptInTemplateId: Int!
folderId: Int!
allowedRedirectionUrl: String!
unsubscriptionPageId: String!
createdAt: DateTime!
scope: EmailCampaignContentScope!
}
Expand Down Expand Up @@ -401,6 +402,7 @@ input BrevoConfigInput {
doubleOptInTemplateId: Int!
folderId: Int!
allowedRedirectionUrl: String!
unsubscriptionPageId: String!
}

input BrevoConfigUpdateInput {
Expand All @@ -409,4 +411,5 @@ input BrevoConfigUpdateInput {
doubleOptInTemplateId: Int
folderId: Int
allowedRedirectionUrl: String
unsubscriptionPageId: String
}
3 changes: 3 additions & 0 deletions packages/api/src/brevo-api/brevo-api-campaigns.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,13 @@ export class BrevoApiCampaignsService {
htmlContent,
sender,
scheduledAt,
unsubscriptionPageId,
}: {
campaign: EmailCampaignInterface;
htmlContent: string;
sender: { name: string; mail: string };
scheduledAt?: Date;
unsubscriptionPageId?: string;
}): Promise<number> {
try {
const targetGroups = await campaign.targetGroups.loadItems();
Expand All @@ -75,6 +77,7 @@ export class BrevoApiCampaignsService {
recipients: { listIds: targetGroups.map((targetGroup) => targetGroup.brevoId) },
htmlContent,
scheduledAt: scheduledAt?.toISOString(),
unsubscriptionPageId,
};

const data = await this.getCampaignsApi(campaign.scope).createEmailCampaign(emailCampaign);
Expand Down
8 changes: 7 additions & 1 deletion packages/api/src/brevo-config/dto/brevo-config.input.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { PartialType } from "@comet/cms-api";
import { Field, InputType, Int } from "@nestjs/graphql";
import { IsEmail, IsInt, IsNotEmpty, IsString, IsUrl } from "class-validator";
import { IsAlphanumeric, IsEmail, IsInt, IsNotEmpty, IsString, IsUrl, Length } from "class-validator";

@InputType()
export class BrevoConfigInput {
Expand All @@ -27,6 +27,12 @@ export class BrevoConfigInput {
@Field()
@IsUrl({ require_tld: process.env.NODE_ENV === "production" })
allowedRedirectionUrl: string;

@IsString()
@Field()
@Length(24)
@IsAlphanumeric()
unsubscriptionPageId: string;
}

@InputType()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export interface BrevoConfigInterface {
doubleOptInTemplateId: number;
folderId: number;
allowedRedirectionUrl: string;
unsubscriptionPageId: string;
createdAt: Date;
updatedAt: Date;
scope: EmailCampaignScopeInterface;
Expand Down Expand Up @@ -52,6 +53,10 @@ export class BrevoConfigEntityFactory {
@Field()
allowedRedirectionUrl: string;

@Property({ columnType: "text" })
@Field(() => String)
unsubscriptionPageId: string;

@Property({
columnType: "timestamp with time zone",
})
Expand Down
1 change: 1 addition & 0 deletions packages/api/src/email-campaign/email-campaigns.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export class EmailCampaignsService {
htmlContent,
sender: { name: brevoConfig.senderName, mail: brevoConfig.senderMail },
scheduledAt,
unsubscriptionPageId: brevoConfig.unsubscriptionPageId,
});

wrap(campaign).assign({ brevoId });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export interface EmailCampaignInterface {
scope: EmailCampaignScopeInterface;
sendingState: SendingState;
targetGroups: Collection<TargetGroupInterface, object>;
unsubscriptionPageId?: string;
}

export function createEmailCampaignEntity({
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Migration } from "@mikro-orm/migrations";

export class Migration20241024071748 extends Migration {
async up(): Promise<void> {
this.addSql('alter table "BrevoConfig" add column "unsubscriptionPageId" text not null;');
}
}
2 changes: 2 additions & 0 deletions packages/api/src/mikro-orm/migrations/migrations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { Migration20240830112400 } from "./Migration20240830112400";
import { Migration20241016123307 } from "./Migration20241016123307";
import { Migration20241018110515 } from "./Migration20241018110515";
import { Migration20241022144400 } from "./Migration20241022144400";
import { Migration20241024071748 } from "./Migration20241024071748";
import { Migration20241119101706 } from "./Migration20241119101706";

export const migrationsList: MigrationObject[] = [
Expand All @@ -28,4 +29,5 @@ export const migrationsList: MigrationObject[] = [
{ name: "Migration20241018110515", class: Migration20241018110515 },
{ name: "Migration20241119101706", class: Migration20241119101706 },
{ name: "Migration20241022144400", class: Migration20241022144400 },
{ name: "Migration20241024071748", class: Migration20241024071748 },
];

0 comments on commit ea503b9

Please sign in to comment.