Skip to content

Commit

Permalink
Merge pull request #46 from vivid-planet/edit-brevo-contact
Browse files Browse the repository at this point in the history
Edit brevo contact
  • Loading branch information
RainbowBunchie authored Jun 11, 2024
2 parents ef828fc + d4b9605 commit 464c3c1
Show file tree
Hide file tree
Showing 22 changed files with 660 additions and 139 deletions.
5 changes: 5 additions & 0 deletions .changeset/slimy-zoos-explode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@comet/brevo-api": patch
---

Fix bug that does not add the contact to all target groups when subscribing
15 changes: 15 additions & 0 deletions .changeset/wet-zebras-relate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
"@comet/brevo-admin": minor
"@comet/brevo-api": minor
---

Add an edit page for brevo contacts
It is possible to configure additional form fields for this page in the `createBrevoContactsPage`.

```diff
createBrevoContactsPage({
//...
+ additionalFormFields: brevoContactConfig.additionalFormFields,
+ input2State: brevoContactConfig.input2State,
});
```
2 changes: 2 additions & 0 deletions demo/admin/src/Routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ export const Routes: React.FC = () => {
scopeParts: ["domain", "language"],
additionalAttributesFragment: brevoContactConfig.additionalAttributesFragment,
additionalGridFields: brevoContactConfig.additionalGridFields,
additionalFormFields: brevoContactConfig.additionalFormFields,
input2State: brevoContactConfig.input2State,
});

