diff --git a/.changeset/cyan-ties-tease.md b/.changeset/cyan-ties-tease.md
new file mode 100644
index 00000000..84df2c10
--- /dev/null
+++ b/.changeset/cyan-ties-tease.md
@@ -0,0 +1,11 @@
+---
+"@comet/brevo-admin": major
+---
+
+Remove factory createEmailCampaignsPage
+
+The `EmailCampaignsPage` can now be created like this:
+
+```tsx
+
+```
diff --git a/.changeset/witty-coats-perform.md b/.changeset/witty-coats-perform.md
new file mode 100644
index 00000000..ab41905e
--- /dev/null
+++ b/.changeset/witty-coats-perform.md
@@ -0,0 +1,24 @@
+---
+"@comet/brevo-admin": major
+---
+
+Define scopeParts in BrevoConfig
+
+Previously the scopeParts had to be defined in the functions:
+
+- createBrevoContactsPage
+- createTargetGroupsPage
+- createEmailCampaignsPage
+
+Now it has to be defined once in the BrevoConfig:
+
+```tsx
+
+ {children}
+
+```
diff --git a/demo/admin/src/App.tsx b/demo/admin/src/App.tsx
index 5d4d66b8..7db3d016 100644
--- a/demo/admin/src/App.tsx
+++ b/demo/admin/src/App.tsx
@@ -2,7 +2,7 @@ import "@fontsource-variable/roboto-flex/full.css";
import "material-design-icons/iconfont/material-icons.css";
import { ApolloProvider } from "@apollo/client";
-import { ErrorDialogHandler, MuiThemeProvider, RouterBrowserRouter, SnackbarProvider } from "@comet/admin";
+import { ErrorDialogHandler, MasterLayout, MuiThemeProvider, RouterBrowserRouter, SnackbarProvider } from "@comet/admin";
import { BrevoConfigProvider } from "@comet/brevo-admin";
import {
AllCategories,
@@ -11,22 +11,26 @@ import {
createHttpClient,
CurrentUserProvider,
LocaleProvider,
+ SitePreview,
SitesConfigProvider,
} from "@comet/cms-admin";
import { css, Global } from "@emotion/react";
-import { ContentScope } from "@src/common/ContentScopeProvider";
+import { ContentScope, ContentScopeProvider } from "@src/common/ContentScopeProvider";
+import { MasterRoutes } from "@src/common/MasterMenu";
import { getMessages } from "@src/lang";
import { theme } from "@src/theme";
import * as React from "react";
import { DndProvider } from "react-dnd";
import { HTML5Backend } from "react-dnd-html5-backend";
import { FormattedMessage, IntlProvider } from "react-intl";
+import { Route, Switch } from "react-router";
import { createApolloClient } from "./common/apollo/createApolloClient";
+import { MasterHeader } from "./common/MasterHeader";
+import { AppMasterMenu } from "./common/MasterMenu";
import { createConfig } from "./config";
import { Link } from "./documents/links/Link";
import { Page } from "./documents/pages/Page";
-import { Routes } from "./Routes";
const GlobalStyle = () => (
{
return `${config.campaignUrl}/block-preview/${scope.domain}/${scope.language}`;
@@ -99,7 +104,21 @@ export function App() {
>
-
+
+ {({ match }) => (
+
+ }
+ />
+
+
+
+
+
+
+ )}
+
diff --git a/demo/admin/src/Routes.tsx b/demo/admin/src/Routes.tsx
deleted file mode 100644
index 2e31869a..00000000
--- a/demo/admin/src/Routes.tsx
+++ /dev/null
@@ -1,101 +0,0 @@
-import { MasterLayout, RouteWithErrorBoundary } from "@comet/admin";
-import { createBrevoContactsPage, createEmailCampaignsPage, createTargetGroupsPage } from "@comet/brevo-admin";
-import { ContentScopeIndicator, createRedirectsPage, DamPage, PagesPage, PublisherPage, SitePreview } from "@comet/cms-admin";
-import { getBrevoContactConfig } from "@src/common/brevoModuleConfig/brevoContactsPageAttributesConfig";
-import { pageTreeCategories, urlParamToCategory } from "@src/pageTree/pageTreeCategories";
-import * as React from "react";
-import { useIntl } from "react-intl";
-import { RouteComponentProps } from "react-router";
-import { Redirect, Route, Switch } from "react-router-dom";
-
-import { additionalFormConfig } from "./common/brevoModuleConfig/targetGroupFormConfig";
-import { ContentScope, ContentScopeProvider } from "./common/ContentScopeProvider";
-import { MasterHeader } from "./common/MasterHeader";
-import { MasterMenu } from "./common/MasterMenu";
-import { DashboardPage } from "./dashboard/DashboardPage";
-import { Link } from "./documents/links/Link";
-import { Page } from "./documents/pages/Page";
-import { EmailCampaignContentBlock } from "./emailCampaigns/blocks/EmailCampaignContentBlock";
-
-const RedirectsPage = createRedirectsPage();
-
-export const Routes: React.FC = () => {
- const intl = useIntl();
- const brevoContactConfig = getBrevoContactConfig(intl);
-
- const BrevoContactsPage = createBrevoContactsPage({
- scopeParts: ["domain", "language"],
- additionalAttributesFragment: brevoContactConfig.additionalAttributesFragment,
- additionalGridFields: brevoContactConfig.additionalGridFields,
- additionalFormFields: brevoContactConfig.additionalFormFields,
- input2State: brevoContactConfig.input2State,
- });
-
- const TargetGroupsPage = createTargetGroupsPage({
- scopeParts: ["domain", "language"],
- additionalFormFields: additionalFormConfig.additionalFormFields,
- exportTargetGroupOptions: {
- additionalAttributesFragment: brevoContactConfig.additionalAttributesFragment,
- exportFields: brevoContactConfig.exportFields,
- },
- nodeFragment: additionalFormConfig.nodeFragment,
- input2State: additionalFormConfig.input2State,
- });
-
- const EmailCampaignsPage = createEmailCampaignsPage({
- scopeParts: ["domain", "language"],
- EmailCampaignContentBlock: EmailCampaignContentBlock,
- });
-
- return (
-
- {({ match }) => (
-
- } />
- (
-
-
-
- ) => {
- const category = urlParamToCategory(params.category);
-
- if (category === undefined) {
- return ;
- }
-
- return (
- }
- />
- );
- }}
- />
-
-
-
-
-
-
-
-
- }
- />
-
-
-
- )}
- />
-
- )}
-
- );
-};
diff --git a/demo/admin/src/common/MasterMenu.tsx b/demo/admin/src/common/MasterMenu.tsx
index 5281c6eb..07776154 100644
--- a/demo/admin/src/common/MasterMenu.tsx
+++ b/demo/admin/src/common/MasterMenu.tsx
@@ -1,69 +1,169 @@
-import { Menu, MenuCollapsibleItem, MenuContext, MenuItemRouterLink, useWindowSize } from "@comet/admin";
import { Assets, Dashboard, Mail, PageTree, Wrench } from "@comet/admin-icons";
-import * as React from "react";
-import { useIntl } from "react-intl";
-import { useRouteMatch } from "react-router";
+import { createBrevoContactsPage, createTargetGroupsPage, EmailCampaignsPage } from "@comet/brevo-admin";
+import {
+ AllCategories,
+ ContentScopeIndicator,
+ createRedirectsPage,
+ DamPage,
+ DocumentInterface,
+ MasterMenu,
+ MasterMenuData,
+ MasterMenuRoutes,
+ PagesPage,
+ PublisherPage,
+} from "@comet/cms-admin";
+import { BrevoContactConfig, getBrevoContactConfig } from "@src/common/brevoModuleConfig/brevoContactsPageAttributesConfig";
+import { additionalFormConfig } from "@src/common/brevoModuleConfig/targetGroupFormConfig";
+import { DashboardPage } from "@src/dashboard/DashboardPage";
+import { Link } from "@src/documents/links/Link";
+import { Page } from "@src/documents/pages/Page";
+import { EmailCampaignContentBlock } from "@src/emailCampaigns/blocks/EmailCampaignContentBlock";
+import React from "react";
+import { FormattedMessage, useIntl } from "react-intl";
-const permanentMenuMinWidth = 1024;
+export const pageTreeCategories: AllCategories = [
+ {
+ category: "MainNavigation",
+ label: ,
+ },
+];
-export const MasterMenu: React.FC = () => {
- const { open, toggleOpen } = React.useContext(MenuContext);
- const windowSize = useWindowSize();
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+export const pageTreeDocumentTypes: Record> = {
+ Page,
+ Link,
+};
+const RedirectsPage = createRedirectsPage({ scopeParts: ["domain"] });
+
+const getMasterMenuData = ({ brevoContactConfig }: { brevoContactConfig: BrevoContactConfig }): MasterMenuData => {
+ const BrevoContactsPage = createBrevoContactsPage({
+ additionalAttributesFragment: brevoContactConfig.additionalAttributesFragment,
+ additionalGridFields: brevoContactConfig.additionalGridFields,
+ additionalFormFields: brevoContactConfig.additionalFormFields,
+ input2State: brevoContactConfig.input2State,
+ });
+
+ const TargetGroupsPage = createTargetGroupsPage({
+ additionalFormFields: additionalFormConfig.additionalFormFields,
+ exportTargetGroupOptions: {
+ additionalAttributesFragment: brevoContactConfig.additionalAttributesFragment,
+ exportFields: brevoContactConfig.exportFields,
+ },
+ nodeFragment: additionalFormConfig.nodeFragment,
+ input2State: additionalFormConfig.input2State,
+ });
+
+ return [
+ {
+ type: "route",
+ primary: ,
+ icon: ,
+ route: {
+ path: "/dashboard",
+ component: DashboardPage,
+ },
+ },
+ {
+ type: "route",
+ primary: ,
+ icon: ,
+ route: {
+ path: "/pages/pagetree/main-navigation",
+ render: () => (
+ }
+ />
+ ),
+ },
+ requiredPermission: "pageTree",
+ },
+ {
+ type: "collapsible",
+ primary: ,
+ icon: ,
+ items: [
+ {
+ type: "route",
+ primary: ,
+ route: {
+ path: "/newsletter/email-campaigns",
+ component: () => ,
+ },
+ },
+ {
+ type: "route",
+ primary: ,
+ route: {
+ path: "/newsletter/contacts",
+ render: () => ,
+ },
+ },
+ {
+ type: "route",
+ primary: ,
+ route: {
+ path: "/newsletter/target-groups",
+ render: () => ,
+ },
+ },
+ ],
+ requiredPermission: "brevo-newsletter",
+ },
+ {
+ type: "route",
+ primary: ,
+ icon: ,
+ route: {
+ path: "/assets",
+ component: DamPage,
+ },
+ requiredPermission: "dam",
+ },
+ {
+ type: "collapsible",
+ primary: ,
+ icon: ,
+ items: [
+ {
+ type: "route",
+ primary: ,
+ route: {
+ path: "/system/publisher",
+ component: PublisherPage,
+ },
+ requiredPermission: "builds",
+ },
+ {
+ type: "route",
+ primary: ,
+ route: {
+ path: "/system/redirects",
+ render: () => ,
+ },
+ requiredPermission: "pageTree",
+ },
+ ],
+ requiredPermission: "pageTree",
+ },
+ ];
+};
+
+export const AppMasterMenu = () => {
const intl = useIntl();
- const match = useRouteMatch();
- const useTemporaryMenu: boolean = windowSize.width < permanentMenuMinWidth;
+ const masterMenuDataForScope = React.useMemo(() => getMasterMenuData({ brevoContactConfig: getBrevoContactConfig(intl) }), [intl]);
+
+ return ;
+};
+
+export const MasterRoutes = () => {
+ const intl = useIntl();
- // Open menu when changing to permanent variant and close when changing to temporary variant.
- React.useEffect(() => {
- if ((useTemporaryMenu && open) || (!useTemporaryMenu && !open)) {
- toggleOpen();
- }
- // useEffect dependencies must only include `location`, because the function should only be called once after changing the location.
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [location]);
+ const masterMenuDataForScope = React.useMemo(() => getMasterMenuData({ brevoContactConfig: getBrevoContactConfig(intl) }), [intl]);
- return (
-
- );
+ return ;
};
diff --git a/demo/admin/src/common/brevoModuleConfig/brevoContactsPageAttributesConfig.tsx b/demo/admin/src/common/brevoModuleConfig/brevoContactsPageAttributesConfig.tsx
index 208219c0..d1712c62 100644
--- a/demo/admin/src/common/brevoModuleConfig/brevoContactsPageAttributesConfig.tsx
+++ b/demo/admin/src/common/brevoModuleConfig/brevoContactsPageAttributesConfig.tsx
@@ -59,9 +59,7 @@ export const additionalFormConfig = {
nodeFragment: attributesFragment,
};
-export const getBrevoContactConfig = (
- intl: IntlShape,
-): {
+export interface BrevoContactConfig {
additionalGridFields: GridColDef[];
additionalFormFields: React.ReactNode;
additionalAttributesFragment: {
@@ -77,7 +75,9 @@ export const getBrevoContactConfig = (
renderValue: (row: GQLBrevoContactAttributesFragmentFragment) => string;
headerName: string;
}[];
-} => {
+}
+
+export const getBrevoContactConfig = (intl: IntlShape): BrevoContactConfig => {
return {
additionalGridFields: [
{
diff --git a/packages/admin/src/brevoContacts/BrevoContactsPage.tsx b/packages/admin/src/brevoContacts/BrevoContactsPage.tsx
index 8ad01cb0..15c59038 100644
--- a/packages/admin/src/brevoContacts/BrevoContactsPage.tsx
+++ b/packages/admin/src/brevoContacts/BrevoContactsPage.tsx
@@ -4,11 +4,11 @@ import { DocumentNode } from "graphql";
import * as React from "react";
import { useIntl } from "react-intl";
+import { useBrevoConfig } from "../common/BrevoConfigProvider";
import { BrevoContactsGrid } from "./BrevoContactsGrid";
import { BrevoContactForm, EditBrevoContactFormValues } from "./form/BrevoContactForm";
interface CreateContactsPageOptions {
- scopeParts: string[];
additionalAttributesFragment?: { name: string; fragment: DocumentNode };
additionalGridFields?: GridColDef[];
additionalFormFields?: React.ReactNode;
@@ -16,7 +16,6 @@ interface CreateContactsPageOptions {
}
function createBrevoContactsPage({
- scopeParts,
additionalAttributesFragment,
additionalFormFields,
additionalGridFields,
@@ -24,6 +23,7 @@ function createBrevoContactsPage({
}: CreateContactsPageOptions) {
function BrevoContactsPage(): JSX.Element {
const intl = useIntl();
+ const { scopeParts } = useBrevoConfig();
const { scope: completeScope } = useContentScope();
const scope = scopeParts.reduce((acc, scopePart) => {
diff --git a/packages/admin/src/common/BrevoConfigProvider.tsx b/packages/admin/src/common/BrevoConfigProvider.tsx
index bce4926c..3f067da4 100644
--- a/packages/admin/src/common/BrevoConfigProvider.tsx
+++ b/packages/admin/src/common/BrevoConfigProvider.tsx
@@ -3,6 +3,7 @@ import React from "react";
export interface BrevoConfig {
apiUrl: string;
+ scopeParts: string[];
resolvePreviewUrlForScope: (scope: ContentScopeInterface) => string;
}
@@ -19,6 +20,7 @@ export const BrevoConfigProvider = ({ children, value }: React.PropsWithChildren
interface UseBrevoConfigReturn {
apiUrl: string;
previewUrl: string;
+ scopeParts: string[];
}
export const useBrevoConfig = (): UseBrevoConfigReturn => {
diff --git a/packages/admin/src/emailCampaigns/EmailCampaignsPage.tsx b/packages/admin/src/emailCampaigns/EmailCampaignsPage.tsx
index 13b08af5..dbda3f55 100644
--- a/packages/admin/src/emailCampaigns/EmailCampaignsPage.tsx
+++ b/packages/admin/src/emailCampaigns/EmailCampaignsPage.tsx
@@ -4,53 +4,51 @@ import { ContentScopeIndicator, useContentScope } from "@comet/cms-admin";
import * as React from "react";
import { useIntl } from "react-intl";
+import { useBrevoConfig } from "../common/BrevoConfigProvider";
import { EmailCampaignsGrid } from "./EmailCampaignsGrid";
import { EmailCampaignForm } from "./form/EmailCampaignForm";
import { EmailCampaignStatistics } from "./statistics/EmailCampaignStatistics";
import { EmailCampaignView } from "./view/EmailCampaignView";
-interface CreateEmailCampaignsPageOptions {
- scopeParts: string[];
+interface EmailCampaignsPageOptions {
EmailCampaignContentBlock: BlockInterface;
}
-export function createEmailCampaignsPage({ scopeParts, EmailCampaignContentBlock }: CreateEmailCampaignsPageOptions) {
- function EmailCampaignsPage(): JSX.Element {
- const { scope: completeScope } = useContentScope();
- const intl = useIntl();
+export function EmailCampaignsPage({ EmailCampaignContentBlock }: EmailCampaignsPageOptions): JSX.Element {
+ const { scopeParts } = useBrevoConfig();
+ const { scope: completeScope } = useContentScope();
+ const intl = useIntl();
- const scope = scopeParts.reduce((acc, scopePart) => {
- acc[scopePart] = completeScope[scopePart];
- return acc;
- }, {} as { [key: string]: unknown });
+ const scope = scopeParts.reduce((acc, scopePart) => {
+ acc[scopePart] = completeScope[scopePart];
+ return acc;
+ }, {} as { [key: string]: unknown });
- return (
-
-
-
- } />
-
-
- {(selectedId) => }
-
- {(selectedId) => }
-
+ return (
+
+
+
+ } />
+
+
+ {(selectedId) => }
+
+ {(selectedId) => }
+
-
- {(selectedId) => }
-
-
-
-
-
-
- );
- }
- return EmailCampaignsPage;
+
+ {(selectedId) => }
+
+
+
+
+
+
+ );
}
diff --git a/packages/admin/src/index.ts b/packages/admin/src/index.ts
index abf8d740..98e9e29c 100644
--- a/packages/admin/src/index.ts
+++ b/packages/admin/src/index.ts
@@ -1,6 +1,6 @@
export { createBrevoContactsPage } from "./brevoContacts/BrevoContactsPage";
export { EditBrevoContactFormValues } from "./brevoContacts/form/BrevoContactForm";
export { BrevoConfig, BrevoConfigProvider, useBrevoConfig } from "./common/BrevoConfigProvider";
-export { createEmailCampaignsPage } from "./emailCampaigns/EmailCampaignsPage";
+export { EmailCampaignsPage } from "./emailCampaigns/EmailCampaignsPage";
export { EditTargetGroupFinalFormValues } from "./targetGroups/TargetGroupForm";
export { createTargetGroupsPage } from "./targetGroups/TargetGroupsPage";
diff --git a/packages/admin/src/targetGroups/TargetGroupsPage.tsx b/packages/admin/src/targetGroups/TargetGroupsPage.tsx
index 9fa9be8c..ffceba69 100644
--- a/packages/admin/src/targetGroups/TargetGroupsPage.tsx
+++ b/packages/admin/src/targetGroups/TargetGroupsPage.tsx
@@ -4,11 +4,11 @@ import { DocumentNode } from "graphql";
import * as React from "react";
import { useIntl } from "react-intl";
+import { useBrevoConfig } from "../common/BrevoConfigProvider";
import { EditTargetGroupFinalFormValues, TargetGroupForm } from "./TargetGroupForm";
import { AdditionalContactAttributesType, TargetGroupsGrid } from "./TargetGroupsGrid";
interface CreateContactsPageOptions {
- scopeParts: string[];
additionalFormFields?: React.ReactNode;
exportTargetGroupOptions?: {
additionalAttributesFragment: { name: string; fragment: DocumentNode };
@@ -19,14 +19,9 @@ interface CreateContactsPageOptions {
valuesToOutput?: (values: EditTargetGroupFinalFormValues) => EditTargetGroupFinalFormValues;
}
-export function createTargetGroupsPage({
- scopeParts,
- additionalFormFields,
- nodeFragment,
- input2State,
- exportTargetGroupOptions,
-}: CreateContactsPageOptions) {
+export function createTargetGroupsPage({ additionalFormFields, nodeFragment, input2State, exportTargetGroupOptions }: CreateContactsPageOptions) {
function TargetGroupsPage(): JSX.Element {
+ const { scopeParts } = useBrevoConfig();
const { scope: completeScope } = useContentScope();
const intl = useIntl();