-
-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
17 changed files
with
469 additions
and
73 deletions.
There are no files selected for viewing
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
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
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
defmodule Canary.Insights.Config do | ||
use Ash.Resource, | ||
domain: Canary.Insights, | ||
data_layer: AshPostgres.DataLayer | ||
|
||
alias Canary.Insights.QueryAlias | ||
|
||
attributes do | ||
uuid_primary_key :id | ||
|
||
attribute :aliases, {:array, QueryAlias}, default: [] | ||
end | ||
|
||
relationships do | ||
belongs_to :project, Canary.Accounts.Project | ||
end | ||
|
||
actions do | ||
defaults [:read, :destroy, create: [:aliases, :project_id], update: [:aliases]] | ||
end | ||
|
||
postgres do | ||
table "insights_configs" | ||
repo Canary.Repo | ||
end | ||
end |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
defmodule Canary.Insights do | ||
use Ash.Domain | ||
|
||
resources do | ||
resource Canary.Insights.Config | ||
end | ||
end |
6 changes: 2 additions & 4 deletions
6
core/lib/canary/interactions/processor.ex → core/lib/canary/insights/processor.ex
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
defmodule Canary.Insights.QueryAlias do | ||
use Ash.Resource, data_layer: :embedded | ||
|
||
attributes do | ||
attribute :name, :string, allow_nil?: false | ||
attribute :members, {:array, :string}, default: [] | ||
end | ||
|
||
actions do | ||
defaults [ | ||
:read, | ||
:destroy, | ||
create: [:name, :members], | ||
update: [:name, :members] | ||
] | ||
end | ||
end |
This file was deleted.
Oops, something went wrong.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,195 @@ | ||
defmodule CanaryWeb.InsightLive.Config do | ||
use CanaryWeb, :live_component | ||
alias PrimerLive.Component, as: Primer | ||
|
||
@impl true | ||
def render(assigns) do | ||
~H""" | ||
<div> | ||
<.form | ||
:let={f} | ||
for={@form} | ||
phx-target={@myself} | ||
phx-change="validate" | ||
phx-submit="submit" | ||
class="flex flex-col gap-4" | ||
> | ||
<input type="hidden" name={f[:project_id].name} value={@current_project.id} /> | ||
<.inputs_for :let={fc} field={f[:aliases]}> | ||
<div class="p-2 border-2 border-gray-200 rounded-md flex flex-col gap-4"> | ||
<div class="flex flex-row justify-between"> | ||
<Primer.text_input | ||
form={fc} | ||
field={:name} | ||
is_full_width | ||
form_control={%{label: "Name"}} | ||
/> | ||
<Primer.octicon | ||
class="ml-auto" | ||
name="x-16" | ||
phx-target={@myself} | ||
phx-click="remove_alias" | ||
phx-value-item={fc.name} | ||
/> | ||
</div> | ||
<.form_group header="Members"> | ||
<%= for {member, index} <- Enum.with_index(fc[:members].value || []) do %> | ||
<div class="flex flex-row gap-2 items-center"> | ||
<Primer.text_input | ||
name={fc.name <> "[members][#{index}]"} | ||
value={member} | ||
is_full_width | ||
/> | ||
<Primer.octicon | ||
class="cursor-pointer" | ||
name="x-16" | ||
phx-target={@myself} | ||
phx-click="remove_member" | ||
phx-value-item={fc.name <> "[members][#{index}]"} | ||
/> | ||
</div> | ||
<% end %> | ||
<Primer.button | ||
type="button" | ||
phx-target={@myself} | ||
phx-click="add_member" | ||
phx-value-item={fc.name} | ||
is_small | ||
> | ||
+ | ||
</Primer.button> | ||
</.form_group> | ||
</div> | ||
</.inputs_for> | ||
<Primer.button type="button" phx-target={@myself} phx-click="add_alias"> | ||
+ | ||
</Primer.button> | ||
<Primer.button type="button" phx-target={@myself} phx-click="submit"> | ||
Save | ||
</Primer.button> | ||
</.form> | ||
</div> | ||
""" | ||
end | ||
|
||
attr :header, :string, required: true | ||
slot :inner_block, required: true | ||
|
||
def form_group(assigns) do | ||
~H""" | ||
<div class="flex flex-col gap-2"> | ||
<div class="form-group-header"> | ||
<span class="FormControl-label"><%= @header %></span> | ||
</div> | ||
<%= render_slot(@inner_block) %> | ||
</div> | ||
""" | ||
end | ||
|
||
@impl true | ||
def update(assigns, socket) do | ||
socket = | ||
socket | ||
|> assign(assigns) | ||
|> assign_form() | ||
|
||
{:ok, socket} | ||
end | ||
|
||
defp assign_form(socket) do | ||
if socket.assigns.current_project.insights_config do | ||
socket |> assign_update_form() | ||
else | ||
socket |> assign_create_form() | ||
end | ||
end | ||
|
||
defp assign_create_form(socket) do | ||
form = | ||
Canary.Insights.Config | ||
|> AshPhoenix.Form.for_create(:create, forms: [auto?: true]) | ||
|> to_form() | ||
|
||
socket |> assign(:form, form) | ||
end | ||
|
||
defp assign_update_form(socket) do | ||
form = | ||
socket.assigns.current_project.insights_config | ||
|> AshPhoenix.Form.for_update(:update, forms: [auto?: true]) | ||
|> to_form() | ||
|
||
socket |> assign(:form, form) | ||
end | ||
|
||
@impl true | ||
def handle_event("validate", %{"form" => params}, socket) do | ||
form = AshPhoenix.Form.validate(socket.assigns.form, params) | ||
{:noreply, assign(socket, form: form)} | ||
end | ||
|
||
def handle_event("submit", _, socket) do | ||
case AshPhoenix.Form.submit(socket.assigns.form, params: socket.assigns.form.params) do | ||
{:ok, _} -> {:noreply, socket |> push_navigate(to: ~p"/insight")} | ||
{:error, form} -> {:noreply, assign(socket, form: form)} | ||
end | ||
end | ||
|
||
def handle_event("add_alias", _, socket) do | ||
empty = %{"name" => "", "members" => %{}} | ||
|
||
form = | ||
socket.assigns.form | ||
|> AshPhoenix.Form.add_form("aliases", params: empty) | ||
|
||
{:noreply, assign(socket, form: form)} | ||
end | ||
|
||
def handle_event("remove_alias", %{"item" => item}, socket) do | ||
form = socket.assigns.form |> AshPhoenix.Form.remove_form(item) | ||
{:noreply, assign(socket, form: form)} | ||
end | ||
|
||
def handle_event("add_member", %{"item" => path}, socket) do | ||
form = | ||
socket.assigns.form | ||
|> AshPhoenix.Form.update_form(path, fn nested_form -> | ||
# TODO: not work with update | ||
params = | ||
nested_form.params | ||
|> Map.update("members", %{}, fn existing -> | ||
new_key = existing |> map_size() |> to_string() | ||
existing |> Map.put(new_key, "") | ||
end) | ||
|
||
AshPhoenix.Form.validate(nested_form, params) | ||
end) | ||
|
||
{:noreply, assign(socket, form: form)} | ||
end | ||
|
||
def handle_event("remove_member", %{"item" => item}, socket) do | ||
[path, nth] = String.split(item, "[members]") | ||
nth = nth |> String.at(1) |> String.to_integer() | ||
|
||
form = | ||
socket.assigns.form | ||
|> AshPhoenix.Form.update_form(path, fn nested_form -> | ||
params = | ||
nested_form.params | ||
|> Map.update("members", %{}, fn existing -> | ||
existing | ||
|> Enum.sort_by(fn {key, _} -> String.to_integer(key) end) | ||
|> List.delete_at(nth) | ||
|> Map.new() | ||
end) | ||
|
||
AshPhoenix.Form.validate(nested_form, params) | ||
end) | ||
|
||
{:noreply, assign(socket, form: form)} | ||
end | ||
end |
Oops, something went wrong.