Skip to content

Commit

Permalink
add insights config
Browse files Browse the repository at this point in the history
  • Loading branch information
yujonglee committed Oct 16, 2024
1 parent 711bd27 commit 1079ea8
Show file tree
Hide file tree
Showing 17 changed files with 469 additions and 73 deletions.
11 changes: 9 additions & 2 deletions core/assets/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ let hooks = {
points() {
return JSON.parse(this.el.dataset.points);
},
mounted() {
render() {
/** @type {Chart} */
const config = {
type: "bar",
Expand All @@ -103,6 +103,7 @@ let hooks = {
beginAtZero: true,
ticks: {
format: {
minimumFractionDigits: 0,
maximumFractionDigits: 0,
}
}
Expand All @@ -119,9 +120,15 @@ let hooks = {
},
},
};

new Chart(this.el, config);
},
mounted() {
this.render();
},
updated() {
this.render();
},
},
LocalTime: {
mounted() {
Expand Down
3 changes: 2 additions & 1 deletion core/config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ config :canary,
ash_domains: [
Canary.Accounts,
Canary.Sources,
Canary.Github
Canary.Github,
Canary.Insights
]

config :hammer,
Expand Down
1 change: 1 addition & 0 deletions core/lib/canary/accounts/project.ex
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ defmodule Canary.Accounts.Project do
relationships do
belongs_to :account, Canary.Accounts.Account, allow_nil?: false
has_many :sources, Canary.Sources.Source
has_one :insights_config, Canary.Insights.Config
end

actions do
Expand Down
2 changes: 1 addition & 1 deletion core/lib/canary/application.ex
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ defmodule Canary.Application do

children =
[
Canary.Interactions.Processor,
Canary.Insights.Processor,
Canary.Vault,
{Cachex, name: :cache},
{Task.Supervisor, name: Canary.TaskSupervisor},
Expand Down
26 changes: 26 additions & 0 deletions core/lib/canary/insights/config.ex
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
7 changes: 7 additions & 0 deletions core/lib/canary/insights/insights.ex
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
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
defmodule Canary.Interactions.Processor do
defmodule Canary.Insights.Processor do
@moduledoc """
Background processor for every interaction.
Usage:
GenServer.cast(Canary.Interactions.Processor, {:search, %{session_id: "...", project_id: "...", query: "..."}})
GenServer.cast(Canary.Insights.Processor, {:search, %{session_id: "...", project_id: "...", query: "..."}})
"""

use GenServer
Expand Down
17 changes: 17 additions & 0 deletions core/lib/canary/insights/query_alias.ex
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
60 changes: 0 additions & 60 deletions core/lib/canary_web/live/insight_live.ex

This file was deleted.

195 changes: 195 additions & 0 deletions core/lib/canary_web/live/insights_live/config.ex
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
Loading

0 comments on commit 1079ea8

Please sign in to comment.