diff --git a/lib/frenzy_web/live/configure_stage/conditional_stage_live.ex b/lib/frenzy_web/live/configure_stage/conditional_stage_live.ex new file mode 100644 index 0000000..788db04 --- /dev/null +++ b/lib/frenzy_web/live/configure_stage/conditional_stage_live.ex @@ -0,0 +1,213 @@ +defmodule FrenzyWeb.ConfigureStage.ConditionalStageLive do + use FrenzyWeb, :live_component + alias Frenzy.{Keypath, JSONSchema} + + @stages FrenzyWeb.EditPipelineLive.stages() + + @impl true + def mount(socket) do + {:ok, assign(socket, stages: @stages, confirm_convert_to_rule: false)} + end + + @impl true + def update(assigns, socket) do + assigns = Map.put(assigns, :opts, Frenzy.Keypath.get(assigns.stage, assigns.keypath)) + {:ok, assign(socket, assigns)} + end + + @impl true + def handle_event("update_stage", %{"opts" => %{"stage" => ""}}, socket) do + {:noreply, socket} + end + + @impl true + def handle_event("update_stage", %{"opts" => %{"stage" => module}}, socket) do + default_options = apply(String.to_existing_atom("Elixir." <> module), :default_opts, []) + + new_opts = + socket.assigns.opts + |> Map.put("stage", module) + |> Map.put("opts", default_options) + + new_stage = Frenzy.Keypath.set(socket.assigns.stage, socket.assigns.keypath, new_opts) + + send(self(), {:update_stage, socket.assigns.index, new_stage}) + {:noreply, socket} + end + + @impl true + def handle_event("update_filter", %{"mode" => mode, "score" => score}, socket) do + new_opts = + socket.assigns.opts + |> Keypath.set(["condition", "mode"], mode) + |> Keypath.set(["condition", "score"], JSONSchema.coerce(:integer, score)) + + new_stage = Frenzy.Keypath.set(socket.assigns.stage, socket.assigns.keypath, new_opts) + + send(self(), {:update_stage, socket.assigns.index, new_stage}) + {:noreply, socket} + end + + @impl true + def handle_event("add_rule", _params, socket) do + new_rules = + socket.assigns.opts["condition"]["rules"] ++ + [%{"mode" => "text", "param" => "", "property" => "title", "weight" => 1}] + + new_stage = + Frenzy.Keypath.set( + socket.assigns.stage, + socket.assigns.keypath ++ ["condition", "rules"], + new_rules + ) + + send(self(), {:update_stage, socket.assigns.index, new_stage}) + {:noreply, socket} + end + + @impl true + def handle_event("delete_rule", %{"index" => index}, socket) do + index = String.to_integer(index) + + new_rules = + socket.assigns.opts + |> Frenzy.Keypath.get(["condition", "rules"]) + |> List.delete_at(index) + + new_stage = + Frenzy.Keypath.set( + socket.assigns.stage, + socket.assigns.keypath ++ ["condition", "rules"], + new_rules + ) + + send(self(), {:update_stage, socket.assigns.index, new_stage}) + {:noreply, socket} + end + + @impl true + def handle_event( + "update_rule", + %{ + "index" => "no_index", + "mode" => mode, + "param" => param, + "property" => property, + "weight" => weight + }, + socket + ) do + new_rule = + socket.assigns.opts["condition"] + |> Map.put("mode", mode) + |> Map.put("param", param) + |> Map.put("property", property) + |> Map.put("weight", JSONSchema.coerce(:integer, weight)) + + new_stage = + Frenzy.Keypath.set( + socket.assigns.stage, + socket.assigns.keypath ++ ["condition"], + new_rule + ) + + send(self(), {:update_stage, socket.assigns.index, new_stage}) + {:noreply, socket} + end + + @impl true + def handle_event( + "update_rule", + %{ + "index" => index, + "mode" => mode, + "param" => param, + "property" => property, + "weight" => weight + }, + socket + ) do + index = String.to_integer(index) + + new_rule = + Enum.at(socket.assigns.opts["condition"]["rules"], index) + |> Map.put("mode", mode) + |> Map.put("param", param) + |> Map.put("property", property) + |> Map.put("weight", JSONSchema.coerce(:integer, weight)) + + new_stage = + Frenzy.Keypath.set( + socket.assigns.stage, + socket.assigns.keypath ++ ["condition", "rules", index], + new_rule + ) + + send(self(), {:update_stage, socket.assigns.index, new_stage}) + {:noreply, socket} + end + + @impl true + def handle_event("convert_to_filter", _value, socket) do + rule = socket.assigns.opts["condition"] + filter = %{"mode" => "accept", "score" => 1, "rules" => [rule]} + + new_stage = + Keypath.set( + socket.assigns.stage, + socket.assigns.keypath ++ ["condition"], + filter + ) + + send(self(), {:update_stage, socket.assigns.index, new_stage}) + {:noreply, socket} + end + + @impl true + def handle_event("convert_to_rule", _value, socket) do + rules = socket.assigns.opts["condition"]["rules"] + + case length(rules) do + 0 -> + new_stage = + Keypath.set( + socket.assigns.stage, + socket.assigns.keypath ++ ["condition"], + %{"mode" => "text", "param" => "", "property" => "title", "weight" => 1} + ) + + send(self(), {:update_stage, socket.assigns.index, new_stage}) + {:noreply, socket} + + 1 -> + handle_event("confirm_convert_to_rule", nil, socket) + + _count -> + {:noreply, assign(socket, confirm_convert_to_rule: true)} + end + end + + @impl true + def handle_event("cancel_convert_to_rule", _value, socket) do + {:noreply, assign(socket, confirm_convert_to_rule: false)} + end + + @impl true + def handle_event("confirm_convert_to_rule", _value, socket) do + rule = socket.assigns.opts["condition"]["rules"] |> List.first() + + new_stage = + Keypath.set( + socket.assigns.stage, + socket.assigns.keypath ++ ["condition"], + rule + ) + + send(self(), {:update_stage, socket.assigns.index, new_stage}) + {:noreply, assign(socket, confirm_convert_to_rule: false)} + end + + def component_module(name) do + FrenzyWeb.EditPipelineLive.component_module(name) + end +end diff --git a/lib/frenzy_web/live/configure_stage/conditional_stage_live.html.leex b/lib/frenzy_web/live/configure_stage/conditional_stage_live.html.leex new file mode 100644 index 0000000..9d34c65 --- /dev/null +++ b/lib/frenzy_web/live/configure_stage/conditional_stage_live.html.leex @@ -0,0 +1,68 @@ +
<%= Jason.encode!(@opts, pretty: true) %>+ <% end %> + + <%= f = form_for @opts, "#", [as: :opts, phx_change: :update_stage, phx_target: @myself] %> +
This will modify the conditional stage to only run when the first rule is met. Are you sure you want to proceed?
+ + +