Skip to content

Commit 9a1fa90

Browse files
authored
feat: Allow saved elements to be deleted. (#293)
1 parent bcdc6d4 commit 9a1fa90

File tree

8 files changed

+100
-18
lines changed

8 files changed

+100
-18
lines changed

packages/webiny-api-cms/src/dataSource/schemas/Page.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,11 @@ export default {
182182
createElement(
183183
data: ElementInput!
184184
): ElementResponse
185+
186+
# Delete element
187+
deleteElement(
188+
id: ID!
189+
): DeleteResponse
185190
},
186191
`
187192
],
@@ -211,7 +216,9 @@ export default {
211216
// Delete a revision
212217
deleteRevision: resolveDelete(pageFetcher),
213218
// Creates a new element
214-
createElement: resolveCreate(elementFetcher)
219+
createElement: resolveCreate(elementFetcher),
220+
// Deletes an element
221+
deleteElement: resolveDelete(elementFetcher)
215222
},
216223
Page: {
217224
createdBy: resolveUser("createdBy"),
Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,28 @@
11
// @flow
22
import * as React from "react";
3+
import { graphql } from "react-apollo";
4+
import { compose, withHandlers } from "recompose";
35
import styled from "react-emotion";
6+
import { removePlugin } from "webiny-app/plugins";
47
import { Typography } from "webiny-ui/Typography";
58
import { IconButton } from "webiny-ui/Button";
9+
import { withSnackbar } from "webiny-app-admin/components";
10+
import { withConfirmation, type WithConfirmationProps } from "webiny-ui/ConfirmationDialog";
611
import { ReactComponent as DeleteIcon } from "webiny-app-cms/editor/assets/icons/close.svg";
7-
8-
type Props = { title: string, onDelete: Function };
12+
import { deleteElement } from "./graphql";
913

1014
const Icon = styled("div")({
1115
position: "absolute",
1216
top: 0,
1317
right: 15
1418
});
1519

16-
export default ({ title, onDelete }: Props) => {
20+
type Props = WithConfirmationProps & {
21+
title: string,
22+
onDelete: Function
23+
};
24+
25+
const Title = ({ title, onDelete }: Props) => {
1726
return (
1827
<Typography use="overline">
1928
{title}
@@ -23,3 +32,50 @@ export default ({ title, onDelete }: Props) => {
2332
</Typography>
2433
);
2534
};
35+
36+
export default compose(
37+
withConfirmation(({ title }) => ({
38+
title: "Delete saved element",
39+
message: (
40+
<p>
41+
Are you sure you want to permanently delete the <strong>{title}</strong> element?
42+
</p>
43+
)
44+
})),
45+
withSnackbar(),
46+
graphql(deleteElement, { name: "deleteElement" }),
47+
withHandlers({
48+
onDelete: ({
49+
id,
50+
title,
51+
plugin,
52+
showConfirmation,
53+
showSnackbar,
54+
deleteElement,
55+
onDelete
56+
}) => () => {
57+
showConfirmation(async () => {
58+
const { data: res } = await deleteElement({
59+
variables: { id }
60+
});
61+
62+
const { error } = res.cms.deleteElement;
63+
if (error) {
64+
return showSnackbar(error.message);
65+
}
66+
67+
removePlugin(plugin);
68+
69+
if (typeof onDelete === "function") {
70+
onDelete();
71+
}
72+
73+
showSnackbar(
74+
<span>
75+
Element <strong>{title}</strong> deleted!
76+
</span>
77+
);
78+
});
79+
}
80+
})
81+
)(Title);

packages/webiny-app-cms/src/admin/components/withSavedElements/createElementPlugin.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,15 @@ export default (el: Element) => {
3131
const previewContent = cloneDeep(el.content);
3232
updateChildPaths(previewContent);
3333

34+
const name = "cms-saved-element-" + el.id;
35+
3436
addPlugin({
35-
name: "cms-saved-element-" + el.id,
37+
name,
3638
type: "cms-element",
3739
target: rootPlugin.target,
3840
toolbar: {
39-
title() {
40-
return <Title title={el.name} onDelete={() => {}} />;
41+
title({ refresh }) {
42+
return <Title plugin={name} title={el.name} id={el.id} onDelete={refresh}/>;
4143
},
4244
group: "cms-element-group-saved",
4345
preview() {
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// @flow
2+
import gql from "graphql-tag";
3+
4+
export const deleteElement = gql`
5+
mutation DeleteElement($id: ID!) {
6+
cms {
7+
deleteElement(id: $id) {
8+
data
9+
error {
10+
code
11+
message
12+
}
13+
}
14+
}
15+
}
16+
`;

packages/webiny-app-cms/src/admin/plugins/pageDetails/header/deletePage/DeletePage.js

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
1+
// @flow
12
import React from "react";
2-
import { compose, withProps, withHandlers } from "recompose";
3+
import { compose, withHandlers } from "recompose";
34
import dot from "dot-prop-immutable";
4-
import { withApollo, graphql } from "react-apollo";
5+
import { graphql } from "react-apollo";
56
import { withRouter } from "webiny-app/components";
67
import { withDialog, withSnackbar } from "webiny-app-admin/components";
78
import { IconButton } from "webiny-ui/Button";
89
import { Tooltip } from "webiny-ui/Tooltip";
910
import { withConfirmation, type WithConfirmationProps } from "webiny-ui/ConfirmationDialog";
1011
import { ReactComponent as DeleteIcon } from "webiny-app-cms/admin/assets/delete.svg";
11-
import { fragments, deletePage } from "webiny-app-cms/admin/graphql/pages";
12+
import { deletePage } from "webiny-app-cms/admin/graphql/pages";
1213

1314
type Props = WithConfirmationProps & {
1415
confirmDelete: Function
@@ -24,7 +25,6 @@ const DeletePage = ({ confirmDelete }: Props) => {
2425

2526
export default compose(
2627
withRouter(),
27-
withApollo,
2828
withConfirmation(({ pageDetails: { page } }) => ({
2929
title: "Delete page",
3030
message: (
@@ -39,12 +39,10 @@ export default compose(
3939
withSnackbar(),
4040
withHandlers({
4141
confirmDelete: ({
42-
client,
4342
pageDetails: { page },
4443
router,
4544
showConfirmation,
4645
deletePage,
47-
pageDetails,
4846
showDialog,
4947
showSnackbar
5048
}) => () => {

packages/webiny-app-cms/src/editor/plugins/elements/column/Column.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ const Column = pure(({ element, dropElement, togglePlugin }) => {
3838
<ColumnContainer>
3939
<ElementStyle element={element} style={{ height: "100%" }}>
4040
{!elements.length && (
41-
<DropZone.Center id={id} type={type} onDrop={dropElement}>
41+
<DropZone.Center key={id} id={id} type={type} onDrop={dropElement}>
4242
<IconButton
4343
className={addIcon + " addIcon"}
4444
icon={<AddCircleOutline />}

packages/webiny-app-cms/src/editor/plugins/elements/column/ColumnChild.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,12 @@ type Props = {
1919
const ColumnChild = ({
2020
target,
2121
element,
22-
index,
2322
last = false,
2423
dropElementAbove,
2524
dropElementBelow
2625
}: Props) => {
2726
return (
28-
<React.Fragment key={element.id}>
27+
<React.Fragment>
2928
<DropZone.Above type={target.type} onDrop={dropElementAbove} />
3029
<Element id={element.id} />
3130
{last && <DropZone.Below type={target.type} onDrop={dropElementBelow} />}
@@ -46,7 +45,7 @@ export default compose(
4645
dropElementAbove: ({ dropElement, target, index }) => (source: Object) => {
4746
dropElement({ source, target: { ...target, position: index } });
4847
},
49-
dropElementBelow: ({ dropElement, target, index, count }) => (source: Object) => {
48+
dropElementBelow: ({ dropElement, target, count }) => (source: Object) => {
5049
dropElement({ source, target: { ...target, position: count } });
5150
}
5251
})

packages/webiny-app-cms/src/editor/plugins/toolbar/addElement/AddElement.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,10 @@ class AddElement extends React.Component<Props, State> {
131131
);
132132
};
133133

134+
refresh = () => {
135+
this.setState({ group: this.state.group });
136+
};
137+
134138
render() {
135139
const { params, theme } = this.props;
136140

@@ -162,7 +166,7 @@ class AddElement extends React.Component<Props, State> {
162166
<Styled.ElementBox>
163167
<Styled.ElementTitle>
164168
{typeof plugin.toolbar.title === "function" ? (
165-
plugin.toolbar.title()
169+
plugin.toolbar.title({ refresh: this.refresh })
166170
) : (
167171
<Typography use="overline">
168172
{plugin.toolbar.title}

0 commit comments

Comments
 (0)