Skip to content

Commit 6e1f5ac

Browse files
committed
fix(app-page-builder): expose a useDeleteElement hook
1 parent 3cc4b02 commit 6e1f5ac

File tree

4 files changed

+95
-52
lines changed

4 files changed

+95
-52
lines changed

packages/app-page-builder/src/editor/hooks/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,5 @@ export { useRootElement } from "./useRootElement";
1717
export { useUI } from "./useUI";
1818
export { useUpdateElement } from "./useUpdateElement";
1919
export { useUpdateHandlers } from "./useUpdateHandlers";
20+
export { useDeleteElement } from "./useDeleteElement";
21+
export { useFindElementBlock } from "./useFindElementBlock";
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { useCallback } from "react";
2+
import { plugins } from "@webiny/plugins";
3+
import { useEventActionHandler, useFindElementBlock, useUpdateElement } from "~/editor";
4+
import { DeleteElementActionEvent } from "~/editor/recoil/actions";
5+
import type { PbBlockVariable, PbEditorElement, PbEditorPageElementPlugin } from "~/types";
6+
7+
const removeVariableFromBlock = (block: PbEditorElement, variableId: string) => {
8+
const variables = block.data.variables ?? [];
9+
10+
const updatedVariables = variables.filter(
11+
(variable: PbBlockVariable) => variable.id.split(".")[0] !== variableId
12+
);
13+
14+
return {
15+
...block,
16+
data: {
17+
...block.data,
18+
variables: updatedVariables
19+
}
20+
};
21+
};
22+
23+
export const useDeleteElement = () => {
24+
const eventActionHandler = useEventActionHandler();
25+
const updateElement = useUpdateElement();
26+
const { findElementBlock } = useFindElementBlock();
27+
28+
const canDeleteElement = useCallback((element: PbEditorElement) => {
29+
const plugin = plugins
30+
.byType<PbEditorPageElementPlugin>("pb-editor-page-element")
31+
.find(pl => pl.elementType === element.type);
32+
33+
if (!plugin) {
34+
return false;
35+
}
36+
37+
if (typeof plugin.canDelete === "function") {
38+
if (!plugin.canDelete({ element })) {
39+
return false;
40+
}
41+
}
42+
43+
return true;
44+
}, []);
45+
46+
const deleteElement = useCallback(async (element: PbEditorElement): Promise<void> => {
47+
const block = await findElementBlock(element.id);
48+
49+
// We need to remove element variable from block if it exists
50+
if (element.data?.variableId && block) {
51+
const updatedBlock = removeVariableFromBlock(block, element.data.variableId);
52+
53+
updateElement(updatedBlock);
54+
}
55+
56+
eventActionHandler.trigger(
57+
new DeleteElementActionEvent({
58+
element
59+
})
60+
);
61+
}, []);
62+
63+
return { canDeleteElement, deleteElement };
64+
};
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { useCallback } from "react";
2+
import { useRecoilCallback } from "recoil";
3+
import { blockByElementSelector } from "~/editor/hooks/useCurrentBlockElement";
4+
5+
/**
6+
* Exposes a getter which traverses the element tree upwards from the given element id, and returns an element
7+
* of type "block", if found.
8+
*/
9+
export const useFindElementBlock = () => {
10+
const findBlock = useRecoilCallback(({ snapshot }) => async (id: string) => {
11+
return await snapshot.getPromise(blockByElementSelector(id));
12+
});
13+
14+
const findElementBlock = useCallback(
15+
async (elementId: string) => {
16+
return findBlock(elementId);
17+
},
18+
[findBlock]
19+
);
20+
21+
return { findElementBlock };
22+
};

packages/app-page-builder/src/editor/plugins/elementSettings/delete/DeleteAction.ts

Lines changed: 7 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,22 @@
11
import React, { useCallback } from "react";
2-
import { plugins } from "@webiny/plugins";
3-
import { useActiveElement, useEventActionHandler } from "~/editor";
4-
import { PbEditorPageElementPlugin, PbBlockVariable, PbEditorElement } from "~/types";
5-
import { useUpdateElement } from "~/editor/hooks/useUpdateElement";
6-
import { useParentBlock } from "~/editor/hooks/useParentBlock";
7-
import { DeleteElementActionEvent } from "~/editor/recoil/actions";
8-
9-
const removeVariableFromBlock = (block: PbEditorElement, variableId: string) => {
10-
const variables = block.data.variables ?? [];
11-
12-
const updatedVariables = variables.filter(
13-
(variable: PbBlockVariable) => variable.id.split(".")[0] !== variableId
14-
);
15-
16-
return {
17-
...block,
18-
data: {
19-
...block.data,
20-
variables: updatedVariables
21-
}
22-
};
23-
};
2+
import { useActiveElement, useDeleteElement } from "~/editor";
243

254
interface DeleteActionPropsType {
265
children: React.ReactElement;
276
}
287
const DeleteAction = ({ children }: DeleteActionPropsType) => {
29-
const eventActionHandler = useEventActionHandler();
308
const [element] = useActiveElement();
31-
const block = useParentBlock();
32-
const updateElement = useUpdateElement();
33-
34-
if (!element) {
35-
return null;
36-
}
9+
const { deleteElement, canDeleteElement } = useDeleteElement();
3710

3811
const onClick = useCallback((): void => {
39-
// We need to remove element variable from block if it exists
40-
if (element.data?.variableId && block) {
41-
const updatedBlock = removeVariableFromBlock(block, element.data.variableId);
42-
43-
updateElement(updatedBlock);
12+
if (!element) {
13+
return;
4414
}
45-
eventActionHandler.trigger(
46-
new DeleteElementActionEvent({
47-
element
48-
})
49-
);
50-
}, [element.id]);
51-
52-
const plugin = plugins
53-
.byType<PbEditorPageElementPlugin>("pb-editor-page-element")
54-
.find(pl => pl.elementType === element.type);
55-
56-
if (!plugin) {
57-
return null;
58-
}
5915

60-
if (typeof plugin.canDelete === "function") {
61-
if (!plugin.canDelete({ element })) {
62-
return null;
16+
if (canDeleteElement(element)) {
17+
deleteElement(element);
6318
}
64-
}
19+
}, [element?.id]);
6520

6621
return React.cloneElement(children, { onClick });
6722
};

0 commit comments

Comments
 (0)