-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
💬 Discussions Epic 💬 #116
Open
rtshkmr
wants to merge
14
commits into
master
Choose a base branch
from
epic/discussions
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
💬 Discussions Epic 💬 #116
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
* Add generic debug dump component This makes life easy when wiring things up * Rename namespace for Context.Read.* * Groundwork: add discuss component w sheafs * Init Context.Components mod for common components * Add skeletons for Sheaf Container Container managers sheaf state within itself. Should actually make the verse-matrix use this container, sometime. * Minor changes, add some TODOs to share explicit todos Minor change * Add live component EditableMarkDisplay * Add UI improvements to EditableMarkDisplay The edit button on quick draft should only be seen when the dropdown is expanded and all the marks can be seen. The general pattern I'm trying to follow is that buttons should only be shown when an action makes sense. So here, if the user can't even see the marks currently accumulating, then the user shouldn't have the chance to edit any marks. Notice that the EditableMarkDisplay is a live_component that is a child of a function component (collapsible_marks_display). This is so that it can keep its own state and do it's own event-handling. I'm not sure if this is pattern-breaking. A reference to the actual parent live_component that calls collapsible_marks_display will always be there in case there's a need for the parent to handle any particular events. So comms b/w live_components is still going to be via phx-target values. * Change <input/> -> <textarea/> fr quick_draft_form * Add tailwind config for custom svg icons not sure how the scaling for this works, seems like i can't just put in the class="h-5 w-5" to do the scaling * Let custom svg be scalable * Subtly shift the ping indicator to control panel * Marks ordering in Sheaf and L-Trees (#114) * do sheafs grow on trees * sangh session dealing with lineage * Solve initial order problem * fix: ensure non-null id used @ EditableMarkDisplay --------- Co-authored-by: ks0m1c_dharma <[email protected]> * Trigger Diff * TOMBSTONING * Fix bugs and revert ui for read_mode:delete marks 1. JIT generate id for marks yet to be inserted to the db: instead of using a temp id, I'm actually assigning a JIT-generated id for a mark even if that isn't inserted into the db yet. this has two benefits: div ids have meaningful static ids (e.g. mark-container-\<\> mark.id) regardless of whether that mark has been inserted into the db or not. While doing this, the changeset for marks has been udpated to add id as well. This fixes a bunch of id-based errors as well. 2. while doing 1, it came to light that the bindHoverune handlers were not handling the draft mark update properly (i.e. not using the already existing update function in mark) . it's changed now, example of the diff: ``` diff @impl true def handle_event( "bindHoveRune", %{"binding" => bind = %{"verse_id" => verse_id}}, %{ assigns: %{ kv_verses: verses, marks: [%Mark{state: :draft, verse_id: curr_verse_id} = d_mark | marks] } } = socket ) when is_binary(curr_verse_id) and verse_id != curr_verse_id do # binding here blocks the stream from appending to quote bind = Draft.bind_node(bind) bound_verses = verses |> then(&put_in(&1[verse_id].binding, bind)) |> then(&put_in(&1[curr_verse_id].binding, nil)) + updated_draft_mark = d_mark |> Mark.update_mark(%{binding: bind, verse_id: verse_id}) + {:noreply, socket |> mutate_verses(curr_verse_id, bound_verses) |> mutate_verses(verse_id, bound_verses) - |> assign(:marks, [%{d_mark | binding: bind, verse_id: verse_id} | marks])} + |> assign(:marks, [updated_draft_mark | marks])} end ``` 3. add ui state structs: all of the relevant ui states have structs that are intended to be static interfaces. this felt better than directly keeping state within various sockets and is done with a view to remove live components and change them to function components wherever possible. 4. bugfix for `order()`: - it had an off-by-one-error - shifted it to Vyasa.Sangh.Mark - also note that the order shall be 1-indexed instead of 0-indexed for human-friendliness 5. minor fixes: 1. fix update<sub>mark</sub> default argument ``` diff -def update_mark(%Mark{} = draft_mark, opts \\ []) do +def update_mark(%Mark{} = draft_mark, opts \\ %{}) do ``` 1. In this commit, the marks<sub>ui</sub> is NOT kept by the read context module, that's why when I update things by create mark or delete mark, the ui state is not preserved and initial, default state is seen. This was intentionally done in this commit because I'm having problems with duplicate ids for verses for some reason, I'll show it in the next commit, so that the problem can be clearly seen. * [BUGGY] keep marks_ui within ReadContext This is buggy, not sure why there's a duplicate yet. will come back to it after lunch Replication Steps: 1. delete all marks and see there's no error 2. create first mark ==> no error 3. create second mark ==> crashes due to duplicate verse id Crash dump: [debug] Replied in 13ms [error] GenServer #PID<0.8416.0> terminating ** (RuntimeError) found duplicate ID "verse-7d9d588a-34fc-4f19-b974-fc32b49b6a61" for component VyasaWeb.Context.Read.VerseMatrix when rendering template (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:634: anonymous fn/5 in Phoenix.LiveView.Diff.render_pending_components/6 (elixir 1.17.2) lib/enum.ex:2531: Enum."-reduce/3-lists^foldl/2-0-"/3 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:631: anonymous fn/4 in Phoenix.LiveView.Diff.render_pending_components/6 (stdlib 5.2.3) maps.erl:416: :maps.fold_1/4 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:625: Phoenix.LiveView.Diff.render_pending_components/6 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:217: Phoenix.LiveView.Diff.write_component/4 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/channel.ex:662: Phoenix.LiveView.Channel.component_handle/4 (stdlib 5.2.3) gen_server.erl:1095: :gen_server.try_handle_info/3 (stdlib 5.2.3) gen_server.erl:1183: :gen_server.handle_msg/6 (stdlib 5.2.3) proc_lib.erl:251: :proc_lib.wake_up/3 Last message: %Phoenix.Socket.Message{topic: "lv:phx-F_1MH_6F0ciqVqwi", event: "event", payload: %{"cid" => 3, "event" => "createMark", "type" => "form", "value" => "body=how+about+now%2C+any+duplicate%3F"}, ref: "23", join_ref: "4"} State: %{socket: #Phoenix.LiveView.Socket<id: "phx-F_1MH_6F0ciqVqwi", endpoint: VyasaWeb.Endpoint, view: VyasaWeb.ModeLive.Mediator, parent_pid: nil, root_pid: #PID<0.8416.0>, router: VyasaWeb.Router, assigns: %{mode: %VyasaWeb.ModeLive.UserMode{mode: "read", default_ui_state: %VyasaWeb.ModeLive.UiState{show_media_bridge?: true, show_action_bar?: true}, mode_icon_name: "hero-book-open", quick_actions: [:mark_quote, :bookmark], control_panel_modes: ["discuss"], mode_actions: [:mark_quote, :bookmark], action_bar_actions: [:nav_back, :nav_fwd], action_bar_info_types: nil, action_bar_component: VyasaWeb.MediaLive.MediaBridge, action_bar_component_selector: "media-bridge", control_panel_component: VyasaWeb.ControlPanel, control_panel_component_selector: "control-panel", mode_context_component: VyasaWeb.Context.Read, mode_context_component_selector: "read"}, session: %VyasaWeb.Session{name: "ritesh kumar", id: "IhrQV0ypqg8bHakbvb2bymNF", active: true, sangh: %Vyasa.Sangh.Session{__meta__: #Ecto.Schema.Metadata<:loaded, "sessions">, id: "164eb05d-221a-4939-b180-8394e1a5515f", sheafs: #Ecto.Association.NotLoaded<association :sheafs is not loaded>, inserted_at: ~U[2024-09-27 00:51:48Z], updated_at: ~U[2024-09-27 00:51:48Z]}, last_opened: "2024-09-23T11:03:32.022987Z"}, __changed__: %{}, flash: %{}, locale: "en-GB", url_params: %{"chap_no" => "1", "source_title" => "hanuman_chalisa"}, live_action: :show_verses, ui_state: %VyasaWeb.ModeLive.UiState{show_media_bridge?: true, show_action_bar?: true}, device_type: :desktop, tz: %{timezone: "Asia/Singapore", timezone_offset: 480}}, transport_pid: #PID<0.8403.0>, ...>, components: {%{15 => {VyasaWeb.Context.Read.VerseMatrix, "verse-aa3ad88b-0de1-443e-b471-c08a44e67c61", %{id: "verse-aa3ad88b-0de1-443e-b471-c08a44e67c61", edge: [%{title: "1.10", field: [:body], verseup: {:big, "dn"}}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body_translit], verseup: :mid}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body_translit_meant], verseup: :mid}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body], verseup: :mid}], __changed__: %{}, flash: %{}, marks: [%Vyasa.Sangh.Mark{__meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "5dfdb167-6c57-46dd-a0c4-10b52cb03a85", body: "wonderful", order: 2, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "001da594-3808-46cf-9b9c-5dfb3559780e", binding: %Vyasa.Adapters.Binding{__meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "001da594-3808-46cf-9b9c-5dfb3559780e", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil}, inserted_at: ~U[2024-10-11 04:31:50Z], updated_at: ~U[2024-10-11 04:31:50Z]}, %Vyasa.Sangh.Mark{__meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "273a093d-4f90-40a4-b19a-2f8f7825d201", body: "truncated utc datetime", order: 1, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "ef39315b-530c-4841-ba32-86773f451727", binding: %Vyasa.Adapt (truncated) [debug] MOUNT VyasaWeb.ModeLive.Mediator Parameters: %{"chap_no" => "1", "source_title" => "hanuman_chalisa"} Session: %{"_csrf_token" => "DJ-RIoXwEzHW82rbb21le_8k"} [debug] QUERY OK source="sessions" db=3.5ms idle=1690.4ms SELECT s0."id", s0."inserted_at", s0."updated_at" FROM "sessions" AS s0 WHERE (s0."id" = $1) ["164eb05d-221a-4939-b180-8394e1a5515f"] ↳ * Fix duplicate id issue on verse matrix * Standardise use of @event_target, cleanups When using @event_target, the intent is that phx-target values will be passed around. This must be agnostic to the 2 main ways of supplying that argument, as a HTML selector, or as a module name (or @Myself). Therefore, we should discourage ourselves from doing format-strings at the point of the @event_target being supplied as an argument, meaning: good, because agnostic: phx-target={@event_target} bad, because hardcoded: phx-target={"#" <> @event_target} * in this case, the event trigger will throw a dom error. * [Attempt]: Sanitise, defrag orders in marks-list If this is an anti-pattern, then this commit should be reverted. * UI fixes: hide buttons on marks when !is_editable? * Add in stub event handlers to prevent crashes Temporary stuff, will be addressed in immediate-next PR * Minor changes * trigger_dom_refresh()->cascade_stream_change() --------- Co-authored-by: ks0m1c_dharma <[email protected]>
rtshkmr
commented
Oct 17, 2024
|
||
socket | ||
|> apply_action(:show_verses, params |> Map.put("chap_no", chapter.no)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would encourage the use of commit message to signpost the bugfix
e.g. in the message body:
"this fixes the issue on navigation that existed in the previous use of helm, when we are short-circuiting the nav for sources with a single chapter."
This fixes the error where our previous way of doing a re-direct wasn't working. The requirement is that for sources without multiple chapters, the sole chapter should be loaded directly. There are 2 ways to go about doing this: A) do a redirect (push-patch) on this scenario B) since it's all handled by the apply_actions within the read context, pipe the execution into the apply action of :show_verses. This commit favours B over A. It's unclear why A doesn't work.
* Add generic debug dump component This makes life easy when wiring things up * Rename namespace for Context.Read.* * Groundwork: add discuss component w sheafs * Init Context.Components mod for common components * Add skeletons for Sheaf Container Container managers sheaf state within itself. Should actually make the verse-matrix use this container, sometime. * Minor changes, add some TODOs to share explicit todos Minor change * Add live component EditableMarkDisplay * Add UI improvements to EditableMarkDisplay The edit button on quick draft should only be seen when the dropdown is expanded and all the marks can be seen. The general pattern I'm trying to follow is that buttons should only be shown when an action makes sense. So here, if the user can't even see the marks currently accumulating, then the user shouldn't have the chance to edit any marks. Notice that the EditableMarkDisplay is a live_component that is a child of a function component (collapsible_marks_display). This is so that it can keep its own state and do it's own event-handling. I'm not sure if this is pattern-breaking. A reference to the actual parent live_component that calls collapsible_marks_display will always be there in case there's a need for the parent to handle any particular events. So comms b/w live_components is still going to be via phx-target values. * Change <input/> -> <textarea/> fr quick_draft_form * Add tailwind config for custom svg icons not sure how the scaling for this works, seems like i can't just put in the class="h-5 w-5" to do the scaling * Let custom svg be scalable * Subtly shift the ping indicator to control panel * Marks ordering in Sheaf and L-Trees (#114) * do sheafs grow on trees * sangh session dealing with lineage * Solve initial order problem * fix: ensure non-null id used @ EditableMarkDisplay --------- Co-authored-by: ks0m1c_dharma <[email protected]> * Trigger Diff * TOMBSTONING * Fix bugs and revert ui for read_mode:delete marks 1. JIT generate id for marks yet to be inserted to the db: instead of using a temp id, I'm actually assigning a JIT-generated id for a mark even if that isn't inserted into the db yet. this has two benefits: div ids have meaningful static ids (e.g. mark-container-\<\> mark.id) regardless of whether that mark has been inserted into the db or not. While doing this, the changeset for marks has been udpated to add id as well. This fixes a bunch of id-based errors as well. 2. while doing 1, it came to light that the bindHoverune handlers were not handling the draft mark update properly (i.e. not using the already existing update function in mark) . it's changed now, example of the diff: ``` diff @impl true def handle_event( "bindHoveRune", %{"binding" => bind = %{"verse_id" => verse_id}}, %{ assigns: %{ kv_verses: verses, marks: [%Mark{state: :draft, verse_id: curr_verse_id} = d_mark | marks] } } = socket ) when is_binary(curr_verse_id) and verse_id != curr_verse_id do # binding here blocks the stream from appending to quote bind = Draft.bind_node(bind) bound_verses = verses |> then(&put_in(&1[verse_id].binding, bind)) |> then(&put_in(&1[curr_verse_id].binding, nil)) + updated_draft_mark = d_mark |> Mark.update_mark(%{binding: bind, verse_id: verse_id}) + {:noreply, socket |> mutate_verses(curr_verse_id, bound_verses) |> mutate_verses(verse_id, bound_verses) - |> assign(:marks, [%{d_mark | binding: bind, verse_id: verse_id} | marks])} + |> assign(:marks, [updated_draft_mark | marks])} end ``` 3. add ui state structs: all of the relevant ui states have structs that are intended to be static interfaces. this felt better than directly keeping state within various sockets and is done with a view to remove live components and change them to function components wherever possible. 4. bugfix for `order()`: - it had an off-by-one-error - shifted it to Vyasa.Sangh.Mark - also note that the order shall be 1-indexed instead of 0-indexed for human-friendliness 5. minor fixes: 1. fix update<sub>mark</sub> default argument ``` diff -def update_mark(%Mark{} = draft_mark, opts \\ []) do +def update_mark(%Mark{} = draft_mark, opts \\ %{}) do ``` 1. In this commit, the marks<sub>ui</sub> is NOT kept by the read context module, that's why when I update things by create mark or delete mark, the ui state is not preserved and initial, default state is seen. This was intentionally done in this commit because I'm having problems with duplicate ids for verses for some reason, I'll show it in the next commit, so that the problem can be clearly seen. * [BUGGY] keep marks_ui within ReadContext This is buggy, not sure why there's a duplicate yet. will come back to it after lunch Replication Steps: 1. delete all marks and see there's no error 2. create first mark ==> no error 3. create second mark ==> crashes due to duplicate verse id Crash dump: [debug] Replied in 13ms [error] GenServer #PID<0.8416.0> terminating ** (RuntimeError) found duplicate ID "verse-7d9d588a-34fc-4f19-b974-fc32b49b6a61" for component VyasaWeb.Context.Read.VerseMatrix when rendering template (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:634: anonymous fn/5 in Phoenix.LiveView.Diff.render_pending_components/6 (elixir 1.17.2) lib/enum.ex:2531: Enum."-reduce/3-lists^foldl/2-0-"/3 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:631: anonymous fn/4 in Phoenix.LiveView.Diff.render_pending_components/6 (stdlib 5.2.3) maps.erl:416: :maps.fold_1/4 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:625: Phoenix.LiveView.Diff.render_pending_components/6 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:217: Phoenix.LiveView.Diff.write_component/4 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/channel.ex:662: Phoenix.LiveView.Channel.component_handle/4 (stdlib 5.2.3) gen_server.erl:1095: :gen_server.try_handle_info/3 (stdlib 5.2.3) gen_server.erl:1183: :gen_server.handle_msg/6 (stdlib 5.2.3) proc_lib.erl:251: :proc_lib.wake_up/3 Last message: %Phoenix.Socket.Message{topic: "lv:phx-F_1MH_6F0ciqVqwi", event: "event", payload: %{"cid" => 3, "event" => "createMark", "type" => "form", "value" => "body=how+about+now%2C+any+duplicate%3F"}, ref: "23", join_ref: "4"} State: %{socket: #Phoenix.LiveView.Socket<id: "phx-F_1MH_6F0ciqVqwi", endpoint: VyasaWeb.Endpoint, view: VyasaWeb.ModeLive.Mediator, parent_pid: nil, root_pid: #PID<0.8416.0>, router: VyasaWeb.Router, assigns: %{mode: %VyasaWeb.ModeLive.UserMode{mode: "read", default_ui_state: %VyasaWeb.ModeLive.UiState{show_media_bridge?: true, show_action_bar?: true}, mode_icon_name: "hero-book-open", quick_actions: [:mark_quote, :bookmark], control_panel_modes: ["discuss"], mode_actions: [:mark_quote, :bookmark], action_bar_actions: [:nav_back, :nav_fwd], action_bar_info_types: nil, action_bar_component: VyasaWeb.MediaLive.MediaBridge, action_bar_component_selector: "media-bridge", control_panel_component: VyasaWeb.ControlPanel, control_panel_component_selector: "control-panel", mode_context_component: VyasaWeb.Context.Read, mode_context_component_selector: "read"}, session: %VyasaWeb.Session{name: "ritesh kumar", id: "IhrQV0ypqg8bHakbvb2bymNF", active: true, sangh: %Vyasa.Sangh.Session{__meta__: #Ecto.Schema.Metadata<:loaded, "sessions">, id: "164eb05d-221a-4939-b180-8394e1a5515f", sheafs: #Ecto.Association.NotLoaded<association :sheafs is not loaded>, inserted_at: ~U[2024-09-27 00:51:48Z], updated_at: ~U[2024-09-27 00:51:48Z]}, last_opened: "2024-09-23T11:03:32.022987Z"}, __changed__: %{}, flash: %{}, locale: "en-GB", url_params: %{"chap_no" => "1", "source_title" => "hanuman_chalisa"}, live_action: :show_verses, ui_state: %VyasaWeb.ModeLive.UiState{show_media_bridge?: true, show_action_bar?: true}, device_type: :desktop, tz: %{timezone: "Asia/Singapore", timezone_offset: 480}}, transport_pid: #PID<0.8403.0>, ...>, components: {%{15 => {VyasaWeb.Context.Read.VerseMatrix, "verse-aa3ad88b-0de1-443e-b471-c08a44e67c61", %{id: "verse-aa3ad88b-0de1-443e-b471-c08a44e67c61", edge: [%{title: "1.10", field: [:body], verseup: {:big, "dn"}}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body_translit], verseup: :mid}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body_translit_meant], verseup: :mid}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body], verseup: :mid}], __changed__: %{}, flash: %{}, marks: [%Vyasa.Sangh.Mark{__meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "5dfdb167-6c57-46dd-a0c4-10b52cb03a85", body: "wonderful", order: 2, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "001da594-3808-46cf-9b9c-5dfb3559780e", binding: %Vyasa.Adapters.Binding{__meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "001da594-3808-46cf-9b9c-5dfb3559780e", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil}, inserted_at: ~U[2024-10-11 04:31:50Z], updated_at: ~U[2024-10-11 04:31:50Z]}, %Vyasa.Sangh.Mark{__meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "273a093d-4f90-40a4-b19a-2f8f7825d201", body: "truncated utc datetime", order: 1, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "ef39315b-530c-4841-ba32-86773f451727", binding: %Vyasa.Adapt (truncated) [debug] MOUNT VyasaWeb.ModeLive.Mediator Parameters: %{"chap_no" => "1", "source_title" => "hanuman_chalisa"} Session: %{"_csrf_token" => "DJ-RIoXwEzHW82rbb21le_8k"} [debug] QUERY OK source="sessions" db=3.5ms idle=1690.4ms SELECT s0."id", s0."inserted_at", s0."updated_at" FROM "sessions" AS s0 WHERE (s0."id" = $1) ["164eb05d-221a-4939-b180-8394e1a5515f"] ↳ * Fix duplicate id issue on verse matrix * Standardise use of @event_target, cleanups When using @event_target, the intent is that phx-target values will be passed around. This must be agnostic to the 2 main ways of supplying that argument, as a HTML selector, or as a module name (or @Myself). Therefore, we should discourage ourselves from doing format-strings at the point of the @event_target being supplied as an argument, meaning: good, because agnostic: phx-target={@event_target} bad, because hardcoded: phx-target={"#" <> @event_target} * in this case, the event trigger will throw a dom error. * [Attempt]: Sanitise, defrag orders in marks-list If this is an anti-pattern, then this commit should be reverted. * UI fixes: hide buttons on marks when !is_editable? * Add in stub event handlers to prevent crashes Temporary stuff, will be addressed in immediate-next PR * Minor changes * Toggle edit state for marks content * Partial implementation of edit marks the form stuff doesn't exist so it's not wired up yet. To be frank, im' not sure how to set up a form without it needing to hold state. * [BUGGY] Wire up form update for edit this does the following: 1. wires up the form like how we usedd it in createMark 2. actually captures the event properly within the event handler, everything looks good at that point, even the edit_mark_in_marks function on inspection looks good 3. the marks is getting assigned to properly because the newly edited mark content is seen after doing a dom refresh 4. HOWEVER, the print statement at the sheaf_update function DOES NOT show the correct, updated marks in the sheaf here's a dump for it for reference [debug] HANDLE EVENT "editMarkContent" in VyasaWeb.ModeLive.Mediator Component: VyasaWeb.Context.Read Parameters: %{"mark_id" => "02218551-591f-4450-abbd-a7b7d76fd48e"} [debug] Replied in 2ms [debug] HANDLE EVENT "editMarkContent" in VyasaWeb.ModeLive.Mediator Component: VyasaWeb.Context.Read Parameters: %{"mark_body" => " testing\n\n\nwhat hte heck", "mark_id" => "02218551-591f-4450-abbd-a7b7d76fd48e"} >>> UPDATE SHEAF -- SHOULD BE WRITING TO DB NOW: %Vyasa.Sangh.Sheaf{ __meta__: #Ecto.Schema.Metadata<:loaded, "sheafs">, id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", body: nil, active: true, path: %EctoLtree.LabelTree{labels: ["7f4ab16b"]}, signature: nil, traits: ["draft"], child_count: 0, session_id: "164eb05d-221a-4939-b180-8394e1a5515f", session: #Ecto.Association.NotLoaded<association :session is not loaded>, parent_id: nil, parent: #Ecto.Association.NotLoaded<association :parent is not loaded>, marks: [ %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "555eb625-e392-496e-9831-4f4c130be6fd", body: "wonderful stuff", order: 5, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "072124d0-5e27-4601-832f-35eaa6426879", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "072124d0-5e27-4601-832f-35eaa6426879", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 08:46:54Z], updated_at: ~U[2024-10-12 08:46:54Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "b22a5661-8268-4875-be26-a12256414136", body: nil, order: 5, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "90e18044-73b2-4ede-a149-a381de893b9f", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "90e18044-73b2-4ede-a149-a381de893b9f", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "fc80709a-39dc-4b9c-95c3-1d64ce818302", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:52:40Z], updated_at: ~U[2024-10-12 09:52:40Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "8af43833-575c-4eb8-83b1-eb4e58509e4c", body: nil, order: 4, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "23b70937-ed81-47fe-a560-ee14287bff7d", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "23b70937-ed81-47fe-a560-ee14287bff7d", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:46:13Z], updated_at: ~U[2024-10-12 09:46:13Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "c7ad47e6-629d-4382-936d-64d757772c4e", body: nil, order: 3, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "d5758230-7966-4f9b-8c16-ae13998cd71b", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "d5758230-7966-4f9b-8c16-ae13998cd71b", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "fc80709a-39dc-4b9c-95c3-1d64ce818302", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:44:09Z], updated_at: ~U[2024-10-12 09:44:09Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "02218551-591f-4450-abbd-a7b7d76fd48e", body: "testing", order: 2, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "19ffdc82-a5d8-49c3-8b01-1559736dad80", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "19ffdc82-a5d8-49c3-8b01-1559736dad80", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "fc80709a-39dc-4b9c-95c3-1d64ce818302", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:43:19Z], updated_at: ~U[2024-10-12 09:43:19Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "90c6036a-9bd1-4b65-82d5-f121ec4d7867", body: nil, order: 2, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "b92f990d-99a2-4f04-a2d4-d1135021ee8c", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "b92f990d-99a2-4f04-a2d4-d1135021ee8c", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-11 09:03:00Z], updated_at: ~U[2024-10-11 09:03:00Z] } ], inserted_at: ~N[2024-09-27 00:51:48], updated_at: ~N[2024-09-27 00:51:48] } [debug] Replied in 81ms [debug] HANDLE EVENT "verses::focus_toggle_on_quick_mark_drafting" in VyasaWeb.ModeLive.Mediator Component: VyasaWeb.Context.Read Parameters: %{"is_focusing?" => false, "value" => ""} [debug] Replied in 129µs iex([email protected])17> * marks order force * old man mark is not feeling so good * ReWrite how marks get initialised @ :show_verse (#119) * Minor change in fn signature * Add init_draft_reflector() --------- Co-authored-by: ks0m1c_dharma <[email protected]>
* Add generic debug dump component This makes life easy when wiring things up * Rename namespace for Context.Read.* * Groundwork: add discuss component w sheafs * Init Context.Components mod for common components * Add skeletons for Sheaf Container Container managers sheaf state within itself. Should actually make the verse-matrix use this container, sometime. * Minor changes, add some TODOs to share explicit todos Minor change * Add live component EditableMarkDisplay * Add UI improvements to EditableMarkDisplay The edit button on quick draft should only be seen when the dropdown is expanded and all the marks can be seen. The general pattern I'm trying to follow is that buttons should only be shown when an action makes sense. So here, if the user can't even see the marks currently accumulating, then the user shouldn't have the chance to edit any marks. Notice that the EditableMarkDisplay is a live_component that is a child of a function component (collapsible_marks_display). This is so that it can keep its own state and do it's own event-handling. I'm not sure if this is pattern-breaking. A reference to the actual parent live_component that calls collapsible_marks_display will always be there in case there's a need for the parent to handle any particular events. So comms b/w live_components is still going to be via phx-target values. * Change <input/> -> <textarea/> fr quick_draft_form * Add tailwind config for custom svg icons not sure how the scaling for this works, seems like i can't just put in the class="h-5 w-5" to do the scaling * Let custom svg be scalable * Subtly shift the ping indicator to control panel * Marks ordering in Sheaf and L-Trees (#114) * do sheafs grow on trees * sangh session dealing with lineage * Solve initial order problem * fix: ensure non-null id used @ EditableMarkDisplay --------- Co-authored-by: ks0m1c_dharma <[email protected]> * Trigger Diff * TOMBSTONING * Fix bugs and revert ui for read_mode:delete marks 1. JIT generate id for marks yet to be inserted to the db: instead of using a temp id, I'm actually assigning a JIT-generated id for a mark even if that isn't inserted into the db yet. this has two benefits: div ids have meaningful static ids (e.g. mark-container-\<\> mark.id) regardless of whether that mark has been inserted into the db or not. While doing this, the changeset for marks has been udpated to add id as well. This fixes a bunch of id-based errors as well. 2. while doing 1, it came to light that the bindHoverune handlers were not handling the draft mark update properly (i.e. not using the already existing update function in mark) . it's changed now, example of the diff: ``` diff @impl true def handle_event( "bindHoveRune", %{"binding" => bind = %{"verse_id" => verse_id}}, %{ assigns: %{ kv_verses: verses, marks: [%Mark{state: :draft, verse_id: curr_verse_id} = d_mark | marks] } } = socket ) when is_binary(curr_verse_id) and verse_id != curr_verse_id do # binding here blocks the stream from appending to quote bind = Draft.bind_node(bind) bound_verses = verses |> then(&put_in(&1[verse_id].binding, bind)) |> then(&put_in(&1[curr_verse_id].binding, nil)) + updated_draft_mark = d_mark |> Mark.update_mark(%{binding: bind, verse_id: verse_id}) + {:noreply, socket |> mutate_verses(curr_verse_id, bound_verses) |> mutate_verses(verse_id, bound_verses) - |> assign(:marks, [%{d_mark | binding: bind, verse_id: verse_id} | marks])} + |> assign(:marks, [updated_draft_mark | marks])} end ``` 3. add ui state structs: all of the relevant ui states have structs that are intended to be static interfaces. this felt better than directly keeping state within various sockets and is done with a view to remove live components and change them to function components wherever possible. 4. bugfix for `order()`: - it had an off-by-one-error - shifted it to Vyasa.Sangh.Mark - also note that the order shall be 1-indexed instead of 0-indexed for human-friendliness 5. minor fixes: 1. fix update<sub>mark</sub> default argument ``` diff -def update_mark(%Mark{} = draft_mark, opts \\ []) do +def update_mark(%Mark{} = draft_mark, opts \\ %{}) do ``` 1. In this commit, the marks<sub>ui</sub> is NOT kept by the read context module, that's why when I update things by create mark or delete mark, the ui state is not preserved and initial, default state is seen. This was intentionally done in this commit because I'm having problems with duplicate ids for verses for some reason, I'll show it in the next commit, so that the problem can be clearly seen. * [BUGGY] keep marks_ui within ReadContext This is buggy, not sure why there's a duplicate yet. will come back to it after lunch Replication Steps: 1. delete all marks and see there's no error 2. create first mark ==> no error 3. create second mark ==> crashes due to duplicate verse id Crash dump: [debug] Replied in 13ms [error] GenServer #PID<0.8416.0> terminating ** (RuntimeError) found duplicate ID "verse-7d9d588a-34fc-4f19-b974-fc32b49b6a61" for component VyasaWeb.Context.Read.VerseMatrix when rendering template (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:634: anonymous fn/5 in Phoenix.LiveView.Diff.render_pending_components/6 (elixir 1.17.2) lib/enum.ex:2531: Enum."-reduce/3-lists^foldl/2-0-"/3 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:631: anonymous fn/4 in Phoenix.LiveView.Diff.render_pending_components/6 (stdlib 5.2.3) maps.erl:416: :maps.fold_1/4 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:625: Phoenix.LiveView.Diff.render_pending_components/6 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:217: Phoenix.LiveView.Diff.write_component/4 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/channel.ex:662: Phoenix.LiveView.Channel.component_handle/4 (stdlib 5.2.3) gen_server.erl:1095: :gen_server.try_handle_info/3 (stdlib 5.2.3) gen_server.erl:1183: :gen_server.handle_msg/6 (stdlib 5.2.3) proc_lib.erl:251: :proc_lib.wake_up/3 Last message: %Phoenix.Socket.Message{topic: "lv:phx-F_1MH_6F0ciqVqwi", event: "event", payload: %{"cid" => 3, "event" => "createMark", "type" => "form", "value" => "body=how+about+now%2C+any+duplicate%3F"}, ref: "23", join_ref: "4"} State: %{socket: #Phoenix.LiveView.Socket<id: "phx-F_1MH_6F0ciqVqwi", endpoint: VyasaWeb.Endpoint, view: VyasaWeb.ModeLive.Mediator, parent_pid: nil, root_pid: #PID<0.8416.0>, router: VyasaWeb.Router, assigns: %{mode: %VyasaWeb.ModeLive.UserMode{mode: "read", default_ui_state: %VyasaWeb.ModeLive.UiState{show_media_bridge?: true, show_action_bar?: true}, mode_icon_name: "hero-book-open", quick_actions: [:mark_quote, :bookmark], control_panel_modes: ["discuss"], mode_actions: [:mark_quote, :bookmark], action_bar_actions: [:nav_back, :nav_fwd], action_bar_info_types: nil, action_bar_component: VyasaWeb.MediaLive.MediaBridge, action_bar_component_selector: "media-bridge", control_panel_component: VyasaWeb.ControlPanel, control_panel_component_selector: "control-panel", mode_context_component: VyasaWeb.Context.Read, mode_context_component_selector: "read"}, session: %VyasaWeb.Session{name: "ritesh kumar", id: "IhrQV0ypqg8bHakbvb2bymNF", active: true, sangh: %Vyasa.Sangh.Session{__meta__: #Ecto.Schema.Metadata<:loaded, "sessions">, id: "164eb05d-221a-4939-b180-8394e1a5515f", sheafs: #Ecto.Association.NotLoaded<association :sheafs is not loaded>, inserted_at: ~U[2024-09-27 00:51:48Z], updated_at: ~U[2024-09-27 00:51:48Z]}, last_opened: "2024-09-23T11:03:32.022987Z"}, __changed__: %{}, flash: %{}, locale: "en-GB", url_params: %{"chap_no" => "1", "source_title" => "hanuman_chalisa"}, live_action: :show_verses, ui_state: %VyasaWeb.ModeLive.UiState{show_media_bridge?: true, show_action_bar?: true}, device_type: :desktop, tz: %{timezone: "Asia/Singapore", timezone_offset: 480}}, transport_pid: #PID<0.8403.0>, ...>, components: {%{15 => {VyasaWeb.Context.Read.VerseMatrix, "verse-aa3ad88b-0de1-443e-b471-c08a44e67c61", %{id: "verse-aa3ad88b-0de1-443e-b471-c08a44e67c61", edge: [%{title: "1.10", field: [:body], verseup: {:big, "dn"}}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body_translit], verseup: :mid}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body_translit_meant], verseup: :mid}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body], verseup: :mid}], __changed__: %{}, flash: %{}, marks: [%Vyasa.Sangh.Mark{__meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "5dfdb167-6c57-46dd-a0c4-10b52cb03a85", body: "wonderful", order: 2, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "001da594-3808-46cf-9b9c-5dfb3559780e", binding: %Vyasa.Adapters.Binding{__meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "001da594-3808-46cf-9b9c-5dfb3559780e", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil}, inserted_at: ~U[2024-10-11 04:31:50Z], updated_at: ~U[2024-10-11 04:31:50Z]}, %Vyasa.Sangh.Mark{__meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "273a093d-4f90-40a4-b19a-2f8f7825d201", body: "truncated utc datetime", order: 1, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "ef39315b-530c-4841-ba32-86773f451727", binding: %Vyasa.Adapt (truncated) [debug] MOUNT VyasaWeb.ModeLive.Mediator Parameters: %{"chap_no" => "1", "source_title" => "hanuman_chalisa"} Session: %{"_csrf_token" => "DJ-RIoXwEzHW82rbb21le_8k"} [debug] QUERY OK source="sessions" db=3.5ms idle=1690.4ms SELECT s0."id", s0."inserted_at", s0."updated_at" FROM "sessions" AS s0 WHERE (s0."id" = $1) ["164eb05d-221a-4939-b180-8394e1a5515f"] ↳ * Fix duplicate id issue on verse matrix * Standardise use of @event_target, cleanups When using @event_target, the intent is that phx-target values will be passed around. This must be agnostic to the 2 main ways of supplying that argument, as a HTML selector, or as a module name (or @Myself). Therefore, we should discourage ourselves from doing format-strings at the point of the @event_target being supplied as an argument, meaning: good, because agnostic: phx-target={@event_target} bad, because hardcoded: phx-target={"#" <> @event_target} * in this case, the event trigger will throw a dom error. * [Attempt]: Sanitise, defrag orders in marks-list If this is an anti-pattern, then this commit should be reverted. * UI fixes: hide buttons on marks when !is_editable? * Add in stub event handlers to prevent crashes Temporary stuff, will be addressed in immediate-next PR * Minor changes * Toggle edit state for marks content * Partial implementation of edit marks the form stuff doesn't exist so it's not wired up yet. To be frank, im' not sure how to set up a form without it needing to hold state. * [BUGGY] Wire up form update for edit this does the following: 1. wires up the form like how we usedd it in createMark 2. actually captures the event properly within the event handler, everything looks good at that point, even the edit_mark_in_marks function on inspection looks good 3. the marks is getting assigned to properly because the newly edited mark content is seen after doing a dom refresh 4. HOWEVER, the print statement at the sheaf_update function DOES NOT show the correct, updated marks in the sheaf here's a dump for it for reference [debug] HANDLE EVENT "editMarkContent" in VyasaWeb.ModeLive.Mediator Component: VyasaWeb.Context.Read Parameters: %{"mark_id" => "02218551-591f-4450-abbd-a7b7d76fd48e"} [debug] Replied in 2ms [debug] HANDLE EVENT "editMarkContent" in VyasaWeb.ModeLive.Mediator Component: VyasaWeb.Context.Read Parameters: %{"mark_body" => " testing\n\n\nwhat hte heck", "mark_id" => "02218551-591f-4450-abbd-a7b7d76fd48e"} >>> UPDATE SHEAF -- SHOULD BE WRITING TO DB NOW: %Vyasa.Sangh.Sheaf{ __meta__: #Ecto.Schema.Metadata<:loaded, "sheafs">, id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", body: nil, active: true, path: %EctoLtree.LabelTree{labels: ["7f4ab16b"]}, signature: nil, traits: ["draft"], child_count: 0, session_id: "164eb05d-221a-4939-b180-8394e1a5515f", session: #Ecto.Association.NotLoaded<association :session is not loaded>, parent_id: nil, parent: #Ecto.Association.NotLoaded<association :parent is not loaded>, marks: [ %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "555eb625-e392-496e-9831-4f4c130be6fd", body: "wonderful stuff", order: 5, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "072124d0-5e27-4601-832f-35eaa6426879", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "072124d0-5e27-4601-832f-35eaa6426879", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 08:46:54Z], updated_at: ~U[2024-10-12 08:46:54Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "b22a5661-8268-4875-be26-a12256414136", body: nil, order: 5, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "90e18044-73b2-4ede-a149-a381de893b9f", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "90e18044-73b2-4ede-a149-a381de893b9f", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "fc80709a-39dc-4b9c-95c3-1d64ce818302", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:52:40Z], updated_at: ~U[2024-10-12 09:52:40Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "8af43833-575c-4eb8-83b1-eb4e58509e4c", body: nil, order: 4, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "23b70937-ed81-47fe-a560-ee14287bff7d", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "23b70937-ed81-47fe-a560-ee14287bff7d", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:46:13Z], updated_at: ~U[2024-10-12 09:46:13Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "c7ad47e6-629d-4382-936d-64d757772c4e", body: nil, order: 3, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "d5758230-7966-4f9b-8c16-ae13998cd71b", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "d5758230-7966-4f9b-8c16-ae13998cd71b", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "fc80709a-39dc-4b9c-95c3-1d64ce818302", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:44:09Z], updated_at: ~U[2024-10-12 09:44:09Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "02218551-591f-4450-abbd-a7b7d76fd48e", body: "testing", order: 2, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "19ffdc82-a5d8-49c3-8b01-1559736dad80", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "19ffdc82-a5d8-49c3-8b01-1559736dad80", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "fc80709a-39dc-4b9c-95c3-1d64ce818302", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:43:19Z], updated_at: ~U[2024-10-12 09:43:19Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "90c6036a-9bd1-4b65-82d5-f121ec4d7867", body: nil, order: 2, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "b92f990d-99a2-4f04-a2d4-d1135021ee8c", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "b92f990d-99a2-4f04-a2d4-d1135021ee8c", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-11 09:03:00Z], updated_at: ~U[2024-10-11 09:03:00Z] } ], inserted_at: ~N[2024-09-27 00:51:48], updated_at: ~N[2024-09-27 00:51:48] } [debug] Replied in 81ms [debug] HANDLE EVENT "verses::focus_toggle_on_quick_mark_drafting" in VyasaWeb.ModeLive.Mediator Component: VyasaWeb.Context.Read Parameters: %{"is_focusing?" => false, "value" => ""} [debug] Replied in 129µs iex([email protected])17> * marks order force * old man mark is not feeling so good * ReWrite how marks get initialised @ :show_verse (#119) * Minor change in fn signature * Add init_draft_reflector() * Use custom generic_modal_wrapper This one has more specific callback attributes and tailwind classes can be injected to it. --------- Co-authored-by: ks0m1c_dharma <[email protected]>
rtshkmr
force-pushed
the
epic/discussions
branch
from
October 18, 2024 01:57
a131bde
to
6b16b92
Compare
* Add generic debug dump component This makes life easy when wiring things up * Rename namespace for Context.Read.* * Groundwork: add discuss component w sheafs * Init Context.Components mod for common components * Add skeletons for Sheaf Container Container managers sheaf state within itself. Should actually make the verse-matrix use this container, sometime. * Minor changes, add some TODOs to share explicit todos Minor change * Add live component EditableMarkDisplay * Add UI improvements to EditableMarkDisplay The edit button on quick draft should only be seen when the dropdown is expanded and all the marks can be seen. The general pattern I'm trying to follow is that buttons should only be shown when an action makes sense. So here, if the user can't even see the marks currently accumulating, then the user shouldn't have the chance to edit any marks. Notice that the EditableMarkDisplay is a live_component that is a child of a function component (collapsible_marks_display). This is so that it can keep its own state and do it's own event-handling. I'm not sure if this is pattern-breaking. A reference to the actual parent live_component that calls collapsible_marks_display will always be there in case there's a need for the parent to handle any particular events. So comms b/w live_components is still going to be via phx-target values. * Change <input/> -> <textarea/> fr quick_draft_form * Add tailwind config for custom svg icons not sure how the scaling for this works, seems like i can't just put in the class="h-5 w-5" to do the scaling * Let custom svg be scalable * Subtly shift the ping indicator to control panel * Marks ordering in Sheaf and L-Trees (#114) * do sheafs grow on trees * sangh session dealing with lineage * Solve initial order problem * fix: ensure non-null id used @ EditableMarkDisplay --------- Co-authored-by: ks0m1c_dharma <[email protected]> * Trigger Diff * TOMBSTONING * Fix bugs and revert ui for read_mode:delete marks 1. JIT generate id for marks yet to be inserted to the db: instead of using a temp id, I'm actually assigning a JIT-generated id for a mark even if that isn't inserted into the db yet. this has two benefits: div ids have meaningful static ids (e.g. mark-container-\<\> mark.id) regardless of whether that mark has been inserted into the db or not. While doing this, the changeset for marks has been udpated to add id as well. This fixes a bunch of id-based errors as well. 2. while doing 1, it came to light that the bindHoverune handlers were not handling the draft mark update properly (i.e. not using the already existing update function in mark) . it's changed now, example of the diff: ``` diff @impl true def handle_event( "bindHoveRune", %{"binding" => bind = %{"verse_id" => verse_id}}, %{ assigns: %{ kv_verses: verses, marks: [%Mark{state: :draft, verse_id: curr_verse_id} = d_mark | marks] } } = socket ) when is_binary(curr_verse_id) and verse_id != curr_verse_id do # binding here blocks the stream from appending to quote bind = Draft.bind_node(bind) bound_verses = verses |> then(&put_in(&1[verse_id].binding, bind)) |> then(&put_in(&1[curr_verse_id].binding, nil)) + updated_draft_mark = d_mark |> Mark.update_mark(%{binding: bind, verse_id: verse_id}) + {:noreply, socket |> mutate_verses(curr_verse_id, bound_verses) |> mutate_verses(verse_id, bound_verses) - |> assign(:marks, [%{d_mark | binding: bind, verse_id: verse_id} | marks])} + |> assign(:marks, [updated_draft_mark | marks])} end ``` 3. add ui state structs: all of the relevant ui states have structs that are intended to be static interfaces. this felt better than directly keeping state within various sockets and is done with a view to remove live components and change them to function components wherever possible. 4. bugfix for `order()`: - it had an off-by-one-error - shifted it to Vyasa.Sangh.Mark - also note that the order shall be 1-indexed instead of 0-indexed for human-friendliness 5. minor fixes: 1. fix update<sub>mark</sub> default argument ``` diff -def update_mark(%Mark{} = draft_mark, opts \\ []) do +def update_mark(%Mark{} = draft_mark, opts \\ %{}) do ``` 1. In this commit, the marks<sub>ui</sub> is NOT kept by the read context module, that's why when I update things by create mark or delete mark, the ui state is not preserved and initial, default state is seen. This was intentionally done in this commit because I'm having problems with duplicate ids for verses for some reason, I'll show it in the next commit, so that the problem can be clearly seen. * [BUGGY] keep marks_ui within ReadContext This is buggy, not sure why there's a duplicate yet. will come back to it after lunch Replication Steps: 1. delete all marks and see there's no error 2. create first mark ==> no error 3. create second mark ==> crashes due to duplicate verse id Crash dump: [debug] Replied in 13ms [error] GenServer #PID<0.8416.0> terminating ** (RuntimeError) found duplicate ID "verse-7d9d588a-34fc-4f19-b974-fc32b49b6a61" for component VyasaWeb.Context.Read.VerseMatrix when rendering template (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:634: anonymous fn/5 in Phoenix.LiveView.Diff.render_pending_components/6 (elixir 1.17.2) lib/enum.ex:2531: Enum."-reduce/3-lists^foldl/2-0-"/3 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:631: anonymous fn/4 in Phoenix.LiveView.Diff.render_pending_components/6 (stdlib 5.2.3) maps.erl:416: :maps.fold_1/4 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:625: Phoenix.LiveView.Diff.render_pending_components/6 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:217: Phoenix.LiveView.Diff.write_component/4 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/channel.ex:662: Phoenix.LiveView.Channel.component_handle/4 (stdlib 5.2.3) gen_server.erl:1095: :gen_server.try_handle_info/3 (stdlib 5.2.3) gen_server.erl:1183: :gen_server.handle_msg/6 (stdlib 5.2.3) proc_lib.erl:251: :proc_lib.wake_up/3 Last message: %Phoenix.Socket.Message{topic: "lv:phx-F_1MH_6F0ciqVqwi", event: "event", payload: %{"cid" => 3, "event" => "createMark", "type" => "form", "value" => "body=how+about+now%2C+any+duplicate%3F"}, ref: "23", join_ref: "4"} State: %{socket: #Phoenix.LiveView.Socket<id: "phx-F_1MH_6F0ciqVqwi", endpoint: VyasaWeb.Endpoint, view: VyasaWeb.ModeLive.Mediator, parent_pid: nil, root_pid: #PID<0.8416.0>, router: VyasaWeb.Router, assigns: %{mode: %VyasaWeb.ModeLive.UserMode{mode: "read", default_ui_state: %VyasaWeb.ModeLive.UiState{show_media_bridge?: true, show_action_bar?: true}, mode_icon_name: "hero-book-open", quick_actions: [:mark_quote, :bookmark], control_panel_modes: ["discuss"], mode_actions: [:mark_quote, :bookmark], action_bar_actions: [:nav_back, :nav_fwd], action_bar_info_types: nil, action_bar_component: VyasaWeb.MediaLive.MediaBridge, action_bar_component_selector: "media-bridge", control_panel_component: VyasaWeb.ControlPanel, control_panel_component_selector: "control-panel", mode_context_component: VyasaWeb.Context.Read, mode_context_component_selector: "read"}, session: %VyasaWeb.Session{name: "ritesh kumar", id: "IhrQV0ypqg8bHakbvb2bymNF", active: true, sangh: %Vyasa.Sangh.Session{__meta__: #Ecto.Schema.Metadata<:loaded, "sessions">, id: "164eb05d-221a-4939-b180-8394e1a5515f", sheafs: #Ecto.Association.NotLoaded<association :sheafs is not loaded>, inserted_at: ~U[2024-09-27 00:51:48Z], updated_at: ~U[2024-09-27 00:51:48Z]}, last_opened: "2024-09-23T11:03:32.022987Z"}, __changed__: %{}, flash: %{}, locale: "en-GB", url_params: %{"chap_no" => "1", "source_title" => "hanuman_chalisa"}, live_action: :show_verses, ui_state: %VyasaWeb.ModeLive.UiState{show_media_bridge?: true, show_action_bar?: true}, device_type: :desktop, tz: %{timezone: "Asia/Singapore", timezone_offset: 480}}, transport_pid: #PID<0.8403.0>, ...>, components: {%{15 => {VyasaWeb.Context.Read.VerseMatrix, "verse-aa3ad88b-0de1-443e-b471-c08a44e67c61", %{id: "verse-aa3ad88b-0de1-443e-b471-c08a44e67c61", edge: [%{title: "1.10", field: [:body], verseup: {:big, "dn"}}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body_translit], verseup: :mid}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body_translit_meant], verseup: :mid}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body], verseup: :mid}], __changed__: %{}, flash: %{}, marks: [%Vyasa.Sangh.Mark{__meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "5dfdb167-6c57-46dd-a0c4-10b52cb03a85", body: "wonderful", order: 2, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "001da594-3808-46cf-9b9c-5dfb3559780e", binding: %Vyasa.Adapters.Binding{__meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "001da594-3808-46cf-9b9c-5dfb3559780e", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil}, inserted_at: ~U[2024-10-11 04:31:50Z], updated_at: ~U[2024-10-11 04:31:50Z]}, %Vyasa.Sangh.Mark{__meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "273a093d-4f90-40a4-b19a-2f8f7825d201", body: "truncated utc datetime", order: 1, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "ef39315b-530c-4841-ba32-86773f451727", binding: %Vyasa.Adapt (truncated) [debug] MOUNT VyasaWeb.ModeLive.Mediator Parameters: %{"chap_no" => "1", "source_title" => "hanuman_chalisa"} Session: %{"_csrf_token" => "DJ-RIoXwEzHW82rbb21le_8k"} [debug] QUERY OK source="sessions" db=3.5ms idle=1690.4ms SELECT s0."id", s0."inserted_at", s0."updated_at" FROM "sessions" AS s0 WHERE (s0."id" = $1) ["164eb05d-221a-4939-b180-8394e1a5515f"] ↳ * Fix duplicate id issue on verse matrix * Standardise use of @event_target, cleanups When using @event_target, the intent is that phx-target values will be passed around. This must be agnostic to the 2 main ways of supplying that argument, as a HTML selector, or as a module name (or @myself). Therefore, we should discourage ourselves from doing format-strings at the point of the @event_target being supplied as an argument, meaning: good, because agnostic: phx-target={@event_target} bad, because hardcoded: phx-target={"#" <> @event_target} * in this case, the event trigger will throw a dom error. * [Attempt]: Sanitise, defrag orders in marks-list If this is an anti-pattern, then this commit should be reverted. * UI fixes: hide buttons on marks when !is_editable? * Add in stub event handlers to prevent crashes Temporary stuff, will be addressed in immediate-next PR * Minor changes * Toggle edit state for marks content * Partial implementation of edit marks the form stuff doesn't exist so it's not wired up yet. To be frank, im' not sure how to set up a form without it needing to hold state. * [BUGGY] Wire up form update for edit this does the following: 1. wires up the form like how we usedd it in createMark 2. actually captures the event properly within the event handler, everything looks good at that point, even the edit_mark_in_marks function on inspection looks good 3. the marks is getting assigned to properly because the newly edited mark content is seen after doing a dom refresh 4. HOWEVER, the print statement at the sheaf_update function DOES NOT show the correct, updated marks in the sheaf here's a dump for it for reference [debug] HANDLE EVENT "editMarkContent" in VyasaWeb.ModeLive.Mediator Component: VyasaWeb.Context.Read Parameters: %{"mark_id" => "02218551-591f-4450-abbd-a7b7d76fd48e"} [debug] Replied in 2ms [debug] HANDLE EVENT "editMarkContent" in VyasaWeb.ModeLive.Mediator Component: VyasaWeb.Context.Read Parameters: %{"mark_body" => " testing\n\n\nwhat hte heck", "mark_id" => "02218551-591f-4450-abbd-a7b7d76fd48e"} >>> UPDATE SHEAF -- SHOULD BE WRITING TO DB NOW: %Vyasa.Sangh.Sheaf{ __meta__: #Ecto.Schema.Metadata<:loaded, "sheafs">, id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", body: nil, active: true, path: %EctoLtree.LabelTree{labels: ["7f4ab16b"]}, signature: nil, traits: ["draft"], child_count: 0, session_id: "164eb05d-221a-4939-b180-8394e1a5515f", session: #Ecto.Association.NotLoaded<association :session is not loaded>, parent_id: nil, parent: #Ecto.Association.NotLoaded<association :parent is not loaded>, marks: [ %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "555eb625-e392-496e-9831-4f4c130be6fd", body: "wonderful stuff", order: 5, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "072124d0-5e27-4601-832f-35eaa6426879", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "072124d0-5e27-4601-832f-35eaa6426879", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 08:46:54Z], updated_at: ~U[2024-10-12 08:46:54Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "b22a5661-8268-4875-be26-a12256414136", body: nil, order: 5, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "90e18044-73b2-4ede-a149-a381de893b9f", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "90e18044-73b2-4ede-a149-a381de893b9f", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "fc80709a-39dc-4b9c-95c3-1d64ce818302", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:52:40Z], updated_at: ~U[2024-10-12 09:52:40Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "8af43833-575c-4eb8-83b1-eb4e58509e4c", body: nil, order: 4, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "23b70937-ed81-47fe-a560-ee14287bff7d", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "23b70937-ed81-47fe-a560-ee14287bff7d", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:46:13Z], updated_at: ~U[2024-10-12 09:46:13Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "c7ad47e6-629d-4382-936d-64d757772c4e", body: nil, order: 3, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "d5758230-7966-4f9b-8c16-ae13998cd71b", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "d5758230-7966-4f9b-8c16-ae13998cd71b", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "fc80709a-39dc-4b9c-95c3-1d64ce818302", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:44:09Z], updated_at: ~U[2024-10-12 09:44:09Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "02218551-591f-4450-abbd-a7b7d76fd48e", body: "testing", order: 2, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "19ffdc82-a5d8-49c3-8b01-1559736dad80", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "19ffdc82-a5d8-49c3-8b01-1559736dad80", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "fc80709a-39dc-4b9c-95c3-1d64ce818302", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:43:19Z], updated_at: ~U[2024-10-12 09:43:19Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "90c6036a-9bd1-4b65-82d5-f121ec4d7867", body: nil, order: 2, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "b92f990d-99a2-4f04-a2d4-d1135021ee8c", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "b92f990d-99a2-4f04-a2d4-d1135021ee8c", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-11 09:03:00Z], updated_at: ~U[2024-10-11 09:03:00Z] } ], inserted_at: ~N[2024-09-27 00:51:48], updated_at: ~N[2024-09-27 00:51:48] } [debug] Replied in 81ms [debug] HANDLE EVENT "verses::focus_toggle_on_quick_mark_drafting" in VyasaWeb.ModeLive.Mediator Component: VyasaWeb.Context.Read Parameters: %{"is_focusing?" => false, "value" => ""} [debug] Replied in 129µs iex([email protected])17> * marks order force * old man mark is not feeling so good * ReWrite how marks get initialised @ :show_verse (#119) * Minor change in fn signature * Add init_draft_reflector() * Don't rely on the time async message passing * Use custom generic_modal_wrapper This one has more specific callback attributes and tailwind classes can be injected to it. * Create data and ui skeletons for sheaf_creator * Add support for human friendly time formatting * Setup skeleton for replyto context Some pending todo functions for how the reply to context shall be determined * Standardise UI, improve wrapper's default UI * Improve generic_modal_wrapper styling slots * Wire sheaf creation form to stubbed event handler Relevant TODOs have been added * Use session.name for signature, add handler stubs * Edit marks in read mode (#118) * Add generic debug dump component This makes life easy when wiring things up * Rename namespace for Context.Read.* * Groundwork: add discuss component w sheafs * Init Context.Components mod for common components * Add skeletons for Sheaf Container Container managers sheaf state within itself. Should actually make the verse-matrix use this container, sometime. * Minor changes, add some TODOs to share explicit todos Minor change * Add live component EditableMarkDisplay * Add UI improvements to EditableMarkDisplay The edit button on quick draft should only be seen when the dropdown is expanded and all the marks can be seen. The general pattern I'm trying to follow is that buttons should only be shown when an action makes sense. So here, if the user can't even see the marks currently accumulating, then the user shouldn't have the chance to edit any marks. Notice that the EditableMarkDisplay is a live_component that is a child of a function component (collapsible_marks_display). This is so that it can keep its own state and do it's own event-handling. I'm not sure if this is pattern-breaking. A reference to the actual parent live_component that calls collapsible_marks_display will always be there in case there's a need for the parent to handle any particular events. So comms b/w live_components is still going to be via phx-target values. * Change <input/> -> <textarea/> fr quick_draft_form * Add tailwind config for custom svg icons not sure how the scaling for this works, seems like i can't just put in the class="h-5 w-5" to do the scaling * Let custom svg be scalable * Subtly shift the ping indicator to control panel * Marks ordering in Sheaf and L-Trees (#114) * do sheafs grow on trees * sangh session dealing with lineage * Solve initial order problem * fix: ensure non-null id used @ EditableMarkDisplay --------- Co-authored-by: ks0m1c_dharma <[email protected]> * Trigger Diff * TOMBSTONING * Fix bugs and revert ui for read_mode:delete marks 1. JIT generate id for marks yet to be inserted to the db: instead of using a temp id, I'm actually assigning a JIT-generated id for a mark even if that isn't inserted into the db yet. this has two benefits: div ids have meaningful static ids (e.g. mark-container-\<\> mark.id) regardless of whether that mark has been inserted into the db or not. While doing this, the changeset for marks has been udpated to add id as well. This fixes a bunch of id-based errors as well. 2. while doing 1, it came to light that the bindHoverune handlers were not handling the draft mark update properly (i.e. not using the already existing update function in mark) . it's changed now, example of the diff: ``` diff @impl true def handle_event( "bindHoveRune", %{"binding" => bind = %{"verse_id" => verse_id}}, %{ assigns: %{ kv_verses: verses, marks: [%Mark{state: :draft, verse_id: curr_verse_id} = d_mark | marks] } } = socket ) when is_binary(curr_verse_id) and verse_id != curr_verse_id do # binding here blocks the stream from appending to quote bind = Draft.bind_node(bind) bound_verses = verses |> then(&put_in(&1[verse_id].binding, bind)) |> then(&put_in(&1[curr_verse_id].binding, nil)) + updated_draft_mark = d_mark |> Mark.update_mark(%{binding: bind, verse_id: verse_id}) + {:noreply, socket |> mutate_verses(curr_verse_id, bound_verses) |> mutate_verses(verse_id, bound_verses) - |> assign(:marks, [%{d_mark | binding: bind, verse_id: verse_id} | marks])} + |> assign(:marks, [updated_draft_mark | marks])} end ``` 3. add ui state structs: all of the relevant ui states have structs that are intended to be static interfaces. this felt better than directly keeping state within various sockets and is done with a view to remove live components and change them to function components wherever possible. 4. bugfix for `order()`: - it had an off-by-one-error - shifted it to Vyasa.Sangh.Mark - also note that the order shall be 1-indexed instead of 0-indexed for human-friendliness 5. minor fixes: 1. fix update<sub>mark</sub> default argument ``` diff -def update_mark(%Mark{} = draft_mark, opts \\ []) do +def update_mark(%Mark{} = draft_mark, opts \\ %{}) do ``` 1. In this commit, the marks<sub>ui</sub> is NOT kept by the read context module, that's why when I update things by create mark or delete mark, the ui state is not preserved and initial, default state is seen. This was intentionally done in this commit because I'm having problems with duplicate ids for verses for some reason, I'll show it in the next commit, so that the problem can be clearly seen. * [BUGGY] keep marks_ui within ReadContext This is buggy, not sure why there's a duplicate yet. will come back to it after lunch Replication Steps: 1. delete all marks and see there's no error 2. create first mark ==> no error 3. create second mark ==> crashes due to duplicate verse id Crash dump: [debug] Replied in 13ms [error] GenServer #PID<0.8416.0> terminating ** (RuntimeError) found duplicate ID "verse-7d9d588a-34fc-4f19-b974-fc32b49b6a61" for component VyasaWeb.Context.Read.VerseMatrix when rendering template (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:634: anonymous fn/5 in Phoenix.LiveView.Diff.render_pending_components/6 (elixir 1.17.2) lib/enum.ex:2531: Enum."-reduce/3-lists^foldl/2-0-"/3 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:631: anonymous fn/4 in Phoenix.LiveView.Diff.render_pending_components/6 (stdlib 5.2.3) maps.erl:416: :maps.fold_1/4 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:625: Phoenix.LiveView.Diff.render_pending_components/6 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:217: Phoenix.LiveView.Diff.write_component/4 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/channel.ex:662: Phoenix.LiveView.Channel.component_handle/4 (stdlib 5.2.3) gen_server.erl:1095: :gen_server.try_handle_info/3 (stdlib 5.2.3) gen_server.erl:1183: :gen_server.handle_msg/6 (stdlib 5.2.3) proc_lib.erl:251: :proc_lib.wake_up/3 Last message: %Phoenix.Socket.Message{topic: "lv:phx-F_1MH_6F0ciqVqwi", event: "event", payload: %{"cid" => 3, "event" => "createMark", "type" => "form", "value" => "body=how+about+now%2C+any+duplicate%3F"}, ref: "23", join_ref: "4"} State: %{socket: #Phoenix.LiveView.Socket<id: "phx-F_1MH_6F0ciqVqwi", endpoint: VyasaWeb.Endpoint, view: VyasaWeb.ModeLive.Mediator, parent_pid: nil, root_pid: #PID<0.8416.0>, router: VyasaWeb.Router, assigns: %{mode: %VyasaWeb.ModeLive.UserMode{mode: "read", default_ui_state: %VyasaWeb.ModeLive.UiState{show_media_bridge?: true, show_action_bar?: true}, mode_icon_name: "hero-book-open", quick_actions: [:mark_quote, :bookmark], control_panel_modes: ["discuss"], mode_actions: [:mark_quote, :bookmark], action_bar_actions: [:nav_back, :nav_fwd], action_bar_info_types: nil, action_bar_component: VyasaWeb.MediaLive.MediaBridge, action_bar_component_selector: "media-bridge", control_panel_component: VyasaWeb.ControlPanel, control_panel_component_selector: "control-panel", mode_context_component: VyasaWeb.Context.Read, mode_context_component_selector: "read"}, session: %VyasaWeb.Session{name: "ritesh kumar", id: "IhrQV0ypqg8bHakbvb2bymNF", active: true, sangh: %Vyasa.Sangh.Session{__meta__: #Ecto.Schema.Metadata<:loaded, "sessions">, id: "164eb05d-221a-4939-b180-8394e1a5515f", sheafs: #Ecto.Association.NotLoaded<association :sheafs is not loaded>, inserted_at: ~U[2024-09-27 00:51:48Z], updated_at: ~U[2024-09-27 00:51:48Z]}, last_opened: "2024-09-23T11:03:32.022987Z"}, __changed__: %{}, flash: %{}, locale: "en-GB", url_params: %{"chap_no" => "1", "source_title" => "hanuman_chalisa"}, live_action: :show_verses, ui_state: %VyasaWeb.ModeLive.UiState{show_media_bridge?: true, show_action_bar?: true}, device_type: :desktop, tz: %{timezone: "Asia/Singapore", timezone_offset: 480}}, transport_pid: #PID<0.8403.0>, ...>, components: {%{15 => {VyasaWeb.Context.Read.VerseMatrix, "verse-aa3ad88b-0de1-443e-b471-c08a44e67c61", %{id: "verse-aa3ad88b-0de1-443e-b471-c08a44e67c61", edge: [%{title: "1.10", field: [:body], verseup: {:big, "dn"}}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body_translit], verseup: :mid}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body_translit_meant], verseup: :mid}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body], verseup: :mid}], __changed__: %{}, flash: %{}, marks: [%Vyasa.Sangh.Mark{__meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "5dfdb167-6c57-46dd-a0c4-10b52cb03a85", body: "wonderful", order: 2, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "001da594-3808-46cf-9b9c-5dfb3559780e", binding: %Vyasa.Adapters.Binding{__meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "001da594-3808-46cf-9b9c-5dfb3559780e", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil}, inserted_at: ~U[2024-10-11 04:31:50Z], updated_at: ~U[2024-10-11 04:31:50Z]}, %Vyasa.Sangh.Mark{__meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "273a093d-4f90-40a4-b19a-2f8f7825d201", body: "truncated utc datetime", order: 1, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "ef39315b-530c-4841-ba32-86773f451727", binding: %Vyasa.Adapt (truncated) [debug] MOUNT VyasaWeb.ModeLive.Mediator Parameters: %{"chap_no" => "1", "source_title" => "hanuman_chalisa"} Session: %{"_csrf_token" => "DJ-RIoXwEzHW82rbb21le_8k"} [debug] QUERY OK source="sessions" db=3.5ms idle=1690.4ms SELECT s0."id", s0."inserted_at", s0."updated_at" FROM "sessions" AS s0 WHERE (s0."id" = $1) ["164eb05d-221a-4939-b180-8394e1a5515f"] ↳ * Fix duplicate id issue on verse matrix * Standardise use of @event_target, cleanups When using @event_target, the intent is that phx-target values will be passed around. This must be agnostic to the 2 main ways of supplying that argument, as a HTML selector, or as a module name (or @myself). Therefore, we should discourage ourselves from doing format-strings at the point of the @event_target being supplied as an argument, meaning: good, because agnostic: phx-target={@event_target} bad, because hardcoded: phx-target={"#" <> @event_target} * in this case, the event trigger will throw a dom error. * [Attempt]: Sanitise, defrag orders in marks-list If this is an anti-pattern, then this commit should be reverted. * UI fixes: hide buttons on marks when !is_editable? * Add in stub event handlers to prevent crashes Temporary stuff, will be addressed in immediate-next PR * Minor changes * Toggle edit state for marks content * Partial implementation of edit marks the form stuff doesn't exist so it's not wired up yet. To be frank, im' not sure how to set up a form without it needing to hold state. * [BUGGY] Wire up form update for edit this does the following: 1. wires up the form like how we usedd it in createMark 2. actually captures the event properly within the event handler, everything looks good at that point, even the edit_mark_in_marks function on inspection looks good 3. the marks is getting assigned to properly because the newly edited mark content is seen after doing a dom refresh 4. HOWEVER, the print statement at the sheaf_update function DOES NOT show the correct, updated marks in the sheaf here's a dump for it for reference [debug] HANDLE EVENT "editMarkContent" in VyasaWeb.ModeLive.Mediator Component: VyasaWeb.Context.Read Parameters: %{"mark_id" => "02218551-591f-4450-abbd-a7b7d76fd48e"} [debug] Replied in 2ms [debug] HANDLE EVENT "editMarkContent" in VyasaWeb.ModeLive.Mediator Component: VyasaWeb.Context.Read Parameters: %{"mark_body" => " testing\n\n\nwhat hte heck", "mark_id" => "02218551-591f-4450-abbd-a7b7d76fd48e"} >>> UPDATE SHEAF -- SHOULD BE WRITING TO DB NOW: %Vyasa.Sangh.Sheaf{ __meta__: #Ecto.Schema.Metadata<:loaded, "sheafs">, id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", body: nil, active: true, path: %EctoLtree.LabelTree{labels: ["7f4ab16b"]}, signature: nil, traits: ["draft"], child_count: 0, session_id: "164eb05d-221a-4939-b180-8394e1a5515f", session: #Ecto.Association.NotLoaded<association :session is not loaded>, parent_id: nil, parent: #Ecto.Association.NotLoaded<association :parent is not loaded>, marks: [ %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "555eb625-e392-496e-9831-4f4c130be6fd", body: "wonderful stuff", order: 5, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "072124d0-5e27-4601-832f-35eaa6426879", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "072124d0-5e27-4601-832f-35eaa6426879", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 08:46:54Z], updated_at: ~U[2024-10-12 08:46:54Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "b22a5661-8268-4875-be26-a12256414136", body: nil, order: 5, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "90e18044-73b2-4ede-a149-a381de893b9f", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "90e18044-73b2-4ede-a149-a381de893b9f", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "fc80709a-39dc-4b9c-95c3-1d64ce818302", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:52:40Z], updated_at: ~U[2024-10-12 09:52:40Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "8af43833-575c-4eb8-83b1-eb4e58509e4c", body: nil, order: 4, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "23b70937-ed81-47fe-a560-ee14287bff7d", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "23b70937-ed81-47fe-a560-ee14287bff7d", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:46:13Z], updated_at: ~U[2024-10-12 09:46:13Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "c7ad47e6-629d-4382-936d-64d757772c4e", body: nil, order: 3, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "d5758230-7966-4f9b-8c16-ae13998cd71b", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "d5758230-7966-4f9b-8c16-ae13998cd71b", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "fc80709a-39dc-4b9c-95c3-1d64ce818302", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:44:09Z], updated_at: ~U[2024-10-12 09:44:09Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "02218551-591f-4450-abbd-a7b7d76fd48e", body: "testing", order: 2, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "19ffdc82-a5d8-49c3-8b01-1559736dad80", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "19ffdc82-a5d8-49c3-8b01-1559736dad80", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "fc80709a-39dc-4b9c-95c3-1d64ce818302", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:43:19Z], updated_at: ~U[2024-10-12 09:43:19Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "90c6036a-9bd1-4b65-82d5-f121ec4d7867", body: nil, order: 2, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "b92f990d-99a2-4f04-a2d4-d1135021ee8c", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "b92f990d-99a2-4f04-a2d4-d1135021ee8c", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-11 09:03:00Z], updated_at: ~U[2024-10-11 09:03:00Z] } ], inserted_at: ~N[2024-09-27 00:51:48], updated_at: ~N[2024-09-27 00:51:48] } [debug] Replied in 81ms [debug] HANDLE EVENT "verses::focus_toggle_on_quick_mark_drafting" in VyasaWeb.ModeLive.Mediator Component: VyasaWeb.Context.Read Parameters: %{"is_focusing?" => false, "value" => ""} [debug] Replied in 129µs iex([email protected])17> * marks order force * old man mark is not feeling so good * ReWrite how marks get initialised @ :show_verse (#119) * Minor change in fn signature * Add init_draft_reflector() --------- Co-authored-by: ks0m1c_dharma <[email protected]> * Minor changes * Add a generic modal wrapper (#120) * Add generic debug dump component This makes life easy when wiring things up * Rename namespace for Context.Read.* * Groundwork: add discuss component w sheafs * Init Context.Components mod for common components * Add skeletons for Sheaf Container Container managers sheaf state within itself. Should actually make the verse-matrix use this container, sometime. * Minor changes, add some TODOs to share explicit todos Minor change * Add live component EditableMarkDisplay * Add UI improvements to EditableMarkDisplay The edit button on quick draft should only be seen when the dropdown is expanded and all the marks can be seen. The general pattern I'm trying to follow is that buttons should only be shown when an action makes sense. So here, if the user can't even see the marks currently accumulating, then the user shouldn't have the chance to edit any marks. Notice that the EditableMarkDisplay is a live_component that is a child of a function component (collapsible_marks_display). This is so that it can keep its own state and do it's own event-handling. I'm not sure if this is pattern-breaking. A reference to the actual parent live_component that calls collapsible_marks_display will always be there in case there's a need for the parent to handle any particular events. So comms b/w live_components is still going to be via phx-target values. * Change <input/> -> <textarea/> fr quick_draft_form * Add tailwind config for custom svg icons not sure how the scaling for this works, seems like i can't just put in the class="h-5 w-5" to do the scaling * Let custom svg be scalable * Subtly shift the ping indicator to control panel * Marks ordering in Sheaf and L-Trees (#114) * do sheafs grow on trees * sangh session dealing with lineage * Solve initial order problem * fix: ensure non-null id used @ EditableMarkDisplay --------- Co-authored-by: ks0m1c_dharma <[email protected]> * Trigger Diff * TOMBSTONING * Fix bugs and revert ui for read_mode:delete marks 1. JIT generate id for marks yet to be inserted to the db: instead of using a temp id, I'm actually assigning a JIT-generated id for a mark even if that isn't inserted into the db yet. this has two benefits: div ids have meaningful static ids (e.g. mark-container-\<\> mark.id) regardless of whether that mark has been inserted into the db or not. While doing this, the changeset for marks has been udpated to add id as well. This fixes a bunch of id-based errors as well. 2. while doing 1, it came to light that the bindHoverune handlers were not handling the draft mark update properly (i.e. not using the already existing update function in mark) . it's changed now, example of the diff: ``` diff @impl true def handle_event( "bindHoveRune", %{"binding" => bind = %{"verse_id" => verse_id}}, %{ assigns: %{ kv_verses: verses, marks: [%Mark{state: :draft, verse_id: curr_verse_id} = d_mark | marks] } } = socket ) when is_binary(curr_verse_id) and verse_id != curr_verse_id do # binding here blocks the stream from appending to quote bind = Draft.bind_node(bind) bound_verses = verses |> then(&put_in(&1[verse_id].binding, bind)) |> then(&put_in(&1[curr_verse_id].binding, nil)) + updated_draft_mark = d_mark |> Mark.update_mark(%{binding: bind, verse_id: verse_id}) + {:noreply, socket |> mutate_verses(curr_verse_id, bound_verses) |> mutate_verses(verse_id, bound_verses) - |> assign(:marks, [%{d_mark | binding: bind, verse_id: verse_id} | marks])} + |> assign(:marks, [updated_draft_mark | marks])} end ``` 3. add ui state structs: all of the relevant ui states have structs that are intended to be static interfaces. this felt better than directly keeping state within various sockets and is done with a view to remove live components and change them to function components wherever possible. 4. bugfix for `order()`: - it had an off-by-one-error - shifted it to Vyasa.Sangh.Mark - also note that the order shall be 1-indexed instead of 0-indexed for human-friendliness 5. minor fixes: 1. fix update<sub>mark</sub> default argument ``` diff -def update_mark(%Mark{} = draft_mark, opts \\ []) do +def update_mark(%Mark{} = draft_mark, opts \\ %{}) do ``` 1. In this commit, the marks<sub>ui</sub> is NOT kept by the read context module, that's why when I update things by create mark or delete mark, the ui state is not preserved and initial, default state is seen. This was intentionally done in this commit because I'm having problems with duplicate ids for verses for some reason, I'll show it in the next commit, so that the problem can be clearly seen. * [BUGGY] keep marks_ui within ReadContext This is buggy, not sure why there's a duplicate yet. will come back to it after lunch Replication Steps: 1. delete all marks and see there's no error 2. create first mark ==> no error 3. create second mark ==> crashes due to duplicate verse id Crash dump: [debug] Replied in 13ms [error] GenServer #PID<0.8416.0> terminating ** (RuntimeError) found duplicate ID "verse-7d9d588a-34fc-4f19-b974-fc32b49b6a61" for component VyasaWeb.Context.Read.VerseMatrix when rendering template (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:634: anonymous fn/5 in Phoenix.LiveView.Diff.render_pending_components/6 (elixir 1.17.2) lib/enum.ex:2531: Enum."-reduce/3-lists^foldl/2-0-"/3 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:631: anonymous fn/4 in Phoenix.LiveView.Diff.render_pending_components/6 (stdlib 5.2.3) maps.erl:416: :maps.fold_1/4 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:625: Phoenix.LiveView.Diff.render_pending_components/6 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:217: Phoenix.LiveView.Diff.write_component/4 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/channel.ex:662: Phoenix.LiveView.Channel.component_handle/4 (stdlib 5.2.3) gen_server.erl:1095: :gen_server.try_handle_info/3 (stdlib 5.2.3) gen_server.erl:1183: :gen_server.handle_msg/6 (stdlib 5.2.3) proc_lib.erl:251: :proc_lib.wake_up/3 Last message: %Phoenix.Socket.Message{topic: "lv:phx-F_1MH_6F0ciqVqwi", event: "event", payload: %{"cid" => 3, "event" => "createMark", "type" => "form", "value" => "body=how+about+now%2C+any+duplicate%3F"}, ref: "23", join_ref: "4"} State: %{socket: #Phoenix.LiveView.Socket<id: "phx-F_1MH_6F0ciqVqwi", endpoint: VyasaWeb.Endpoint, view: VyasaWeb.ModeLive.Mediator, parent_pid: nil, root_pid: #PID<0.8416.0>, router: VyasaWeb.Router, assigns: %{mode: %VyasaWeb.ModeLive.UserMode{mode: "read", default_ui_state: %VyasaWeb.ModeLive.UiState{show_media_bridge?: true, show_action_bar?: true}, mode_icon_name: "hero-book-open", quick_actions: [:mark_quote, :bookmark], control_panel_modes: ["discuss"], mode_actions: [:mark_quote, :bookmark], action_bar_actions: [:nav_back, :nav_fwd], action_bar_info_types: nil, action_bar_component: VyasaWeb.MediaLive.MediaBridge, action_bar_component_selector: "media-bridge", control_panel_component: VyasaWeb.ControlPanel, control_panel_component_selector: "control-panel", mode_context_component: VyasaWeb.Context.Read, mode_context_component_selector: "read"}, session: %VyasaWeb.Session{name: "ritesh kumar", id: "IhrQV0ypqg8bHakbvb2bymNF", active: true, sangh: %Vyasa.Sangh.Session{__meta__: #Ecto.Schema.Metadata<:loaded, "sessions">, id: "164eb05d-221a-4939-b180-8394e1a5515f", sheafs: #Ecto.Association.NotLoaded<association :sheafs is not loaded>, inserted_at: ~U[2024-09-27 00:51:48Z], updated_at: ~U[2024-09-27 00:51:48Z]}, last_opened: "2024-09-23T11:03:32.022987Z"}, __changed__: %{}, flash: %{}, locale: "en-GB", url_params: %{"chap_no" => "1", "source_title" => "hanuman_chalisa"}, live_action: :show_verses, ui_state: %VyasaWeb.ModeLive.UiState{show_media_bridge?: true, show_action_bar?: true}, device_type: :desktop, tz: %{timezone: "Asia/Singapore", timezone_offset: 480}}, transport_pid: #PID<0.8403.0>, ...>, components: {%{15 => {VyasaWeb.Context.Read.VerseMatrix, "verse-aa3ad88b-0de1-443e-b471-c08a44e67c61", %{id: "verse-aa3ad88b-0de1-443e-b471-c08a44e67c61", edge: [%{title: "1.10", field: [:body], verseup: {:big, "dn"}}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body_translit], verseup: :mid}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body_translit_meant], verseup: :mid}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body], verseup: :mid}], __changed__: %{}, flash: %{}, marks: [%Vyasa.Sangh.Mark{__meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "5dfdb167-6c57-46dd-a0c4-10b52cb03a85", body: "wonderful", order: 2, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "001da594-3808-46cf-9b9c-5dfb3559780e", binding: %Vyasa.Adapters.Binding{__meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "001da594-3808-46cf-9b9c-5dfb3559780e", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil}, inserted_at: ~U[2024-10-11 04:31:50Z], updated_at: ~U[2024-10-11 04:31:50Z]}, %Vyasa.Sangh.Mark{__meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "273a093d-4f90-40a4-b19a-2f8f7825d201", body: "truncated utc datetime", order: 1, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "ef39315b-530c-4841-ba32-86773f451727", binding: %Vyasa.Adapt (truncated) [debug] MOUNT VyasaWeb.ModeLive.Mediator Parameters: %{"chap_no" => "1", "source_title" => "hanuman_chalisa"} Session: %{"_csrf_token" => "DJ-RIoXwEzHW82rbb21le_8k"} [debug] QUERY OK source="sessions" db=3.5ms idle=1690.4ms SELECT s0."id", s0."inserted_at", s0."updated_at" FROM "sessions" AS s0 WHERE (s0."id" = $1) ["164eb05d-221a-4939-b180-8394e1a5515f"] ↳ * Fix duplicate id issue on verse matrix * Standardise use of @event_target, cleanups When using @event_target, the intent is that phx-target values will be passed around. This must be agnostic to the 2 main ways of supplying that argument, as a HTML selector, or as a module name (or @myself). Therefore, we should discourage ourselves from doing format-strings at the point of the @event_target being supplied as an argument, meaning: good, because agnostic: phx-target={@event_target} bad, because hardcoded: phx-target={"#" <> @event_target} * in this case, the event trigger will th…
* Add generic debug dump component This makes life easy when wiring things up * Rename namespace for Context.Read.* * Groundwork: add discuss component w sheafs * Init Context.Components mod for common components * Add skeletons for Sheaf Container Container managers sheaf state within itself. Should actually make the verse-matrix use this container, sometime. * Minor changes, add some TODOs to share explicit todos Minor change * Add live component EditableMarkDisplay * Add UI improvements to EditableMarkDisplay The edit button on quick draft should only be seen when the dropdown is expanded and all the marks can be seen. The general pattern I'm trying to follow is that buttons should only be shown when an action makes sense. So here, if the user can't even see the marks currently accumulating, then the user shouldn't have the chance to edit any marks. Notice that the EditableMarkDisplay is a live_component that is a child of a function component (collapsible_marks_display). This is so that it can keep its own state and do it's own event-handling. I'm not sure if this is pattern-breaking. A reference to the actual parent live_component that calls collapsible_marks_display will always be there in case there's a need for the parent to handle any particular events. So comms b/w live_components is still going to be via phx-target values. * Change <input/> -> <textarea/> fr quick_draft_form * Add tailwind config for custom svg icons not sure how the scaling for this works, seems like i can't just put in the class="h-5 w-5" to do the scaling * Let custom svg be scalable * Subtly shift the ping indicator to control panel * Marks ordering in Sheaf and L-Trees (#114) * do sheafs grow on trees * sangh session dealing with lineage * Solve initial order problem * fix: ensure non-null id used @ EditableMarkDisplay --------- Co-authored-by: ks0m1c_dharma <[email protected]> * Trigger Diff * TOMBSTONING * Fix bugs and revert ui for read_mode:delete marks 1. JIT generate id for marks yet to be inserted to the db: instead of using a temp id, I'm actually assigning a JIT-generated id for a mark even if that isn't inserted into the db yet. this has two benefits: div ids have meaningful static ids (e.g. mark-container-\<\> mark.id) regardless of whether that mark has been inserted into the db or not. While doing this, the changeset for marks has been udpated to add id as well. This fixes a bunch of id-based errors as well. 2. while doing 1, it came to light that the bindHoverune handlers were not handling the draft mark update properly (i.e. not using the already existing update function in mark) . it's changed now, example of the diff: ``` diff @impl true def handle_event( "bindHoveRune", %{"binding" => bind = %{"verse_id" => verse_id}}, %{ assigns: %{ kv_verses: verses, marks: [%Mark{state: :draft, verse_id: curr_verse_id} = d_mark | marks] } } = socket ) when is_binary(curr_verse_id) and verse_id != curr_verse_id do # binding here blocks the stream from appending to quote bind = Draft.bind_node(bind) bound_verses = verses |> then(&put_in(&1[verse_id].binding, bind)) |> then(&put_in(&1[curr_verse_id].binding, nil)) + updated_draft_mark = d_mark |> Mark.update_mark(%{binding: bind, verse_id: verse_id}) + {:noreply, socket |> mutate_verses(curr_verse_id, bound_verses) |> mutate_verses(verse_id, bound_verses) - |> assign(:marks, [%{d_mark | binding: bind, verse_id: verse_id} | marks])} + |> assign(:marks, [updated_draft_mark | marks])} end ``` 3. add ui state structs: all of the relevant ui states have structs that are intended to be static interfaces. this felt better than directly keeping state within various sockets and is done with a view to remove live components and change them to function components wherever possible. 4. bugfix for `order()`: - it had an off-by-one-error - shifted it to Vyasa.Sangh.Mark - also note that the order shall be 1-indexed instead of 0-indexed for human-friendliness 5. minor fixes: 1. fix update<sub>mark</sub> default argument ``` diff -def update_mark(%Mark{} = draft_mark, opts \\ []) do +def update_mark(%Mark{} = draft_mark, opts \\ %{}) do ``` 1. In this commit, the marks<sub>ui</sub> is NOT kept by the read context module, that's why when I update things by create mark or delete mark, the ui state is not preserved and initial, default state is seen. This was intentionally done in this commit because I'm having problems with duplicate ids for verses for some reason, I'll show it in the next commit, so that the problem can be clearly seen. * [BUGGY] keep marks_ui within ReadContext This is buggy, not sure why there's a duplicate yet. will come back to it after lunch Replication Steps: 1. delete all marks and see there's no error 2. create first mark ==> no error 3. create second mark ==> crashes due to duplicate verse id Crash dump: [debug] Replied in 13ms [error] GenServer #PID<0.8416.0> terminating ** (RuntimeError) found duplicate ID "verse-7d9d588a-34fc-4f19-b974-fc32b49b6a61" for component VyasaWeb.Context.Read.VerseMatrix when rendering template (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:634: anonymous fn/5 in Phoenix.LiveView.Diff.render_pending_components/6 (elixir 1.17.2) lib/enum.ex:2531: Enum."-reduce/3-lists^foldl/2-0-"/3 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:631: anonymous fn/4 in Phoenix.LiveView.Diff.render_pending_components/6 (stdlib 5.2.3) maps.erl:416: :maps.fold_1/4 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:625: Phoenix.LiveView.Diff.render_pending_components/6 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:217: Phoenix.LiveView.Diff.write_component/4 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/channel.ex:662: Phoenix.LiveView.Channel.component_handle/4 (stdlib 5.2.3) gen_server.erl:1095: :gen_server.try_handle_info/3 (stdlib 5.2.3) gen_server.erl:1183: :gen_server.handle_msg/6 (stdlib 5.2.3) proc_lib.erl:251: :proc_lib.wake_up/3 Last message: %Phoenix.Socket.Message{topic: "lv:phx-F_1MH_6F0ciqVqwi", event: "event", payload: %{"cid" => 3, "event" => "createMark", "type" => "form", "value" => "body=how+about+now%2C+any+duplicate%3F"}, ref: "23", join_ref: "4"} State: %{socket: #Phoenix.LiveView.Socket<id: "phx-F_1MH_6F0ciqVqwi", endpoint: VyasaWeb.Endpoint, view: VyasaWeb.ModeLive.Mediator, parent_pid: nil, root_pid: #PID<0.8416.0>, router: VyasaWeb.Router, assigns: %{mode: %VyasaWeb.ModeLive.UserMode{mode: "read", default_ui_state: %VyasaWeb.ModeLive.UiState{show_media_bridge?: true, show_action_bar?: true}, mode_icon_name: "hero-book-open", quick_actions: [:mark_quote, :bookmark], control_panel_modes: ["discuss"], mode_actions: [:mark_quote, :bookmark], action_bar_actions: [:nav_back, :nav_fwd], action_bar_info_types: nil, action_bar_component: VyasaWeb.MediaLive.MediaBridge, action_bar_component_selector: "media-bridge", control_panel_component: VyasaWeb.ControlPanel, control_panel_component_selector: "control-panel", mode_context_component: VyasaWeb.Context.Read, mode_context_component_selector: "read"}, session: %VyasaWeb.Session{name: "ritesh kumar", id: "IhrQV0ypqg8bHakbvb2bymNF", active: true, sangh: %Vyasa.Sangh.Session{__meta__: #Ecto.Schema.Metadata<:loaded, "sessions">, id: "164eb05d-221a-4939-b180-8394e1a5515f", sheafs: #Ecto.Association.NotLoaded<association :sheafs is not loaded>, inserted_at: ~U[2024-09-27 00:51:48Z], updated_at: ~U[2024-09-27 00:51:48Z]}, last_opened: "2024-09-23T11:03:32.022987Z"}, __changed__: %{}, flash: %{}, locale: "en-GB", url_params: %{"chap_no" => "1", "source_title" => "hanuman_chalisa"}, live_action: :show_verses, ui_state: %VyasaWeb.ModeLive.UiState{show_media_bridge?: true, show_action_bar?: true}, device_type: :desktop, tz: %{timezone: "Asia/Singapore", timezone_offset: 480}}, transport_pid: #PID<0.8403.0>, ...>, components: {%{15 => {VyasaWeb.Context.Read.VerseMatrix, "verse-aa3ad88b-0de1-443e-b471-c08a44e67c61", %{id: "verse-aa3ad88b-0de1-443e-b471-c08a44e67c61", edge: [%{title: "1.10", field: [:body], verseup: {:big, "dn"}}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body_translit], verseup: :mid}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body_translit_meant], verseup: :mid}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body], verseup: :mid}], __changed__: %{}, flash: %{}, marks: [%Vyasa.Sangh.Mark{__meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "5dfdb167-6c57-46dd-a0c4-10b52cb03a85", body: "wonderful", order: 2, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "001da594-3808-46cf-9b9c-5dfb3559780e", binding: %Vyasa.Adapters.Binding{__meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "001da594-3808-46cf-9b9c-5dfb3559780e", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil}, inserted_at: ~U[2024-10-11 04:31:50Z], updated_at: ~U[2024-10-11 04:31:50Z]}, %Vyasa.Sangh.Mark{__meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "273a093d-4f90-40a4-b19a-2f8f7825d201", body: "truncated utc datetime", order: 1, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "ef39315b-530c-4841-ba32-86773f451727", binding: %Vyasa.Adapt (truncated) [debug] MOUNT VyasaWeb.ModeLive.Mediator Parameters: %{"chap_no" => "1", "source_title" => "hanuman_chalisa"} Session: %{"_csrf_token" => "DJ-RIoXwEzHW82rbb21le_8k"} [debug] QUERY OK source="sessions" db=3.5ms idle=1690.4ms SELECT s0."id", s0."inserted_at", s0."updated_at" FROM "sessions" AS s0 WHERE (s0."id" = $1) ["164eb05d-221a-4939-b180-8394e1a5515f"] ↳ * Fix duplicate id issue on verse matrix * Standardise use of @event_target, cleanups When using @event_target, the intent is that phx-target values will be passed around. This must be agnostic to the 2 main ways of supplying that argument, as a HTML selector, or as a module name (or @myself). Therefore, we should discourage ourselves from doing format-strings at the point of the @event_target being supplied as an argument, meaning: good, because agnostic: phx-target={@event_target} bad, because hardcoded: phx-target={"#" <> @event_target} * in this case, the event trigger will throw a dom error. * [Attempt]: Sanitise, defrag orders in marks-list If this is an anti-pattern, then this commit should be reverted. * UI fixes: hide buttons on marks when !is_editable? * Add in stub event handlers to prevent crashes Temporary stuff, will be addressed in immediate-next PR * Minor changes * Toggle edit state for marks content * Partial implementation of edit marks the form stuff doesn't exist so it's not wired up yet. To be frank, im' not sure how to set up a form without it needing to hold state. * [BUGGY] Wire up form update for edit this does the following: 1. wires up the form like how we usedd it in createMark 2. actually captures the event properly within the event handler, everything looks good at that point, even the edit_mark_in_marks function on inspection looks good 3. the marks is getting assigned to properly because the newly edited mark content is seen after doing a dom refresh 4. HOWEVER, the print statement at the sheaf_update function DOES NOT show the correct, updated marks in the sheaf here's a dump for it for reference [debug] HANDLE EVENT "editMarkContent" in VyasaWeb.ModeLive.Mediator Component: VyasaWeb.Context.Read Parameters: %{"mark_id" => "02218551-591f-4450-abbd-a7b7d76fd48e"} [debug] Replied in 2ms [debug] HANDLE EVENT "editMarkContent" in VyasaWeb.ModeLive.Mediator Component: VyasaWeb.Context.Read Parameters: %{"mark_body" => " testing\n\n\nwhat hte heck", "mark_id" => "02218551-591f-4450-abbd-a7b7d76fd48e"} >>> UPDATE SHEAF -- SHOULD BE WRITING TO DB NOW: %Vyasa.Sangh.Sheaf{ __meta__: #Ecto.Schema.Metadata<:loaded, "sheafs">, id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", body: nil, active: true, path: %EctoLtree.LabelTree{labels: ["7f4ab16b"]}, signature: nil, traits: ["draft"], child_count: 0, session_id: "164eb05d-221a-4939-b180-8394e1a5515f", session: #Ecto.Association.NotLoaded<association :session is not loaded>, parent_id: nil, parent: #Ecto.Association.NotLoaded<association :parent is not loaded>, marks: [ %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "555eb625-e392-496e-9831-4f4c130be6fd", body: "wonderful stuff", order: 5, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "072124d0-5e27-4601-832f-35eaa6426879", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "072124d0-5e27-4601-832f-35eaa6426879", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 08:46:54Z], updated_at: ~U[2024-10-12 08:46:54Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "b22a5661-8268-4875-be26-a12256414136", body: nil, order: 5, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "90e18044-73b2-4ede-a149-a381de893b9f", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "90e18044-73b2-4ede-a149-a381de893b9f", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "fc80709a-39dc-4b9c-95c3-1d64ce818302", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:52:40Z], updated_at: ~U[2024-10-12 09:52:40Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "8af43833-575c-4eb8-83b1-eb4e58509e4c", body: nil, order: 4, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "23b70937-ed81-47fe-a560-ee14287bff7d", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "23b70937-ed81-47fe-a560-ee14287bff7d", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:46:13Z], updated_at: ~U[2024-10-12 09:46:13Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "c7ad47e6-629d-4382-936d-64d757772c4e", body: nil, order: 3, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "d5758230-7966-4f9b-8c16-ae13998cd71b", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "d5758230-7966-4f9b-8c16-ae13998cd71b", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "fc80709a-39dc-4b9c-95c3-1d64ce818302", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:44:09Z], updated_at: ~U[2024-10-12 09:44:09Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "02218551-591f-4450-abbd-a7b7d76fd48e", body: "testing", order: 2, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "19ffdc82-a5d8-49c3-8b01-1559736dad80", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "19ffdc82-a5d8-49c3-8b01-1559736dad80", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "fc80709a-39dc-4b9c-95c3-1d64ce818302", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:43:19Z], updated_at: ~U[2024-10-12 09:43:19Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "90c6036a-9bd1-4b65-82d5-f121ec4d7867", body: nil, order: 2, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "b92f990d-99a2-4f04-a2d4-d1135021ee8c", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "b92f990d-99a2-4f04-a2d4-d1135021ee8c", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-11 09:03:00Z], updated_at: ~U[2024-10-11 09:03:00Z] } ], inserted_at: ~N[2024-09-27 00:51:48], updated_at: ~N[2024-09-27 00:51:48] } [debug] Replied in 81ms [debug] HANDLE EVENT "verses::focus_toggle_on_quick_mark_drafting" in VyasaWeb.ModeLive.Mediator Component: VyasaWeb.Context.Read Parameters: %{"is_focusing?" => false, "value" => ""} [debug] Replied in 129µs iex([email protected])17> * marks order force * old man mark is not feeling so good * ReWrite how marks get initialised @ :show_verse (#119) * Minor change in fn signature * Add init_draft_reflector() * Don't rely on the time async message passing * Use custom generic_modal_wrapper This one has more specific callback attributes and tailwind classes can be injected to it. * Create data and ui skeletons for sheaf_creator * Add support for human friendly time formatting * Setup skeleton for replyto context Some pending todo functions for how the reply to context shall be determined * Standardise UI, improve wrapper's default UI * Improve generic_modal_wrapper styling slots * Wire sheaf creation form to stubbed event handler Relevant TODOs have been added * Use session.name for signature, add handler stubs * Edit marks in read mode (#118) * Add generic debug dump component This makes life easy when wiring things up * Rename namespace for Context.Read.* * Groundwork: add discuss component w sheafs * Init Context.Components mod for common components * Add skeletons for Sheaf Container Container managers sheaf state within itself. Should actually make the verse-matrix use this container, sometime. * Minor changes, add some TODOs to share explicit todos Minor change * Add live component EditableMarkDisplay * Add UI improvements to EditableMarkDisplay The edit button on quick draft should only be seen when the dropdown is expanded and all the marks can be seen. The general pattern I'm trying to follow is that buttons should only be shown when an action makes sense. So here, if the user can't even see the marks currently accumulating, then the user shouldn't have the chance to edit any marks. Notice that the EditableMarkDisplay is a live_component that is a child of a function component (collapsible_marks_display). This is so that it can keep its own state and do it's own event-handling. I'm not sure if this is pattern-breaking. A reference to the actual parent live_component that calls collapsible_marks_display will always be there in case there's a need for the parent to handle any particular events. So comms b/w live_components is still going to be via phx-target values. * Change <input/> -> <textarea/> fr quick_draft_form * Add tailwind config for custom svg icons not sure how the scaling for this works, seems like i can't just put in the class="h-5 w-5" to do the scaling * Let custom svg be scalable * Subtly shift the ping indicator to control panel * Marks ordering in Sheaf and L-Trees (#114) * do sheafs grow on trees * sangh session dealing with lineage * Solve initial order problem * fix: ensure non-null id used @ EditableMarkDisplay --------- Co-authored-by: ks0m1c_dharma <[email protected]> * Trigger Diff * TOMBSTONING * Fix bugs and revert ui for read_mode:delete marks 1. JIT generate id for marks yet to be inserted to the db: instead of using a temp id, I'm actually assigning a JIT-generated id for a mark even if that isn't inserted into the db yet. this has two benefits: div ids have meaningful static ids (e.g. mark-container-\<\> mark.id) regardless of whether that mark has been inserted into the db or not. While doing this, the changeset for marks has been udpated to add id as well. This fixes a bunch of id-based errors as well. 2. while doing 1, it came to light that the bindHoverune handlers were not handling the draft mark update properly (i.e. not using the already existing update function in mark) . it's changed now, example of the diff: ``` diff @impl true def handle_event( "bindHoveRune", %{"binding" => bind = %{"verse_id" => verse_id}}, %{ assigns: %{ kv_verses: verses, marks: [%Mark{state: :draft, verse_id: curr_verse_id} = d_mark | marks] } } = socket ) when is_binary(curr_verse_id) and verse_id != curr_verse_id do # binding here blocks the stream from appending to quote bind = Draft.bind_node(bind) bound_verses = verses |> then(&put_in(&1[verse_id].binding, bind)) |> then(&put_in(&1[curr_verse_id].binding, nil)) + updated_draft_mark = d_mark |> Mark.update_mark(%{binding: bind, verse_id: verse_id}) + {:noreply, socket |> mutate_verses(curr_verse_id, bound_verses) |> mutate_verses(verse_id, bound_verses) - |> assign(:marks, [%{d_mark | binding: bind, verse_id: verse_id} | marks])} + |> assign(:marks, [updated_draft_mark | marks])} end ``` 3. add ui state structs: all of the relevant ui states have structs that are intended to be static interfaces. this felt better than directly keeping state within various sockets and is done with a view to remove live components and change them to function components wherever possible. 4. bugfix for `order()`: - it had an off-by-one-error - shifted it to Vyasa.Sangh.Mark - also note that the order shall be 1-indexed instead of 0-indexed for human-friendliness 5. minor fixes: 1. fix update<sub>mark</sub> default argument ``` diff -def update_mark(%Mark{} = draft_mark, opts \\ []) do +def update_mark(%Mark{} = draft_mark, opts \\ %{}) do ``` 1. In this commit, the marks<sub>ui</sub> is NOT kept by the read context module, that's why when I update things by create mark or delete mark, the ui state is not preserved and initial, default state is seen. This was intentionally done in this commit because I'm having problems with duplicate ids for verses for some reason, I'll show it in the next commit, so that the problem can be clearly seen. * [BUGGY] keep marks_ui within ReadContext This is buggy, not sure why there's a duplicate yet. will come back to it after lunch Replication Steps: 1. delete all marks and see there's no error 2. create first mark ==> no error 3. create second mark ==> crashes due to duplicate verse id Crash dump: [debug] Replied in 13ms [error] GenServer #PID<0.8416.0> terminating ** (RuntimeError) found duplicate ID "verse-7d9d588a-34fc-4f19-b974-fc32b49b6a61" for component VyasaWeb.Context.Read.VerseMatrix when rendering template (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:634: anonymous fn/5 in Phoenix.LiveView.Diff.render_pending_components/6 (elixir 1.17.2) lib/enum.ex:2531: Enum."-reduce/3-lists^foldl/2-0-"/3 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:631: anonymous fn/4 in Phoenix.LiveView.Diff.render_pending_components/6 (stdlib 5.2.3) maps.erl:416: :maps.fold_1/4 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:625: Phoenix.LiveView.Diff.render_pending_components/6 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:217: Phoenix.LiveView.Diff.write_component/4 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/channel.ex:662: Phoenix.LiveView.Channel.component_handle/4 (stdlib 5.2.3) gen_server.erl:1095: :gen_server.try_handle_info/3 (stdlib 5.2.3) gen_server.erl:1183: :gen_server.handle_msg/6 (stdlib 5.2.3) proc_lib.erl:251: :proc_lib.wake_up/3 Last message: %Phoenix.Socket.Message{topic: "lv:phx-F_1MH_6F0ciqVqwi", event: "event", payload: %{"cid" => 3, "event" => "createMark", "type" => "form", "value" => "body=how+about+now%2C+any+duplicate%3F"}, ref: "23", join_ref: "4"} State: %{socket: #Phoenix.LiveView.Socket<id: "phx-F_1MH_6F0ciqVqwi", endpoint: VyasaWeb.Endpoint, view: VyasaWeb.ModeLive.Mediator, parent_pid: nil, root_pid: #PID<0.8416.0>, router: VyasaWeb.Router, assigns: %{mode: %VyasaWeb.ModeLive.UserMode{mode: "read", default_ui_state: %VyasaWeb.ModeLive.UiState{show_media_bridge?: true, show_action_bar?: true}, mode_icon_name: "hero-book-open", quick_actions: [:mark_quote, :bookmark], control_panel_modes: ["discuss"], mode_actions: [:mark_quote, :bookmark], action_bar_actions: [:nav_back, :nav_fwd], action_bar_info_types: nil, action_bar_component: VyasaWeb.MediaLive.MediaBridge, action_bar_component_selector: "media-bridge", control_panel_component: VyasaWeb.ControlPanel, control_panel_component_selector: "control-panel", mode_context_component: VyasaWeb.Context.Read, mode_context_component_selector: "read"}, session: %VyasaWeb.Session{name: "ritesh kumar", id: "IhrQV0ypqg8bHakbvb2bymNF", active: true, sangh: %Vyasa.Sangh.Session{__meta__: #Ecto.Schema.Metadata<:loaded, "sessions">, id: "164eb05d-221a-4939-b180-8394e1a5515f", sheafs: #Ecto.Association.NotLoaded<association :sheafs is not loaded>, inserted_at: ~U[2024-09-27 00:51:48Z], updated_at: ~U[2024-09-27 00:51:48Z]}, last_opened: "2024-09-23T11:03:32.022987Z"}, __changed__: %{}, flash: %{}, locale: "en-GB", url_params: %{"chap_no" => "1", "source_title" => "hanuman_chalisa"}, live_action: :show_verses, ui_state: %VyasaWeb.ModeLive.UiState{show_media_bridge?: true, show_action_bar?: true}, device_type: :desktop, tz: %{timezone: "Asia/Singapore", timezone_offset: 480}}, transport_pid: #PID<0.8403.0>, ...>, components: {%{15 => {VyasaWeb.Context.Read.VerseMatrix, "verse-aa3ad88b-0de1-443e-b471-c08a44e67c61", %{id: "verse-aa3ad88b-0de1-443e-b471-c08a44e67c61", edge: [%{title: "1.10", field: [:body], verseup: {:big, "dn"}}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body_translit], verseup: :mid}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body_translit_meant], verseup: :mid}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body], verseup: :mid}], __changed__: %{}, flash: %{}, marks: [%Vyasa.Sangh.Mark{__meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "5dfdb167-6c57-46dd-a0c4-10b52cb03a85", body: "wonderful", order: 2, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "001da594-3808-46cf-9b9c-5dfb3559780e", binding: %Vyasa.Adapters.Binding{__meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "001da594-3808-46cf-9b9c-5dfb3559780e", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil}, inserted_at: ~U[2024-10-11 04:31:50Z], updated_at: ~U[2024-10-11 04:31:50Z]}, %Vyasa.Sangh.Mark{__meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "273a093d-4f90-40a4-b19a-2f8f7825d201", body: "truncated utc datetime", order: 1, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "ef39315b-530c-4841-ba32-86773f451727", binding: %Vyasa.Adapt (truncated) [debug] MOUNT VyasaWeb.ModeLive.Mediator Parameters: %{"chap_no" => "1", "source_title" => "hanuman_chalisa"} Session: %{"_csrf_token" => "DJ-RIoXwEzHW82rbb21le_8k"} [debug] QUERY OK source="sessions" db=3.5ms idle=1690.4ms SELECT s0."id", s0."inserted_at", s0."updated_at" FROM "sessions" AS s0 WHERE (s0."id" = $1) ["164eb05d-221a-4939-b180-8394e1a5515f"] ↳ * Fix duplicate id issue on verse matrix * Standardise use of @event_target, cleanups When using @event_target, the intent is that phx-target values will be passed around. This must be agnostic to the 2 main ways of supplying that argument, as a HTML selector, or as a module name (or @myself). Therefore, we should discourage ourselves from doing format-strings at the point of the @event_target being supplied as an argument, meaning: good, because agnostic: phx-target={@event_target} bad, because hardcoded: phx-target={"#" <> @event_target} * in this case, the event trigger will throw a dom error. * [Attempt]: Sanitise, defrag orders in marks-list If this is an anti-pattern, then this commit should be reverted. * UI fixes: hide buttons on marks when !is_editable? * Add in stub event handlers to prevent crashes Temporary stuff, will be addressed in immediate-next PR * Minor changes * Toggle edit state for marks content * Partial implementation of edit marks the form stuff doesn't exist so it's not wired up yet. To be frank, im' not sure how to set up a form without it needing to hold state. * [BUGGY] Wire up form update for edit this does the following: 1. wires up the form like how we usedd it in createMark 2. actually captures the event properly within the event handler, everything looks good at that point, even the edit_mark_in_marks function on inspection looks good 3. the marks is getting assigned to properly because the newly edited mark content is seen after doing a dom refresh 4. HOWEVER, the print statement at the sheaf_update function DOES NOT show the correct, updated marks in the sheaf here's a dump for it for reference [debug] HANDLE EVENT "editMarkContent" in VyasaWeb.ModeLive.Mediator Component: VyasaWeb.Context.Read Parameters: %{"mark_id" => "02218551-591f-4450-abbd-a7b7d76fd48e"} [debug] Replied in 2ms [debug] HANDLE EVENT "editMarkContent" in VyasaWeb.ModeLive.Mediator Component: VyasaWeb.Context.Read Parameters: %{"mark_body" => " testing\n\n\nwhat hte heck", "mark_id" => "02218551-591f-4450-abbd-a7b7d76fd48e"} >>> UPDATE SHEAF -- SHOULD BE WRITING TO DB NOW: %Vyasa.Sangh.Sheaf{ __meta__: #Ecto.Schema.Metadata<:loaded, "sheafs">, id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", body: nil, active: true, path: %EctoLtree.LabelTree{labels: ["7f4ab16b"]}, signature: nil, traits: ["draft"], child_count: 0, session_id: "164eb05d-221a-4939-b180-8394e1a5515f", session: #Ecto.Association.NotLoaded<association :session is not loaded>, parent_id: nil, parent: #Ecto.Association.NotLoaded<association :parent is not loaded>, marks: [ %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "555eb625-e392-496e-9831-4f4c130be6fd", body: "wonderful stuff", order: 5, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "072124d0-5e27-4601-832f-35eaa6426879", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "072124d0-5e27-4601-832f-35eaa6426879", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 08:46:54Z], updated_at: ~U[2024-10-12 08:46:54Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "b22a5661-8268-4875-be26-a12256414136", body: nil, order: 5, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "90e18044-73b2-4ede-a149-a381de893b9f", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "90e18044-73b2-4ede-a149-a381de893b9f", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "fc80709a-39dc-4b9c-95c3-1d64ce818302", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:52:40Z], updated_at: ~U[2024-10-12 09:52:40Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "8af43833-575c-4eb8-83b1-eb4e58509e4c", body: nil, order: 4, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "23b70937-ed81-47fe-a560-ee14287bff7d", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "23b70937-ed81-47fe-a560-ee14287bff7d", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:46:13Z], updated_at: ~U[2024-10-12 09:46:13Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "c7ad47e6-629d-4382-936d-64d757772c4e", body: nil, order: 3, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "d5758230-7966-4f9b-8c16-ae13998cd71b", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "d5758230-7966-4f9b-8c16-ae13998cd71b", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "fc80709a-39dc-4b9c-95c3-1d64ce818302", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:44:09Z], updated_at: ~U[2024-10-12 09:44:09Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "02218551-591f-4450-abbd-a7b7d76fd48e", body: "testing", order: 2, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "19ffdc82-a5d8-49c3-8b01-1559736dad80", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "19ffdc82-a5d8-49c3-8b01-1559736dad80", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "fc80709a-39dc-4b9c-95c3-1d64ce818302", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:43:19Z], updated_at: ~U[2024-10-12 09:43:19Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "90c6036a-9bd1-4b65-82d5-f121ec4d7867", body: nil, order: 2, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "b92f990d-99a2-4f04-a2d4-d1135021ee8c", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "b92f990d-99a2-4f04-a2d4-d1135021ee8c", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-11 09:03:00Z], updated_at: ~U[2024-10-11 09:03:00Z] } ], inserted_at: ~N[2024-09-27 00:51:48], updated_at: ~N[2024-09-27 00:51:48] } [debug] Replied in 81ms [debug] HANDLE EVENT "verses::focus_toggle_on_quick_mark_drafting" in VyasaWeb.ModeLive.Mediator Component: VyasaWeb.Context.Read Parameters: %{"is_focusing?" => false, "value" => ""} [debug] Replied in 129µs iex([email protected])17> * marks order force * old man mark is not feeling so good * ReWrite how marks get initialised @ :show_verse (#119) * Minor change in fn signature * Add init_draft_reflector() --------- Co-authored-by: ks0m1c_dharma <[email protected]> * Minor changes * Add a generic modal wrapper (#120) * Add generic debug dump component This makes life easy when wiring things up * Rename namespace for Context.Read.* * Groundwork: add discuss component w sheafs * Init Context.Components mod for common components * Add skeletons for Sheaf Container Container managers sheaf state within itself. Should actually make the verse-matrix use this container, sometime. * Minor changes, add some TODOs to share explicit todos Minor change * Add live component EditableMarkDisplay * Add UI improvements to EditableMarkDisplay The edit button on quick draft should only be seen when the dropdown is expanded and all the marks can be seen. The general pattern I'm trying to follow is that buttons should only be shown when an action makes sense. So here, if the user can't even see the marks currently accumulating, then the user shouldn't have the chance to edit any marks. Notice that the EditableMarkDisplay is a live_component that is a child of a function component (collapsible_marks_display). This is so that it can keep its own state and do it's own event-handling. I'm not sure if this is pattern-breaking. A reference to the actual parent live_component that calls collapsible_marks_display will always be there in case there's a need for the parent to handle any particular events. So comms b/w live_components is still going to be via phx-target values. * Change <input/> -> <textarea/> fr quick_draft_form * Add tailwind config for custom svg icons not sure how the scaling for this works, seems like i can't just put in the class="h-5 w-5" to do the scaling * Let custom svg be scalable * Subtly shift the ping indicator to control panel * Marks ordering in Sheaf and L-Trees (#114) * do sheafs grow on trees * sangh session dealing with lineage * Solve initial order problem * fix: ensure non-null id used @ EditableMarkDisplay --------- Co-authored-by: ks0m1c_dharma <[email protected]> * Trigger Diff * TOMBSTONING * Fix bugs and revert ui for read_mode:delete marks 1. JIT generate id for marks yet to be inserted to the db: instead of using a temp id, I'm actually assigning a JIT-generated id for a mark even if that isn't inserted into the db yet. this has two benefits: div ids have meaningful static ids (e.g. mark-container-\<\> mark.id) regardless of whether that mark has been inserted into the db or not. While doing this, the changeset for marks has been udpated to add id as well. This fixes a bunch of id-based errors as well. 2. while doing 1, it came to light that the bindHoverune handlers were not handling the draft mark update properly (i.e. not using the already existing update function in mark) . it's changed now, example of the diff: ``` diff @impl true def handle_event( "bindHoveRune", %{"binding" => bind = %{"verse_id" => verse_id}}, %{ assigns: %{ kv_verses: verses, marks: [%Mark{state: :draft, verse_id: curr_verse_id} = d_mark | marks] } } = socket ) when is_binary(curr_verse_id) and verse_id != curr_verse_id do # binding here blocks the stream from appending to quote bind = Draft.bind_node(bind) bound_verses = verses |> then(&put_in(&1[verse_id].binding, bind)) |> then(&put_in(&1[curr_verse_id].binding, nil)) + updated_draft_mark = d_mark |> Mark.update_mark(%{binding: bind, verse_id: verse_id}) + {:noreply, socket |> mutate_verses(curr_verse_id, bound_verses) |> mutate_verses(verse_id, bound_verses) - |> assign(:marks, [%{d_mark | binding: bind, verse_id: verse_id} | marks])} + |> assign(:marks, [updated_draft_mark | marks])} end ``` 3. add ui state structs: all of the relevant ui states have structs that are intended to be static interfaces. this felt better than directly keeping state within various sockets and is done with a view to remove live components and change them to function components wherever possible. 4. bugfix for `order()`: - it had an off-by-one-error - shifted it to Vyasa.Sangh.Mark - also note that the order shall be 1-indexed instead of 0-indexed for human-friendliness 5. minor fixes: 1. fix update<sub>mark</sub> default argument ``` diff -def update_mark(%Mark{} = draft_mark, opts \\ []) do +def update_mark(%Mark{} = draft_mark, opts \\ %{}) do ``` 1. In this commit, the marks<sub>ui</sub> is NOT kept by the read context module, that's why when I update things by create mark or delete mark, the ui state is not preserved and initial, default state is seen. This was intentionally done in this commit because I'm having problems with duplicate ids for verses for some reason, I'll show it in the next commit, so that the problem can be clearly seen. * [BUGGY] keep marks_ui within ReadContext This is buggy, not sure why there's a duplicate yet. will come back to it after lunch Replication Steps: 1. delete all marks and see there's no error 2. create first mark ==> no error 3. create second mark ==> crashes due to duplicate verse id Crash dump: [debug] Replied in 13ms [error] GenServer #PID<0.8416.0> terminating ** (RuntimeError) found duplicate ID "verse-7d9d588a-34fc-4f19-b974-fc32b49b6a61" for component VyasaWeb.Context.Read.VerseMatrix when rendering template (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:634: anonymous fn/5 in Phoenix.LiveView.Diff.render_pending_components/6 (elixir 1.17.2) lib/enum.ex:2531: Enum."-reduce/3-lists^foldl/2-0-"/3 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:631: anonymous fn/4 in Phoenix.LiveView.Diff.render_pending_components/6 (stdlib 5.2.3) maps.erl:416: :maps.fold_1/4 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:625: Phoenix.LiveView.Diff.render_pending_components/6 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:217: Phoenix.LiveView.Diff.write_component/4 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/channel.ex:662: Phoenix.LiveView.Channel.component_handle/4 (stdlib 5.2.3) gen_server.erl:1095: :gen_server.try_handle_info/3 (stdlib 5.2.3) gen_server.erl:1183: :gen_server.handle_msg/6 (stdlib 5.2.3) proc_lib.erl:251: :proc_lib.wake_up/3 Last message: %Phoenix.Socket.Message{topic: "lv:phx-F_1MH_6F0ciqVqwi", event: "event", payload: %{"cid" => 3, "event" => "createMark", "type" => "form", "value" => "body=how+about+now%2C+any+duplicate%3F"}, ref: "23", join_ref: "4"} State: %{socket: #Phoenix.LiveView.Socket<id: "phx-F_1MH_6F0ciqVqwi", endpoint: VyasaWeb.Endpoint, view: VyasaWeb.ModeLive.Mediator, parent_pid: nil, root_pid: #PID<0.8416.0>, router: VyasaWeb.Router, assigns: %{mode: %VyasaWeb.ModeLive.UserMode{mode: "read", default_ui_state: %VyasaWeb.ModeLive.UiState{show_media_bridge?: true, show_action_bar?: true}, mode_icon_name: "hero-book-open", quick_actions: [:mark_quote, :bookmark], control_panel_modes: ["discuss"], mode_actions: [:mark_quote, :bookmark], action_bar_actions: [:nav_back, :nav_fwd], action_bar_info_types: nil, action_bar_component: VyasaWeb.MediaLive.MediaBridge, action_bar_component_selector: "media-bridge", control_panel_component: VyasaWeb.ControlPanel, control_panel_component_selector: "control-panel", mode_context_component: VyasaWeb.Context.Read, mode_context_component_selector: "read"}, session: %VyasaWeb.Session{name: "ritesh kumar", id: "IhrQV0ypqg8bHakbvb2bymNF", active: true, sangh: %Vyasa.Sangh.Session{__meta__: #Ecto.Schema.Metadata<:loaded, "sessions">, id: "164eb05d-221a-4939-b180-8394e1a5515f", sheafs: #Ecto.Association.NotLoaded<association :sheafs is not loaded>, inserted_at: ~U[2024-09-27 00:51:48Z], updated_at: ~U[2024-09-27 00:51:48Z]}, last_opened: "2024-09-23T11:03:32.022987Z"}, __changed__: %{}, flash: %{}, locale: "en-GB", url_params: %{"chap_no" => "1", "source_title" => "hanuman_chalisa"}, live_action: :show_verses, ui_state: %VyasaWeb.ModeLive.UiState{show_media_bridge?: true, show_action_bar?: true}, device_type: :desktop, tz: %{timezone: "Asia/Singapore", timezone_offset: 480}}, transport_pid: #PID<0.8403.0>, ...>, components: {%{15 => {VyasaWeb.Context.Read.VerseMatrix, "verse-aa3ad88b-0de1-443e-b471-c08a44e67c61", %{id: "verse-aa3ad88b-0de1-443e-b471-c08a44e67c61", edge: [%{title: "1.10", field: [:body], verseup: {:big, "dn"}}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body_translit], verseup: :mid}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body_translit_meant], verseup: :mid}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body], verseup: :mid}], __changed__: %{}, flash: %{}, marks: [%Vyasa.Sangh.Mark{__meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "5dfdb167-6c57-46dd-a0c4-10b52cb03a85", body: "wonderful", order: 2, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "001da594-3808-46cf-9b9c-5dfb3559780e", binding: %Vyasa.Adapters.Binding{__meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "001da594-3808-46cf-9b9c-5dfb3559780e", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil}, inserted_at: ~U[2024-10-11 04:31:50Z], updated_at: ~U[2024-10-11 04:31:50Z]}, %Vyasa.Sangh.Mark{__meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "273a093d-4f90-40a4-b19a-2f8f7825d201", body: "truncated utc datetime", order: 1, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "ef39315b-530c-4841-ba32-86773f451727", binding: %Vyasa.Adapt (truncated) [debug] MOUNT VyasaWeb.ModeLive.Mediator Parameters: %{"chap_no" => "1", "source_title" => "hanuman_chalisa"} Session: %{"_csrf_token" => "DJ-RIoXwEzHW82rbb21le_8k"} [debug] QUERY OK source="sessions" db=3.5ms idle=1690.4ms SELECT s0."id", s0."inserted_at", s0."updated_at" FROM "sessions" AS s0 WHERE (s0."id" = $1) ["164eb05d-221a-4939-b180-8394e1a5515f"] ↳ * Fix duplicate id issue on verse matrix * Standardise use of @event_target, cleanups When using @event_target, the intent is that phx-target values will be passed around. This must be agnostic to the 2 main ways of supplying that argument, as a HTML selector, or as a module name (or @myself). Therefore, we should discourage ourselves from doing format-strings at the point of the @event_target being supplied as an argument, meaning: good, because agnostic: phx-target={@event_target} bad, because hardcoded: phx-target={"#" <> @event_target} * in this case, the event trigger will …
* Add generic debug dump component This makes life easy when wiring things up * Rename namespace for Context.Read.* * Groundwork: add discuss component w sheafs * Init Context.Components mod for common components * Add skeletons for Sheaf Container Container managers sheaf state within itself. Should actually make the verse-matrix use this container, sometime. * Minor changes, add some TODOs to share explicit todos Minor change * Add live component EditableMarkDisplay * Add UI improvements to EditableMarkDisplay The edit button on quick draft should only be seen when the dropdown is expanded and all the marks can be seen. The general pattern I'm trying to follow is that buttons should only be shown when an action makes sense. So here, if the user can't even see the marks currently accumulating, then the user shouldn't have the chance to edit any marks. Notice that the EditableMarkDisplay is a live_component that is a child of a function component (collapsible_marks_display). This is so that it can keep its own state and do it's own event-handling. I'm not sure if this is pattern-breaking. A reference to the actual parent live_component that calls collapsible_marks_display will always be there in case there's a need for the parent to handle any particular events. So comms b/w live_components is still going to be via phx-target values. * Change <input/> -> <textarea/> fr quick_draft_form * Add tailwind config for custom svg icons not sure how the scaling for this works, seems like i can't just put in the class="h-5 w-5" to do the scaling * Let custom svg be scalable * Subtly shift the ping indicator to control panel * Marks ordering in Sheaf and L-Trees (#114) * do sheafs grow on trees * sangh session dealing with lineage * Solve initial order problem * fix: ensure non-null id used @ EditableMarkDisplay --------- Co-authored-by: ks0m1c_dharma <[email protected]> * Trigger Diff * TOMBSTONING * Fix bugs and revert ui for read_mode:delete marks 1. JIT generate id for marks yet to be inserted to the db: instead of using a temp id, I'm actually assigning a JIT-generated id for a mark even if that isn't inserted into the db yet. this has two benefits: div ids have meaningful static ids (e.g. mark-container-\<\> mark.id) regardless of whether that mark has been inserted into the db or not. While doing this, the changeset for marks has been udpated to add id as well. This fixes a bunch of id-based errors as well. 2. while doing 1, it came to light that the bindHoverune handlers were not handling the draft mark update properly (i.e. not using the already existing update function in mark) . it's changed now, example of the diff: ``` diff @impl true def handle_event( "bindHoveRune", %{"binding" => bind = %{"verse_id" => verse_id}}, %{ assigns: %{ kv_verses: verses, marks: [%Mark{state: :draft, verse_id: curr_verse_id} = d_mark | marks] } } = socket ) when is_binary(curr_verse_id) and verse_id != curr_verse_id do # binding here blocks the stream from appending to quote bind = Draft.bind_node(bind) bound_verses = verses |> then(&put_in(&1[verse_id].binding, bind)) |> then(&put_in(&1[curr_verse_id].binding, nil)) + updated_draft_mark = d_mark |> Mark.update_mark(%{binding: bind, verse_id: verse_id}) + {:noreply, socket |> mutate_verses(curr_verse_id, bound_verses) |> mutate_verses(verse_id, bound_verses) - |> assign(:marks, [%{d_mark | binding: bind, verse_id: verse_id} | marks])} + |> assign(:marks, [updated_draft_mark | marks])} end ``` 3. add ui state structs: all of the relevant ui states have structs that are intended to be static interfaces. this felt better than directly keeping state within various sockets and is done with a view to remove live components and change them to function components wherever possible. 4. bugfix for `order()`: - it had an off-by-one-error - shifted it to Vyasa.Sangh.Mark - also note that the order shall be 1-indexed instead of 0-indexed for human-friendliness 5. minor fixes: 1. fix update<sub>mark</sub> default argument ``` diff -def update_mark(%Mark{} = draft_mark, opts \\ []) do +def update_mark(%Mark{} = draft_mark, opts \\ %{}) do ``` 1. In this commit, the marks<sub>ui</sub> is NOT kept by the read context module, that's why when I update things by create mark or delete mark, the ui state is not preserved and initial, default state is seen. This was intentionally done in this commit because I'm having problems with duplicate ids for verses for some reason, I'll show it in the next commit, so that the problem can be clearly seen. * [BUGGY] keep marks_ui within ReadContext This is buggy, not sure why there's a duplicate yet. will come back to it after lunch Replication Steps: 1. delete all marks and see there's no error 2. create first mark ==> no error 3. create second mark ==> crashes due to duplicate verse id Crash dump: [debug] Replied in 13ms [error] GenServer #PID<0.8416.0> terminating ** (RuntimeError) found duplicate ID "verse-7d9d588a-34fc-4f19-b974-fc32b49b6a61" for component VyasaWeb.Context.Read.VerseMatrix when rendering template (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:634: anonymous fn/5 in Phoenix.LiveView.Diff.render_pending_components/6 (elixir 1.17.2) lib/enum.ex:2531: Enum."-reduce/3-lists^foldl/2-0-"/3 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:631: anonymous fn/4 in Phoenix.LiveView.Diff.render_pending_components/6 (stdlib 5.2.3) maps.erl:416: :maps.fold_1/4 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:625: Phoenix.LiveView.Diff.render_pending_components/6 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:217: Phoenix.LiveView.Diff.write_component/4 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/channel.ex:662: Phoenix.LiveView.Channel.component_handle/4 (stdlib 5.2.3) gen_server.erl:1095: :gen_server.try_handle_info/3 (stdlib 5.2.3) gen_server.erl:1183: :gen_server.handle_msg/6 (stdlib 5.2.3) proc_lib.erl:251: :proc_lib.wake_up/3 Last message: %Phoenix.Socket.Message{topic: "lv:phx-F_1MH_6F0ciqVqwi", event: "event", payload: %{"cid" => 3, "event" => "createMark", "type" => "form", "value" => "body=how+about+now%2C+any+duplicate%3F"}, ref: "23", join_ref: "4"} State: %{socket: #Phoenix.LiveView.Socket<id: "phx-F_1MH_6F0ciqVqwi", endpoint: VyasaWeb.Endpoint, view: VyasaWeb.ModeLive.Mediator, parent_pid: nil, root_pid: #PID<0.8416.0>, router: VyasaWeb.Router, assigns: %{mode: %VyasaWeb.ModeLive.UserMode{mode: "read", default_ui_state: %VyasaWeb.ModeLive.UiState{show_media_bridge?: true, show_action_bar?: true}, mode_icon_name: "hero-book-open", quick_actions: [:mark_quote, :bookmark], control_panel_modes: ["discuss"], mode_actions: [:mark_quote, :bookmark], action_bar_actions: [:nav_back, :nav_fwd], action_bar_info_types: nil, action_bar_component: VyasaWeb.MediaLive.MediaBridge, action_bar_component_selector: "media-bridge", control_panel_component: VyasaWeb.ControlPanel, control_panel_component_selector: "control-panel", mode_context_component: VyasaWeb.Context.Read, mode_context_component_selector: "read"}, session: %VyasaWeb.Session{name: "ritesh kumar", id: "IhrQV0ypqg8bHakbvb2bymNF", active: true, sangh: %Vyasa.Sangh.Session{__meta__: #Ecto.Schema.Metadata<:loaded, "sessions">, id: "164eb05d-221a-4939-b180-8394e1a5515f", sheafs: #Ecto.Association.NotLoaded<association :sheafs is not loaded>, inserted_at: ~U[2024-09-27 00:51:48Z], updated_at: ~U[2024-09-27 00:51:48Z]}, last_opened: "2024-09-23T11:03:32.022987Z"}, __changed__: %{}, flash: %{}, locale: "en-GB", url_params: %{"chap_no" => "1", "source_title" => "hanuman_chalisa"}, live_action: :show_verses, ui_state: %VyasaWeb.ModeLive.UiState{show_media_bridge?: true, show_action_bar?: true}, device_type: :desktop, tz: %{timezone: "Asia/Singapore", timezone_offset: 480}}, transport_pid: #PID<0.8403.0>, ...>, components: {%{15 => {VyasaWeb.Context.Read.VerseMatrix, "verse-aa3ad88b-0de1-443e-b471-c08a44e67c61", %{id: "verse-aa3ad88b-0de1-443e-b471-c08a44e67c61", edge: [%{title: "1.10", field: [:body], verseup: {:big, "dn"}}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body_translit], verseup: :mid}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body_translit_meant], verseup: :mid}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body], verseup: :mid}], __changed__: %{}, flash: %{}, marks: [%Vyasa.Sangh.Mark{__meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "5dfdb167-6c57-46dd-a0c4-10b52cb03a85", body: "wonderful", order: 2, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "001da594-3808-46cf-9b9c-5dfb3559780e", binding: %Vyasa.Adapters.Binding{__meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "001da594-3808-46cf-9b9c-5dfb3559780e", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil}, inserted_at: ~U[2024-10-11 04:31:50Z], updated_at: ~U[2024-10-11 04:31:50Z]}, %Vyasa.Sangh.Mark{__meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "273a093d-4f90-40a4-b19a-2f8f7825d201", body: "truncated utc datetime", order: 1, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "ef39315b-530c-4841-ba32-86773f451727", binding: %Vyasa.Adapt (truncated) [debug] MOUNT VyasaWeb.ModeLive.Mediator Parameters: %{"chap_no" => "1", "source_title" => "hanuman_chalisa"} Session: %{"_csrf_token" => "DJ-RIoXwEzHW82rbb21le_8k"} [debug] QUERY OK source="sessions" db=3.5ms idle=1690.4ms SELECT s0."id", s0."inserted_at", s0."updated_at" FROM "sessions" AS s0 WHERE (s0."id" = $1) ["164eb05d-221a-4939-b180-8394e1a5515f"] ↳ * Fix duplicate id issue on verse matrix * Standardise use of @event_target, cleanups When using @event_target, the intent is that phx-target values will be passed around. This must be agnostic to the 2 main ways of supplying that argument, as a HTML selector, or as a module name (or @myself). Therefore, we should discourage ourselves from doing format-strings at the point of the @event_target being supplied as an argument, meaning: good, because agnostic: phx-target={@event_target} bad, because hardcoded: phx-target={"#" <> @event_target} * in this case, the event trigger will throw a dom error. * [Attempt]: Sanitise, defrag orders in marks-list If this is an anti-pattern, then this commit should be reverted. * UI fixes: hide buttons on marks when !is_editable? * Add in stub event handlers to prevent crashes Temporary stuff, will be addressed in immediate-next PR * Minor changes * Toggle edit state for marks content * Partial implementation of edit marks the form stuff doesn't exist so it's not wired up yet. To be frank, im' not sure how to set up a form without it needing to hold state. * [BUGGY] Wire up form update for edit this does the following: 1. wires up the form like how we usedd it in createMark 2. actually captures the event properly within the event handler, everything looks good at that point, even the edit_mark_in_marks function on inspection looks good 3. the marks is getting assigned to properly because the newly edited mark content is seen after doing a dom refresh 4. HOWEVER, the print statement at the sheaf_update function DOES NOT show the correct, updated marks in the sheaf here's a dump for it for reference [debug] HANDLE EVENT "editMarkContent" in VyasaWeb.ModeLive.Mediator Component: VyasaWeb.Context.Read Parameters: %{"mark_id" => "02218551-591f-4450-abbd-a7b7d76fd48e"} [debug] Replied in 2ms [debug] HANDLE EVENT "editMarkContent" in VyasaWeb.ModeLive.Mediator Component: VyasaWeb.Context.Read Parameters: %{"mark_body" => " testing\n\n\nwhat hte heck", "mark_id" => "02218551-591f-4450-abbd-a7b7d76fd48e"} >>> UPDATE SHEAF -- SHOULD BE WRITING TO DB NOW: %Vyasa.Sangh.Sheaf{ __meta__: #Ecto.Schema.Metadata<:loaded, "sheafs">, id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", body: nil, active: true, path: %EctoLtree.LabelTree{labels: ["7f4ab16b"]}, signature: nil, traits: ["draft"], child_count: 0, session_id: "164eb05d-221a-4939-b180-8394e1a5515f", session: #Ecto.Association.NotLoaded<association :session is not loaded>, parent_id: nil, parent: #Ecto.Association.NotLoaded<association :parent is not loaded>, marks: [ %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "555eb625-e392-496e-9831-4f4c130be6fd", body: "wonderful stuff", order: 5, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "072124d0-5e27-4601-832f-35eaa6426879", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "072124d0-5e27-4601-832f-35eaa6426879", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 08:46:54Z], updated_at: ~U[2024-10-12 08:46:54Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "b22a5661-8268-4875-be26-a12256414136", body: nil, order: 5, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "90e18044-73b2-4ede-a149-a381de893b9f", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "90e18044-73b2-4ede-a149-a381de893b9f", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "fc80709a-39dc-4b9c-95c3-1d64ce818302", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:52:40Z], updated_at: ~U[2024-10-12 09:52:40Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "8af43833-575c-4eb8-83b1-eb4e58509e4c", body: nil, order: 4, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "23b70937-ed81-47fe-a560-ee14287bff7d", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "23b70937-ed81-47fe-a560-ee14287bff7d", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:46:13Z], updated_at: ~U[2024-10-12 09:46:13Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "c7ad47e6-629d-4382-936d-64d757772c4e", body: nil, order: 3, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "d5758230-7966-4f9b-8c16-ae13998cd71b", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "d5758230-7966-4f9b-8c16-ae13998cd71b", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "fc80709a-39dc-4b9c-95c3-1d64ce818302", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:44:09Z], updated_at: ~U[2024-10-12 09:44:09Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "02218551-591f-4450-abbd-a7b7d76fd48e", body: "testing", order: 2, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "19ffdc82-a5d8-49c3-8b01-1559736dad80", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "19ffdc82-a5d8-49c3-8b01-1559736dad80", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "fc80709a-39dc-4b9c-95c3-1d64ce818302", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:43:19Z], updated_at: ~U[2024-10-12 09:43:19Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "90c6036a-9bd1-4b65-82d5-f121ec4d7867", body: nil, order: 2, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "b92f990d-99a2-4f04-a2d4-d1135021ee8c", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "b92f990d-99a2-4f04-a2d4-d1135021ee8c", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-11 09:03:00Z], updated_at: ~U[2024-10-11 09:03:00Z] } ], inserted_at: ~N[2024-09-27 00:51:48], updated_at: ~N[2024-09-27 00:51:48] } [debug] Replied in 81ms [debug] HANDLE EVENT "verses::focus_toggle_on_quick_mark_drafting" in VyasaWeb.ModeLive.Mediator Component: VyasaWeb.Context.Read Parameters: %{"is_focusing?" => false, "value" => ""} [debug] Replied in 129µs iex([email protected])17> * marks order force * old man mark is not feeling so good * ReWrite how marks get initialised @ :show_verse (#119) * Minor change in fn signature * Add init_draft_reflector() * Don't rely on the time async message passing * Use custom generic_modal_wrapper This one has more specific callback attributes and tailwind classes can be injected to it. * Create data and ui skeletons for sheaf_creator * Add support for human friendly time formatting * Setup skeleton for replyto context Some pending todo functions for how the reply to context shall be determined * Standardise UI, improve wrapper's default UI * Improve generic_modal_wrapper styling slots * Wire sheaf creation form to stubbed event handler Relevant TODOs have been added * Use session.name for signature, add handler stubs * Edit marks in read mode (#118) * Add generic debug dump component This makes life easy when wiring things up * Rename namespace for Context.Read.* * Groundwork: add discuss component w sheafs * Init Context.Components mod for common components * Add skeletons for Sheaf Container Container managers sheaf state within itself. Should actually make the verse-matrix use this container, sometime. * Minor changes, add some TODOs to share explicit todos Minor change * Add live component EditableMarkDisplay * Add UI improvements to EditableMarkDisplay The edit button on quick draft should only be seen when the dropdown is expanded and all the marks can be seen. The general pattern I'm trying to follow is that buttons should only be shown when an action makes sense. So here, if the user can't even see the marks currently accumulating, then the user shouldn't have the chance to edit any marks. Notice that the EditableMarkDisplay is a live_component that is a child of a function component (collapsible_marks_display). This is so that it can keep its own state and do it's own event-handling. I'm not sure if this is pattern-breaking. A reference to the actual parent live_component that calls collapsible_marks_display will always be there in case there's a need for the parent to handle any particular events. So comms b/w live_components is still going to be via phx-target values. * Change <input/> -> <textarea/> fr quick_draft_form * Add tailwind config for custom svg icons not sure how the scaling for this works, seems like i can't just put in the class="h-5 w-5" to do the scaling * Let custom svg be scalable * Subtly shift the ping indicator to control panel * Marks ordering in Sheaf and L-Trees (#114) * do sheafs grow on trees * sangh session dealing with lineage * Solve initial order problem * fix: ensure non-null id used @ EditableMarkDisplay --------- Co-authored-by: ks0m1c_dharma <[email protected]> * Trigger Diff * TOMBSTONING * Fix bugs and revert ui for read_mode:delete marks 1. JIT generate id for marks yet to be inserted to the db: instead of using a temp id, I'm actually assigning a JIT-generated id for a mark even if that isn't inserted into the db yet. this has two benefits: div ids have meaningful static ids (e.g. mark-container-\<\> mark.id) regardless of whether that mark has been inserted into the db or not. While doing this, the changeset for marks has been udpated to add id as well. This fixes a bunch of id-based errors as well. 2. while doing 1, it came to light that the bindHoverune handlers were not handling the draft mark update properly (i.e. not using the already existing update function in mark) . it's changed now, example of the diff: ``` diff @impl true def handle_event( "bindHoveRune", %{"binding" => bind = %{"verse_id" => verse_id}}, %{ assigns: %{ kv_verses: verses, marks: [%Mark{state: :draft, verse_id: curr_verse_id} = d_mark | marks] } } = socket ) when is_binary(curr_verse_id) and verse_id != curr_verse_id do # binding here blocks the stream from appending to quote bind = Draft.bind_node(bind) bound_verses = verses |> then(&put_in(&1[verse_id].binding, bind)) |> then(&put_in(&1[curr_verse_id].binding, nil)) + updated_draft_mark = d_mark |> Mark.update_mark(%{binding: bind, verse_id: verse_id}) + {:noreply, socket |> mutate_verses(curr_verse_id, bound_verses) |> mutate_verses(verse_id, bound_verses) - |> assign(:marks, [%{d_mark | binding: bind, verse_id: verse_id} | marks])} + |> assign(:marks, [updated_draft_mark | marks])} end ``` 3. add ui state structs: all of the relevant ui states have structs that are intended to be static interfaces. this felt better than directly keeping state within various sockets and is done with a view to remove live components and change them to function components wherever possible. 4. bugfix for `order()`: - it had an off-by-one-error - shifted it to Vyasa.Sangh.Mark - also note that the order shall be 1-indexed instead of 0-indexed for human-friendliness 5. minor fixes: 1. fix update<sub>mark</sub> default argument ``` diff -def update_mark(%Mark{} = draft_mark, opts \\ []) do +def update_mark(%Mark{} = draft_mark, opts \\ %{}) do ``` 1. In this commit, the marks<sub>ui</sub> is NOT kept by the read context module, that's why when I update things by create mark or delete mark, the ui state is not preserved and initial, default state is seen. This was intentionally done in this commit because I'm having problems with duplicate ids for verses for some reason, I'll show it in the next commit, so that the problem can be clearly seen. * [BUGGY] keep marks_ui within ReadContext This is buggy, not sure why there's a duplicate yet. will come back to it after lunch Replication Steps: 1. delete all marks and see there's no error 2. create first mark ==> no error 3. create second mark ==> crashes due to duplicate verse id Crash dump: [debug] Replied in 13ms [error] GenServer #PID<0.8416.0> terminating ** (RuntimeError) found duplicate ID "verse-7d9d588a-34fc-4f19-b974-fc32b49b6a61" for component VyasaWeb.Context.Read.VerseMatrix when rendering template (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:634: anonymous fn/5 in Phoenix.LiveView.Diff.render_pending_components/6 (elixir 1.17.2) lib/enum.ex:2531: Enum."-reduce/3-lists^foldl/2-0-"/3 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:631: anonymous fn/4 in Phoenix.LiveView.Diff.render_pending_components/6 (stdlib 5.2.3) maps.erl:416: :maps.fold_1/4 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:625: Phoenix.LiveView.Diff.render_pending_components/6 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:217: Phoenix.LiveView.Diff.write_component/4 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/channel.ex:662: Phoenix.LiveView.Channel.component_handle/4 (stdlib 5.2.3) gen_server.erl:1095: :gen_server.try_handle_info/3 (stdlib 5.2.3) gen_server.erl:1183: :gen_server.handle_msg/6 (stdlib 5.2.3) proc_lib.erl:251: :proc_lib.wake_up/3 Last message: %Phoenix.Socket.Message{topic: "lv:phx-F_1MH_6F0ciqVqwi", event: "event", payload: %{"cid" => 3, "event" => "createMark", "type" => "form", "value" => "body=how+about+now%2C+any+duplicate%3F"}, ref: "23", join_ref: "4"} State: %{socket: #Phoenix.LiveView.Socket<id: "phx-F_1MH_6F0ciqVqwi", endpoint: VyasaWeb.Endpoint, view: VyasaWeb.ModeLive.Mediator, parent_pid: nil, root_pid: #PID<0.8416.0>, router: VyasaWeb.Router, assigns: %{mode: %VyasaWeb.ModeLive.UserMode{mode: "read", default_ui_state: %VyasaWeb.ModeLive.UiState{show_media_bridge?: true, show_action_bar?: true}, mode_icon_name: "hero-book-open", quick_actions: [:mark_quote, :bookmark], control_panel_modes: ["discuss"], mode_actions: [:mark_quote, :bookmark], action_bar_actions: [:nav_back, :nav_fwd], action_bar_info_types: nil, action_bar_component: VyasaWeb.MediaLive.MediaBridge, action_bar_component_selector: "media-bridge", control_panel_component: VyasaWeb.ControlPanel, control_panel_component_selector: "control-panel", mode_context_component: VyasaWeb.Context.Read, mode_context_component_selector: "read"}, session: %VyasaWeb.Session{name: "ritesh kumar", id: "IhrQV0ypqg8bHakbvb2bymNF", active: true, sangh: %Vyasa.Sangh.Session{__meta__: #Ecto.Schema.Metadata<:loaded, "sessions">, id: "164eb05d-221a-4939-b180-8394e1a5515f", sheafs: #Ecto.Association.NotLoaded<association :sheafs is not loaded>, inserted_at: ~U[2024-09-27 00:51:48Z], updated_at: ~U[2024-09-27 00:51:48Z]}, last_opened: "2024-09-23T11:03:32.022987Z"}, __changed__: %{}, flash: %{}, locale: "en-GB", url_params: %{"chap_no" => "1", "source_title" => "hanuman_chalisa"}, live_action: :show_verses, ui_state: %VyasaWeb.ModeLive.UiState{show_media_bridge?: true, show_action_bar?: true}, device_type: :desktop, tz: %{timezone: "Asia/Singapore", timezone_offset: 480}}, transport_pid: #PID<0.8403.0>, ...>, components: {%{15 => {VyasaWeb.Context.Read.VerseMatrix, "verse-aa3ad88b-0de1-443e-b471-c08a44e67c61", %{id: "verse-aa3ad88b-0de1-443e-b471-c08a44e67c61", edge: [%{title: "1.10", field: [:body], verseup: {:big, "dn"}}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body_translit], verseup: :mid}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body_translit_meant], verseup: :mid}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body], verseup: :mid}], __changed__: %{}, flash: %{}, marks: [%Vyasa.Sangh.Mark{__meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "5dfdb167-6c57-46dd-a0c4-10b52cb03a85", body: "wonderful", order: 2, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "001da594-3808-46cf-9b9c-5dfb3559780e", binding: %Vyasa.Adapters.Binding{__meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "001da594-3808-46cf-9b9c-5dfb3559780e", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil}, inserted_at: ~U[2024-10-11 04:31:50Z], updated_at: ~U[2024-10-11 04:31:50Z]}, %Vyasa.Sangh.Mark{__meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "273a093d-4f90-40a4-b19a-2f8f7825d201", body: "truncated utc datetime", order: 1, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "ef39315b-530c-4841-ba32-86773f451727", binding: %Vyasa.Adapt (truncated) [debug] MOUNT VyasaWeb.ModeLive.Mediator Parameters: %{"chap_no" => "1", "source_title" => "hanuman_chalisa"} Session: %{"_csrf_token" => "DJ-RIoXwEzHW82rbb21le_8k"} [debug] QUERY OK source="sessions" db=3.5ms idle=1690.4ms SELECT s0."id", s0."inserted_at", s0."updated_at" FROM "sessions" AS s0 WHERE (s0."id" = $1) ["164eb05d-221a-4939-b180-8394e1a5515f"] ↳ * Fix duplicate id issue on verse matrix * Standardise use of @event_target, cleanups When using @event_target, the intent is that phx-target values will be passed around. This must be agnostic to the 2 main ways of supplying that argument, as a HTML selector, or as a module name (or @myself). Therefore, we should discourage ourselves from doing format-strings at the point of the @event_target being supplied as an argument, meaning: good, because agnostic: phx-target={@event_target} bad, because hardcoded: phx-target={"#" <> @event_target} * in this case, the event trigger will throw a dom error. * [Attempt]: Sanitise, defrag orders in marks-list If this is an anti-pattern, then this commit should be reverted. * UI fixes: hide buttons on marks when !is_editable? * Add in stub event handlers to prevent crashes Temporary stuff, will be addressed in immediate-next PR * Minor changes * Toggle edit state for marks content * Partial implementation of edit marks the form stuff doesn't exist so it's not wired up yet. To be frank, im' not sure how to set up a form without it needing to hold state. * [BUGGY] Wire up form update for edit this does the following: 1. wires up the form like how we usedd it in createMark 2. actually captures the event properly within the event handler, everything looks good at that point, even the edit_mark_in_marks function on inspection looks good 3. the marks is getting assigned to properly because the newly edited mark content is seen after doing a dom refresh 4. HOWEVER, the print statement at the sheaf_update function DOES NOT show the correct, updated marks in the sheaf here's a dump for it for reference [debug] HANDLE EVENT "editMarkContent" in VyasaWeb.ModeLive.Mediator Component: VyasaWeb.Context.Read Parameters: %{"mark_id" => "02218551-591f-4450-abbd-a7b7d76fd48e"} [debug] Replied in 2ms [debug] HANDLE EVENT "editMarkContent" in VyasaWeb.ModeLive.Mediator Component: VyasaWeb.Context.Read Parameters: %{"mark_body" => " testing\n\n\nwhat hte heck", "mark_id" => "02218551-591f-4450-abbd-a7b7d76fd48e"} >>> UPDATE SHEAF -- SHOULD BE WRITING TO DB NOW: %Vyasa.Sangh.Sheaf{ __meta__: #Ecto.Schema.Metadata<:loaded, "sheafs">, id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", body: nil, active: true, path: %EctoLtree.LabelTree{labels: ["7f4ab16b"]}, signature: nil, traits: ["draft"], child_count: 0, session_id: "164eb05d-221a-4939-b180-8394e1a5515f", session: #Ecto.Association.NotLoaded<association :session is not loaded>, parent_id: nil, parent: #Ecto.Association.NotLoaded<association :parent is not loaded>, marks: [ %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "555eb625-e392-496e-9831-4f4c130be6fd", body: "wonderful stuff", order: 5, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "072124d0-5e27-4601-832f-35eaa6426879", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "072124d0-5e27-4601-832f-35eaa6426879", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 08:46:54Z], updated_at: ~U[2024-10-12 08:46:54Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "b22a5661-8268-4875-be26-a12256414136", body: nil, order: 5, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "90e18044-73b2-4ede-a149-a381de893b9f", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "90e18044-73b2-4ede-a149-a381de893b9f", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "fc80709a-39dc-4b9c-95c3-1d64ce818302", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:52:40Z], updated_at: ~U[2024-10-12 09:52:40Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "8af43833-575c-4eb8-83b1-eb4e58509e4c", body: nil, order: 4, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "23b70937-ed81-47fe-a560-ee14287bff7d", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "23b70937-ed81-47fe-a560-ee14287bff7d", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:46:13Z], updated_at: ~U[2024-10-12 09:46:13Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "c7ad47e6-629d-4382-936d-64d757772c4e", body: nil, order: 3, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "d5758230-7966-4f9b-8c16-ae13998cd71b", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "d5758230-7966-4f9b-8c16-ae13998cd71b", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "fc80709a-39dc-4b9c-95c3-1d64ce818302", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:44:09Z], updated_at: ~U[2024-10-12 09:44:09Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "02218551-591f-4450-abbd-a7b7d76fd48e", body: "testing", order: 2, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "19ffdc82-a5d8-49c3-8b01-1559736dad80", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "19ffdc82-a5d8-49c3-8b01-1559736dad80", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "fc80709a-39dc-4b9c-95c3-1d64ce818302", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:43:19Z], updated_at: ~U[2024-10-12 09:43:19Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "90c6036a-9bd1-4b65-82d5-f121ec4d7867", body: nil, order: 2, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "b92f990d-99a2-4f04-a2d4-d1135021ee8c", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "b92f990d-99a2-4f04-a2d4-d1135021ee8c", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-11 09:03:00Z], updated_at: ~U[2024-10-11 09:03:00Z] } ], inserted_at: ~N[2024-09-27 00:51:48], updated_at: ~N[2024-09-27 00:51:48] } [debug] Replied in 81ms [debug] HANDLE EVENT "verses::focus_toggle_on_quick_mark_drafting" in VyasaWeb.ModeLive.Mediator Component: VyasaWeb.Context.Read Parameters: %{"is_focusing?" => false, "value" => ""} [debug] Replied in 129µs iex([email protected])17> * marks order force * old man mark is not feeling so good * ReWrite how marks get initialised @ :show_verse (#119) * Minor change in fn signature * Add init_draft_reflector() --------- Co-authored-by: ks0m1c_dharma <[email protected]> * Minor changes * Add a generic modal wrapper (#120) * Add generic debug dump component This makes life easy when wiring things up * Rename namespace for Context.Read.* * Groundwork: add discuss component w sheafs * Init Context.Components mod for common components * Add skeletons for Sheaf Container Container managers sheaf state within itself. Should actually make the verse-matrix use this container, sometime. * Minor changes, add some TODOs to share explicit todos Minor change * Add live component EditableMarkDisplay * Add UI improvements to EditableMarkDisplay The edit button on quick draft should only be seen when the dropdown is expanded and all the marks can be seen. The general pattern I'm trying to follow is that buttons should only be shown when an action makes sense. So here, if the user can't even see the marks currently accumulating, then the user shouldn't have the chance to edit any marks. Notice that the EditableMarkDisplay is a live_component that is a child of a function component (collapsible_marks_display). This is so that it can keep its own state and do it's own event-handling. I'm not sure if this is pattern-breaking. A reference to the actual parent live_component that calls collapsible_marks_display will always be there in case there's a need for the parent to handle any particular events. So comms b/w live_components is still going to be via phx-target values. * Change <input/> -> <textarea/> fr quick_draft_form * Add tailwind config for custom svg icons not sure how the scaling for this works, seems like i can't just put in the class="h-5 w-5" to do the scaling * Let custom svg be scalable * Subtly shift the ping indicator to control panel * Marks ordering in Sheaf and L-Trees (#114) * do sheafs grow on trees * sangh session dealing with lineage * Solve initial order problem * fix: ensure non-null id used @ EditableMarkDisplay --------- Co-authored-by: ks0m1c_dharma <[email protected]> * Trigger Diff * TOMBSTONING * Fix bugs and revert ui for read_mode:delete marks 1. JIT generate id for marks yet to be inserted to the db: instead of using a temp id, I'm actually assigning a JIT-generated id for a mark even if that isn't inserted into the db yet. this has two benefits: div ids have meaningful static ids (e.g. mark-container-\<\> mark.id) regardless of whether that mark has been inserted into the db or not. While doing this, the changeset for marks has been udpated to add id as well. This fixes a bunch of id-based errors as well. 2. while doing 1, it came to light that the bindHoverune handlers were not handling the draft mark update properly (i.e. not using the already existing update function in mark) . it's changed now, example of the diff: ``` diff @impl true def handle_event( "bindHoveRune", %{"binding" => bind = %{"verse_id" => verse_id}}, %{ assigns: %{ kv_verses: verses, marks: [%Mark{state: :draft, verse_id: curr_verse_id} = d_mark | marks] } } = socket ) when is_binary(curr_verse_id) and verse_id != curr_verse_id do # binding here blocks the stream from appending to quote bind = Draft.bind_node(bind) bound_verses = verses |> then(&put_in(&1[verse_id].binding, bind)) |> then(&put_in(&1[curr_verse_id].binding, nil)) + updated_draft_mark = d_mark |> Mark.update_mark(%{binding: bind, verse_id: verse_id}) + {:noreply, socket |> mutate_verses(curr_verse_id, bound_verses) |> mutate_verses(verse_id, bound_verses) - |> assign(:marks, [%{d_mark | binding: bind, verse_id: verse_id} | marks])} + |> assign(:marks, [updated_draft_mark | marks])} end ``` 3. add ui state structs: all of the relevant ui states have structs that are intended to be static interfaces. this felt better than directly keeping state within various sockets and is done with a view to remove live components and change them to function components wherever possible. 4. bugfix for `order()`: - it had an off-by-one-error - shifted it to Vyasa.Sangh.Mark - also note that the order shall be 1-indexed instead of 0-indexed for human-friendliness 5. minor fixes: 1. fix update<sub>mark</sub> default argument ``` diff -def update_mark(%Mark{} = draft_mark, opts \\ []) do +def update_mark(%Mark{} = draft_mark, opts \\ %{}) do ``` 1. In this commit, the marks<sub>ui</sub> is NOT kept by the read context module, that's why when I update things by create mark or delete mark, the ui state is not preserved and initial, default state is seen. This was intentionally done in this commit because I'm having problems with duplicate ids for verses for some reason, I'll show it in the next commit, so that the problem can be clearly seen. * [BUGGY] keep marks_ui within ReadContext This is buggy, not sure why there's a duplicate yet. will come back to it after lunch Replication Steps: 1. delete all marks and see there's no error 2. create first mark ==> no error 3. create second mark ==> crashes due to duplicate verse id Crash dump: [debug] Replied in 13ms [error] GenServer #PID<0.8416.0> terminating ** (RuntimeError) found duplicate ID "verse-7d9d588a-34fc-4f19-b974-fc32b49b6a61" for component VyasaWeb.Context.Read.VerseMatrix when rendering template (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:634: anonymous fn/5 in Phoenix.LiveView.Diff.render_pending_components/6 (elixir 1.17.2) lib/enum.ex:2531: Enum."-reduce/3-lists^foldl/2-0-"/3 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:631: anonymous fn/4 in Phoenix.LiveView.Diff.render_pending_components/6 (stdlib 5.2.3) maps.erl:416: :maps.fold_1/4 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:625: Phoenix.LiveView.Diff.render_pending_components/6 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:217: Phoenix.LiveView.Diff.write_component/4 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/channel.ex:662: Phoenix.LiveView.Channel.component_handle/4 (stdlib 5.2.3) gen_server.erl:1095: :gen_server.try_handle_info/3 (stdlib 5.2.3) gen_server.erl:1183: :gen_server.handle_msg/6 (stdlib 5.2.3) proc_lib.erl:251: :proc_lib.wake_up/3 Last message: %Phoenix.Socket.Message{topic: "lv:phx-F_1MH_6F0ciqVqwi", event: "event", payload: %{"cid" => 3, "event" => "createMark", "type" => "form", "value" => "body=how+about+now%2C+any+duplicate%3F"}, ref: "23", join_ref: "4"} State: %{socket: #Phoenix.LiveView.Socket<id: "phx-F_1MH_6F0ciqVqwi", endpoint: VyasaWeb.Endpoint, view: VyasaWeb.ModeLive.Mediator, parent_pid: nil, root_pid: #PID<0.8416.0>, router: VyasaWeb.Router, assigns: %{mode: %VyasaWeb.ModeLive.UserMode{mode: "read", default_ui_state: %VyasaWeb.ModeLive.UiState{show_media_bridge?: true, show_action_bar?: true}, mode_icon_name: "hero-book-open", quick_actions: [:mark_quote, :bookmark], control_panel_modes: ["discuss"], mode_actions: [:mark_quote, :bookmark], action_bar_actions: [:nav_back, :nav_fwd], action_bar_info_types: nil, action_bar_component: VyasaWeb.MediaLive.MediaBridge, action_bar_component_selector: "media-bridge", control_panel_component: VyasaWeb.ControlPanel, control_panel_component_selector: "control-panel", mode_context_component: VyasaWeb.Context.Read, mode_context_component_selector: "read"}, session: %VyasaWeb.Session{name: "ritesh kumar", id: "IhrQV0ypqg8bHakbvb2bymNF", active: true, sangh: %Vyasa.Sangh.Session{__meta__: #Ecto.Schema.Metadata<:loaded, "sessions">, id: "164eb05d-221a-4939-b180-8394e1a5515f", sheafs: #Ecto.Association.NotLoaded<association :sheafs is not loaded>, inserted_at: ~U[2024-09-27 00:51:48Z], updated_at: ~U[2024-09-27 00:51:48Z]}, last_opened: "2024-09-23T11:03:32.022987Z"}, __changed__: %{}, flash: %{}, locale: "en-GB", url_params: %{"chap_no" => "1", "source_title" => "hanuman_chalisa"}, live_action: :show_verses, ui_state: %VyasaWeb.ModeLive.UiState{show_media_bridge?: true, show_action_bar?: true}, device_type: :desktop, tz: %{timezone: "Asia/Singapore", timezone_offset: 480}}, transport_pid: #PID<0.8403.0>, ...>, components: {%{15 => {VyasaWeb.Context.Read.VerseMatrix, "verse-aa3ad88b-0de1-443e-b471-c08a44e67c61", %{id: "verse-aa3ad88b-0de1-443e-b471-c08a44e67c61", edge: [%{title: "1.10", field: [:body], verseup: {:big, "dn"}}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body_translit], verseup: :mid}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body_translit_meant], verseup: :mid}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body], verseup: :mid}], __changed__: %{}, flash: %{}, marks: [%Vyasa.Sangh.Mark{__meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "5dfdb167-6c57-46dd-a0c4-10b52cb03a85", body: "wonderful", order: 2, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "001da594-3808-46cf-9b9c-5dfb3559780e", binding: %Vyasa.Adapters.Binding{__meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "001da594-3808-46cf-9b9c-5dfb3559780e", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil}, inserted_at: ~U[2024-10-11 04:31:50Z], updated_at: ~U[2024-10-11 04:31:50Z]}, %Vyasa.Sangh.Mark{__meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "273a093d-4f90-40a4-b19a-2f8f7825d201", body: "truncated utc datetime", order: 1, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "ef39315b-530c-4841-ba32-86773f451727", binding: %Vyasa.Adapt (truncated) [debug] MOUNT VyasaWeb.ModeLive.Mediator Parameters: %{"chap_no" => "1", "source_title" => "hanuman_chalisa"} Session: %{"_csrf_token" => "DJ-RIoXwEzHW82rbb21le_8k"} [debug] QUERY OK source="sessions" db=3.5ms idle=1690.4ms SELECT s0."id", s0."inserted_at", s0."updated_at" FROM "sessions" AS s0 WHERE (s0."id" = $1) ["164eb05d-221a-4939-b180-8394e1a5515f"] ↳ * Fix duplicate id issue on verse matrix * Standardise use of @event_target, cleanups When using @event_target, the intent is that phx-target values will be passed around. This must be agnostic to the 2 main ways of supplying that argument, as a HTML selector, or as a module name (or @myself). Therefore, we should discourage ourselves from doing format-strings at the point of the @event_target being supplied as an argument, meaning: good, because agnostic: phx-target={@event_target} bad, because hardcoded: phx-target={"#" <> @event_target} * in this case, the event trigger will t…
* Add generic debug dump component This makes life easy when wiring things up * Rename namespace for Context.Read.* * Groundwork: add discuss component w sheafs * Init Context.Components mod for common components * Add skeletons for Sheaf Container Container managers sheaf state within itself. Should actually make the verse-matrix use this container, sometime. * Minor changes, add some TODOs to share explicit todos Minor change * Add live component EditableMarkDisplay * Add UI improvements to EditableMarkDisplay The edit button on quick draft should only be seen when the dropdown is expanded and all the marks can be seen. The general pattern I'm trying to follow is that buttons should only be shown when an action makes sense. So here, if the user can't even see the marks currently accumulating, then the user shouldn't have the chance to edit any marks. Notice that the EditableMarkDisplay is a live_component that is a child of a function component (collapsible_marks_display). This is so that it can keep its own state and do it's own event-handling. I'm not sure if this is pattern-breaking. A reference to the actual parent live_component that calls collapsible_marks_display will always be there in case there's a need for the parent to handle any particular events. So comms b/w live_components is still going to be via phx-target values. * Change <input/> -> <textarea/> fr quick_draft_form * Add tailwind config for custom svg icons not sure how the scaling for this works, seems like i can't just put in the class="h-5 w-5" to do the scaling * Let custom svg be scalable * Subtly shift the ping indicator to control panel * Marks ordering in Sheaf and L-Trees (#114) * do sheafs grow on trees * sangh session dealing with lineage * Solve initial order problem * fix: ensure non-null id used @ EditableMarkDisplay --------- Co-authored-by: ks0m1c_dharma <[email protected]> * Trigger Diff * TOMBSTONING * Fix bugs and revert ui for read_mode:delete marks 1. JIT generate id for marks yet to be inserted to the db: instead of using a temp id, I'm actually assigning a JIT-generated id for a mark even if that isn't inserted into the db yet. this has two benefits: div ids have meaningful static ids (e.g. mark-container-\<\> mark.id) regardless of whether that mark has been inserted into the db or not. While doing this, the changeset for marks has been udpated to add id as well. This fixes a bunch of id-based errors as well. 2. while doing 1, it came to light that the bindHoverune handlers were not handling the draft mark update properly (i.e. not using the already existing update function in mark) . it's changed now, example of the diff: ``` diff @impl true def handle_event( "bindHoveRune", %{"binding" => bind = %{"verse_id" => verse_id}}, %{ assigns: %{ kv_verses: verses, marks: [%Mark{state: :draft, verse_id: curr_verse_id} = d_mark | marks] } } = socket ) when is_binary(curr_verse_id) and verse_id != curr_verse_id do # binding here blocks the stream from appending to quote bind = Draft.bind_node(bind) bound_verses = verses |> then(&put_in(&1[verse_id].binding, bind)) |> then(&put_in(&1[curr_verse_id].binding, nil)) + updated_draft_mark = d_mark |> Mark.update_mark(%{binding: bind, verse_id: verse_id}) + {:noreply, socket |> mutate_verses(curr_verse_id, bound_verses) |> mutate_verses(verse_id, bound_verses) - |> assign(:marks, [%{d_mark | binding: bind, verse_id: verse_id} | marks])} + |> assign(:marks, [updated_draft_mark | marks])} end ``` 3. add ui state structs: all of the relevant ui states have structs that are intended to be static interfaces. this felt better than directly keeping state within various sockets and is done with a view to remove live components and change them to function components wherever possible. 4. bugfix for `order()`: - it had an off-by-one-error - shifted it to Vyasa.Sangh.Mark - also note that the order shall be 1-indexed instead of 0-indexed for human-friendliness 5. minor fixes: 1. fix update<sub>mark</sub> default argument ``` diff -def update_mark(%Mark{} = draft_mark, opts \\ []) do +def update_mark(%Mark{} = draft_mark, opts \\ %{}) do ``` 1. In this commit, the marks<sub>ui</sub> is NOT kept by the read context module, that's why when I update things by create mark or delete mark, the ui state is not preserved and initial, default state is seen. This was intentionally done in this commit because I'm having problems with duplicate ids for verses for some reason, I'll show it in the next commit, so that the problem can be clearly seen. * [BUGGY] keep marks_ui within ReadContext This is buggy, not sure why there's a duplicate yet. will come back to it after lunch Replication Steps: 1. delete all marks and see there's no error 2. create first mark ==> no error 3. create second mark ==> crashes due to duplicate verse id Crash dump: [debug] Replied in 13ms [error] GenServer #PID<0.8416.0> terminating ** (RuntimeError) found duplicate ID "verse-7d9d588a-34fc-4f19-b974-fc32b49b6a61" for component VyasaWeb.Context.Read.VerseMatrix when rendering template (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:634: anonymous fn/5 in Phoenix.LiveView.Diff.render_pending_components/6 (elixir 1.17.2) lib/enum.ex:2531: Enum."-reduce/3-lists^foldl/2-0-"/3 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:631: anonymous fn/4 in Phoenix.LiveView.Diff.render_pending_components/6 (stdlib 5.2.3) maps.erl:416: :maps.fold_1/4 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:625: Phoenix.LiveView.Diff.render_pending_components/6 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:217: Phoenix.LiveView.Diff.write_component/4 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/channel.ex:662: Phoenix.LiveView.Channel.component_handle/4 (stdlib 5.2.3) gen_server.erl:1095: :gen_server.try_handle_info/3 (stdlib 5.2.3) gen_server.erl:1183: :gen_server.handle_msg/6 (stdlib 5.2.3) proc_lib.erl:251: :proc_lib.wake_up/3 Last message: %Phoenix.Socket.Message{topic: "lv:phx-F_1MH_6F0ciqVqwi", event: "event", payload: %{"cid" => 3, "event" => "createMark", "type" => "form", "value" => "body=how+about+now%2C+any+duplicate%3F"}, ref: "23", join_ref: "4"} State: %{socket: #Phoenix.LiveView.Socket<id: "phx-F_1MH_6F0ciqVqwi", endpoint: VyasaWeb.Endpoint, view: VyasaWeb.ModeLive.Mediator, parent_pid: nil, root_pid: #PID<0.8416.0>, router: VyasaWeb.Router, assigns: %{mode: %VyasaWeb.ModeLive.UserMode{mode: "read", default_ui_state: %VyasaWeb.ModeLive.UiState{show_media_bridge?: true, show_action_bar?: true}, mode_icon_name: "hero-book-open", quick_actions: [:mark_quote, :bookmark], control_panel_modes: ["discuss"], mode_actions: [:mark_quote, :bookmark], action_bar_actions: [:nav_back, :nav_fwd], action_bar_info_types: nil, action_bar_component: VyasaWeb.MediaLive.MediaBridge, action_bar_component_selector: "media-bridge", control_panel_component: VyasaWeb.ControlPanel, control_panel_component_selector: "control-panel", mode_context_component: VyasaWeb.Context.Read, mode_context_component_selector: "read"}, session: %VyasaWeb.Session{name: "ritesh kumar", id: "IhrQV0ypqg8bHakbvb2bymNF", active: true, sangh: %Vyasa.Sangh.Session{__meta__: #Ecto.Schema.Metadata<:loaded, "sessions">, id: "164eb05d-221a-4939-b180-8394e1a5515f", sheafs: #Ecto.Association.NotLoaded<association :sheafs is not loaded>, inserted_at: ~U[2024-09-27 00:51:48Z], updated_at: ~U[2024-09-27 00:51:48Z]}, last_opened: "2024-09-23T11:03:32.022987Z"}, __changed__: %{}, flash: %{}, locale: "en-GB", url_params: %{"chap_no" => "1", "source_title" => "hanuman_chalisa"}, live_action: :show_verses, ui_state: %VyasaWeb.ModeLive.UiState{show_media_bridge?: true, show_action_bar?: true}, device_type: :desktop, tz: %{timezone: "Asia/Singapore", timezone_offset: 480}}, transport_pid: #PID<0.8403.0>, ...>, components: {%{15 => {VyasaWeb.Context.Read.VerseMatrix, "verse-aa3ad88b-0de1-443e-b471-c08a44e67c61", %{id: "verse-aa3ad88b-0de1-443e-b471-c08a44e67c61", edge: [%{title: "1.10", field: [:body], verseup: {:big, "dn"}}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body_translit], verseup: :mid}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body_translit_meant], verseup: :mid}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body], verseup: :mid}], __changed__: %{}, flash: %{}, marks: [%Vyasa.Sangh.Mark{__meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "5dfdb167-6c57-46dd-a0c4-10b52cb03a85", body: "wonderful", order: 2, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "001da594-3808-46cf-9b9c-5dfb3559780e", binding: %Vyasa.Adapters.Binding{__meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "001da594-3808-46cf-9b9c-5dfb3559780e", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil}, inserted_at: ~U[2024-10-11 04:31:50Z], updated_at: ~U[2024-10-11 04:31:50Z]}, %Vyasa.Sangh.Mark{__meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "273a093d-4f90-40a4-b19a-2f8f7825d201", body: "truncated utc datetime", order: 1, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "ef39315b-530c-4841-ba32-86773f451727", binding: %Vyasa.Adapt (truncated) [debug] MOUNT VyasaWeb.ModeLive.Mediator Parameters: %{"chap_no" => "1", "source_title" => "hanuman_chalisa"} Session: %{"_csrf_token" => "DJ-RIoXwEzHW82rbb21le_8k"} [debug] QUERY OK source="sessions" db=3.5ms idle=1690.4ms SELECT s0."id", s0."inserted_at", s0."updated_at" FROM "sessions" AS s0 WHERE (s0."id" = $1) ["164eb05d-221a-4939-b180-8394e1a5515f"] ↳ * Fix duplicate id issue on verse matrix * Standardise use of @event_target, cleanups When using @event_target, the intent is that phx-target values will be passed around. This must be agnostic to the 2 main ways of supplying that argument, as a HTML selector, or as a module name (or @myself). Therefore, we should discourage ourselves from doing format-strings at the point of the @event_target being supplied as an argument, meaning: good, because agnostic: phx-target={@event_target} bad, because hardcoded: phx-target={"#" <> @event_target} * in this case, the event trigger will throw a dom error. * [Attempt]: Sanitise, defrag orders in marks-list If this is an anti-pattern, then this commit should be reverted. * UI fixes: hide buttons on marks when !is_editable? * Add in stub event handlers to prevent crashes Temporary stuff, will be addressed in immediate-next PR * Minor changes * Toggle edit state for marks content * Partial implementation of edit marks the form stuff doesn't exist so it's not wired up yet. To be frank, im' not sure how to set up a form without it needing to hold state. * [BUGGY] Wire up form update for edit this does the following: 1. wires up the form like how we usedd it in createMark 2. actually captures the event properly within the event handler, everything looks good at that point, even the edit_mark_in_marks function on inspection looks good 3. the marks is getting assigned to properly because the newly edited mark content is seen after doing a dom refresh 4. HOWEVER, the print statement at the sheaf_update function DOES NOT show the correct, updated marks in the sheaf here's a dump for it for reference [debug] HANDLE EVENT "editMarkContent" in VyasaWeb.ModeLive.Mediator Component: VyasaWeb.Context.Read Parameters: %{"mark_id" => "02218551-591f-4450-abbd-a7b7d76fd48e"} [debug] Replied in 2ms [debug] HANDLE EVENT "editMarkContent" in VyasaWeb.ModeLive.Mediator Component: VyasaWeb.Context.Read Parameters: %{"mark_body" => " testing\n\n\nwhat hte heck", "mark_id" => "02218551-591f-4450-abbd-a7b7d76fd48e"} >>> UPDATE SHEAF -- SHOULD BE WRITING TO DB NOW: %Vyasa.Sangh.Sheaf{ __meta__: #Ecto.Schema.Metadata<:loaded, "sheafs">, id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", body: nil, active: true, path: %EctoLtree.LabelTree{labels: ["7f4ab16b"]}, signature: nil, traits: ["draft"], child_count: 0, session_id: "164eb05d-221a-4939-b180-8394e1a5515f", session: #Ecto.Association.NotLoaded<association :session is not loaded>, parent_id: nil, parent: #Ecto.Association.NotLoaded<association :parent is not loaded>, marks: [ %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "555eb625-e392-496e-9831-4f4c130be6fd", body: "wonderful stuff", order: 5, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "072124d0-5e27-4601-832f-35eaa6426879", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "072124d0-5e27-4601-832f-35eaa6426879", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 08:46:54Z], updated_at: ~U[2024-10-12 08:46:54Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "b22a5661-8268-4875-be26-a12256414136", body: nil, order: 5, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "90e18044-73b2-4ede-a149-a381de893b9f", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "90e18044-73b2-4ede-a149-a381de893b9f", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "fc80709a-39dc-4b9c-95c3-1d64ce818302", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:52:40Z], updated_at: ~U[2024-10-12 09:52:40Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "8af43833-575c-4eb8-83b1-eb4e58509e4c", body: nil, order: 4, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "23b70937-ed81-47fe-a560-ee14287bff7d", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "23b70937-ed81-47fe-a560-ee14287bff7d", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:46:13Z], updated_at: ~U[2024-10-12 09:46:13Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "c7ad47e6-629d-4382-936d-64d757772c4e", body: nil, order: 3, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "d5758230-7966-4f9b-8c16-ae13998cd71b", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "d5758230-7966-4f9b-8c16-ae13998cd71b", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "fc80709a-39dc-4b9c-95c3-1d64ce818302", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:44:09Z], updated_at: ~U[2024-10-12 09:44:09Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "02218551-591f-4450-abbd-a7b7d76fd48e", body: "testing", order: 2, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "19ffdc82-a5d8-49c3-8b01-1559736dad80", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "19ffdc82-a5d8-49c3-8b01-1559736dad80", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "fc80709a-39dc-4b9c-95c3-1d64ce818302", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:43:19Z], updated_at: ~U[2024-10-12 09:43:19Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "90c6036a-9bd1-4b65-82d5-f121ec4d7867", body: nil, order: 2, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "b92f990d-99a2-4f04-a2d4-d1135021ee8c", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "b92f990d-99a2-4f04-a2d4-d1135021ee8c", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-11 09:03:00Z], updated_at: ~U[2024-10-11 09:03:00Z] } ], inserted_at: ~N[2024-09-27 00:51:48], updated_at: ~N[2024-09-27 00:51:48] } [debug] Replied in 81ms [debug] HANDLE EVENT "verses::focus_toggle_on_quick_mark_drafting" in VyasaWeb.ModeLive.Mediator Component: VyasaWeb.Context.Read Parameters: %{"is_focusing?" => false, "value" => ""} [debug] Replied in 129µs iex([email protected])17> * marks order force * old man mark is not feeling so good * ReWrite how marks get initialised @ :show_verse (#119) * Minor change in fn signature * Add init_draft_reflector() * Don't rely on the time async message passing * Use custom generic_modal_wrapper This one has more specific callback attributes and tailwind classes can be injected to it. * Create data and ui skeletons for sheaf_creator * Add support for human friendly time formatting * Setup skeleton for replyto context Some pending todo functions for how the reply to context shall be determined * Standardise UI, improve wrapper's default UI * Improve generic_modal_wrapper styling slots * Wire sheaf creation form to stubbed event handler Relevant TODOs have been added * Use session.name for signature, add handler stubs * Edit marks in read mode (#118) * Add generic debug dump component This makes life easy when wiring things up * Rename namespace for Context.Read.* * Groundwork: add discuss component w sheafs * Init Context.Components mod for common components * Add skeletons for Sheaf Container Container managers sheaf state within itself. Should actually make the verse-matrix use this container, sometime. * Minor changes, add some TODOs to share explicit todos Minor change * Add live component EditableMarkDisplay * Add UI improvements to EditableMarkDisplay The edit button on quick draft should only be seen when the dropdown is expanded and all the marks can be seen. The general pattern I'm trying to follow is that buttons should only be shown when an action makes sense. So here, if the user can't even see the marks currently accumulating, then the user shouldn't have the chance to edit any marks. Notice that the EditableMarkDisplay is a live_component that is a child of a function component (collapsible_marks_display). This is so that it can keep its own state and do it's own event-handling. I'm not sure if this is pattern-breaking. A reference to the actual parent live_component that calls collapsible_marks_display will always be there in case there's a need for the parent to handle any particular events. So comms b/w live_components is still going to be via phx-target values. * Change <input/> -> <textarea/> fr quick_draft_form * Add tailwind config for custom svg icons not sure how the scaling for this works, seems like i can't just put in the class="h-5 w-5" to do the scaling * Let custom svg be scalable * Subtly shift the ping indicator to control panel * Marks ordering in Sheaf and L-Trees (#114) * do sheafs grow on trees * sangh session dealing with lineage * Solve initial order problem * fix: ensure non-null id used @ EditableMarkDisplay --------- Co-authored-by: ks0m1c_dharma <[email protected]> * Trigger Diff * TOMBSTONING * Fix bugs and revert ui for read_mode:delete marks 1. JIT generate id for marks yet to be inserted to the db: instead of using a temp id, I'm actually assigning a JIT-generated id for a mark even if that isn't inserted into the db yet. this has two benefits: div ids have meaningful static ids (e.g. mark-container-\<\> mark.id) regardless of whether that mark has been inserted into the db or not. While doing this, the changeset for marks has been udpated to add id as well. This fixes a bunch of id-based errors as well. 2. while doing 1, it came to light that the bindHoverune handlers were not handling the draft mark update properly (i.e. not using the already existing update function in mark) . it's changed now, example of the diff: ``` diff @impl true def handle_event( "bindHoveRune", %{"binding" => bind = %{"verse_id" => verse_id}}, %{ assigns: %{ kv_verses: verses, marks: [%Mark{state: :draft, verse_id: curr_verse_id} = d_mark | marks] } } = socket ) when is_binary(curr_verse_id) and verse_id != curr_verse_id do # binding here blocks the stream from appending to quote bind = Draft.bind_node(bind) bound_verses = verses |> then(&put_in(&1[verse_id].binding, bind)) |> then(&put_in(&1[curr_verse_id].binding, nil)) + updated_draft_mark = d_mark |> Mark.update_mark(%{binding: bind, verse_id: verse_id}) + {:noreply, socket |> mutate_verses(curr_verse_id, bound_verses) |> mutate_verses(verse_id, bound_verses) - |> assign(:marks, [%{d_mark | binding: bind, verse_id: verse_id} | marks])} + |> assign(:marks, [updated_draft_mark | marks])} end ``` 3. add ui state structs: all of the relevant ui states have structs that are intended to be static interfaces. this felt better than directly keeping state within various sockets and is done with a view to remove live components and change them to function components wherever possible. 4. bugfix for `order()`: - it had an off-by-one-error - shifted it to Vyasa.Sangh.Mark - also note that the order shall be 1-indexed instead of 0-indexed for human-friendliness 5. minor fixes: 1. fix update<sub>mark</sub> default argument ``` diff -def update_mark(%Mark{} = draft_mark, opts \\ []) do +def update_mark(%Mark{} = draft_mark, opts \\ %{}) do ``` 1. In this commit, the marks<sub>ui</sub> is NOT kept by the read context module, that's why when I update things by create mark or delete mark, the ui state is not preserved and initial, default state is seen. This was intentionally done in this commit because I'm having problems with duplicate ids for verses for some reason, I'll show it in the next commit, so that the problem can be clearly seen. * [BUGGY] keep marks_ui within ReadContext This is buggy, not sure why there's a duplicate yet. will come back to it after lunch Replication Steps: 1. delete all marks and see there's no error 2. create first mark ==> no error 3. create second mark ==> crashes due to duplicate verse id Crash dump: [debug] Replied in 13ms [error] GenServer #PID<0.8416.0> terminating ** (RuntimeError) found duplicate ID "verse-7d9d588a-34fc-4f19-b974-fc32b49b6a61" for component VyasaWeb.Context.Read.VerseMatrix when rendering template (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:634: anonymous fn/5 in Phoenix.LiveView.Diff.render_pending_components/6 (elixir 1.17.2) lib/enum.ex:2531: Enum."-reduce/3-lists^foldl/2-0-"/3 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:631: anonymous fn/4 in Phoenix.LiveView.Diff.render_pending_components/6 (stdlib 5.2.3) maps.erl:416: :maps.fold_1/4 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:625: Phoenix.LiveView.Diff.render_pending_components/6 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:217: Phoenix.LiveView.Diff.write_component/4 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/channel.ex:662: Phoenix.LiveView.Channel.component_handle/4 (stdlib 5.2.3) gen_server.erl:1095: :gen_server.try_handle_info/3 (stdlib 5.2.3) gen_server.erl:1183: :gen_server.handle_msg/6 (stdlib 5.2.3) proc_lib.erl:251: :proc_lib.wake_up/3 Last message: %Phoenix.Socket.Message{topic: "lv:phx-F_1MH_6F0ciqVqwi", event: "event", payload: %{"cid" => 3, "event" => "createMark", "type" => "form", "value" => "body=how+about+now%2C+any+duplicate%3F"}, ref: "23", join_ref: "4"} State: %{socket: #Phoenix.LiveView.Socket<id: "phx-F_1MH_6F0ciqVqwi", endpoint: VyasaWeb.Endpoint, view: VyasaWeb.ModeLive.Mediator, parent_pid: nil, root_pid: #PID<0.8416.0>, router: VyasaWeb.Router, assigns: %{mode: %VyasaWeb.ModeLive.UserMode{mode: "read", default_ui_state: %VyasaWeb.ModeLive.UiState{show_media_bridge?: true, show_action_bar?: true}, mode_icon_name: "hero-book-open", quick_actions: [:mark_quote, :bookmark], control_panel_modes: ["discuss"], mode_actions: [:mark_quote, :bookmark], action_bar_actions: [:nav_back, :nav_fwd], action_bar_info_types: nil, action_bar_component: VyasaWeb.MediaLive.MediaBridge, action_bar_component_selector: "media-bridge", control_panel_component: VyasaWeb.ControlPanel, control_panel_component_selector: "control-panel", mode_context_component: VyasaWeb.Context.Read, mode_context_component_selector: "read"}, session: %VyasaWeb.Session{name: "ritesh kumar", id: "IhrQV0ypqg8bHakbvb2bymNF", active: true, sangh: %Vyasa.Sangh.Session{__meta__: #Ecto.Schema.Metadata<:loaded, "sessions">, id: "164eb05d-221a-4939-b180-8394e1a5515f", sheafs: #Ecto.Association.NotLoaded<association :sheafs is not loaded>, inserted_at: ~U[2024-09-27 00:51:48Z], updated_at: ~U[2024-09-27 00:51:48Z]}, last_opened: "2024-09-23T11:03:32.022987Z"}, __changed__: %{}, flash: %{}, locale: "en-GB", url_params: %{"chap_no" => "1", "source_title" => "hanuman_chalisa"}, live_action: :show_verses, ui_state: %VyasaWeb.ModeLive.UiState{show_media_bridge?: true, show_action_bar?: true}, device_type: :desktop, tz: %{timezone: "Asia/Singapore", timezone_offset: 480}}, transport_pid: #PID<0.8403.0>, ...>, components: {%{15 => {VyasaWeb.Context.Read.VerseMatrix, "verse-aa3ad88b-0de1-443e-b471-c08a44e67c61", %{id: "verse-aa3ad88b-0de1-443e-b471-c08a44e67c61", edge: [%{title: "1.10", field: [:body], verseup: {:big, "dn"}}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body_translit], verseup: :mid}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body_translit_meant], verseup: :mid}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body], verseup: :mid}], __changed__: %{}, flash: %{}, marks: [%Vyasa.Sangh.Mark{__meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "5dfdb167-6c57-46dd-a0c4-10b52cb03a85", body: "wonderful", order: 2, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "001da594-3808-46cf-9b9c-5dfb3559780e", binding: %Vyasa.Adapters.Binding{__meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "001da594-3808-46cf-9b9c-5dfb3559780e", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil}, inserted_at: ~U[2024-10-11 04:31:50Z], updated_at: ~U[2024-10-11 04:31:50Z]}, %Vyasa.Sangh.Mark{__meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "273a093d-4f90-40a4-b19a-2f8f7825d201", body: "truncated utc datetime", order: 1, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "ef39315b-530c-4841-ba32-86773f451727", binding: %Vyasa.Adapt (truncated) [debug] MOUNT VyasaWeb.ModeLive.Mediator Parameters: %{"chap_no" => "1", "source_title" => "hanuman_chalisa"} Session: %{"_csrf_token" => "DJ-RIoXwEzHW82rbb21le_8k"} [debug] QUERY OK source="sessions" db=3.5ms idle=1690.4ms SELECT s0."id", s0."inserted_at", s0."updated_at" FROM "sessions" AS s0 WHERE (s0."id" = $1) ["164eb05d-221a-4939-b180-8394e1a5515f"] ↳ * Fix duplicate id issue on verse matrix * Standardise use of @event_target, cleanups When using @event_target, the intent is that phx-target values will be passed around. This must be agnostic to the 2 main ways of supplying that argument, as a HTML selector, or as a module name (or @myself). Therefore, we should discourage ourselves from doing format-strings at the point of the @event_target being supplied as an argument, meaning: good, because agnostic: phx-target={@event_target} bad, because hardcoded: phx-target={"#" <> @event_target} * in this case, the event trigger will throw a dom error. * [Attempt]: Sanitise, defrag orders in marks-list If this is an anti-pattern, then this commit should be reverted. * UI fixes: hide buttons on marks when !is_editable? * Add in stub event handlers to prevent crashes Temporary stuff, will be addressed in immediate-next PR * Minor changes * Toggle edit state for marks content * Partial implementation of edit marks the form stuff doesn't exist so it's not wired up yet. To be frank, im' not sure how to set up a form without it needing to hold state. * [BUGGY] Wire up form update for edit this does the following: 1. wires up the form like how we usedd it in createMark 2. actually captures the event properly within the event handler, everything looks good at that point, even the edit_mark_in_marks function on inspection looks good 3. the marks is getting assigned to properly because the newly edited mark content is seen after doing a dom refresh 4. HOWEVER, the print statement at the sheaf_update function DOES NOT show the correct, updated marks in the sheaf here's a dump for it for reference [debug] HANDLE EVENT "editMarkContent" in VyasaWeb.ModeLive.Mediator Component: VyasaWeb.Context.Read Parameters: %{"mark_id" => "02218551-591f-4450-abbd-a7b7d76fd48e"} [debug] Replied in 2ms [debug] HANDLE EVENT "editMarkContent" in VyasaWeb.ModeLive.Mediator Component: VyasaWeb.Context.Read Parameters: %{"mark_body" => " testing\n\n\nwhat hte heck", "mark_id" => "02218551-591f-4450-abbd-a7b7d76fd48e"} >>> UPDATE SHEAF -- SHOULD BE WRITING TO DB NOW: %Vyasa.Sangh.Sheaf{ __meta__: #Ecto.Schema.Metadata<:loaded, "sheafs">, id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", body: nil, active: true, path: %EctoLtree.LabelTree{labels: ["7f4ab16b"]}, signature: nil, traits: ["draft"], child_count: 0, session_id: "164eb05d-221a-4939-b180-8394e1a5515f", session: #Ecto.Association.NotLoaded<association :session is not loaded>, parent_id: nil, parent: #Ecto.Association.NotLoaded<association :parent is not loaded>, marks: [ %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "555eb625-e392-496e-9831-4f4c130be6fd", body: "wonderful stuff", order: 5, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "072124d0-5e27-4601-832f-35eaa6426879", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "072124d0-5e27-4601-832f-35eaa6426879", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 08:46:54Z], updated_at: ~U[2024-10-12 08:46:54Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "b22a5661-8268-4875-be26-a12256414136", body: nil, order: 5, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "90e18044-73b2-4ede-a149-a381de893b9f", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "90e18044-73b2-4ede-a149-a381de893b9f", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "fc80709a-39dc-4b9c-95c3-1d64ce818302", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:52:40Z], updated_at: ~U[2024-10-12 09:52:40Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "8af43833-575c-4eb8-83b1-eb4e58509e4c", body: nil, order: 4, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "23b70937-ed81-47fe-a560-ee14287bff7d", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "23b70937-ed81-47fe-a560-ee14287bff7d", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:46:13Z], updated_at: ~U[2024-10-12 09:46:13Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "c7ad47e6-629d-4382-936d-64d757772c4e", body: nil, order: 3, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "d5758230-7966-4f9b-8c16-ae13998cd71b", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "d5758230-7966-4f9b-8c16-ae13998cd71b", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "fc80709a-39dc-4b9c-95c3-1d64ce818302", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:44:09Z], updated_at: ~U[2024-10-12 09:44:09Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "02218551-591f-4450-abbd-a7b7d76fd48e", body: "testing", order: 2, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "19ffdc82-a5d8-49c3-8b01-1559736dad80", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "19ffdc82-a5d8-49c3-8b01-1559736dad80", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "fc80709a-39dc-4b9c-95c3-1d64ce818302", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:43:19Z], updated_at: ~U[2024-10-12 09:43:19Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "90c6036a-9bd1-4b65-82d5-f121ec4d7867", body: nil, order: 2, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "b92f990d-99a2-4f04-a2d4-d1135021ee8c", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "b92f990d-99a2-4f04-a2d4-d1135021ee8c", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-11 09:03:00Z], updated_at: ~U[2024-10-11 09:03:00Z] } ], inserted_at: ~N[2024-09-27 00:51:48], updated_at: ~N[2024-09-27 00:51:48] } [debug] Replied in 81ms [debug] HANDLE EVENT "verses::focus_toggle_on_quick_mark_drafting" in VyasaWeb.ModeLive.Mediator Component: VyasaWeb.Context.Read Parameters: %{"is_focusing?" => false, "value" => ""} [debug] Replied in 129µs iex([email protected])17> * marks order force * old man mark is not feeling so good * ReWrite how marks get initialised @ :show_verse (#119) * Minor change in fn signature * Add init_draft_reflector() --------- Co-authored-by: ks0m1c_dharma <[email protected]> * Minor changes * Add a generic modal wrapper (#120) * Add generic debug dump component This makes life easy when wiring things up * Rename namespace for Context.Read.* * Groundwork: add discuss component w sheafs * Init Context.Components mod for common components * Add skeletons for Sheaf Container Container managers sheaf state within itself. Should actually make the verse-matrix use this container, sometime. * Minor changes, add some TODOs to share explicit todos Minor change * Add live component EditableMarkDisplay * Add UI improvements to EditableMarkDisplay The edit button on quick draft should only be seen when the dropdown is expanded and all the marks can be seen. The general pattern I'm trying to follow is that buttons should only be shown when an action makes sense. So here, if the user can't even see the marks currently accumulating, then the user shouldn't have the chance to edit any marks. Notice that the EditableMarkDisplay is a live_component that is a child of a function component (collapsible_marks_display). This is so that it can keep its own state and do it's own event-handling. I'm not sure if this is pattern-breaking. A reference to the actual parent live_component that calls collapsible_marks_display will always be there in case there's a need for the parent to handle any particular events. So comms b/w live_components is still going to be via phx-target values. * Change <input/> -> <textarea/> fr quick_draft_form * Add tailwind config for custom svg icons not sure how the scaling for this works, seems like i can't just put in the class="h-5 w-5" to do the scaling * Let custom svg be scalable * Subtly shift the ping indicator to control panel * Marks ordering in Sheaf and L-Trees (#114) * do sheafs grow on trees * sangh session dealing with lineage * Solve initial order problem * fix: ensure non-null id used @ EditableMarkDisplay --------- Co-authored-by: ks0m1c_dharma <[email protected]> * Trigger Diff * TOMBSTONING * Fix bugs and revert ui for read_mode:delete marks 1. JIT generate id for marks yet to be inserted to the db: instead of using a temp id, I'm actually assigning a JIT-generated id for a mark even if that isn't inserted into the db yet. this has two benefits: div ids have meaningful static ids (e.g. mark-container-\<\> mark.id) regardless of whether that mark has been inserted into the db or not. While doing this, the changeset for marks has been udpated to add id as well. This fixes a bunch of id-based errors as well. 2. while doing 1, it came to light that the bindHoverune handlers were not handling the draft mark update properly (i.e. not using the already existing update function in mark) . it's changed now, example of the diff: ``` diff @impl true def handle_event( "bindHoveRune", %{"binding" => bind = %{"verse_id" => verse_id}}, %{ assigns: %{ kv_verses: verses, marks: [%Mark{state: :draft, verse_id: curr_verse_id} = d_mark | marks] } } = socket ) when is_binary(curr_verse_id) and verse_id != curr_verse_id do # binding here blocks the stream from appending to quote bind = Draft.bind_node(bind) bound_verses = verses |> then(&put_in(&1[verse_id].binding, bind)) |> then(&put_in(&1[curr_verse_id].binding, nil)) + updated_draft_mark = d_mark |> Mark.update_mark(%{binding: bind, verse_id: verse_id}) + {:noreply, socket |> mutate_verses(curr_verse_id, bound_verses) |> mutate_verses(verse_id, bound_verses) - |> assign(:marks, [%{d_mark | binding: bind, verse_id: verse_id} | marks])} + |> assign(:marks, [updated_draft_mark | marks])} end ``` 3. add ui state structs: all of the relevant ui states have structs that are intended to be static interfaces. this felt better than directly keeping state within various sockets and is done with a view to remove live components and change them to function components wherever possible. 4. bugfix for `order()`: - it had an off-by-one-error - shifted it to Vyasa.Sangh.Mark - also note that the order shall be 1-indexed instead of 0-indexed for human-friendliness 5. minor fixes: 1. fix update<sub>mark</sub> default argument ``` diff -def update_mark(%Mark{} = draft_mark, opts \\ []) do +def update_mark(%Mark{} = draft_mark, opts \\ %{}) do ``` 1. In this commit, the marks<sub>ui</sub> is NOT kept by the read context module, that's why when I update things by create mark or delete mark, the ui state is not preserved and initial, default state is seen. This was intentionally done in this commit because I'm having problems with duplicate ids for verses for some reason, I'll show it in the next commit, so that the problem can be clearly seen. * [BUGGY] keep marks_ui within ReadContext This is buggy, not sure why there's a duplicate yet. will come back to it after lunch Replication Steps: 1. delete all marks and see there's no error 2. create first mark ==> no error 3. create second mark ==> crashes due to duplicate verse id Crash dump: [debug] Replied in 13ms [error] GenServer #PID<0.8416.0> terminating ** (RuntimeError) found duplicate ID "verse-7d9d588a-34fc-4f19-b974-fc32b49b6a61" for component VyasaWeb.Context.Read.VerseMatrix when rendering template (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:634: anonymous fn/5 in Phoenix.LiveView.Diff.render_pending_components/6 (elixir 1.17.2) lib/enum.ex:2531: Enum."-reduce/3-lists^foldl/2-0-"/3 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:631: anonymous fn/4 in Phoenix.LiveView.Diff.render_pending_components/6 (stdlib 5.2.3) maps.erl:416: :maps.fold_1/4 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:625: Phoenix.LiveView.Diff.render_pending_components/6 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:217: Phoenix.LiveView.Diff.write_component/4 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/channel.ex:662: Phoenix.LiveView.Channel.component_handle/4 (stdlib 5.2.3) gen_server.erl:1095: :gen_server.try_handle_info/3 (stdlib 5.2.3) gen_server.erl:1183: :gen_server.handle_msg/6 (stdlib 5.2.3) proc_lib.erl:251: :proc_lib.wake_up/3 Last message: %Phoenix.Socket.Message{topic: "lv:phx-F_1MH_6F0ciqVqwi", event: "event", payload: %{"cid" => 3, "event" => "createMark", "type" => "form", "value" => "body=how+about+now%2C+any+duplicate%3F"}, ref: "23", join_ref: "4"} State: %{socket: #Phoenix.LiveView.Socket<id: "phx-F_1MH_6F0ciqVqwi", endpoint: VyasaWeb.Endpoint, view: VyasaWeb.ModeLive.Mediator, parent_pid: nil, root_pid: #PID<0.8416.0>, router: VyasaWeb.Router, assigns: %{mode: %VyasaWeb.ModeLive.UserMode{mode: "read", default_ui_state: %VyasaWeb.ModeLive.UiState{show_media_bridge?: true, show_action_bar?: true}, mode_icon_name: "hero-book-open", quick_actions: [:mark_quote, :bookmark], control_panel_modes: ["discuss"], mode_actions: [:mark_quote, :bookmark], action_bar_actions: [:nav_back, :nav_fwd], action_bar_info_types: nil, action_bar_component: VyasaWeb.MediaLive.MediaBridge, action_bar_component_selector: "media-bridge", control_panel_component: VyasaWeb.ControlPanel, control_panel_component_selector: "control-panel", mode_context_component: VyasaWeb.Context.Read, mode_context_component_selector: "read"}, session: %VyasaWeb.Session{name: "ritesh kumar", id: "IhrQV0ypqg8bHakbvb2bymNF", active: true, sangh: %Vyasa.Sangh.Session{__meta__: #Ecto.Schema.Metadata<:loaded, "sessions">, id: "164eb05d-221a-4939-b180-8394e1a5515f", sheafs: #Ecto.Association.NotLoaded<association :sheafs is not loaded>, inserted_at: ~U[2024-09-27 00:51:48Z], updated_at: ~U[2024-09-27 00:51:48Z]}, last_opened: "2024-09-23T11:03:32.022987Z"}, __changed__: %{}, flash: %{}, locale: "en-GB", url_params: %{"chap_no" => "1", "source_title" => "hanuman_chalisa"}, live_action: :show_verses, ui_state: %VyasaWeb.ModeLive.UiState{show_media_bridge?: true, show_action_bar?: true}, device_type: :desktop, tz: %{timezone: "Asia/Singapore", timezone_offset: 480}}, transport_pid: #PID<0.8403.0>, ...>, components: {%{15 => {VyasaWeb.Context.Read.VerseMatrix, "verse-aa3ad88b-0de1-443e-b471-c08a44e67c61", %{id: "verse-aa3ad88b-0de1-443e-b471-c08a44e67c61", edge: [%{title: "1.10", field: [:body], verseup: {:big, "dn"}}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body_translit], verseup: :mid}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body_translit_meant], verseup: :mid}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body], verseup: :mid}], __changed__: %{}, flash: %{}, marks: [%Vyasa.Sangh.Mark{__meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "5dfdb167-6c57-46dd-a0c4-10b52cb03a85", body: "wonderful", order: 2, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "001da594-3808-46cf-9b9c-5dfb3559780e", binding: %Vyasa.Adapters.Binding{__meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "001da594-3808-46cf-9b9c-5dfb3559780e", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil}, inserted_at: ~U[2024-10-11 04:31:50Z], updated_at: ~U[2024-10-11 04:31:50Z]}, %Vyasa.Sangh.Mark{__meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "273a093d-4f90-40a4-b19a-2f8f7825d201", body: "truncated utc datetime", order: 1, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "ef39315b-530c-4841-ba32-86773f451727", binding: %Vyasa.Adapt (truncated) [debug] MOUNT VyasaWeb.ModeLive.Mediator Parameters: %{"chap_no" => "1", "source_title" => "hanuman_chalisa"} Session: %{"_csrf_token" => "DJ-RIoXwEzHW82rbb21le_8k"} [debug] QUERY OK source="sessions" db=3.5ms idle=1690.4ms SELECT s0."id", s0."inserted_at", s0."updated_at" FROM "sessions" AS s0 WHERE (s0."id" = $1) ["164eb05d-221a-4939-b180-8394e1a5515f"] ↳ * Fix duplicate id issue on verse matrix * Standardise use of @event_target, cleanups When using @event_target, the intent is that phx-target values will be passed around. This must be agnostic to the 2 main ways of supplying that argument, as a HTML selector, or as a module name (or @myself). Therefore, we should discourage ourselves from doing format-strings at the point of the @event_target being supplied as an argument, meaning: good, because agnostic: phx-target={@event_target} bad, because hardcoded: phx-target={"#" <> @event_target} * in this case, the event trigger will throw a dom error. …
* Add generic debug dump component This makes life easy when wiring things up * Rename namespace for Context.Read.* * Groundwork: add discuss component w sheafs * Init Context.Components mod for common components * Add skeletons for Sheaf Container Container managers sheaf state within itself. Should actually make the verse-matrix use this container, sometime. * Minor changes, add some TODOs to share explicit todos Minor change * Add live component EditableMarkDisplay * Add UI improvements to EditableMarkDisplay The edit button on quick draft should only be seen when the dropdown is expanded and all the marks can be seen. The general pattern I'm trying to follow is that buttons should only be shown when an action makes sense. So here, if the user can't even see the marks currently accumulating, then the user shouldn't have the chance to edit any marks. Notice that the EditableMarkDisplay is a live_component that is a child of a function component (collapsible_marks_display). This is so that it can keep its own state and do it's own event-handling. I'm not sure if this is pattern-breaking. A reference to the actual parent live_component that calls collapsible_marks_display will always be there in case there's a need for the parent to handle any particular events. So comms b/w live_components is still going to be via phx-target values. * Change <input/> -> <textarea/> fr quick_draft_form * Add tailwind config for custom svg icons not sure how the scaling for this works, seems like i can't just put in the class="h-5 w-5" to do the scaling * Let custom svg be scalable * Subtly shift the ping indicator to control panel * Marks ordering in Sheaf and L-Trees (#114) * do sheafs grow on trees * sangh session dealing with lineage * Solve initial order problem * fix: ensure non-null id used @ EditableMarkDisplay --------- Co-authored-by: ks0m1c_dharma <[email protected]> * Trigger Diff * TOMBSTONING * Fix bugs and revert ui for read_mode:delete marks 1. JIT generate id for marks yet to be inserted to the db: instead of using a temp id, I'm actually assigning a JIT-generated id for a mark even if that isn't inserted into the db yet. this has two benefits: div ids have meaningful static ids (e.g. mark-container-\<\> mark.id) regardless of whether that mark has been inserted into the db or not. While doing this, the changeset for marks has been udpated to add id as well. This fixes a bunch of id-based errors as well. 2. while doing 1, it came to light that the bindHoverune handlers were not handling the draft mark update properly (i.e. not using the already existing update function in mark) . it's changed now, example of the diff: ``` diff @impl true def handle_event( "bindHoveRune", %{"binding" => bind = %{"verse_id" => verse_id}}, %{ assigns: %{ kv_verses: verses, marks: [%Mark{state: :draft, verse_id: curr_verse_id} = d_mark | marks] } } = socket ) when is_binary(curr_verse_id) and verse_id != curr_verse_id do # binding here blocks the stream from appending to quote bind = Draft.bind_node(bind) bound_verses = verses |> then(&put_in(&1[verse_id].binding, bind)) |> then(&put_in(&1[curr_verse_id].binding, nil)) + updated_draft_mark = d_mark |> Mark.update_mark(%{binding: bind, verse_id: verse_id}) + {:noreply, socket |> mutate_verses(curr_verse_id, bound_verses) |> mutate_verses(verse_id, bound_verses) - |> assign(:marks, [%{d_mark | binding: bind, verse_id: verse_id} | marks])} + |> assign(:marks, [updated_draft_mark | marks])} end ``` 3. add ui state structs: all of the relevant ui states have structs that are intended to be static interfaces. this felt better than directly keeping state within various sockets and is done with a view to remove live components and change them to function components wherever possible. 4. bugfix for `order()`: - it had an off-by-one-error - shifted it to Vyasa.Sangh.Mark - also note that the order shall be 1-indexed instead of 0-indexed for human-friendliness 5. minor fixes: 1. fix update<sub>mark</sub> default argument ``` diff -def update_mark(%Mark{} = draft_mark, opts \\ []) do +def update_mark(%Mark{} = draft_mark, opts \\ %{}) do ``` 1. In this commit, the marks<sub>ui</sub> is NOT kept by the read context module, that's why when I update things by create mark or delete mark, the ui state is not preserved and initial, default state is seen. This was intentionally done in this commit because I'm having problems with duplicate ids for verses for some reason, I'll show it in the next commit, so that the problem can be clearly seen. * [BUGGY] keep marks_ui within ReadContext This is buggy, not sure why there's a duplicate yet. will come back to it after lunch Replication Steps: 1. delete all marks and see there's no error 2. create first mark ==> no error 3. create second mark ==> crashes due to duplicate verse id Crash dump: [debug] Replied in 13ms [error] GenServer #PID<0.8416.0> terminating ** (RuntimeError) found duplicate ID "verse-7d9d588a-34fc-4f19-b974-fc32b49b6a61" for component VyasaWeb.Context.Read.VerseMatrix when rendering template (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:634: anonymous fn/5 in Phoenix.LiveView.Diff.render_pending_components/6 (elixir 1.17.2) lib/enum.ex:2531: Enum."-reduce/3-lists^foldl/2-0-"/3 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:631: anonymous fn/4 in Phoenix.LiveView.Diff.render_pending_components/6 (stdlib 5.2.3) maps.erl:416: :maps.fold_1/4 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:625: Phoenix.LiveView.Diff.render_pending_components/6 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:217: Phoenix.LiveView.Diff.write_component/4 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/channel.ex:662: Phoenix.LiveView.Channel.component_handle/4 (stdlib 5.2.3) gen_server.erl:1095: :gen_server.try_handle_info/3 (stdlib 5.2.3) gen_server.erl:1183: :gen_server.handle_msg/6 (stdlib 5.2.3) proc_lib.erl:251: :proc_lib.wake_up/3 Last message: %Phoenix.Socket.Message{topic: "lv:phx-F_1MH_6F0ciqVqwi", event: "event", payload: %{"cid" => 3, "event" => "createMark", "type" => "form", "value" => "body=how+about+now%2C+any+duplicate%3F"}, ref: "23", join_ref: "4"} State: %{socket: #Phoenix.LiveView.Socket<id: "phx-F_1MH_6F0ciqVqwi", endpoint: VyasaWeb.Endpoint, view: VyasaWeb.ModeLive.Mediator, parent_pid: nil, root_pid: #PID<0.8416.0>, router: VyasaWeb.Router, assigns: %{mode: %VyasaWeb.ModeLive.UserMode{mode: "read", default_ui_state: %VyasaWeb.ModeLive.UiState{show_media_bridge?: true, show_action_bar?: true}, mode_icon_name: "hero-book-open", quick_actions: [:mark_quote, :bookmark], control_panel_modes: ["discuss"], mode_actions: [:mark_quote, :bookmark], action_bar_actions: [:nav_back, :nav_fwd], action_bar_info_types: nil, action_bar_component: VyasaWeb.MediaLive.MediaBridge, action_bar_component_selector: "media-bridge", control_panel_component: VyasaWeb.ControlPanel, control_panel_component_selector: "control-panel", mode_context_component: VyasaWeb.Context.Read, mode_context_component_selector: "read"}, session: %VyasaWeb.Session{name: "ritesh kumar", id: "IhrQV0ypqg8bHakbvb2bymNF", active: true, sangh: %Vyasa.Sangh.Session{__meta__: #Ecto.Schema.Metadata<:loaded, "sessions">, id: "164eb05d-221a-4939-b180-8394e1a5515f", sheafs: #Ecto.Association.NotLoaded<association :sheafs is not loaded>, inserted_at: ~U[2024-09-27 00:51:48Z], updated_at: ~U[2024-09-27 00:51:48Z]}, last_opened: "2024-09-23T11:03:32.022987Z"}, __changed__: %{}, flash: %{}, locale: "en-GB", url_params: %{"chap_no" => "1", "source_title" => "hanuman_chalisa"}, live_action: :show_verses, ui_state: %VyasaWeb.ModeLive.UiState{show_media_bridge?: true, show_action_bar?: true}, device_type: :desktop, tz: %{timezone: "Asia/Singapore", timezone_offset: 480}}, transport_pid: #PID<0.8403.0>, ...>, components: {%{15 => {VyasaWeb.Context.Read.VerseMatrix, "verse-aa3ad88b-0de1-443e-b471-c08a44e67c61", %{id: "verse-aa3ad88b-0de1-443e-b471-c08a44e67c61", edge: [%{title: "1.10", field: [:body], verseup: {:big, "dn"}}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body_translit], verseup: :mid}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body_translit_meant], verseup: :mid}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body], verseup: :mid}], __changed__: %{}, flash: %{}, marks: [%Vyasa.Sangh.Mark{__meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "5dfdb167-6c57-46dd-a0c4-10b52cb03a85", body: "wonderful", order: 2, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "001da594-3808-46cf-9b9c-5dfb3559780e", binding: %Vyasa.Adapters.Binding{__meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "001da594-3808-46cf-9b9c-5dfb3559780e", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil}, inserted_at: ~U[2024-10-11 04:31:50Z], updated_at: ~U[2024-10-11 04:31:50Z]}, %Vyasa.Sangh.Mark{__meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "273a093d-4f90-40a4-b19a-2f8f7825d201", body: "truncated utc datetime", order: 1, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "ef39315b-530c-4841-ba32-86773f451727", binding: %Vyasa.Adapt (truncated) [debug] MOUNT VyasaWeb.ModeLive.Mediator Parameters: %{"chap_no" => "1", "source_title" => "hanuman_chalisa"} Session: %{"_csrf_token" => "DJ-RIoXwEzHW82rbb21le_8k"} [debug] QUERY OK source="sessions" db=3.5ms idle=1690.4ms SELECT s0."id", s0."inserted_at", s0."updated_at" FROM "sessions" AS s0 WHERE (s0."id" = $1) ["164eb05d-221a-4939-b180-8394e1a5515f"] ↳ * Fix duplicate id issue on verse matrix * Standardise use of @event_target, cleanups When using @event_target, the intent is that phx-target values will be passed around. This must be agnostic to the 2 main ways of supplying that argument, as a HTML selector, or as a module name (or @myself). Therefore, we should discourage ourselves from doing format-strings at the point of the @event_target being supplied as an argument, meaning: good, because agnostic: phx-target={@event_target} bad, because hardcoded: phx-target={"#" <> @event_target} * in this case, the event trigger will throw a dom error. * [Attempt]: Sanitise, defrag orders in marks-list If this is an anti-pattern, then this commit should be reverted. * UI fixes: hide buttons on marks when !is_editable? * Add in stub event handlers to prevent crashes Temporary stuff, will be addressed in immediate-next PR * Minor changes * Toggle edit state for marks content * Partial implementation of edit marks the form stuff doesn't exist so it's not wired up yet. To be frank, im' not sure how to set up a form without it needing to hold state. * [BUGGY] Wire up form update for edit this does the following: 1. wires up the form like how we usedd it in createMark 2. actually captures the event properly within the event handler, everything looks good at that point, even the edit_mark_in_marks function on inspection looks good 3. the marks is getting assigned to properly because the newly edited mark content is seen after doing a dom refresh 4. HOWEVER, the print statement at the sheaf_update function DOES NOT show the correct, updated marks in the sheaf here's a dump for it for reference [debug] HANDLE EVENT "editMarkContent" in VyasaWeb.ModeLive.Mediator Component: VyasaWeb.Context.Read Parameters: %{"mark_id" => "02218551-591f-4450-abbd-a7b7d76fd48e"} [debug] Replied in 2ms [debug] HANDLE EVENT "editMarkContent" in VyasaWeb.ModeLive.Mediator Component: VyasaWeb.Context.Read Parameters: %{"mark_body" => " testing\n\n\nwhat hte heck", "mark_id" => "02218551-591f-4450-abbd-a7b7d76fd48e"} >>> UPDATE SHEAF -- SHOULD BE WRITING TO DB NOW: %Vyasa.Sangh.Sheaf{ __meta__: #Ecto.Schema.Metadata<:loaded, "sheafs">, id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", body: nil, active: true, path: %EctoLtree.LabelTree{labels: ["7f4ab16b"]}, signature: nil, traits: ["draft"], child_count: 0, session_id: "164eb05d-221a-4939-b180-8394e1a5515f", session: #Ecto.Association.NotLoaded<association :session is not loaded>, parent_id: nil, parent: #Ecto.Association.NotLoaded<association :parent is not loaded>, marks: [ %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "555eb625-e392-496e-9831-4f4c130be6fd", body: "wonderful stuff", order: 5, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "072124d0-5e27-4601-832f-35eaa6426879", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "072124d0-5e27-4601-832f-35eaa6426879", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 08:46:54Z], updated_at: ~U[2024-10-12 08:46:54Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "b22a5661-8268-4875-be26-a12256414136", body: nil, order: 5, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "90e18044-73b2-4ede-a149-a381de893b9f", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "90e18044-73b2-4ede-a149-a381de893b9f", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "fc80709a-39dc-4b9c-95c3-1d64ce818302", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:52:40Z], updated_at: ~U[2024-10-12 09:52:40Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "8af43833-575c-4eb8-83b1-eb4e58509e4c", body: nil, order: 4, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "23b70937-ed81-47fe-a560-ee14287bff7d", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "23b70937-ed81-47fe-a560-ee14287bff7d", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:46:13Z], updated_at: ~U[2024-10-12 09:46:13Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "c7ad47e6-629d-4382-936d-64d757772c4e", body: nil, order: 3, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "d5758230-7966-4f9b-8c16-ae13998cd71b", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "d5758230-7966-4f9b-8c16-ae13998cd71b", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "fc80709a-39dc-4b9c-95c3-1d64ce818302", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:44:09Z], updated_at: ~U[2024-10-12 09:44:09Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "02218551-591f-4450-abbd-a7b7d76fd48e", body: "testing", order: 2, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "19ffdc82-a5d8-49c3-8b01-1559736dad80", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "19ffdc82-a5d8-49c3-8b01-1559736dad80", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "fc80709a-39dc-4b9c-95c3-1d64ce818302", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:43:19Z], updated_at: ~U[2024-10-12 09:43:19Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "90c6036a-9bd1-4b65-82d5-f121ec4d7867", body: nil, order: 2, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "b92f990d-99a2-4f04-a2d4-d1135021ee8c", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "b92f990d-99a2-4f04-a2d4-d1135021ee8c", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-11 09:03:00Z], updated_at: ~U[2024-10-11 09:03:00Z] } ], inserted_at: ~N[2024-09-27 00:51:48], updated_at: ~N[2024-09-27 00:51:48] } [debug] Replied in 81ms [debug] HANDLE EVENT "verses::focus_toggle_on_quick_mark_drafting" in VyasaWeb.ModeLive.Mediator Component: VyasaWeb.Context.Read Parameters: %{"is_focusing?" => false, "value" => ""} [debug] Replied in 129µs iex([email protected])17> * marks order force * old man mark is not feeling so good * ReWrite how marks get initialised @ :show_verse (#119) * Minor change in fn signature * Add init_draft_reflector() * Don't rely on the time async message passing * Use custom generic_modal_wrapper This one has more specific callback attributes and tailwind classes can be injected to it. * Create data and ui skeletons for sheaf_creator * Add support for human friendly time formatting * Setup skeleton for replyto context Some pending todo functions for how the reply to context shall be determined * Standardise UI, improve wrapper's default UI * Improve generic_modal_wrapper styling slots * Wire sheaf creation form to stubbed event handler Relevant TODOs have been added * Use session.name for signature, add handler stubs * Edit marks in read mode (#118) * Add generic debug dump component This makes life easy when wiring things up * Rename namespace for Context.Read.* * Groundwork: add discuss component w sheafs * Init Context.Components mod for common components * Add skeletons for Sheaf Container Container managers sheaf state within itself. Should actually make the verse-matrix use this container, sometime. * Minor changes, add some TODOs to share explicit todos Minor change * Add live component EditableMarkDisplay * Add UI improvements to EditableMarkDisplay The edit button on quick draft should only be seen when the dropdown is expanded and all the marks can be seen. The general pattern I'm trying to follow is that buttons should only be shown when an action makes sense. So here, if the user can't even see the marks currently accumulating, then the user shouldn't have the chance to edit any marks. Notice that the EditableMarkDisplay is a live_component that is a child of a function component (collapsible_marks_display). This is so that it can keep its own state and do it's own event-handling. I'm not sure if this is pattern-breaking. A reference to the actual parent live_component that calls collapsible_marks_display will always be there in case there's a need for the parent to handle any particular events. So comms b/w live_components is still going to be via phx-target values. * Change <input/> -> <textarea/> fr quick_draft_form * Add tailwind config for custom svg icons not sure how the scaling for this works, seems like i can't just put in the class="h-5 w-5" to do the scaling * Let custom svg be scalable * Subtly shift the ping indicator to control panel * Marks ordering in Sheaf and L-Trees (#114) * do sheafs grow on trees * sangh session dealing with lineage * Solve initial order problem * fix: ensure non-null id used @ EditableMarkDisplay --------- Co-authored-by: ks0m1c_dharma <[email protected]> * Trigger Diff * TOMBSTONING * Fix bugs and revert ui for read_mode:delete marks 1. JIT generate id for marks yet to be inserted to the db: instead of using a temp id, I'm actually assigning a JIT-generated id for a mark even if that isn't inserted into the db yet. this has two benefits: div ids have meaningful static ids (e.g. mark-container-\<\> mark.id) regardless of whether that mark has been inserted into the db or not. While doing this, the changeset for marks has been udpated to add id as well. This fixes a bunch of id-based errors as well. 2. while doing 1, it came to light that the bindHoverune handlers were not handling the draft mark update properly (i.e. not using the already existing update function in mark) . it's changed now, example of the diff: ``` diff @impl true def handle_event( "bindHoveRune", %{"binding" => bind = %{"verse_id" => verse_id}}, %{ assigns: %{ kv_verses: verses, marks: [%Mark{state: :draft, verse_id: curr_verse_id} = d_mark | marks] } } = socket ) when is_binary(curr_verse_id) and verse_id != curr_verse_id do # binding here blocks the stream from appending to quote bind = Draft.bind_node(bind) bound_verses = verses |> then(&put_in(&1[verse_id].binding, bind)) |> then(&put_in(&1[curr_verse_id].binding, nil)) + updated_draft_mark = d_mark |> Mark.update_mark(%{binding: bind, verse_id: verse_id}) + {:noreply, socket |> mutate_verses(curr_verse_id, bound_verses) |> mutate_verses(verse_id, bound_verses) - |> assign(:marks, [%{d_mark | binding: bind, verse_id: verse_id} | marks])} + |> assign(:marks, [updated_draft_mark | marks])} end ``` 3. add ui state structs: all of the relevant ui states have structs that are intended to be static interfaces. this felt better than directly keeping state within various sockets and is done with a view to remove live components and change them to function components wherever possible. 4. bugfix for `order()`: - it had an off-by-one-error - shifted it to Vyasa.Sangh.Mark - also note that the order shall be 1-indexed instead of 0-indexed for human-friendliness 5. minor fixes: 1. fix update<sub>mark</sub> default argument ``` diff -def update_mark(%Mark{} = draft_mark, opts \\ []) do +def update_mark(%Mark{} = draft_mark, opts \\ %{}) do ``` 1. In this commit, the marks<sub>ui</sub> is NOT kept by the read context module, that's why when I update things by create mark or delete mark, the ui state is not preserved and initial, default state is seen. This was intentionally done in this commit because I'm having problems with duplicate ids for verses for some reason, I'll show it in the next commit, so that the problem can be clearly seen. * [BUGGY] keep marks_ui within ReadContext This is buggy, not sure why there's a duplicate yet. will come back to it after lunch Replication Steps: 1. delete all marks and see there's no error 2. create first mark ==> no error 3. create second mark ==> crashes due to duplicate verse id Crash dump: [debug] Replied in 13ms [error] GenServer #PID<0.8416.0> terminating ** (RuntimeError) found duplicate ID "verse-7d9d588a-34fc-4f19-b974-fc32b49b6a61" for component VyasaWeb.Context.Read.VerseMatrix when rendering template (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:634: anonymous fn/5 in Phoenix.LiveView.Diff.render_pending_components/6 (elixir 1.17.2) lib/enum.ex:2531: Enum."-reduce/3-lists^foldl/2-0-"/3 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:631: anonymous fn/4 in Phoenix.LiveView.Diff.render_pending_components/6 (stdlib 5.2.3) maps.erl:416: :maps.fold_1/4 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:625: Phoenix.LiveView.Diff.render_pending_components/6 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:217: Phoenix.LiveView.Diff.write_component/4 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/channel.ex:662: Phoenix.LiveView.Channel.component_handle/4 (stdlib 5.2.3) gen_server.erl:1095: :gen_server.try_handle_info/3 (stdlib 5.2.3) gen_server.erl:1183: :gen_server.handle_msg/6 (stdlib 5.2.3) proc_lib.erl:251: :proc_lib.wake_up/3 Last message: %Phoenix.Socket.Message{topic: "lv:phx-F_1MH_6F0ciqVqwi", event: "event", payload: %{"cid" => 3, "event" => "createMark", "type" => "form", "value" => "body=how+about+now%2C+any+duplicate%3F"}, ref: "23", join_ref: "4"} State: %{socket: #Phoenix.LiveView.Socket<id: "phx-F_1MH_6F0ciqVqwi", endpoint: VyasaWeb.Endpoint, view: VyasaWeb.ModeLive.Mediator, parent_pid: nil, root_pid: #PID<0.8416.0>, router: VyasaWeb.Router, assigns: %{mode: %VyasaWeb.ModeLive.UserMode{mode: "read", default_ui_state: %VyasaWeb.ModeLive.UiState{show_media_bridge?: true, show_action_bar?: true}, mode_icon_name: "hero-book-open", quick_actions: [:mark_quote, :bookmark], control_panel_modes: ["discuss"], mode_actions: [:mark_quote, :bookmark], action_bar_actions: [:nav_back, :nav_fwd], action_bar_info_types: nil, action_bar_component: VyasaWeb.MediaLive.MediaBridge, action_bar_component_selector: "media-bridge", control_panel_component: VyasaWeb.ControlPanel, control_panel_component_selector: "control-panel", mode_context_component: VyasaWeb.Context.Read, mode_context_component_selector: "read"}, session: %VyasaWeb.Session{name: "ritesh kumar", id: "IhrQV0ypqg8bHakbvb2bymNF", active: true, sangh: %Vyasa.Sangh.Session{__meta__: #Ecto.Schema.Metadata<:loaded, "sessions">, id: "164eb05d-221a-4939-b180-8394e1a5515f", sheafs: #Ecto.Association.NotLoaded<association :sheafs is not loaded>, inserted_at: ~U[2024-09-27 00:51:48Z], updated_at: ~U[2024-09-27 00:51:48Z]}, last_opened: "2024-09-23T11:03:32.022987Z"}, __changed__: %{}, flash: %{}, locale: "en-GB", url_params: %{"chap_no" => "1", "source_title" => "hanuman_chalisa"}, live_action: :show_verses, ui_state: %VyasaWeb.ModeLive.UiState{show_media_bridge?: true, show_action_bar?: true}, device_type: :desktop, tz: %{timezone: "Asia/Singapore", timezone_offset: 480}}, transport_pid: #PID<0.8403.0>, ...>, components: {%{15 => {VyasaWeb.Context.Read.VerseMatrix, "verse-aa3ad88b-0de1-443e-b471-c08a44e67c61", %{id: "verse-aa3ad88b-0de1-443e-b471-c08a44e67c61", edge: [%{title: "1.10", field: [:body], verseup: {:big, "dn"}}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body_translit], verseup: :mid}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body_translit_meant], verseup: :mid}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body], verseup: :mid}], __changed__: %{}, flash: %{}, marks: [%Vyasa.Sangh.Mark{__meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "5dfdb167-6c57-46dd-a0c4-10b52cb03a85", body: "wonderful", order: 2, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "001da594-3808-46cf-9b9c-5dfb3559780e", binding: %Vyasa.Adapters.Binding{__meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "001da594-3808-46cf-9b9c-5dfb3559780e", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil}, inserted_at: ~U[2024-10-11 04:31:50Z], updated_at: ~U[2024-10-11 04:31:50Z]}, %Vyasa.Sangh.Mark{__meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "273a093d-4f90-40a4-b19a-2f8f7825d201", body: "truncated utc datetime", order: 1, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "ef39315b-530c-4841-ba32-86773f451727", binding: %Vyasa.Adapt (truncated) [debug] MOUNT VyasaWeb.ModeLive.Mediator Parameters: %{"chap_no" => "1", "source_title" => "hanuman_chalisa"} Session: %{"_csrf_token" => "DJ-RIoXwEzHW82rbb21le_8k"} [debug] QUERY OK source="sessions" db=3.5ms idle=1690.4ms SELECT s0."id", s0."inserted_at", s0."updated_at" FROM "sessions" AS s0 WHERE (s0."id" = $1) ["164eb05d-221a-4939-b180-8394e1a5515f"] ↳ * Fix duplicate id issue on verse matrix * Standardise use of @event_target, cleanups When using @event_target, the intent is that phx-target values will be passed around. This must be agnostic to the 2 main ways of supplying that argument, as a HTML selector, or as a module name (or @myself). Therefore, we should discourage ourselves from doing format-strings at the point of the @event_target being supplied as an argument, meaning: good, because agnostic: phx-target={@event_target} bad, because hardcoded: phx-target={"#" <> @event_target} * in this case, the event trigger will throw a dom error. * [Attempt]: Sanitise, defrag orders in marks-list If this is an anti-pattern, then this commit should be reverted. * UI fixes: hide buttons on marks when !is_editable? * Add in stub event handlers to prevent crashes Temporary stuff, will be addressed in immediate-next PR * Minor changes * Toggle edit state for marks content * Partial implementation of edit marks the form stuff doesn't exist so it's not wired up yet. To be frank, im' not sure how to set up a form without it needing to hold state. * [BUGGY] Wire up form update for edit this does the following: 1. wires up the form like how we usedd it in createMark 2. actually captures the event properly within the event handler, everything looks good at that point, even the edit_mark_in_marks function on inspection looks good 3. the marks is getting assigned to properly because the newly edited mark content is seen after doing a dom refresh 4. HOWEVER, the print statement at the sheaf_update function DOES NOT show the correct, updated marks in the sheaf here's a dump for it for reference [debug] HANDLE EVENT "editMarkContent" in VyasaWeb.ModeLive.Mediator Component: VyasaWeb.Context.Read Parameters: %{"mark_id" => "02218551-591f-4450-abbd-a7b7d76fd48e"} [debug] Replied in 2ms [debug] HANDLE EVENT "editMarkContent" in VyasaWeb.ModeLive.Mediator Component: VyasaWeb.Context.Read Parameters: %{"mark_body" => " testing\n\n\nwhat hte heck", "mark_id" => "02218551-591f-4450-abbd-a7b7d76fd48e"} >>> UPDATE SHEAF -- SHOULD BE WRITING TO DB NOW: %Vyasa.Sangh.Sheaf{ __meta__: #Ecto.Schema.Metadata<:loaded, "sheafs">, id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", body: nil, active: true, path: %EctoLtree.LabelTree{labels: ["7f4ab16b"]}, signature: nil, traits: ["draft"], child_count: 0, session_id: "164eb05d-221a-4939-b180-8394e1a5515f", session: #Ecto.Association.NotLoaded<association :session is not loaded>, parent_id: nil, parent: #Ecto.Association.NotLoaded<association :parent is not loaded>, marks: [ %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "555eb625-e392-496e-9831-4f4c130be6fd", body: "wonderful stuff", order: 5, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "072124d0-5e27-4601-832f-35eaa6426879", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "072124d0-5e27-4601-832f-35eaa6426879", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 08:46:54Z], updated_at: ~U[2024-10-12 08:46:54Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "b22a5661-8268-4875-be26-a12256414136", body: nil, order: 5, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "90e18044-73b2-4ede-a149-a381de893b9f", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "90e18044-73b2-4ede-a149-a381de893b9f", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "fc80709a-39dc-4b9c-95c3-1d64ce818302", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:52:40Z], updated_at: ~U[2024-10-12 09:52:40Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "8af43833-575c-4eb8-83b1-eb4e58509e4c", body: nil, order: 4, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "23b70937-ed81-47fe-a560-ee14287bff7d", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "23b70937-ed81-47fe-a560-ee14287bff7d", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:46:13Z], updated_at: ~U[2024-10-12 09:46:13Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "c7ad47e6-629d-4382-936d-64d757772c4e", body: nil, order: 3, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "d5758230-7966-4f9b-8c16-ae13998cd71b", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "d5758230-7966-4f9b-8c16-ae13998cd71b", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "fc80709a-39dc-4b9c-95c3-1d64ce818302", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:44:09Z], updated_at: ~U[2024-10-12 09:44:09Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "02218551-591f-4450-abbd-a7b7d76fd48e", body: "testing", order: 2, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "19ffdc82-a5d8-49c3-8b01-1559736dad80", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "19ffdc82-a5d8-49c3-8b01-1559736dad80", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "fc80709a-39dc-4b9c-95c3-1d64ce818302", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-12 09:43:19Z], updated_at: ~U[2024-10-12 09:43:19Z] }, %Vyasa.Sangh.Mark{ __meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "90c6036a-9bd1-4b65-82d5-f121ec4d7867", body: nil, order: 2, state: :draft, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "b92f990d-99a2-4f04-a2d4-d1135021ee8c", binding: %Vyasa.Adapters.Binding{ __meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "b92f990d-99a2-4f04-a2d4-d1135021ee8c", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil }, inserted_at: ~U[2024-10-11 09:03:00Z], updated_at: ~U[2024-10-11 09:03:00Z] } ], inserted_at: ~N[2024-09-27 00:51:48], updated_at: ~N[2024-09-27 00:51:48] } [debug] Replied in 81ms [debug] HANDLE EVENT "verses::focus_toggle_on_quick_mark_drafting" in VyasaWeb.ModeLive.Mediator Component: VyasaWeb.Context.Read Parameters: %{"is_focusing?" => false, "value" => ""} [debug] Replied in 129µs iex([email protected])17> * marks order force * old man mark is not feeling so good * ReWrite how marks get initialised @ :show_verse (#119) * Minor change in fn signature * Add init_draft_reflector() --------- Co-authored-by: ks0m1c_dharma <[email protected]> * Minor changes * Add a generic modal wrapper (#120) * Add generic debug dump component This makes life easy when wiring things up * Rename namespace for Context.Read.* * Groundwork: add discuss component w sheafs * Init Context.Components mod for common components * Add skeletons for Sheaf Container Container managers sheaf state within itself. Should actually make the verse-matrix use this container, sometime. * Minor changes, add some TODOs to share explicit todos Minor change * Add live component EditableMarkDisplay * Add UI improvements to EditableMarkDisplay The edit button on quick draft should only be seen when the dropdown is expanded and all the marks can be seen. The general pattern I'm trying to follow is that buttons should only be shown when an action makes sense. So here, if the user can't even see the marks currently accumulating, then the user shouldn't have the chance to edit any marks. Notice that the EditableMarkDisplay is a live_component that is a child of a function component (collapsible_marks_display). This is so that it can keep its own state and do it's own event-handling. I'm not sure if this is pattern-breaking. A reference to the actual parent live_component that calls collapsible_marks_display will always be there in case there's a need for the parent to handle any particular events. So comms b/w live_components is still going to be via phx-target values. * Change <input/> -> <textarea/> fr quick_draft_form * Add tailwind config for custom svg icons not sure how the scaling for this works, seems like i can't just put in the class="h-5 w-5" to do the scaling * Let custom svg be scalable * Subtly shift the ping indicator to control panel * Marks ordering in Sheaf and L-Trees (#114) * do sheafs grow on trees * sangh session dealing with lineage * Solve initial order problem * fix: ensure non-null id used @ EditableMarkDisplay --------- Co-authored-by: ks0m1c_dharma <[email protected]> * Trigger Diff * TOMBSTONING * Fix bugs and revert ui for read_mode:delete marks 1. JIT generate id for marks yet to be inserted to the db: instead of using a temp id, I'm actually assigning a JIT-generated id for a mark even if that isn't inserted into the db yet. this has two benefits: div ids have meaningful static ids (e.g. mark-container-\<\> mark.id) regardless of whether that mark has been inserted into the db or not. While doing this, the changeset for marks has been udpated to add id as well. This fixes a bunch of id-based errors as well. 2. while doing 1, it came to light that the bindHoverune handlers were not handling the draft mark update properly (i.e. not using the already existing update function in mark) . it's changed now, example of the diff: ``` diff @impl true def handle_event( "bindHoveRune", %{"binding" => bind = %{"verse_id" => verse_id}}, %{ assigns: %{ kv_verses: verses, marks: [%Mark{state: :draft, verse_id: curr_verse_id} = d_mark | marks] } } = socket ) when is_binary(curr_verse_id) and verse_id != curr_verse_id do # binding here blocks the stream from appending to quote bind = Draft.bind_node(bind) bound_verses = verses |> then(&put_in(&1[verse_id].binding, bind)) |> then(&put_in(&1[curr_verse_id].binding, nil)) + updated_draft_mark = d_mark |> Mark.update_mark(%{binding: bind, verse_id: verse_id}) + {:noreply, socket |> mutate_verses(curr_verse_id, bound_verses) |> mutate_verses(verse_id, bound_verses) - |> assign(:marks, [%{d_mark | binding: bind, verse_id: verse_id} | marks])} + |> assign(:marks, [updated_draft_mark | marks])} end ``` 3. add ui state structs: all of the relevant ui states have structs that are intended to be static interfaces. this felt better than directly keeping state within various sockets and is done with a view to remove live components and change them to function components wherever possible. 4. bugfix for `order()`: - it had an off-by-one-error - shifted it to Vyasa.Sangh.Mark - also note that the order shall be 1-indexed instead of 0-indexed for human-friendliness 5. minor fixes: 1. fix update<sub>mark</sub> default argument ``` diff -def update_mark(%Mark{} = draft_mark, opts \\ []) do +def update_mark(%Mark{} = draft_mark, opts \\ %{}) do ``` 1. In this commit, the marks<sub>ui</sub> is NOT kept by the read context module, that's why when I update things by create mark or delete mark, the ui state is not preserved and initial, default state is seen. This was intentionally done in this commit because I'm having problems with duplicate ids for verses for some reason, I'll show it in the next commit, so that the problem can be clearly seen. * [BUGGY] keep marks_ui within ReadContext This is buggy, not sure why there's a duplicate yet. will come back to it after lunch Replication Steps: 1. delete all marks and see there's no error 2. create first mark ==> no error 3. create second mark ==> crashes due to duplicate verse id Crash dump: [debug] Replied in 13ms [error] GenServer #PID<0.8416.0> terminating ** (RuntimeError) found duplicate ID "verse-7d9d588a-34fc-4f19-b974-fc32b49b6a61" for component VyasaWeb.Context.Read.VerseMatrix when rendering template (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:634: anonymous fn/5 in Phoenix.LiveView.Diff.render_pending_components/6 (elixir 1.17.2) lib/enum.ex:2531: Enum."-reduce/3-lists^foldl/2-0-"/3 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:631: anonymous fn/4 in Phoenix.LiveView.Diff.render_pending_components/6 (stdlib 5.2.3) maps.erl:416: :maps.fold_1/4 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:625: Phoenix.LiveView.Diff.render_pending_components/6 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/diff.ex:217: Phoenix.LiveView.Diff.write_component/4 (phoenix_live_view 1.0.0-rc.6) lib/phoenix_live_view/channel.ex:662: Phoenix.LiveView.Channel.component_handle/4 (stdlib 5.2.3) gen_server.erl:1095: :gen_server.try_handle_info/3 (stdlib 5.2.3) gen_server.erl:1183: :gen_server.handle_msg/6 (stdlib 5.2.3) proc_lib.erl:251: :proc_lib.wake_up/3 Last message: %Phoenix.Socket.Message{topic: "lv:phx-F_1MH_6F0ciqVqwi", event: "event", payload: %{"cid" => 3, "event" => "createMark", "type" => "form", "value" => "body=how+about+now%2C+any+duplicate%3F"}, ref: "23", join_ref: "4"} State: %{socket: #Phoenix.LiveView.Socket<id: "phx-F_1MH_6F0ciqVqwi", endpoint: VyasaWeb.Endpoint, view: VyasaWeb.ModeLive.Mediator, parent_pid: nil, root_pid: #PID<0.8416.0>, router: VyasaWeb.Router, assigns: %{mode: %VyasaWeb.ModeLive.UserMode{mode: "read", default_ui_state: %VyasaWeb.ModeLive.UiState{show_media_bridge?: true, show_action_bar?: true}, mode_icon_name: "hero-book-open", quick_actions: [:mark_quote, :bookmark], control_panel_modes: ["discuss"], mode_actions: [:mark_quote, :bookmark], action_bar_actions: [:nav_back, :nav_fwd], action_bar_info_types: nil, action_bar_component: VyasaWeb.MediaLive.MediaBridge, action_bar_component_selector: "media-bridge", control_panel_component: VyasaWeb.ControlPanel, control_panel_component_selector: "control-panel", mode_context_component: VyasaWeb.Context.Read, mode_context_component_selector: "read"}, session: %VyasaWeb.Session{name: "ritesh kumar", id: "IhrQV0ypqg8bHakbvb2bymNF", active: true, sangh: %Vyasa.Sangh.Session{__meta__: #Ecto.Schema.Metadata<:loaded, "sessions">, id: "164eb05d-221a-4939-b180-8394e1a5515f", sheafs: #Ecto.Association.NotLoaded<association :sheafs is not loaded>, inserted_at: ~U[2024-09-27 00:51:48Z], updated_at: ~U[2024-09-27 00:51:48Z]}, last_opened: "2024-09-23T11:03:32.022987Z"}, __changed__: %{}, flash: %{}, locale: "en-GB", url_params: %{"chap_no" => "1", "source_title" => "hanuman_chalisa"}, live_action: :show_verses, ui_state: %VyasaWeb.ModeLive.UiState{show_media_bridge?: true, show_action_bar?: true}, device_type: :desktop, tz: %{timezone: "Asia/Singapore", timezone_offset: 480}}, transport_pid: #PID<0.8403.0>, ...>, components: {%{15 => {VyasaWeb.Context.Read.VerseMatrix, "verse-aa3ad88b-0de1-443e-b471-c08a44e67c61", %{id: "verse-aa3ad88b-0de1-443e-b471-c08a44e67c61", edge: [%{title: "1.10", field: [:body], verseup: {:big, "dn"}}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body_translit], verseup: :mid}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body_translit_meant], verseup: :mid}, %{node: %Vyasa.Written.Translation{__meta__: #Ecto.Schema.Metadata<:loaded, "translations">, id: "651676b6-ffc3-41c1-b525-f376989f639e", lang: "en", type: "verses", target: %Vyasa.Written.Translation.Target{id: "dd20a94f-8f34-49f8-8da8-4321cfecf172", title: nil, title_translit: nil, body: "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", body_meant: nil, body_translit: "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", body_translit_meant: "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart."}, verse_id: "aa3ad88b-0de1-443e-b471-c08a44e67c61", verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: "63918acd-77a9-451a-b8d1-8d5b73208eae", source: #Ecto.Association.NotLoaded<association :source is not loaded>}, field: [:target, :body], verseup: :mid}], __changed__: %{}, flash: %{}, marks: [%Vyasa.Sangh.Mark{__meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "5dfdb167-6c57-46dd-a0c4-10b52cb03a85", body: "wonderful", order: 2, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "001da594-3808-46cf-9b9c-5dfb3559780e", binding: %Vyasa.Adapters.Binding{__meta__: #Ecto.Schema.Metadata<:loaded, "bindings">, id: "001da594-3808-46cf-9b9c-5dfb3559780e", w_type: nil, field_key: ["target", "body_translit_meant"], node_id: nil, verse_id: nil, verse: #Ecto.Association.NotLoaded<association :verse is not loaded>, chapter_no: nil, chapter: #Ecto.Association.NotLoaded<association :chapter is not loaded>, source_id: nil, source: #Ecto.Association.NotLoaded<association :source is not loaded>, translation_id: "97a7a662-a91b-486f-93e8-7ae932d01a1a", translation: #Ecto.Association.NotLoaded<association :translation is not loaded>, sheaf_id: nil, sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, window: nil}, inserted_at: ~U[2024-10-11 04:31:50Z], updated_at: ~U[2024-10-11 04:31:50Z]}, %Vyasa.Sangh.Mark{__meta__: #Ecto.Schema.Metadata<:loaded, "marks">, id: "273a093d-4f90-40a4-b19a-2f8f7825d201", body: "truncated utc datetime", order: 1, state: :live, verse_id: nil, sheaf_id: "7f4ab16b-0caf-4009-ba2a-3ddded81d9aa", sheaf: #Ecto.Association.NotLoaded<association :sheaf is not loaded>, binding_id: "ef39315b-530c-4841-ba32-86773f451727", binding: %Vyasa.Adapt (truncated) [debug] MOUNT VyasaWeb.ModeLive.Mediator Parameters: %{"chap_no" => "1", "source_title" => "hanuman_chalisa"} Session: %{"_csrf_token" => "DJ-RIoXwEzHW82rbb21le_8k"} [debug] QUERY OK source="sessions" db=3.5ms idle=1690.4ms SELECT s0."id", s0."inserted_at", s0."updated_at" FROM "sessions" AS s0 WHERE (s0."id" = $1) ["164eb05d-221a-4939-b180-8394e1a5515f"] ↳ * Fix duplicate id issue on verse matrix * Standardise use of @event_target, cleanups When using @event_target, the intent is that phx-target values will be passed around. This must be agnostic to the 2 main ways of supplying that argument, as a HTML selector, or as a module name (or @myself). Therefore, we should discourage ourselves from doing format-strings at the point of the @event_target being supplied as an argument, meaning: good, because agnostic: phx-target={@event_target} bad, because hardcoded: phx-target={"#" <> @event_target} * in this case, the event trigger will throw a dom er…
* HoverBraces * css madness as expected * certified icon wrangler * the forgotten icon lolol * specify top-3 for closing quote icon --------- Co-authored-by: ks0m1c_dharma <[email protected]> Co-authored-by: Ritesh Kumar <[email protected]>
* force diffs * Simplify read::init_reply_to_context * Add init routines for draft & replyto 1 Init Drafting and Reply To Contexts ═════════════════════════════════════ now that we have the read context cleaned up for both data and ui being managed at the sheaf-level, we just have to do the same for discuss, interfaced via the lattice. 1.1 Notes ───────── 1. At the same time we need to provision contexts: ‣ Reply to context: what is the current intent that you’re replying to ‣ drafting context: what are we currently drafting marks for? the lattices shall be the source of truth: -> sheaf_lattice: for data on sheafs, including marks -> sheaf_ui_lattice: for data on ui states We shall keep the lattices as the source of truth, so the `reply_to' and `draft_reflector' will be keeping the state, and the variables in state will just be the paths that point to the state, or in this case, the labels. Since state will be within the lattices, we don’t need a `draft_reflector_ui_id' 2. There’s actually a bit of duplicated patterns in both read and discuss modes, but I shall continue with the duplication until the patterns are well defined and ready to be refactored. I think the way to know if it’s time to refactor something is if the refactoring is going to be an easy task.
* share binding * binding jump * supress field for user selected bindings * focus bindings and cleanup --------- Co-authored-by: ks0m1c_dharma <[email protected]>
* suneye * faviconagraphy * sharing primitives to sessionbox more universal * Foundations of Disciple Panels * Resolve Refs to Anonymised User IDs * WorksPID assigned for future Binding Acked-by: ks0m1c_dharma <[email protected]> * Moduledocs & PR Cleanup --------- Co-authored-by: ks0m1c_dharma <[email protected]>
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
No description provided.