Skip to content

Commit

Permalink
feat(app-page-builder): make PageOptionsMenu composable
Browse files Browse the repository at this point in the history
  • Loading branch information
Pavel910 committed Dec 2, 2022
1 parent 859a3fb commit 990c3ab
Show file tree
Hide file tree
Showing 7 changed files with 190 additions and 72 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import { PageSettingsPlugin } from "./PageSettings";
import { RevisionsPlugin } from "./Revisions";
import { PublishPageButtonPlugin } from "./PublishPageButton";
import { TitlePlugin } from "./Title";
import { PageOptionsMenuPlugin } from "./PageOptionsMenu";
import { PageOptionsMenuPlugin } from "./PageOptionsMenu/PageOptionsMenuPlugin";
import { PreviewPageButtonPlugin } from "./PreviewPageButton/PreviewPageButton";
import { SetAsHomepageButtonPlugin } from "./SetAsHomepageButton/SetAsHomepageButton";

export const EditorBarPlugins = () => {
return (
Expand All @@ -15,6 +17,8 @@ export const EditorBarPlugins = () => {
<PageSettingsPlugin />
<PageOptionsMenuPlugin />
<PublishPageButtonPlugin />
<PreviewPageButtonPlugin />
<SetAsHomepageButtonPlugin />
</>
);
};
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import React from "react";
import { css } from "emotion";
import { createComponentPlugin } from "@webiny/app-admin";
import { Menu } from "@webiny/ui/Menu";
import { makeComposable } from "@webiny/app-admin";
import { Menu, MenuItem } from "@webiny/ui/Menu";
import { IconButton } from "@webiny/ui/Button";
import { ReactComponent as MoreVerticalIcon } from "~/admin/assets/more_vert.svg";
import { EditorBar } from "~/editor";
import { PreviewPageButton } from "./PreviewPageButton";
import { SetAsHomepageButton } from "./SetAsHomepageButton";
import { ListItemGraphic } from "@webiny/ui/List";
import { Icon } from "@webiny/ui/Icon";

const menuStyles = css({
".disabled": {
Expand All @@ -15,26 +14,45 @@ const menuStyles = css({
}
});

const PageOptionsMenu: React.FC = () => {
return (
<Menu
data-testid="pb-editor-page-options-menu"
className={menuStyles}
handle={<IconButton icon={<MoreVerticalIcon />} />}
>
<PreviewPageButton />
<SetAsHomepageButton />
</Menu>
);
};
export interface PageOptionsMenuItem {
label: string;
icon: React.ReactElement;
onClick: () => void;
disabled?: boolean;
"data-testid"?: string;
}

export interface PageOptionsMenuProps {
items: PageOptionsMenuItem[];
}

export const PageOptionsMenu = makeComposable<PageOptionsMenuProps>(
"PageOptionsMenu",
({ items }) => {
if (!items.length) {
return null;
}

export const PageOptionsMenuPlugin = createComponentPlugin(EditorBar.RightSection, RightSection => {
return function AddRevisionSelector(props) {
return (
<RightSection>
<PageOptionsMenu />
{props.children}
</RightSection>
<Menu
data-testid="pb-editor-page-options-menu"
className={menuStyles}
handle={<IconButton icon={<MoreVerticalIcon />} />}
>
{items.map(item => (
<MenuItem
key={item.label}
disabled={item.disabled ?? false}
onClick={item.onClick}
data-testid={item["data-testid"]}
>
<ListItemGraphic>
<Icon icon={item.icon} />
</ListItemGraphic>
{item.label}
</MenuItem>
))}
</Menu>
);
};
});
}
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from "react";
import { createComponentPlugin } from "@webiny/react-composition";
import { EditorBar } from "~/editor";
import { PageOptionsMenu } from "~/pageEditor";

export const PageOptionsMenuPlugin = createComponentPlugin(EditorBar.RightSection, RightSection => {
return function AddRevisionSelector(props) {
return (
<RightSection>
<PageOptionsMenu items={[]} />
{props.children}
</RightSection>
);
};
});

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React from "react";
import { ReactComponent as PreviewIcon } from "~/admin/assets/visibility.svg";
import { usePage } from "~/pageEditor/hooks/usePage";
import { usePageBuilderSettings } from "~/admin/hooks/usePageBuilderSettings";
import { useSiteStatus } from "~/admin/hooks/useSiteStatus";
import { useConfigureWebsiteUrlDialog } from "~/admin/hooks/useConfigureWebsiteUrl";
import { createComponentPlugin } from "@webiny/react-composition";
import { PageOptionsMenu, PageOptionsMenuItem } from "~/pageEditor";

const openTarget = window.Cypress ? "_self" : "_blank";

export const PreviewPageButtonPlugin = createComponentPlugin(PageOptionsMenu, Original => {
return function PreviewPageButton({ items, ...props }) {
const [page] = usePage();
const { getPageUrl, getWebsiteUrl } = usePageBuilderSettings();
const [isSiteRunning, refreshSiteStatus] = useSiteStatus(getWebsiteUrl());

const { showConfigureWebsiteUrlDialog } = useConfigureWebsiteUrlDialog(
getWebsiteUrl(),
refreshSiteStatus
);

const pageData = {
id: page.id,
status: page.status,
path: page.path
};

const onClick = () => {
if (isSiteRunning) {
window.open(getPageUrl(pageData, true), openTarget, "noopener");
} else {
showConfigureWebsiteUrlDialog();
}
};

const previewItem: PageOptionsMenuItem = {
label: "Preview",
icon: <PreviewIcon />,
onClick,
"data-testid": "pb-editor-page-options-menu-preview"
};
return <Original {...props} items={[previewItem, ...items]} />;
};
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import React, { useCallback } from "react";
import { useSnackbar } from "@webiny/app-admin/hooks/useSnackbar";
import { useRouter } from "@webiny/react-router";
import { ReactComponent as HomeIcon } from "~/admin/assets/round-home-24px.svg";
import { usePageBuilderSettings } from "~/admin/hooks/usePageBuilderSettings";
import { useAdminPageBuilder } from "~/admin/hooks/useAdminPageBuilder";
import { usePage } from "~/pageEditor/hooks/usePage";
import { createComponentPlugin } from "@webiny/react-composition";
import { PageOptionsMenu, PageOptionsMenuItem } from "~/pageEditor";
import { useConfirmationDialog } from "@webiny/app-admin";

export const SetAsHomepageButtonPlugin = createComponentPlugin(PageOptionsMenu, Original => {
return function SetAsHomepageButton({ items, ...props }) {
const [page] = usePage();
const { history } = useRouter();
const { showSnackbar } = useSnackbar();
const pageBuilder = useAdminPageBuilder();
const { showConfirmation } = useConfirmationDialog({
message: (
<span>
You&#39;re about to set this page as your new homepage, are you sure you want to
continue?
<br />
Note that the page will automatically be published.
</span>
)
});

const { settings, updateSettingsMutation, isSpecialPage } = usePageBuilderSettings();

const setPageAsHomepage = useCallback(async () => {
const publishPageResult = await pageBuilder.publishPage(page as { id: string }, {
client: pageBuilder.client
});
/**
* In case of exit in "publishPage" lifecycle, "publishPage" hook will return undefined,
* indicating an immediate exit.
*/
if (!publishPageResult) {
return;
}

if (publishPageResult.error) {
return showSnackbar(publishPageResult.error.message);
}

const [updateSettings] = updateSettingsMutation;
const response = await updateSettings({
variables: {
data: {
pages: {
...settings.pages,
home: page.id
}
}
}
});

const { error } = response.data.pageBuilder.updateSettings;
if (error) {
return showSnackbar(error.message);
}

history.push(`/page-builder/pages?id=${page.id}`);

// Let's wait a bit, because we are also redirecting the user.
setTimeout(() => showSnackbar("New homepage set successfully!"), 500);
}, [page.id]);

const setAsHomepageItem: PageOptionsMenuItem = {
label: "Set as homepage",
icon: <HomeIcon />,
onClick: () => showConfirmation(setPageAsHomepage),
disabled: isSpecialPage(page.pid!, "home")
};

return <Original {...props} items={[setAsHomepageItem, ...items]} />;
};
});
3 changes: 3 additions & 0 deletions packages/app-page-builder/src/pageEditor/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
export { PublishPageButton } from "./config/editorBar/PublishPageButton";
export { PageOptionsMenu } from "./config/editorBar/PageOptionsMenu";
export type { PageOptionsMenuItem, PageOptionsMenuProps } from "./config/editorBar/PageOptionsMenu";
export { usePage } from "./hooks/usePage";

0 comments on commit 990c3ab

Please sign in to comment.