const TargetGroupsPage = createTargetGroupsPage({
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import { Field, FinalFormSelect, TextField } from "@comet/admin";
import { EditBrevoContactFormValues } from "@comet/brevo-admin";
import { MenuItem } from "@mui/material";
import { GridColDef } from "@mui/x-data-grid";
import { GQLBrevoContactSalutation } from "@src/graphql.generated";
import { DocumentNode } from "graphql";
import gql from "graphql-tag";
import React from "react";
import { FormattedMessage, IntlShape } from "react-intl";

import { GQLBrevoContactAttributesFragmentFragment } from "./brevoContactsPageAttributesConfig.generated";

const attributesFragment = gql`
fragment BrevoContactAttributesFragment on BrevoContact {
attributes {
LASTNAME
FIRSTNAME
SALUTATION
}
}
`;

const salutationOptions: Array<{ label: React.ReactNode; value: GQLBrevoContactSalutation }> = [
{
label: <FormattedMessage id="brevoContact.filters.salutation.male" defaultMessage="Male" />,
value: "MALE",
},
{
label: <FormattedMessage id="brevoContact.filters.salutation.female" defaultMessage="Female" />,
value: "FEMALE",
},
];

interface AdditionalFormConfigInputProps extends EditBrevoContactFormValues {
attributes: {
SALUTATION?: GQLBrevoContactSalutation;
FIRSTNAME?: string;
LASTNAME?: string;
};
}

export const additionalFormConfig = {
nodeFragment: attributesFragment,
};

export const getBrevoContactConfig = (
intl: IntlShape,
): {
additionalGridFields: GridColDef<GQLBrevoContactAttributesFragmentFragment>[];
additionalFormFields: React.ReactNode;
additionalAttributesFragment: {
fragment: DocumentNode;
name: string;
};
input2State: (values?: AdditionalFormConfigInputProps) => {
email: string;
attributes: { SALUTATION?: GQLBrevoContactSalutation; FIRSTNAME?: string; LASTNAME?: string };
};
exportFields: {
renderValue: (row: GQLBrevoContactAttributesFragmentFragment) => string;
headerName: string;
}[];
} => {
return {
additionalGridFields: [
{
field: "attributes.firstName",
headerName: intl.formatMessage({ id: "brevoContact.firstName", defaultMessage: "First name" }),
filterable: false,
sortable: false,
width: 150,
renderCell: ({ row }) => row.attributes?.FIRSTNAME,
},
{
field: "attributes.lastName",
headerName: intl.formatMessage({ id: "brevoContact.lastName", defaultMessage: "Last name" }),
filterable: false,
sortable: false,
width: 150,
renderCell: ({ row }) => row.attributes?.LASTNAME,
},
],
additionalFormFields: (
<>
<Field
label={<FormattedMessage id="brevoContact.fields.salutation" defaultMessage="Salutation" />}
name="attributes.SALUTATION"
fullWidth
>
{(props) => (
<FinalFormSelect {...props} fullWidth>
{salutationOptions.map((option) => (
<MenuItem value={option.value} key={option.value}>
{option.label}
</MenuItem>
))}
</FinalFormSelect>
)}
</Field>
<TextField
label={<FormattedMessage id="brevoContact.fields.salutation" defaultMessage="First name" />}
name="attributes.FIRSTNAME"
fullWidth
/>
<TextField
label={<FormattedMessage id="brevoContact.fields.salutation" defaultMessage="Last name" />}
name="attributes.LASTNAME"
fullWidth
/>
</>
),
input2State: (values?: AdditionalFormConfigInputProps) => {
return {
email: values?.email ?? "",
attributes: {
SALUTATION: values?.attributes?.SALUTATION,
FIRSTNAME: values?.attributes?.FIRSTNAME,
LASTNAME: values?.attributes?.LASTNAME,
},
};
},
additionalAttributesFragment: {
fragment: attributesFragment,
name: "BrevoContactAttributesFragment",
},
exportFields: [
{
renderValue: (row: GQLBrevoContactAttributesFragmentFragment) => row.attributes?.FIRSTNAME,
headerName: intl.formatMessage({ id: "brevoContact.firstName", defaultMessage: "First name" }),
},
{
renderValue: (row: GQLBrevoContactAttributesFragmentFragment) => row.attributes?.LASTNAME,
headerName: intl.formatMessage({ id: "brevoContact.lastName", defaultMessage: "Last name" }),
},
],
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ import { FormattedMessage } from "react-intl";

const salutationOptions: Array<{ label: React.ReactNode; value: GQLBrevoContactSalutation }> = [
{
label: <FormattedMessage id="targetGroup.filters.salutation.male." defaultMessage="Male" />,
label: <FormattedMessage id="targetGroup.filters.salutation.male" defaultMessage="Male" />,
value: "MALE",
},
{
label: <FormattedMessage id="targetGroup.filters.salutation.female." defaultMessage="Female" />,
label: <FormattedMessage id="targetGroup.filters.salutation.female" defaultMessage="Female" />,
value: "FEMALE",
},
];
Expand Down
5 changes: 4 additions & 1 deletion demo/api/schema.gql
Original file line number Diff line number Diff line change
Expand Up @@ -792,6 +792,7 @@ type Mutation {
updateProduct(id: ID!, input: ProductInput!, lastUpdatedAt: DateTime): Product!
deleteProduct(id: ID!): Boolean!
updateBrevoContact(id: Int!, input: BrevoContactUpdateInput!): BrevoContact!
createBrevoContact(scope: EmailCampaignContentScopeInput!, input: BrevoContactUpdateInput!): BrevoContact
deleteBrevoContact(id: Int!): Boolean!
subscribeBrevoContact(input: SubscribeInput!, scope: EmailCampaignContentScopeInput!): SubscribeResponse!
createEmailCampaign(scope: EmailCampaignContentScopeInput!, input: EmailCampaignInput!): EmailCampaign!
Expand Down Expand Up @@ -937,7 +938,9 @@ input ProductInput {
}

input BrevoContactUpdateInput {
blocked: Boolean!
email: String
blocked: Boolean
attributes: BrevoContactAttributesInput
}

enum SubscribeResponse {
Expand Down
69 changes: 38 additions & 31 deletions packages/admin/src/brevoContacts/BrevoContactsGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
messages,
RowActionsItem,
RowActionsMenu,
StackLink,
Toolbar,
ToolbarFillSpace,
ToolbarItem,
Expand All @@ -12,8 +13,9 @@ import {
useDataGridRemote,
usePersistentColumnState,
} from "@comet/admin";
import { Block, Check, Delete } from "@comet/admin-icons";
import { Block, Check, Delete, Edit } from "@comet/admin-icons";
import { ContentScopeInterface } from "@comet/cms-admin";
import { IconButton } from "@mui/material";
import { DataGrid, GridColDef, GridToolbarQuickFilter } from "@mui/x-data-grid";
import * as React from "react";
import { FormattedMessage, IntlShape, useIntl } from "react-intl";
Expand Down Expand Up @@ -137,39 +139,44 @@ export function BrevoContactsGrid({
type: "actions",
renderCell: (params) => {
return (
<RowActionsMenu>
<>
<IconButton component={StackLink} pageName="edit" payload={params.row.id.toString()}>
<Edit color="primary" />
</IconButton>
<RowActionsMenu>
<RowActionsItem
onClick={async () => {
await client.mutate<GQLUpdateBrevoContactMutation, GQLUpdateBrevoContactMutationVariables>({
mutation: updateBrevoContactMutation,
variables: { id: params.row.id, input: { blocked: !params.row.emailBlacklisted } },
refetchQueries: [brevoContactsQuery],
});
}}
icon={params.row.emailBlacklisted ? <Check /> : <Block />}
>
{params.row.emailBlacklisted ? (
<FormattedMessage id="cometBrevoModule.brevoContact.actions.unblock" defaultMessage="Unblock" />
) : (
<FormattedMessage id="cometBrevoModule.brevoContact.actions.block" defaultMessage="Block" />
)}
</RowActionsItem>
<RowActionsMenu>
<RowActionsItem
onClick={async () => {
await client.mutate<GQLUpdateBrevoContactMutation, GQLUpdateBrevoContactMutationVariables>({
mutation: updateBrevoContactMutation,
variables: { id: params.row.id, input: { blocked: !params.row.emailBlacklisted } },
refetchQueries: [brevoContactsQuery],
});
}}
icon={params.row.emailBlacklisted ? <Check /> : <Block />}
>
{params.row.emailBlacklisted ? (
<FormattedMessage id="cometBrevoModule.brevoContact.actions.unblock" defaultMessage="Unblock" />
) : (
<FormattedMessage id="cometBrevoModule.brevoContact.actions.block" defaultMessage="Block" />
)}
</RowActionsItem>

<RowActionsItem
onClick={async () => {
await client.mutate<GQLDeleteBrevoContactMutation, GQLDeleteBrevoContactMutationVariables>({
mutation: deleteBrevoContactMutation,
variables: { id: params.row.id },
refetchQueries: [brevoContactsQuery],
});
}}
icon={<Delete />}
>
<FormattedMessage {...messages.delete} />
</RowActionsItem>
<RowActionsItem
onClick={async () => {
await client.mutate<GQLDeleteBrevoContactMutation, GQLDeleteBrevoContactMutationVariables>({
mutation: deleteBrevoContactMutation,
variables: { id: params.row.id },
refetchQueries: [brevoContactsQuery],
});
}}
icon={<Delete />}
>
<FormattedMessage {...messages.delete} />
</RowActionsItem>
</RowActionsMenu>
</RowActionsMenu>
</RowActionsMenu>
</>
);
},
},
Expand Down
Loading

0 comments on commit 464c3c1

Please sign in to comment.