Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added "Preview" and "Set as homepage" actions in pages list view #493

Merged
merged 3 commits into from
Mar 24, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions packages/webiny-api-cms/src/entities/Page.entity.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,27 @@ export const pageFactory = (context: Object): Class<IPage> => {

this.attr("parent").char();

this.attr("isHomePage")
.boolean()
.setDynamic(async () => {
const settings = await context.cms.entities.CmsSettings.load();
return settings.data.pages.home === this.parent;
});

this.attr("isErrorPage")
.boolean()
.setDynamic(async () => {
const settings = await context.cms.entities.CmsSettings.load();
return settings.data.pages.error === this.parent;
});

this.attr("isNotFoundPage")
.boolean()
.setDynamic(async () => {
const settings = await context.cms.entities.CmsSettings.load();
return settings.data.pages.notFound === this.parent;
});

this.attr("revisions")
.entities(Page)
.setDynamic(() => {
Expand Down
9 changes: 9 additions & 0 deletions packages/webiny-api-cms/src/plugins/graphql/Page.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import listPages from "./pageResolvers/listPages";
import listPublishedPages from "./pageResolvers/listPublishedPages";
import getPublishedPage from "./pageResolvers/getPublishedPage";
import getHomePage from "./pageResolvers/getHomePage";
import setHomePage from "./pageResolvers/setHomePage";
import getNotFoundPage from "./pageResolvers/getNotFoundPage";
import getErrorPage from "./pageResolvers/getErrorPage";
import searchTags from "./pageResolvers/searchTags";
Expand All @@ -37,6 +38,9 @@ export default {
settings: PageSettings
content: JSON
published: Boolean
isHomePage: Boolean
isErrorPage: Boolean
isNotFoundPage: Boolean
locked: Boolean
parent: ID
revisions: [Page]
Expand Down Expand Up @@ -184,6 +188,9 @@ export default {
data: CreatePageInput!
): PageResponse

# Sets given page as new homepage.
setHomePage(id: ID!): PageResponse

# Create a new revision from an existing revision
createRevisionFrom(
revision: ID!
Expand Down Expand Up @@ -247,6 +254,8 @@ export default {
createPage: resolveCreate(pageFetcher),
// Deletes the entire page
deletePage: resolveDelete(pageFetcher),
// Sets given page as home page.
setHomePage,
// Creates a revision from the given revision
createRevisionFrom: createRevisionFrom(pageFetcher),
// Updates revision
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// @flow
import { ErrorResponse, Response, NotFoundResponse } from "webiny-api/graphql";

export default async (root: any, args: Object, context: Object) => {
const { CmsSettings, Page } = context.cms.entities;
const { id } = args;

const newHomePage = await Page.findById(id);

if (!newHomePage) {
return new NotFoundResponse(id);
}

const settings = await CmsSettings.load();
if (settings.data.pages.home === newHomePage.parent) {
return new ErrorResponse({
code: "ALREADY_HOMEPAGE",
message: `The page is already set as homepage.`
});
}

if (!newHomePage.published) {
newHomePage.published = true;
await newHomePage.save();
}

settings.data.pages.home = newHomePage.parent;
await settings.save();

return new Response(newHomePage);
};
5 changes: 2 additions & 3 deletions packages/webiny-api/src/lambda/lambda.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@ const createApolloHandler = async (config: Object) => {
await ctxPlugin.apply(context);
}
});

console.log(config.apollo);

const apollo = new ApolloServer({
...(config.apollo || {}),
Expand Down Expand Up @@ -92,7 +90,8 @@ export const createHandler = (configFactory: (context: Object) => Promise<Object
await setup(config);

return await new Promise(async (resolve, reject) => {
const cacheKey = (config.handler && config.handler.cacheKey) ? config.handler.cacheKey : "default";
const cacheKey =
config.handler && config.handler.cacheKey ? config.handler.cacheKey : "default";
if (!handler[cacheKey]) {
try {
handler[cacheKey] = await createApolloHandler(config);
Expand Down
16 changes: 16 additions & 0 deletions packages/webiny-app-cms/__tests__/getPagePreviewUrl.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import getPagePreviewUrl from "webiny-app-cms/src/admin/components/withCmsSettings/getPagePreviewUrl";

describe("getPagePreviewUrl test", () => {
test(`if no domain, just return path ("id" query param must be present)`, async () => {
const url = getPagePreviewUrl({ page: { id: "xyz", url: "/testers" } });
expect(url).toBe("/testers?preview=xyz");
});

test(`if domain, path must be prefixed with id ("id" query param must be present)`, async () => {
const url = getPagePreviewUrl({
domain: "http://localhost:3002",
page: { id: "xyz", url: "/testers" }
});
expect(url).toBe("//localhost:3002/testers?preview=xyz");
});
});
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@
import { trimEnd } from "lodash";

export default ({ page: { url, id }, domain }: Object) => {
let previewUrl = "";

if (!domain) {
return url;
previewUrl += url;
previewUrl += "?preview=" + id;
return previewUrl;
}

let previewUrl = "//";
previewUrl = "//";

// Removes protocol from the beggining of the URL.
previewUrl += domain.replace(/(^\w+:|^)\/\//, "");
Expand Down
3 changes: 3 additions & 0 deletions packages/webiny-app-cms/src/admin/graphql/pages.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ const sharedFields = `
version
parent
published
isHomePage
isErrorPage
isNotFoundPage
locked
savedOn
`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,25 @@ const headerActions = css({

type Props = WithPageDetailsProps;

const PageActions = ({ pageDetails, pageDetails: { page } }: Props) => {
const Header = (props: Props) => {
const {
pageDetails,
pageDetails: { page },
refreshPages
} = props;
return (
<React.Fragment>
<Grid className={headerTitle}>
<Cell span={8} className={pageTitle}>
<Typography use="headline5">{page.title}</Typography>
</Cell>
<Cell span={4} className={headerActions}>
{renderPlugins("cms-page-details-header-left", { pageDetails })}
{renderPlugins("cms-page-details-header-right", { pageDetails })}
{renderPlugins("cms-page-details-header-left", { pageDetails, refreshPages })}
{renderPlugins("cms-page-details-header-right", { pageDetails, refreshPages })}
</Cell>
</Grid>
</React.Fragment>
);
};

export default PageActions;
export default Header;
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import RevisionSelector from "./revisionSelector/RevisionSelector";
import PublishRevision from "./publishRevision/PublishRevision";
import EditRevision from "./editRevision/EditRevision";
import DeletePage from "./deletePage/DeletePage";
import PageOptionsMenu from "./pageOptionsMenu/PageOptionsMenu";

export default ([
{
Expand Down Expand Up @@ -42,5 +43,12 @@ export default ([
render(props: WithPageDetailsProps) {
return <DeletePage {...props} />;
}
},
{
name: "cms-page-details-header-options-menu",
type: "cms-page-details-header-right",
render(props: WithPageDetailsProps) {
return <PageOptionsMenu {...props} />;
}
}
]: Array<CmsPageDetailsPluginType>);
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// @flow
import React from "react";
import { type WithPageDetailsProps } from "webiny-app-cms/admin/components";
import { IconButton } from "webiny-ui/Button";
import { Icon } from "webiny-ui/Icon";
import { ReactComponent as MoreVerticalIcon } from "webiny-app-cms/admin/assets/more_vert.svg";
import { ReactComponent as PreviewIcon } from "webiny-app-cms/admin/assets/visibility.svg";
import { ReactComponent as HomeIcon } from "webiny-app-cms/admin/assets/round-home-24px.svg";
import { ListItemGraphic } from "webiny-ui/List";
import { MenuItem, Menu } from "webiny-ui/Menu";
import { withConfirmation, type WithConfirmationProps } from "webiny-ui/ConfirmationDialog";
import { compose } from "recompose";
import { withCmsSettings } from "webiny-app-cms/admin/components";
import { css } from "emotion";
import { setHomePage } from "./graphql";
import { Mutation } from "react-apollo";
import { withSnackbar, type WithSnackbarProps } from "webiny-admin/components";
import classNames from "classnames";

const menuStyles = css({
width: 250,
right: -105,
left: "auto !important",
".disabled": {
opacity: 0.5,
pointerEvents: "none"
}
});

type Props = WithPageDetailsProps & WithConfirmationProps & WithSnackbarProps;

const PageOptionsMenu = (props: Props) => {
const {
showConfirmation,
cmsSettings: { getPagePreviewUrl },
showSnackbar,
pageDetails: { page }
} = props;

return (
<Menu
className={menuStyles}
handle={<IconButton icon={<MoreVerticalIcon />} />}
openSide={"left"}
>
<MenuItem onClick={() => window.open(getPagePreviewUrl(page), "_blank")}>
<ListItemGraphic>
<Icon icon={<PreviewIcon />} />
</ListItemGraphic>
Preview
</MenuItem>

<Mutation mutation={setHomePage}>
{update => (
<MenuItem
className={classNames({ disabled: page.isHomePage })}
onClick={() => {
showConfirmation(async () => {
const response = await update({
variables: {
id: page.id
}
});

const { error } = response.data.cms.setHomePage;
if (error) {
showSnackbar(error.message);
} else {
showSnackbar("Homepage set successfully!");
if (!page.published) {
props.refreshPages();
}
}
});
}}
>
<ListItemGraphic>
<Icon icon={<HomeIcon />} />
</ListItemGraphic>
Set as homepage
</MenuItem>
)}
</Mutation>
</Menu>
);
};

export default compose(
withSnackbar(),
withCmsSettings(),
withConfirmation(props => {
const {
pageDetails: { page }
} = props;

return {
message: (
<span>
You&#39;re about to set the <strong>{page.title}</strong> page as your new
homepage, are you sure you want to continue?{" "}
{!page.published && "Note that your page will be automatically published."}
</span>
)
};
})
)(PageOptionsMenu);
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// @flow
import gql from "graphql-tag";

export const setHomePage = gql`
mutation SetHomePage($id: ID!) {
cms {
setHomePage(id: $id) {
error {
message
}
}
}
}
`;
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,16 @@ export default ([
{
name: "cms-page-details-revision-content-preview",
type: "cms-page-details-revision-content",
render({ pageDetails, loading }: WithPageDetailsProps) {
render({ pageDetails, loading, refreshPages }: WithPageDetailsProps) {
return (
<Tab label={"Page preview"} disabled={loading}>
<RenderBlock>
<Elevation z={2}>
<div style={{ position: "relative" }}>
{loading && <CircularProgress />}
{renderPlugins("cms-page-details-revision-content-preview", {
pageDetails
pageDetails,
refreshPages
})}
</div>
</Elevation>
Expand Down
4 changes: 3 additions & 1 deletion packages/webiny-app-cms/src/admin/views/Pages/PageDetails.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { get } from "lodash";

type Props = WithRouterProps &
WithSnackbarProps & {
refreshPages: Function,
pageId: string,
page: Object,
loading: boolean
Expand Down Expand Up @@ -55,7 +56,7 @@ const EmptyPageDetails = () => {
);
};

const PageDetails = ({ pageId, router, showSnackbar }: Props) => {
const PageDetails = ({ pageId, router, showSnackbar, refreshPages }: Props) => {
if (!pageId) {
return <EmptyPageDetails />;
}
Expand Down Expand Up @@ -86,6 +87,7 @@ const PageDetails = ({ pageId, router, showSnackbar }: Props) => {
{pageDetails => (
<React.Fragment>
{renderPlugins("cms-page-details", {
refreshPages,
pageDetails,
loading
})}
Expand Down
Loading