Skip to content

Commit

Permalink
Initial version of admin UI (#5)
Browse files Browse the repository at this point in the history
  • Loading branch information
yujonglee authored Jun 26, 2024
1 parent c0124e6 commit 4b325b6
Show file tree
Hide file tree
Showing 28 changed files with 692 additions and 94 deletions.
15 changes: 15 additions & 0 deletions core/assets/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,24 @@ import topbar from "../vendor/topbar";
let csrfToken = document
.querySelector("meta[name='csrf-token']")
.getAttribute("content");

let hooks = {
LocalTime: {
mounted() {
this.updated();
},
updated() {
let dt = new Date(this.el.textContent);
this.el.textContent = dt.toLocaleString();
this.el.classList.remove("invisible");
},
},
};

let liveSocket = new LiveSocket("/live", Socket, {
longPollFallbackMs: 2500,
params: { _csrf_token: csrfToken },
hooks,
});

// Show progress bar on live navigation and form submits
Expand Down
11 changes: 6 additions & 5 deletions core/lib/canary/accounts/account.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@ defmodule Canary.Accounts.Account do
attributes do
uuid_primary_key :id

attribute :user_id, :uuid do
allow_nil? false
end

attribute :name, :string do
allow_nil? false
end
Expand All @@ -21,13 +17,18 @@ defmodule Canary.Accounts.Account do
end

has_many :sources, Canary.Sources.Source
has_many :clients, Canary.Clients.Client
end

actions do
defaults [:read]

create :create do
accept [:user_id, :name]
argument :user, :map, allow_nil?: false
argument :name, :string, allow_nil?: false

change manage_relationship(:user, :users, type: :append)
change set_attribute(:name, expr(^arg(:name)))
end

update :update do
Expand Down
2 changes: 1 addition & 1 deletion core/lib/canary/accounts/changes/init_account.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ defmodule Canary.Accounts.Changes.InitAccount do
def change(changeset, _, _) do
Ash.Changeset.after_action(changeset, fn _, user ->
case Canary.Accounts.Account
|> Ash.Changeset.for_create(:create, %{user_id: user.id, name: @default_account_name})
|> Ash.Changeset.for_create(:create, %{user: user, name: @default_account_name})
|> Ash.create() do
{:ok, _} -> {:ok, user}
error -> error
Expand Down
12 changes: 7 additions & 5 deletions core/lib/canary/accounts/user.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@ defmodule Canary.Accounts.User do
attributes do
uuid_primary_key :id

attribute :email, :ci_string do
allow_nil? false
public? true
end

attribute :email, :ci_string, allow_nil?: false, public?: true
attribute :hashed_password, :string, allow_nil?: false, sensitive?: true
end

actions do
defaults [:read]

create :mock, accept: [:email, :hashed_password]
end

relationships do
many_to_many :accounts, Canary.Accounts.Account do
through Canary.Accounts.AccountUser
Expand Down
40 changes: 22 additions & 18 deletions core/lib/canary/clients/client.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@ defmodule Canary.Clients.Client do

attributes do
uuid_primary_key :id
create_timestamp :created_at
attribute :account_id, :uuid, allow_nil?: false

attribute :account_id, :uuid do
allow_nil? false
end

attribute :name, :string, allow_nil?: false
attribute :type, :atom, constraints: [one_of: [:web, :discord]]

attribute :web_base_url, :string
Expand All @@ -25,7 +24,12 @@ defmodule Canary.Clients.Client do
end

actions do
defaults [:read, :destroy]
defaults [:destroy]

read :read do
primary? true
prepare build(load: [:sources])
end

read :find_discord do
argument :discord_server_id, :integer, allow_nil?: false
Expand All @@ -40,24 +44,22 @@ defmodule Canary.Clients.Client do
end

create :create_web do
argument :account_id, :uuid do
allow_nil? false
end
argument :account, :map, allow_nil?: false
argument :name, :string, allow_nil?: false

argument :web_base_url, :string do
allow_nil? false
end
argument :web_base_url, :string, allow_nil?: false

change set_attribute(:type, :web)
change set_attribute(:account_id, expr(^arg(:account_id)))
change set_attribute(:name, expr(^arg(:name)))
change manage_relationship(:account, :account, type: :append)
change set_attribute(:web_base_url, expr(^arg(:web_base_url)))
change set_attribute(:web_public_key, &Ash.UUID.generate/0)
change load(:sources)
end

create :create_discord do
argument :account_id, :uuid do
allow_nil? false
end
argument :account, :map, allow_nil?: false
argument :name, :string, allow_nil?: false

argument :discord_server_id, :integer do
allow_nil? false
Expand All @@ -68,23 +70,25 @@ defmodule Canary.Clients.Client do
end

change set_attribute(:type, :discord)
change set_attribute(:account_id, expr(^arg(:account_id)))
change set_attribute(:name, expr(^arg(:name)))
change manage_relationship(:account, :account, type: :append)
change set_attribute(:discord_server_id, expr(^arg(:discord_server_id)))
change set_attribute(:discord_channel_id, expr(^arg(:discord_channel_id)))
change load(:sources)
end

update :add_sources do
require_atomic? false

argument :sources, {:array, :map}, allow_nil?: true
change manage_relationship(:sources, type: :append)
change manage_relationship(:sources, :sources, type: :append)
end

update :remove_sources do
require_atomic? false

argument :sources, {:array, :map}, allow_nil?: true
change manage_relationship(:sources, type: :remove)
change manage_relationship(:sources, :sources, type: :remove)
end
end

Expand Down
28 changes: 15 additions & 13 deletions core/lib/canary/sources/source.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@ defmodule Canary.Sources.Source do

attributes do
uuid_primary_key :id
create_timestamp :created_at
attribute :account_id, :uuid, allow_nil?: false

attribute :account_id, :uuid do
allow_nil? false
end

attribute :name, :string, allow_nil?: false
attribute :type, :atom, constraints: [one_of: [:web]]

attribute :web_base_url, :string
Expand All @@ -21,20 +20,23 @@ defmodule Canary.Sources.Source do
end

actions do
defaults [:read]
defaults [:destroy]

create :create_web do
argument :account_id, :uuid do
allow_nil? false
end
read :read do
primary? true
prepare build(load: [:updated_at])
end

argument :web_base_url, :string do
allow_nil? false
end
create :create_web do
argument :name, :string, allow_nil?: false
argument :account, :map, allow_nil?: false
argument :web_base_url, :string, allow_nil?: false

change set_attribute(:type, :web)
change set_attribute(:account_id, expr(^arg(:account_id)))
change set_attribute(:name, expr(^arg(:name)))
change manage_relationship(:account, :account, type: :append)
change set_attribute(:web_base_url, expr(^arg(:web_base_url)))
change load(:updated_at)
end
end

Expand Down
9 changes: 9 additions & 0 deletions core/lib/canary_web/components/core_components.ex
Original file line number Diff line number Diff line change
Expand Up @@ -672,4 +672,13 @@ defmodule CanaryWeb.CoreComponents do
def translate_errors(errors, field) when is_list(errors) do
for {^field, {msg, opts}} <- errors, do: translate_error({msg, opts})
end

attr :id, :string
attr :date, :string

def local_time(assigns) do
~H"""
<time phx-hook="LocalTime" id={@id} class="invisible"><%= @date %></time>
"""
end
end
30 changes: 29 additions & 1 deletion core/lib/canary_web/components/layouts.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ defmodule CanaryWeb.Layouts do
~H"""
<aside class="drawer-side z-10">
<label for="canary-drawer" class="drawer-overlay"></label>
<nav class="flex min-h-screen w-72 flex-col gap-2 overflow-y-auto bg-base-100 px-6 py-10">
<nav class="flex min-h-screen w-72 flex-col gap-2 overflow-y-auto bg-base-100 px-6 pt-10 pb-4">
<.link class="mx-4 font-black flex flex-row gap-2" href="/">
<span>🐤</span>
<span>Canary</span>
Expand Down Expand Up @@ -51,6 +51,18 @@ defmodule CanaryWeb.Layouts do
<span>Clients</span>
</.link>
</li>
<li>
<.link class={if @active_tab == :sessions, do: "active"} navigate={~p"/sessions"}>
<span class={[
"h-4 w-4",
if(@active_tab == :sessions,
do: "hero-rectangle-stack-solid",
else: "hero-rectangle-stack"
)
]} />
<span>Sessions</span>
</.link>
</li>
<li>
<.link class={if @active_tab == :settings, do: "active"} navigate={~p"/settings"}>
<span class={[
Expand All @@ -64,8 +76,24 @@ defmodule CanaryWeb.Layouts do
</.link>
</li>
</ul>
<.link href="/sign-out" class="btn btn-sm btn-outline btn-neutral mt-auto">
Log out
</.link>
</nav>
</aside>
"""
end

slot :inner_block

def content_header(assigns) do
~H"""
<header class="flex items-center">
<label for="canary-drawer" class="btn btn-square btn-ghost drawer-button lg:hidden">
<span class="hero-bars-3-solid h-5 w-5" />
</label>
<%= render_slot(@inner_block) %>
</header>
"""
end
end
36 changes: 36 additions & 0 deletions core/lib/canary_web/live/client_live.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
defmodule CanaryWeb.ClientLive do
use CanaryWeb, :live_view
import CanaryWeb.Layouts, only: [content_header: 1]

def render(assigns) do
~H"""
<.content_header>
<div class="breadcrumbs text-md flex flex-row items-center justify-between">
<ul>
<li><.link navigate={~p"/clients"}>Clients</.link></li>
<li><a><%= @client.name %></a></li>
</ul>
</div>
<button class="btn btn-sm btn-neutral ml-auto" phx-click="delete">
Delete
</button>
</.content_header>
"""
end

def mount(%{"id" => id}, _session, socket) do
client = Canary.Clients.Client |> Ash.get!(id)

socket =
socket
|> assign(client: client)

{:ok, socket}
end

def handle_event("delete", _, socket) do
socket.assigns.client |> Ash.destroy!()
{:noreply, socket |> push_navigate(to: ~p"/clients")}
end
end
Loading

0 comments on commit 4b325b6

Please sign in to comment.