Add conditional stage live configuration
This commit is contained in:
parent
daa0c51db5
commit
f5dc0b8deb
|
@ -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
|
|
@ -0,0 +1,68 @@
|
||||||
|
<div id="<%= @id %>">
|
||||||
|
<%= if Mix.env == :dev do %>
|
||||||
|
<pre><%= Jason.encode!(@opts, pretty: true) %></pre>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<%= f = form_for @opts, "#", [as: :opts, phx_change: :update_stage, phx_target: @myself] %>
|
||||||
|
<div class="form-group row">
|
||||||
|
<label class="col-sm-2 col-form-label" for="<%= @id %>-stage">Module</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<%= select f, :stage, @stages, prompt: "Select a stage...", id: "#{@id}-stage", class: "custom-select" %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div class="card mb-2">
|
||||||
|
<div class="card-header">
|
||||||
|
<h4 class="m-0"><%= @opts["stage"] %></h4>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<% component = component_module(@opts["stage"]) %>
|
||||||
|
<%= unless is_nil(component) do %>
|
||||||
|
<%= live_component(@socket, component, index: @index, id: "#{@id}-conditional", stage: @stage, keypath: @keypath ++ ["opts"]) %>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<%= if @opts["condition"]["mode"] in ["accept", "reject"] do %>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<h4 class="m-0">Condition: Filter</h4>
|
||||||
|
</div>
|
||||||
|
<div class="col text-right">
|
||||||
|
<button phx-click="convert_to_rule" phx-target="#<%= @id %>" class="btn btn-primary btn-sm">Convert to Rule</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<%= if @confirm_convert_to_rule do %>
|
||||||
|
<div class="alert alert-danger mb-2">
|
||||||
|
<p>This will modify the conditional stage to only run when the first rule is met. Are you sure you want to proceed?</p>
|
||||||
|
<button class="btn btn-danger btn-sm" phx-click="confirm_convert_to_rule" phx-target="#<%= @id %>">Convert to Rule</button>
|
||||||
|
<button class="btn btn-secondary btn-sm" phx-click="cancel_convert_to_rule" phx-target="#<%= @id %>">Cancel</button>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<%= live_component @socket, FrenzyWeb.FilterLive, id: "##{@id}-filter", parent_id: @id, filter: @opts["condition"] %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% else %>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<h4 class="m-0">Condition: Rule</h4>
|
||||||
|
</div>
|
||||||
|
<div class="col text-right">
|
||||||
|
<button phx-click="convert_to_filter" phx-target="#<%= @id %>" class="btn btn-primary btn-sm">Convert to Filter</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<%= live_component @socket, FrenzyWeb.FilterRuleLive, id: "##{@id}-rule", parent_id: @id, rule: @opts["condition"], index: :no_index %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
|
@ -84,9 +84,8 @@ defmodule FrenzyWeb.EditPipelineLive do
|
||||||
{:noreply, assign(socket, pipeline: pipeline)}
|
{:noreply, assign(socket, pipeline: pipeline)}
|
||||||
end
|
end
|
||||||
|
|
||||||
def component_for(socket, %{"module_name" => module} = stage, index) do
|
def component_module(module_name) do
|
||||||
component =
|
case module_name do
|
||||||
case module do
|
|
||||||
"Frenzy.Pipeline.ScrapeStage" ->
|
"Frenzy.Pipeline.ScrapeStage" ->
|
||||||
FrenzyWeb.ConfigureStage.ScrapeStageLive
|
FrenzyWeb.ConfigureStage.ScrapeStageLive
|
||||||
|
|
||||||
|
@ -99,8 +98,10 @@ defmodule FrenzyWeb.EditPipelineLive do
|
||||||
_ ->
|
_ ->
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
case component do
|
def component_for(socket, %{"module_name" => module} = stage, index) do
|
||||||
|
case component_module(module) do
|
||||||
nil ->
|
nil ->
|
||||||
nil
|
nil
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,22 @@
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<%= for {rule, index} <- Enum.with_index(@filter["rules"]) do %>
|
<%= for {rule, index} <- Enum.with_index(@filter["rules"]) do %>
|
||||||
|
<div class="card mt-2">
|
||||||
|
<div class="card-header container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<h5 class="m-0">Rule <%= index %></h5>
|
||||||
|
</div>
|
||||||
|
<div class="col text-right">
|
||||||
|
<button phx-click="delete_rule" phx-value-index="<%= index %>" phx-target="#<%= @id %>">Delete</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
<%= live_component @socket, FrenzyWeb.FilterRuleLive, id: "#{@id}-rule-#{index}", parent_id: @parent_id, rule: rule, index: index %>
|
<%= live_component @socket, FrenzyWeb.FilterRuleLive, id: "#{@id}-rule-#{index}", parent_id: @parent_id, rule: rule, index: index %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<%= f = form_for :rule, "#", class: "mt-2", phx_submit: :add_rule, phx_target: "##{@parent_id}" %>
|
<%= f = form_for :rule, "#", class: "mt-2", phx_submit: :add_rule, phx_target: "##{@parent_id}" %>
|
||||||
<%= submit "Add Rule", class: "btn btn-primary" %>
|
<%= submit "Add Rule", class: "btn btn-primary" %>
|
||||||
|
|
|
@ -1,15 +1,4 @@
|
||||||
<div id="<%= @id %>" class="card mt-2">
|
<div id="<%= @id %>">
|
||||||
<div class="card-header container-fluid">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col">
|
|
||||||
<h5 class="m-0">Rule <%= @index %></h5>
|
|
||||||
</div>
|
|
||||||
<div class="col text-right">
|
|
||||||
<button phx-click="delete_rule" phx-value-index="<%= @index %>" phx-target="#<%= @parent_id %>">Delete</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<%= f = form_for @rule, "#", [phx_change: :update_rule, phx_target: "##{@parent_id}"] %>
|
<%= f = form_for @rule, "#", [phx_change: :update_rule, phx_target: "##{@parent_id}"] %>
|
||||||
<%= hidden_input f, :index, value: @index %>
|
<%= hidden_input f, :index, value: @index %>
|
||||||
<div class="form-group row mb-2">
|
<div class="form-group row mb-2">
|
||||||
|
@ -37,5 +26,4 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue