From 840b7386f84377d2baf1f791f8caa66f8faaec84 Mon Sep 17 00:00:00 2001 From: Miguel Camba Date: Sat, 11 Jan 2025 00:04:33 +0100 Subject: [PATCH 01/10] This does nothing yet, but the UI works --- .../SelectedElementFloatingMenu/DragMenuOption.svelte | 9 ++++++--- lib/beacon/live_admin/live/page_editor_live/edit.ex | 6 ++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/assets/svelte/components/SelectedElementFloatingMenu/DragMenuOption.svelte b/assets/svelte/components/SelectedElementFloatingMenu/DragMenuOption.svelte index d540da98..5d04a70c 100644 --- a/assets/svelte/components/SelectedElementFloatingMenu/DragMenuOption.svelte +++ b/assets/svelte/components/SelectedElementFloatingMenu/DragMenuOption.svelte @@ -6,6 +6,8 @@ selectedAstElementId, parentOfSelectedAstElement, grandParentOfSelectedAstElement, + parentSelectedAstElementId, + grandParentSelectedAstElementId, } from "$lib/stores/page" import { findHoveredSiblingIndex, getBoundingRect, getDragDirection, type Coords } from "$lib/utils/drag-helpers" import { live } from "$lib/stores/live" @@ -168,7 +170,7 @@ } function applyNewOrder() { - let parent = isParent ? $grandParentOfSelectedAstElement : $parentOfSelectedAstElement + let [parent, parentId] = isParent ? [$grandParentOfSelectedAstElement, $grandParentSelectedAstElementId] : [$parentOfSelectedAstElement, $parentSelectedAstElementId] if (newIndex !== null && newIndex !== dragElementInfo.selectedIndex && !!parent) { // Reordering happened, apply new order @@ -188,9 +190,10 @@ parts[parts.length - 1] = newSelectedIndex.toString() $selectedAstElementId = parts.join(".") } - $pageAst = [...$pageAst] + // $pageAst = [...$pageAst] // Update in the server - $live.pushEvent("update_page_ast", { id: $pageInfo.id, ast: $pageAst }) + $live.pushEvent("update_page_node", { id: $pageInfo.id, node_id: parentId, node: parent }) + // $live.pushEvent("update_page_ast", { id: $pageInfo.id, ast: $pageAst }) } } diff --git a/lib/beacon/live_admin/live/page_editor_live/edit.ex b/lib/beacon/live_admin/live/page_editor_live/edit.ex index d999113f..8de5dd20 100644 --- a/lib/beacon/live_admin/live/page_editor_live/edit.ex +++ b/lib/beacon/live_admin/live/page_editor_live/edit.ex @@ -54,6 +54,12 @@ defmodule Beacon.LiveAdmin.PageEditorLive.Edit do {:noreply, socket} end + + def handle_event("update_page_node", %{"node_id" => node_id, "node" => node}, socket) do + # TODO: update the ast node + + {:noreply, socket} + end def handle_event( "render_component_in_page", From 87f364e51a1ea89b502542115643ee3496dce402 Mon Sep 17 00:00:00 2001 From: Miguel Camba Date: Fri, 17 Jan 2025 20:16:53 +0100 Subject: [PATCH 02/10] Kind of working --- .../live_admin/live/page_editor_live/edit.ex | 10 +++++++--- .../live/page_editor_live/form_component.ex | 13 ++++++++++++- lib/beacon/live_admin/visual_editor.ex | 15 +++++++++++++++ 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/lib/beacon/live_admin/live/page_editor_live/edit.ex b/lib/beacon/live_admin/live/page_editor_live/edit.ex index 8de5dd20..e23838b6 100644 --- a/lib/beacon/live_admin/live/page_editor_live/edit.ex +++ b/lib/beacon/live_admin/live/page_editor_live/edit.ex @@ -54,10 +54,14 @@ defmodule Beacon.LiveAdmin.PageEditorLive.Edit do {:noreply, socket} end - - def handle_event("update_page_node", %{"node_id" => node_id, "node" => node}, socket) do - # TODO: update the ast node + def handle_event("update_page_node", %{"node_id" => path, "node" => node}, socket) do + # TODO: update the ast node + send_update(Beacon.LiveAdmin.PageEditorLive.FormComponent, + id: "page-editor-form", + path: path, + node: node + ) {:noreply, socket} end diff --git a/lib/beacon/live_admin/live/page_editor_live/form_component.ex b/lib/beacon/live_admin/live/page_editor_live/form_component.ex index 3b82f590..e223a9fc 100644 --- a/lib/beacon/live_admin/live/page_editor_live/form_component.ex +++ b/lib/beacon/live_admin/live/page_editor_live/form_component.ex @@ -88,7 +88,17 @@ defmodule Beacon.LiveAdmin.PageEditorLive.FormComponent do deleted_attrs = Map.get(payload, :deleted, []) ast = VisualEditor.update_node(socket.assigns.builder_page_ast, path, attrs, deleted_attrs) - # TODO: Don't save immediately. Debounce serializing this to a template + update_template_later(socket, ast) + end + + # changed element from visual editor control + def update(%{path: path, node: node}, %{assigns: %{editor: "visual"}} = socket) do + ast = VisualEditor.replace_node(socket.assigns.builder_page_ast, path, node) + + update_template_later(socket, ast) + end + + defp update_template_later(socket, ast) do template = Beacon.Template.HEEx.HEExDecoder.decode(ast) params = Map.merge(socket.assigns.form.params, %{"template" => template}) changeset = Content.change_page(socket.assigns.site, socket.assigns.page, params) @@ -98,6 +108,7 @@ defmodule Beacon.LiveAdmin.PageEditorLive.FormComponent do |> assign_form(changeset) |> assign_template(template) |> assign(builder_page_ast: ast)} + {:ok, socket} end @impl true diff --git a/lib/beacon/live_admin/visual_editor.ex b/lib/beacon/live_admin/visual_editor.ex index 85d58218..19fff351 100644 --- a/lib/beacon/live_admin/visual_editor.ex +++ b/lib/beacon/live_admin/visual_editor.ex @@ -53,6 +53,21 @@ defmodule Beacon.LiveAdmin.VisualEditor do end end + def replace_node(nodes, path, new_node) do + path = resolve_path(path) + replace_node_recursive(nodes, path, new_node) + end + + defp replace_node_recursive(nodes, [index], new_node) do + List.update_at(nodes, index, fn _ -> new_node end) + end + + defp replace_node_recursive(nodes, [index | rest], new_node) do + List.update_at(nodes, index, fn node -> + %{node | "content" => replace_node_recursive(node["content"], rest, new_node)} + end) + end + # FIXME: update "root" node - it will crash if any property is updated on the root node (choose Up one level up to root) def update_node(nodes, path, attrs, deleted_attrs) do path = resolve_path(path) From 446cb74d37bcc9f3c0c19158d3a972ce92b758d4 Mon Sep 17 00:00:00 2001 From: cibernox <265339+cibernox@users.noreply.github.com> Date: Fri, 17 Jan 2025 19:17:44 +0000 Subject: [PATCH 03/10] auto format code --- .../SelectedElementFloatingMenu/DragMenuOption.svelte | 4 +++- lib/beacon/live_admin/live/page_editor_live/edit.ex | 1 + lib/beacon/live_admin/live/page_editor_live/form_component.ex | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/assets/svelte/components/SelectedElementFloatingMenu/DragMenuOption.svelte b/assets/svelte/components/SelectedElementFloatingMenu/DragMenuOption.svelte index 5d04a70c..a71bb1b9 100644 --- a/assets/svelte/components/SelectedElementFloatingMenu/DragMenuOption.svelte +++ b/assets/svelte/components/SelectedElementFloatingMenu/DragMenuOption.svelte @@ -170,7 +170,9 @@ } function applyNewOrder() { - let [parent, parentId] = isParent ? [$grandParentOfSelectedAstElement, $grandParentSelectedAstElementId] : [$parentOfSelectedAstElement, $parentSelectedAstElementId] + let [parent, parentId] = isParent + ? [$grandParentOfSelectedAstElement, $grandParentSelectedAstElementId] + : [$parentOfSelectedAstElement, $parentSelectedAstElementId] if (newIndex !== null && newIndex !== dragElementInfo.selectedIndex && !!parent) { // Reordering happened, apply new order diff --git a/lib/beacon/live_admin/live/page_editor_live/edit.ex b/lib/beacon/live_admin/live/page_editor_live/edit.ex index e23838b6..90fc99e5 100644 --- a/lib/beacon/live_admin/live/page_editor_live/edit.ex +++ b/lib/beacon/live_admin/live/page_editor_live/edit.ex @@ -62,6 +62,7 @@ defmodule Beacon.LiveAdmin.PageEditorLive.Edit do path: path, node: node ) + {:noreply, socket} end diff --git a/lib/beacon/live_admin/live/page_editor_live/form_component.ex b/lib/beacon/live_admin/live/page_editor_live/form_component.ex index e223a9fc..51406491 100644 --- a/lib/beacon/live_admin/live/page_editor_live/form_component.ex +++ b/lib/beacon/live_admin/live/page_editor_live/form_component.ex @@ -108,6 +108,7 @@ defmodule Beacon.LiveAdmin.PageEditorLive.FormComponent do |> assign_form(changeset) |> assign_template(template) |> assign(builder_page_ast: ast)} + {:ok, socket} end From db1a55fb94ecc6d3d36761a286c6dbc80e2354c0 Mon Sep 17 00:00:00 2001 From: Miguel Camba Date: Fri, 17 Jan 2025 20:47:47 +0100 Subject: [PATCH 04/10] Finally working --- lib/beacon/live_admin/live/page_editor_live/form_component.ex | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/beacon/live_admin/live/page_editor_live/form_component.ex b/lib/beacon/live_admin/live/page_editor_live/form_component.ex index 51406491..2a5f4721 100644 --- a/lib/beacon/live_admin/live/page_editor_live/form_component.ex +++ b/lib/beacon/live_admin/live/page_editor_live/form_component.ex @@ -108,8 +108,6 @@ defmodule Beacon.LiveAdmin.PageEditorLive.FormComponent do |> assign_form(changeset) |> assign_template(template) |> assign(builder_page_ast: ast)} - - {:ok, socket} end @impl true From 1ec9cd1ed577b58df023a198b65957e4c7d31d52 Mon Sep 17 00:00:00 2001 From: Miguel Camba Date: Fri, 17 Jan 2025 20:48:23 +0100 Subject: [PATCH 05/10] Remove commented code --- .../SelectedElementFloatingMenu/DragMenuOption.svelte | 2 -- 1 file changed, 2 deletions(-) diff --git a/assets/svelte/components/SelectedElementFloatingMenu/DragMenuOption.svelte b/assets/svelte/components/SelectedElementFloatingMenu/DragMenuOption.svelte index a71bb1b9..02867728 100644 --- a/assets/svelte/components/SelectedElementFloatingMenu/DragMenuOption.svelte +++ b/assets/svelte/components/SelectedElementFloatingMenu/DragMenuOption.svelte @@ -192,10 +192,8 @@ parts[parts.length - 1] = newSelectedIndex.toString() $selectedAstElementId = parts.join(".") } - // $pageAst = [...$pageAst] // Update in the server $live.pushEvent("update_page_node", { id: $pageInfo.id, node_id: parentId, node: parent }) - // $live.pushEvent("update_page_ast", { id: $pageInfo.id, ast: $pageAst }) } } From 70679e65b145072b6dd2070f5808379e8973f0b1 Mon Sep 17 00:00:00 2001 From: Miguel Camba Date: Fri, 17 Jan 2025 21:13:55 +0100 Subject: [PATCH 06/10] Use fine grained updates when editing content too --- assets/svelte/components/PageAstNode.svelte | 7 +- .../svelte/components/SidebarSection.svelte | 229 ------------------ assets/svelte/utils/ast-manipulation.ts | 9 +- 3 files changed, 11 insertions(+), 234 deletions(-) delete mode 100644 assets/svelte/components/SidebarSection.svelte diff --git a/assets/svelte/components/PageAstNode.svelte b/assets/svelte/components/PageAstNode.svelte index b74d582f..4c02e762 100644 --- a/assets/svelte/components/PageAstNode.svelte +++ b/assets/svelte/components/PageAstNode.svelte @@ -1,5 +1,6 @@ - -
-
- - {/if} - - - - - - - - -
- {#if $$slots["value"]} - - - -
- {:else if expanded} - - {#if internalValue} - {#if large} - - - {:else} - - {/if} - {#if $$slots["value"]} -
- {/if} - {:else if astNodes} - {#each astNodes as astNode, idx} - {#if isAstElement(astNode)} - -
highlightAstElement(astNode)} - on:mouseleave={() => unhighlightAstElement()} - class="mt-5" - > -
- <{astNode.tag}> - -
-
- - -
-
- {:else if large} - - {:else} - updateNodeContents(e, idx)} - /> - {/if} - {/each} - {/if} -
- {/if} -
diff --git a/assets/svelte/utils/ast-manipulation.ts b/assets/svelte/utils/ast-manipulation.ts index e08eaf5c..4aca4eb8 100644 --- a/assets/svelte/utils/ast-manipulation.ts +++ b/assets/svelte/utils/ast-manipulation.ts @@ -4,10 +4,10 @@ import { get } from "svelte/store" import type { AstNode, Page, PageInfo } from "$lib/types" import { getParentNodeId } from "./ast-helpers" -export function updateNodeContent(node, text) { +export function updateNodeContent(path, node, text) { if (node && isAstElement(node)) { node.content = [text] - updateAst() + updateNode(path, node) } } @@ -17,6 +17,11 @@ export function updateAst() { let live = get(liveStore) live.pushEvent("update_page_ast", { id: info.id, ast }) } +export function updateNode(path, node) { + let live = get(liveStore) + let info: PageInfo = get(pageInfo) + live.pushEvent("update_page_node", { id: info.id, node_id: path, node: node }) +} export function deleteAstNode(astElementId: string) { let ast: AstNode[] = get(pageAst) From 0baeb0656c010f272d38da1416c229fa4e5ee783 Mon Sep 17 00:00:00 2001 From: cibernox <265339+cibernox@users.noreply.github.com> Date: Fri, 17 Jan 2025 20:37:42 +0000 Subject: [PATCH 07/10] auto format code --- assets/svelte/components/PageAstNode.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/svelte/components/PageAstNode.svelte b/assets/svelte/components/PageAstNode.svelte index 4c02e762..6d3c493a 100644 --- a/assets/svelte/components/PageAstNode.svelte +++ b/assets/svelte/components/PageAstNode.svelte @@ -98,7 +98,7 @@ let newText = tmpClone.textContent?.trim() || "" if (node.content[stringChildIndex] !== newText) { node.content[stringChildIndex] = newText - updateNode($selectedAstElementId, node); + updateNode($selectedAstElementId, node) } } } From d260195838b6d623b0e3f3b299ff4d1ead51e94d Mon Sep 17 00:00:00 2001 From: Miguel Camba Date: Fri, 17 Jan 2025 21:39:10 +0100 Subject: [PATCH 08/10] Fix node deletion --- assets/svelte/utils/ast-manipulation.ts | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/assets/svelte/utils/ast-manipulation.ts b/assets/svelte/utils/ast-manipulation.ts index 4aca4eb8..c4219bf1 100644 --- a/assets/svelte/utils/ast-manipulation.ts +++ b/assets/svelte/utils/ast-manipulation.ts @@ -17,6 +17,7 @@ export function updateAst() { let live = get(liveStore) live.pushEvent("update_page_ast", { id: info.id, ast }) } + export function updateNode(path, node) { let live = get(liveStore) let info: PageInfo = get(pageInfo) @@ -28,10 +29,21 @@ export function deleteAstNode(astElementId: string) { let astElement = findAstElement(ast, astElementId) let parentId = getParentNodeId(astElementId) - let content = parentId && parentId !== "root" ? findAstElement(ast, parentId)?.content : ast + let content; + let parentNode; + if (parentId && parentId !== "root") { + parentNode = findAstElement(ast, parentId); + content = parentNode.content; + } else { + content = ast + } if (content) { let targetIndex = (content as unknown[]).indexOf(astElement) - content.splice(targetIndex, 1) - updateAst() + content.splice(targetIndex, 1); + if (parentNode) { + updateNode(parentId, parentNode) + } else { + updateAst() + } } } From 9da9f01ecfece112e37a3a68ec431d915b78f4cf Mon Sep 17 00:00:00 2001 From: Leandro Pereira Date: Fri, 17 Jan 2025 16:46:09 -0500 Subject: [PATCH 09/10] update_node on new pages --- lib/beacon/live_admin/live/page_editor_live/edit.ex | 1 - lib/beacon/live_admin/live/page_editor_live/new.ex | 10 ++++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/beacon/live_admin/live/page_editor_live/edit.ex b/lib/beacon/live_admin/live/page_editor_live/edit.ex index 90fc99e5..4ec4e3be 100644 --- a/lib/beacon/live_admin/live/page_editor_live/edit.ex +++ b/lib/beacon/live_admin/live/page_editor_live/edit.ex @@ -56,7 +56,6 @@ defmodule Beacon.LiveAdmin.PageEditorLive.Edit do end def handle_event("update_page_node", %{"node_id" => path, "node" => node}, socket) do - # TODO: update the ast node send_update(Beacon.LiveAdmin.PageEditorLive.FormComponent, id: "page-editor-form", path: path, diff --git a/lib/beacon/live_admin/live/page_editor_live/new.ex b/lib/beacon/live_admin/live/page_editor_live/new.ex index 88274b28..3a5a27f8 100644 --- a/lib/beacon/live_admin/live/page_editor_live/new.ex +++ b/lib/beacon/live_admin/live/page_editor_live/new.ex @@ -88,6 +88,16 @@ defmodule Beacon.LiveAdmin.PageEditorLive.New do {:noreply, socket} end + def handle_event("update_page_node", %{"node_id" => path, "node" => node}, socket) do + send_update(Beacon.LiveAdmin.PageEditorLive.FormComponent, + id: "page-editor-form", + path: path, + node: node + ) + + {:noreply, socket} + end + def handle_event("select_element", %{"path" => path}, socket) do ElementSelection.select_element(path, socket) end From 03fbe1bafe7f98a4a20d8cb839d0cf81def94c91 Mon Sep 17 00:00:00 2001 From: cibernox <265339+cibernox@users.noreply.github.com> Date: Fri, 17 Jan 2025 22:02:39 +0000 Subject: [PATCH 10/10] auto format code --- assets/svelte/utils/ast-manipulation.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/assets/svelte/utils/ast-manipulation.ts b/assets/svelte/utils/ast-manipulation.ts index c4219bf1..6529f5c1 100644 --- a/assets/svelte/utils/ast-manipulation.ts +++ b/assets/svelte/utils/ast-manipulation.ts @@ -29,17 +29,17 @@ export function deleteAstNode(astElementId: string) { let astElement = findAstElement(ast, astElementId) let parentId = getParentNodeId(astElementId) - let content; - let parentNode; + let content + let parentNode if (parentId && parentId !== "root") { - parentNode = findAstElement(ast, parentId); - content = parentNode.content; + parentNode = findAstElement(ast, parentId) + content = parentNode.content } else { content = ast } if (content) { let targetIndex = (content as unknown[]).indexOf(astElement) - content.splice(targetIndex, 1); + content.splice(targetIndex, 1) if (parentNode) { updateNode(parentId, parentNode) } else {