diff --git a/docs/migration_wow.livemd b/docs/migration_wow.livemd index 38b18d61..af8e2b9c 100644 --- a/docs/migration_wow.livemd +++ b/docs/migration_wow.livemd @@ -54,7 +54,6 @@ Vyasa.Release.migrate() ```elixir Path.expand(mypath, "#{File.cwd!()}/data/Elixir.Vyasa.Written.Source") -|> Vyasa.Corpus.Migrator.Restore.read() |> Vyasa.Corpus.Migrator.Restore.run() ``` @@ -93,10 +92,12 @@ end) ```elixir # can test if events are seeded correctly here: voice_id = "b1db78be-0bdf-443c-afdf-3221bac38758" -loaded_voice = Vyasa.Repo.get(Vyasa.Medium.Voice, voice_id) -|> Vyasa.Medium.get_voices!() -|> List.first() -|> Vyasa.Medium.Store.hydrate() + +loaded_voice = + Vyasa.Repo.get(Vyasa.Medium.Voice, voice_id) + |> Vyasa.Medium.get_voices!() + |> List.first() + |> Vyasa.Medium.Store.hydrate() loaded_voice.events ``` diff --git a/lib/vyasa/corpus/migrator/restore.ex b/lib/vyasa/corpus/migrator/restore.ex index 9f0ed127..bf7d2fca 100644 --- a/lib/vyasa/corpus/migrator/restore.ex +++ b/lib/vyasa/corpus/migrator/restore.ex @@ -41,6 +41,7 @@ defmodule Vyasa.Corpus.Migrator.Restore do # events are dependent on both verse and voice source + |> read() |> Enum.map(fn x -> # &1["translations"] x["events"] diff --git a/lib/vyasa/draft.ex b/lib/vyasa/draft.ex index f525372e..1e90739e 100644 --- a/lib/vyasa/draft.ex +++ b/lib/vyasa/draft.ex @@ -6,7 +6,6 @@ defmodule Vyasa.Draft do import Ecto.Query, warn: false alias Vyasa.Adapters.Binding alias Vyasa.Sangh.Mark - alias Vyasa.Sangh alias Vyasa.Repo # Inits the binding for an empty selection @@ -45,10 +44,6 @@ defmodule Vyasa.Draft do %{bind | node_field_name => node_id, :node_id => node_id} end - def create_comment([%Mark{} | _] = marks) do - Sangh.create_comment(%{marks: marks}) - end - @doc """ Returns the list of marks. diff --git a/lib/vyasa/sangh/comments.ex b/lib/vyasa/sangh/comments.ex index c12c6ee7..4a190b04 100644 --- a/lib/vyasa/sangh/comments.ex +++ b/lib/vyasa/sangh/comments.ex @@ -1,4 +1,13 @@ defmodule Vyasa.Sangh.Comment do + @moduledoc """ + Not your traditional comments, waypoints and containers for marks + so that they can be referred to and moved around + + Can create a trail of marks and tied to session + Can seperate marks into collapsible categories + + Sangh session Ids is SOT on shared and individual context + """ use Ecto.Schema import Ecto.Changeset alias EctoLtree.LabelTree, as: Ltree @@ -10,22 +19,22 @@ defmodule Vyasa.Sangh.Comment do field :active, :boolean, default: true field :path, Ltree field :signature, :string + field :traits, {:array, :string}, default: [] field :child_count, :integer, default: 0, virtual: true belongs_to :session, Session, references: :id, type: Ecto.UUID belongs_to :parent, Comment, references: :id, type: Ecto.UUID - #has_many :marks, Mark, references: :id, foreign_key: :comment_bind_id, on_replace: :delete_if_exists + has_many :marks, Mark, references: :id, foreign_key: :comment_id, on_replace: :delete_if_exists #has_many :bindings, Binding, references: :id, foreign_key: :comment_bind_id, on_replace: :delete_if_exists - timestamps() end @doc false def changeset(%Comment{} = comment, attrs) do comment - |> cast(attrs, [:id, :body, :path, :chapter_number, :p_type, :session_id, :parent_id, :text_id]) - |> cast_assoc(:bindings, with: &Mark.changeset/2) + |> cast(attrs, [:id, :body, :path, :session_id, :signature, :parent_id]) + |> cast_assoc(:marks, with: &Mark.changeset/2) |> validate_required([:id, :session_id]) end diff --git a/lib/vyasa/sangh/mark.ex b/lib/vyasa/sangh/mark.ex index e14d2673..c539de4e 100644 --- a/lib/vyasa/sangh/mark.ex +++ b/lib/vyasa/sangh/mark.ex @@ -27,7 +27,7 @@ defmodule Vyasa.Sangh.Mark do def changeset(event, attrs) do event - |> cast(attrs, [:body, :order, :status, :comment_id, :binding_id]) + |> cast(attrs, [:body, :order, :state, :comment_id, :binding_id]) end def update_mark(%Mark{} = draft_mark, opts \\ []) do diff --git a/lib/vyasa/sangh/session.ex b/lib/vyasa/sangh/session.ex index eee306f4..b77789d6 100644 --- a/lib/vyasa/sangh/session.ex +++ b/lib/vyasa/sangh/session.ex @@ -4,6 +4,7 @@ defmodule Vyasa.Sangh.Session do alias Vyasa.Sangh.{Comment} + @derive {Jason.Encoder, only: [:id]} @primary_key {:id, Ecto.UUID, autogenerate: true} schema "sessions" do @@ -16,6 +17,5 @@ defmodule Vyasa.Sangh.Session do def changeset(session, attrs) do session |> cast(attrs, [:id]) - |> validate_required([:id]) end end diff --git a/lib/vyasa/written/verse.ex b/lib/vyasa/written/verse.ex index 5659677d..95b56461 100644 --- a/lib/vyasa/written/verse.ex +++ b/lib/vyasa/written/verse.ex @@ -3,20 +3,18 @@ defmodule Vyasa.Written.Verse do import Ecto.Changeset alias Vyasa.Written.{Source, Chapter, Translation} - alias Vyasa.Sangh.{Comment} - alias Vyasa.Adapters.Binding @primary_key {:id, Ecto.UUID, autogenerate: true} schema "verses" do field :no, :integer field :body, :string field :binding, :map, virtual: true + field :comments, {:array, :map}, virtual: true, default: [] belongs_to :source, Source, type: Ecto.UUID belongs_to :chapter, Chapter, type: :integer, references: :no, foreign_key: :chapter_no has_many :translations, Translation - many_to_many :comments, Comment, join_through: Binding end @doc false diff --git a/lib/vyasa_web/components/source_content/reading_content.ex b/lib/vyasa_web/components/source_content/reading_content.ex index 6f500748..fcf582ac 100644 --- a/lib/vyasa_web/components/source_content/reading_content.ex +++ b/lib/vyasa_web/components/source_content/reading_content.ex @@ -13,7 +13,7 @@ defmodule VyasaWeb.Content.ReadingContent do alias Vyasa.Medium.{Voice} alias Vyasa.Written.{Source, Chapter} alias Phoenix.LiveView.Socket - alias Vyasa.Sangh.{Comment, Mark} + alias Vyasa.Sangh.{Mark} alias VyasaWeb.OgImageController @impl true @@ -43,7 +43,7 @@ defmodule VyasaWeb.Content.ReadingContent do @impl true # received updates from parent liveview when a handshake is init, does a pub for the voice to use def update( - %{id: "reading-content", sess_id: sess_id} = _props, + %{id: "reading-content"} = _props, %{ assigns: %{ session: %{id: sess_id}, @@ -127,27 +127,16 @@ defmodule VyasaWeb.Content.ReadingContent do socket - |> sync_session() - |> assign(:content_action, :show_verses) - |> maybe_stream_configure(:verses, dom_id: &"verse-#{&1.id}") - |> stream(:verses, verses) |> assign( :kv_verses, # creates a map of verse_id_to_verses - Enum.into( - verses, - %{}, - &{&1.id, - %{ - &1 - | comments: [ - %Comment{signature: "Pope", body: "Achilles’ wrath, to Greece the direful spring - Of woes unnumber’d, heavenly goddess, sing"} - ] - }} - ) - ) + Enum.into(verses, %{},&({&1.id, &1}) + )) |> assign(:marks, [%Mark{state: :draft, order: 0}]) + |> sync_session() + |> assign(:content_action, :show_verses) + |> maybe_stream_configure(:verses, dom_id: &"verse-#{&1.id}") + |> stream(:verses, verses) # DEPRECATED # RENAME? |> assign(:src, source) @@ -209,12 +198,10 @@ defmodule VyasaWeb.Content.ReadingContent do defp sync_session(%Socket{assigns: %{session: %{id: sess_id}}} = socket) when is_binary(sess_id) do Vyasa.PubSub.subscribe("written:session:" <> sess_id) Vyasa.PubSub.publish(:init, :written_handshake, "media:session:" <> sess_id) - IO.inspect(sess_id <> " sync la") socket end defp sync_session(socket) do - IO.inspect(socket, label: "not ready to init sync of session from within ReadingContent") socket end @@ -421,6 +408,7 @@ defmodule VyasaWeb.Content.ReadingContent do ~H"""
Hello world, i'm the ReadingContent
+ Session: <%= @session && @session.name %>
<%= @user_mode.mode_context_component %> <%= @user_mode.mode_context_component_selector %> <.button phx-click="foo" phx-target={@myself}> diff --git a/lib/vyasa_web/live/display_manager/display_live.ex b/lib/vyasa_web/live/display_manager/display_live.ex index 0e59fade..9466d9f1 100644 --- a/lib/vyasa_web/live/display_manager/display_live.ex +++ b/lib/vyasa_web/live/display_manager/display_live.ex @@ -37,12 +37,21 @@ defmodule VyasaWeb.DisplayManager.DisplayLive do } end - defp sync_session(%{assigns: %{session: %Session{name: name} = sess}} = socket) when is_binary(name) do + defp sync_session(%{assigns: %{session: %Session{name: name, sangh: %{id: _s_id}} = sess}} = socket) when is_binary(name) do # currently needs name prerequisite to save socket |> push_event("initSession", sess) end + defp sync_session(%{assigns: %{session: %Session{name: name} = sess}} = socket) when is_binary(name) do + # initialises sangh if uninitiated (didnt init at Vyasa.Session) + {:ok, sangh} = Vyasa.Sangh.create_session() + sangh_sess = %{sess | sangh: sangh} + socket + |> assign(session: sangh_sess) + |> push_event("initSession", sangh_sess) + end + defp sync_session(socket) do socket end @@ -149,7 +158,6 @@ defmodule VyasaWeb.DisplayManager.DisplayLive do {_, :media_handshake, :init} = _msg, %{ assigns: %{ - session: %VyasaWeb.Session{id: sess_id}, mode: %UserMode{ mode_context_component: component, mode_context_component_selector: selector @@ -157,8 +165,8 @@ defmodule VyasaWeb.DisplayManager.DisplayLive do } } = socket ) do - IO.inspect(sess_id, label: "media handshake") - send_update(component, id: selector, sess_id: sess_id) + + send_update(component, id: selector) {:noreply, socket} end diff --git a/lib/vyasa_web/live/media_live/media_bridge.ex b/lib/vyasa_web/live/media_live/media_bridge.ex index 3e725a61..835a2209 100644 --- a/lib/vyasa_web/live/media_live/media_bridge.ex +++ b/lib/vyasa_web/live/media_live/media_bridge.ex @@ -358,7 +358,6 @@ defmodule VyasaWeb.MediaLive.MediaBridge do true -> nil end - IO.inspect("voice acked") is_new_voice = id !== prev_id diff --git a/lib/vyasa_web/session.ex b/lib/vyasa_web/session.ex index 59b393c3..75f977e3 100644 --- a/lib/vyasa_web/session.ex +++ b/lib/vyasa_web/session.ex @@ -3,12 +3,20 @@ defmodule VyasaWeb.Session do import Phoenix.LiveView, only: [get_connect_params: 1] @derive Jason.Encoder - defstruct name: nil, id: nil, active: true, sangh_id: Ecto.UUID.generate(), last_opened: DateTime.now!("Etc/UTC") + defstruct name: nil, id: nil, active: true, sangh: nil, last_opened: DateTime.now!("Etc/UTC") @default_locale "en" @timezone "UTC" @timezone_offset 0 + defguard is_uuid?(value) + when is_bitstring(value) and + byte_size(value) == 36 and + binary_part(value, 8, 1) == "-" and + binary_part(value, 13, 1) == "-" and + binary_part(value, 18, 1) == "-" and + binary_part(value, 23, 1) == "-" + def on_mount(:sangh, params, _sessions, socket) do # get_connect_params returns nil on the first (static rendering) mount call, and has the added connect params from the js LiveSocket creation on the subsequent (LiveSocket) call # @@ -22,23 +30,29 @@ defmodule VyasaWeb.Session do )} end - defp mutate_session(%{"id" => id} = sess, %{"s" => s_id}) when is_binary(id) and is_binary(s_id)do + defp mutate_session(%{"id" => id} = sess, %{"s" => s_id}) when is_binary(id) and is_uuid?(s_id)do atomised_sess = for {key, val} <- sess, into: %{} do - {String.to_existing_atom(key), val} + hydrate_session(key, val) end - %{struct(%__MODULE__{}, atomised_sess ) | sangh_id: s_id} + %{struct(%__MODULE__{}, atomised_sess ) | sangh: Vyasa.Sangh.get_session!(s_id)} end # careful of client and server state race. id here is not SOT defp mutate_session(%{"id" => id} = sess, _) when is_binary(id) do atomised_sess = for {key, val} <- sess, into: %{} do - {String.to_existing_atom(key), val} + hydrate_session(key, val) end - IO.inspect(struct(%__MODULE__{}, atomised_sess), label: "wow") struct(%__MODULE__{}, atomised_sess) end # false first load defp mutate_session(_, _), do: %__MODULE__{} + + + defp hydrate_session("sangh", %{"id" => s_id}) do + {:sangh, Vyasa.Sangh.get_session!(s_id)} + end + + defp hydrate_session(key, val), do: {String.to_existing_atom(key), val} end diff --git a/priv/repo/migrations/20240151122233_create_sangh_sessions.exs b/priv/repo/migrations/20240151122233_create_sangh_sessions.exs index 793ee07a..d9761732 100644 --- a/priv/repo/migrations/20240151122233_create_sangh_sessions.exs +++ b/priv/repo/migrations/20240151122233_create_sangh_sessions.exs @@ -13,16 +13,19 @@ defmodule Vyasa.Repo.Migrations.CreateSanghSessions do create table(:comments, primary_key: false) do add :id, :uuid, primary_key: true - add :body, :text, null: false + add :body, :text add :active, :boolean, default: false add :path, :ltree add :signature, :string add :session_id, references(:sessions, column: :id, type: :uuid) add :parent_id, references(:comments, column: :id, type: :uuid) + add :traits, :jsonb timestamps(type: :utc_datetime_usec) end + execute("CREATE INDEX comments_traits_index ON comments USING GIN(traits jsonb_path_ops)", "DROP INDEX comments_traits_index") + create table(:bindings, primary_key: false) do add :id, :uuid, primary_key: true @@ -41,4 +44,5 @@ defmodule Vyasa.Repo.Migrations.CreateSanghSessions do create index(:bindings, [:chapter_no, :source_id]) end + end diff --git a/priv/repo/migrations/20240831122233_create_marks.exs b/priv/repo/migrations/20240831122233_create_marks.exs index c3ccf5c8..be9f9989 100644 --- a/priv/repo/migrations/20240831122233_create_marks.exs +++ b/priv/repo/migrations/20240831122233_create_marks.exs @@ -6,17 +6,17 @@ defmodule Vyasa.Repo.Migrations.CreateMarks do create table(:marks, primary_key: false) do add :id, :uuid, primary_key: true add :body, :string - add :order, :integer + add :state, :string - add :window, :jsonb + add :order, :integer - add :verse_id, references(:verses, column: :id, type: :uuid, on_delete: :nothing) + add :comment_id, references(:comments, column: :id, type: :uuid, on_delete: :nothing) add :binding_id, references(:bindings, column: :id, type: :uuid, on_delete: :nothing) timestamps(type: :utc_datetime_usec) end - create index(:marks, [:verse_id]) + create index(:marks, [:comment_id]) create index(:marks, [:binding_id]) end