diff --git a/apps/client/src/widgets/bulk_actions/execute_script.ts b/apps/client/src/widgets/bulk_actions/execute_script.ts
deleted file mode 100644
index a9d83ceca..000000000
--- a/apps/client/src/widgets/bulk_actions/execute_script.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-import { t } from "../../services/i18n.js";
-import SpacedUpdate from "../../services/spaced_update.js";
-import AbstractBulkAction from "./abstract_bulk_action.js";
-
-const TPL = /*html*/`
-
-
- ${t("execute_script.execute_script")}
- |
-
-
- |
-
-
- |
-
`;
-
-export default class ExecuteScriptBulkAction extends AbstractBulkAction {
- static get actionName() {
- return "executeScript";
- }
- static get actionTitle() {
- return t("execute_script.execute_script");
- }
-
- doRender() {
- const $action = $(TPL);
- const $script = $action.find(".script");
- $script.val(this.actionDef.script || "");
-
- const spacedUpdate = new SpacedUpdate(async () => {
- await this.saveAction({ script: $script.val() });
- }, 1000);
-
- $script.on("input", () => spacedUpdate.scheduleUpdate());
-
- return $action;
- }
-}
diff --git a/apps/client/src/widgets/bulk_actions/execute_script.tsx b/apps/client/src/widgets/bulk_actions/execute_script.tsx
new file mode 100644
index 000000000..aef6c2505
--- /dev/null
+++ b/apps/client/src/widgets/bulk_actions/execute_script.tsx
@@ -0,0 +1,50 @@
+import { useEffect, useState } from "preact/hooks";
+import { t } from "../../services/i18n.js";
+import FormTextBox from "../react/FormTextBox.jsx";
+import AbstractBulkAction, { ActionDefinition } from "./abstract_bulk_action.js";
+import BulkAction from "./BulkAction.jsx";
+import { useSpacedUpdate } from "../react/hooks.jsx";
+
+function ExecuteScriptBulkActionComponent({ bulkAction, actionDef }: { bulkAction: AbstractBulkAction, actionDef: ActionDefinition }) {
+ const [ script, setScript ] = useState(actionDef.script);
+ const spacedUpdate = useSpacedUpdate(() => bulkAction.saveAction({ script }));
+ useEffect(() => spacedUpdate.scheduleUpdate(), [ script ]);
+
+ return (
+
+ {t("execute_script.help_text")}
+
+ {t("execute_script.example_1")}
+
+ note.title = note.title + ' - suffix';
+
+ {t("execute_script.example_2")}
+
+ {"for (const attr of note.getOwnedAttributes) { attr.markAsDeleted(); }"}
+ >}
+ >
+
+
+ );
+}
+
+export default class ExecuteScriptBulkAction extends AbstractBulkAction {
+
+ static get actionName() {
+ return "executeScript";
+ }
+ static get actionTitle() {
+ return t("execute_script.execute_script");
+ }
+
+ doRender() {
+ return
+ }
+
+}