From efd5f1d126cd609be9a4381550f9a95d2e8a2c37 Mon Sep 17 00:00:00 2001
From: Nikos Papadakis
Date: Fri, 24 Nov 2023 00:56:38 +0200
Subject: [PATCH] app: alpine.js + dropdown
---
.editorconfig | 4 +
app/assets/js/app.js | 17 ++-
app/assets/package-lock.json | 33 +++++
app/assets/package.json | 5 +
app/lib/prymn_web/components/button.ex | 2 +-
.../prymn_web/components/core_components.ex | 56 +++++++++
.../components/layouts/app.html.heex | 23 ++--
app/lib/prymn_web/live/server_live/show.ex | 116 ++++++++++--------
8 files changed, 192 insertions(+), 64 deletions(-)
create mode 100644 app/assets/package-lock.json
create mode 100644 app/assets/package.json
diff --git a/.editorconfig b/.editorconfig
index 01be004..122b31f 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -2,6 +2,10 @@ root = true
charset = utf-8
end_of_line = lf
+[*.js]
+indent_style = space
+indent_size = 2
+
[*.nix]
indent_style = space
indent_size = 2
diff --git a/app/assets/js/app.js b/app/assets/js/app.js
index df0cdd9..b7a5ad9 100644
--- a/app/assets/js/app.js
+++ b/app/assets/js/app.js
@@ -15,15 +15,26 @@
// import "some-package"
//
-// Include phoenix_html to handle method=PUT/DELETE in forms and buttons.
import "phoenix_html"
-// Establish Phoenix Socket and LiveView configuration.
import {Socket} from "phoenix"
import {LiveSocket} from "phoenix_live_view"
import topbar from "../vendor/topbar"
+import Alpine from "alpinejs"
+
+Alpine.start()
+window.Alpine = Alpine
let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
-let liveSocket = new LiveSocket("/live", Socket, {params: {_csrf_token: csrfToken}})
+let liveSocket = new LiveSocket("/live", Socket, {
+ params: {_csrf_token: csrfToken},
+ dom: {
+ onBeforeElUpdated(from, to) {
+ if (from._x_dataStack) {
+ window.Alpine.clone(from, to)
+ }
+ }
+ }
+})
// Show progress bar on live navigation and form submits
topbar.config({barColors: {0: "#29d"}, shadowColor: "rgba(0, 0, 0, .3)"})
diff --git a/app/assets/package-lock.json b/app/assets/package-lock.json
new file mode 100644
index 0000000..ff530ff
--- /dev/null
+++ b/app/assets/package-lock.json
@@ -0,0 +1,33 @@
+{
+ "name": "assets",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "dependencies": {
+ "alpinejs": "^3.13.3"
+ }
+ },
+ "node_modules/@vue/reactivity": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.1.5.tgz",
+ "integrity": "sha512-1tdfLmNjWG6t/CsPldh+foumYFo3cpyCHgBYQ34ylaMsJ+SNHQ1kApMIa8jN+i593zQuaw3AdWH0nJTARzCFhg==",
+ "dependencies": {
+ "@vue/shared": "3.1.5"
+ }
+ },
+ "node_modules/@vue/shared": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.1.5.tgz",
+ "integrity": "sha512-oJ4F3TnvpXaQwZJNF3ZK+kLPHKarDmJjJ6jyzVNDKH9md1dptjC7lWR//jrGuLdek/U6iltWxqAnYOu8gCiOvA=="
+ },
+ "node_modules/alpinejs": {
+ "version": "3.13.3",
+ "resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-3.13.3.tgz",
+ "integrity": "sha512-WZ6WQjkAOl+WdW/jukzNHq9zHFDNKmkk/x6WF7WdyNDD6woinrfXCVsZXm0galjbco+pEpYmJLtwlZwcOfIVdg==",
+ "dependencies": {
+ "@vue/reactivity": "~3.1.1"
+ }
+ }
+ }
+}
diff --git a/app/assets/package.json b/app/assets/package.json
new file mode 100644
index 0000000..63b363b
--- /dev/null
+++ b/app/assets/package.json
@@ -0,0 +1,5 @@
+{
+ "dependencies": {
+ "alpinejs": "^3.13.3"
+ }
+}
diff --git a/app/lib/prymn_web/components/button.ex b/app/lib/prymn_web/components/button.ex
index a9e9c18..34ec4d8 100644
--- a/app/lib/prymn_web/components/button.ex
+++ b/app/lib/prymn_web/components/button.ex
@@ -36,7 +36,7 @@ defmodule PrymnWeb.Button do
assigns,
:style,
[
- "inline-flex justify-center items-end rounded-2xl shadow transition-colors active:shadow-sm",
+ "inline-flex justify-center items-center rounded-2xl shadow transition-colors active:shadow-sm",
by_variant(assigns.variant),
by_size(assigns.size),
assigns[:class]
diff --git a/app/lib/prymn_web/components/core_components.ex b/app/lib/prymn_web/components/core_components.ex
index adf7fc3..8dde58c 100644
--- a/app/lib/prymn_web/components/core_components.ex
+++ b/app/lib/prymn_web/components/core_components.ex
@@ -587,6 +587,62 @@ defmodule PrymnWeb.CoreComponents do
"""
end
+ @doc """
+ A simple dropdown menu
+ """
+
+ attr :title, :string, default: nil
+ attr :position, :string, default: "left", values: ~w(left right)
+
+ slot :button
+ slot :item
+
+ def dropdown(assigns) do
+ ~H"""
+
+
+
+
+ <%= render_slot(item, item) %>
+
+
+
+ """
+ end
+
## JS Commands
def show(js \\ %JS{}, selector) do
diff --git a/app/lib/prymn_web/components/layouts/app.html.heex b/app/lib/prymn_web/components/layouts/app.html.heex
index ab86cad..f63ac91 100644
--- a/app/lib/prymn_web/components/layouts/app.html.heex
+++ b/app/lib/prymn_web/components/layouts/app.html.heex
@@ -16,18 +16,17 @@
- <.link class="border-r border-l px-3 py-4 hover:bg-white" href={~p"/users/settings"}>
- <.icon name="hero-user" />
- <.icon name="hero-chevron-down" />
-
- <.link
- title="Log out"
- class="border-r px-3 py-4 hover:bg-white"
- method="DELETE"
- href={~p"/auth/log_out"}
- >
- <.icon name="hero-x-mark" />
-
+ <.dropdown>
+ <:button>
+ <.icon name="hero-user-solid" />
+
+ <:item>
+ <.link href={~p"/users/settings"}>Settings
+
+ <:item>
+ <.link method="DELETE" href={~p"/auth/log_out"}>Log out
+
+
diff --git a/app/lib/prymn_web/live/server_live/show.ex b/app/lib/prymn_web/live/server_live/show.ex
index 378eaf1..a8ac1f7 100644
--- a/app/lib/prymn_web/live/server_live/show.ex
+++ b/app/lib/prymn_web/live/server_live/show.ex
@@ -1,5 +1,4 @@
defmodule PrymnWeb.ServerLive.Show do
- alias DBConnection.App
use PrymnWeb, :live_view
require Logger
@@ -7,44 +6,38 @@ defmodule PrymnWeb.ServerLive.Show do
@impl true
def mount(_params, _session, socket) do
- {:ok, socket}
+ # TODO: A more lightweight call instead of listing all data?
+ servers = Servers.list_servers()
+ {:ok, assign(socket, :servers, servers)}
end
@impl true
def render(assigns) do
~H"""
- <.header>
-
-
-
-
+
+ <.dropdown title="Select a different server">
+ <:button>Server <%= @server.name %>
+ <:item :for={server <- Enum.filter(@servers, fn s -> s.id != @server.id end)}>
+ <.link
+ patch={~p"/servers/#{server}"}
+ class="block text-sm text-gray-700"
+ role="menuitem"
+ >
+ <%= server.name %>
+
+
+
+
+ <.indicator message={@health.message} />
+
- <:subtitle>
- <%= @server.public_ip %>
-
- <:actions>
+
New App
-
- Quick actions <.icon name="hero-chevron-down" class="ml-1" />
-
-
-
-
- <%= for {name, task} <- @health.tasks do %>
- Background task in progress: <%= name %>
-
<%= task.progress %> complete
- <% end %>
+ <.dropdown>
+ <:button>
+ Quick actions
+
+ <:item>
+ Test
+
+
+
+
+ <%= @server.public_ip %>
+
+
Background task in progress: <%= name %>
+
<%= task.progress %> complete
@@ -229,4 +223,30 @@ defmodule PrymnWeb.ServerLive.Show do
|> JS.hide()
|> JS.show(to: "#server-name", display: "flex")
end
+
+ defp indicator(assigns) do
+ ~H"""
+
+ <%= case @message do %>
+ <% "Connected" -> %>
+
+
+ <% "Disconnected" -> %>
+
+ <% _ -> %>
+
+ <% end %>
+
+ """
+ end
end