From a10f1bea3016d0dce4129562beb99f65f8c6b426 Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Sat, 18 Jul 2020 10:25:43 -0400 Subject: [PATCH] Add live filter configuration --- .../live/configure_stage/filter_stage_live.ex | 78 +++++++++++++++++++ .../filter_stage_live.html.leex | 6 ++ lib/frenzy_web/live/edit_pipeline_live.ex | 8 +- lib/frenzy_web/live/filter/filter_live.ex | 13 ++++ .../live/filter/filter_live.html.leex | 22 ++++++ .../live/filter/filter_rule_live.ex | 19 +++++ .../live/filter/filter_rule_live.html.leex | 41 ++++++++++ 7 files changed, 184 insertions(+), 3 deletions(-) create mode 100644 lib/frenzy_web/live/configure_stage/filter_stage_live.ex create mode 100644 lib/frenzy_web/live/configure_stage/filter_stage_live.html.leex create mode 100644 lib/frenzy_web/live/filter/filter_live.ex create mode 100644 lib/frenzy_web/live/filter/filter_live.html.leex create mode 100644 lib/frenzy_web/live/filter/filter_rule_live.ex create mode 100644 lib/frenzy_web/live/filter/filter_rule_live.html.leex diff --git a/lib/frenzy_web/live/configure_stage/filter_stage_live.ex b/lib/frenzy_web/live/configure_stage/filter_stage_live.ex new file mode 100644 index 0000000..c721dda --- /dev/null +++ b/lib/frenzy_web/live/configure_stage/filter_stage_live.ex @@ -0,0 +1,78 @@ +defmodule FrenzyWeb.ConfigureStage.FilterStageLive do + use FrenzyWeb, :live_component + + @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_filter", %{"mode" => mode, "score" => score}, socket) do + new_opts = + socket.assigns.opts + |> Map.put("mode", mode) + |> Map.put("score", 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["rules"] ++ + [%{"mode" => "text", "param" => "", "property" => "title", "weight" => 1}] + + new_opts = Map.put(socket.assigns.opts, "rules", new_rules) + 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("delete_rule", %{"index" => index}, socket) do + index = String.to_integer(index) + new_rules = List.delete_at(socket.assigns.opts["rules"], index) + new_opts = Map.put(socket.assigns.opts, "rules", new_rules) + 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_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["rules"], index) + |> Map.put("mode", mode) + |> Map.put("param", param) + |> Map.put("property", property) + |> Map.put("weight", weight) + + new_stage = + Frenzy.Keypath.set( + socket.assigns.stage, + socket.assigns.keypath ++ ["rules", index], + new_rule + ) + + send(self(), {:update_stage, socket.assigns.index, new_stage}) + {:noreply, socket} + end +end diff --git a/lib/frenzy_web/live/configure_stage/filter_stage_live.html.leex b/lib/frenzy_web/live/configure_stage/filter_stage_live.html.leex new file mode 100644 index 0000000..4fb09c3 --- /dev/null +++ b/lib/frenzy_web/live/configure_stage/filter_stage_live.html.leex @@ -0,0 +1,6 @@ +
+ <%= if Mix.env == :dev do %> +
<%= Jason.encode!(@opts, pretty: true) %>
+ <% end %> + <%= live_component @socket, FrenzyWeb.FilterLive, id: "#{@id}-filter", parent_id: @id, filter: @opts %> +
diff --git a/lib/frenzy_web/live/edit_pipeline_live.ex b/lib/frenzy_web/live/edit_pipeline_live.ex index 0091f6e..850eec8 100644 --- a/lib/frenzy_web/live/edit_pipeline_live.ex +++ b/lib/frenzy_web/live/edit_pipeline_live.ex @@ -9,6 +9,8 @@ defmodule FrenzyWeb.EditPipelineLive do {"Conditional Stage", "Frenzy.Pipeline.ConditionalStage"} ] + def stages, do: @stages + @impl true def mount(%{"id" => pipeline_id}, _session, socket) do pipeline = Repo.get(Pipeline, pipeline_id) @@ -76,9 +78,6 @@ defmodule FrenzyWeb.EditPipelineLive do @impl true def handle_info({:update_stage, index, new_stage}, socket) do pipeline = socket.assigns.pipeline - # stages = pipeline.stages - # stage = Enum.at(stages, index) - # new_stage = Map.put(stage, "options", new_opts) new_stages = List.replace_at(pipeline.stages, index, new_stage) changeset = Pipeline.changeset(pipeline, %{stages: new_stages}) {:ok, pipeline} = Repo.update(changeset) @@ -91,6 +90,9 @@ defmodule FrenzyWeb.EditPipelineLive do "Frenzy.Pipeline.ScrapeStage" -> FrenzyWeb.ConfigureStage.ScrapeStageLive + "Frenzy.Pipeline.FilterStage" -> + FrenzyWeb.ConfigureStage.FilterStageLive + "Frenzy.Pipeline.ConditionalStage" -> FrenzyWeb.ConfigureStage.ConditionalStageLive diff --git a/lib/frenzy_web/live/filter/filter_live.ex b/lib/frenzy_web/live/filter/filter_live.ex new file mode 100644 index 0000000..d739020 --- /dev/null +++ b/lib/frenzy_web/live/filter/filter_live.ex @@ -0,0 +1,13 @@ +defmodule FrenzyWeb.FilterLive do + use FrenzyWeb, :live_component + + @filter_modes [ + {"Accept", "accept"}, + {"Reject", "reject"} + ] + + @impl true + def mount(socket) do + {:ok, assign(socket, modes: @filter_modes)} + end +end diff --git a/lib/frenzy_web/live/filter/filter_live.html.leex b/lib/frenzy_web/live/filter/filter_live.html.leex new file mode 100644 index 0000000..f6dd5d4 --- /dev/null +++ b/lib/frenzy_web/live/filter/filter_live.html.leex @@ -0,0 +1,22 @@ +
+ <%= f = form_for @filter, "#", [phx_change: :update_filter, phx_target: "##{@parent_id}"] %> +
+ +
+ <%= select f, :mode, @modes, id: "#{@id}-mode", class: "custom-select" %> +
+
+
+ +
+ <%= number_input f, :score, id: "#{@id}-score", class: "form-control" %> +
+
+ + <%= for {rule, index} <- Enum.with_index(@filter["rules"]) do %> + <%= live_component @socket, FrenzyWeb.FilterRuleLive, id: "#{@id}-rule-#{index}", parent_id: @parent_id, rule: rule, index: index %> + <% end %> + <%= f = form_for :rule, "#", class: "mt-2", phx_submit: :add_rule, phx_target: "##{@parent_id}" %> + <%= submit "Add Rule", class: "btn btn-primary" %> + +
diff --git a/lib/frenzy_web/live/filter/filter_rule_live.ex b/lib/frenzy_web/live/filter/filter_rule_live.ex new file mode 100644 index 0000000..b33b274 --- /dev/null +++ b/lib/frenzy_web/live/filter/filter_rule_live.ex @@ -0,0 +1,19 @@ +defmodule FrenzyWeb.FilterRuleLive do + use FrenzyWeb, :live_component + + @modes [ + {"Contains Substring", "contains_string"}, + {"Matches Regex", "matches_regex"} + ] + + @properties [ + {"Title", "title"}, + {"URL", "url"}, + {"Author", "author"} + ] + + @impl true + def mount(socket) do + {:ok, assign(socket, modes: @modes, properties: @properties)} + end +end diff --git a/lib/frenzy_web/live/filter/filter_rule_live.html.leex b/lib/frenzy_web/live/filter/filter_rule_live.html.leex new file mode 100644 index 0000000..2f3a1f3 --- /dev/null +++ b/lib/frenzy_web/live/filter/filter_rule_live.html.leex @@ -0,0 +1,41 @@ +
+
+
+
+
Rule <%= @index %>
+
+
+ +
+
+
+
+ <%= f = form_for @rule, "#", [phx_change: :update_rule, phx_target: "##{@parent_id}"] %> + <%= hidden_input f, :index, value: @index %> +
+ +
+ <%= select f, :property, @properties, id: "#{@id}-property", class: "custom-select" %> +
+
+
+ +
+ <%= select f, :mode, @modes, id: "#{@id}-mode", class: "custom-select" %> +
+
+
+ +
+ <%= text_input f, :param, id: "#{@id}-param", placeholder: if(@rule["mode"] == "contains_string", do: "substring", else: "regex"), class: "form-control text-monospace" %> +
+
+
+ +
+ <%= number_input f, :weight, id: "#{@id}-weight", class: "form-control" %> +
+
+ +
+