Adding a restart process button in Pluto

I’m trying to get a SnoopCompile workflow going inside a Pluto notebook. Since SnoopCompile requires a lot of process restarts, it would be nice to have a “Restart” button. I think that this should be possible by sending a CustomEvent to the backend, but I’m unable to locate the current notebook id.

HTML("""
<div>
	<button id="myrestart" href="#">Restart</button>
	
	<script>
		const div = currentScript.parentElement
		const button = div.querySelector("button#myrestart")
		button.onclick = function() { restart_nb() };
		function restart_nb() {
			div.dispatchEvent(
				new CustomEvent("restart_process"),
				{},
				{ notebook_id: div.state.notebook.notebook.id }
			);
		};
		
	</script>
</div>
""")

When clicking the button, this fails on

Uncaught TypeError: Cannot read properties of undefined (reading 'notebook')
    at restart_nb (eval at ga (editor.9e18b711.js:248:175), <anonymous>:12:30)
    at HTMLButtonElement.button.onclick (eval at ga (editor.9e18b711.js:248:175), <anonymous>:7:33)

So, the question is: where I can find the current notebook id?

3 Likes

Not a direct answer to your question but Pluto already has a restart option which gets triggered when you make changes to your environment, maybe have a look into how that works?

1 Like

It’s here. I already looked at it, but notebook is not defined in global Javascript scope.

Answering your question did help out :partying_face: The following code sets the process status to “no_process”. Clicking next to the cell will then show the “Restart required” message:

HTML("""
<!-- the wrapper span -->
<div>
	<button id="myrestart" href="#">Restart</button>
	
	<script>
		const div = currentScript.parentElement
		const button = div.querySelector("button#myrestart")
		console.log(button);
		button.onclick = function() { restart_nb() };
		console.log(div.dispatchEvent)
		function restart_nb() {
			console.log("Send event");
			editor_state.notebook.process_status = "no_process";
			window.dispatchEvent(
				new CustomEvent("restart_process"),
				{},
				{ notebook_id: editor_state.notebook.id }
			);
		};
	</script>
</div>
""")

It’s something

3 Likes

Here you go!! Based on what @rikh started, with changes:

  • use the react setter, editor_state_set instead of modifying react state directly
  • wait for the change to take effect, then search for the button an .click() it :slight_smile:

(This is not official API so it might break in a future patch.)

html"""
<script>
	const button = document.createElement("button")

	button.addEventListener("click", () => {
		editor_state_set(old_state => ({
			notebook: {
				...old_state.notebook,
				process_status: "no_process",
			},
		})).then(() => {
			window.requestAnimationFrame(() => {
				document.querySelector("#process_status a").click()
			})
		})
	})
	button.innerText = "Restart process"

	return button
</script>
"""
2 Likes