From f1bc4280867025c0100de2e71cbfb610acdc0ddb Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Sat, 5 Jul 2025 12:51:28 -0500 Subject: [PATCH] deploy fix --- assets/js/features/weather_charts.ts | 27 ++-- assets/package-lock.json | 52 ------- assets/package.json | 7 - config/config.exs | 2 +- .../components/layouts/root.html.heex | 7 + .../status_live/connection_card_component.ex | 144 ++++++++++++++++++ lib/aprsme_web/live/status_live/index.ex | 12 +- 7 files changed, 173 insertions(+), 78 deletions(-) delete mode 100644 assets/package-lock.json delete mode 100644 assets/package.json create mode 100644 lib/aprsme_web/live/status_live/connection_card_component.ex diff --git a/assets/js/features/weather_charts.ts b/assets/js/features/weather_charts.ts index 575cf71..f01e21d 100644 --- a/assets/js/features/weather_charts.ts +++ b/assets/js/features/weather_charts.ts @@ -1,10 +1,13 @@ -/// -/// -// The above triple-slash directives help TypeScript find types for Chart.js and Phoenix LiveView. -// If you use a custom build or alias, ensure types are available in node_modules. +// Declare global Chart object from CDN +declare global { + interface Window { + Chart: any; + chartInstances?: Map; + } +} -import Chart from 'chart.js/auto'; -import type { Hook } from 'phoenix_live_view'; +// Type for LiveView hooks +type Hook = any; // Type for weather history data interface WeatherHistoryDatum { @@ -86,7 +89,7 @@ export const WeatherChartHooks: Record = { const colors = getThemeColors(); const canvas = self.el.querySelector('canvas') as HTMLCanvasElement; if (!canvas) return; - self.chart = new Chart(canvas, { + self.chart = new window.Chart(canvas, { type: 'line', data: { labels: times, @@ -137,7 +140,7 @@ export const WeatherChartHooks: Record = { const colors = getThemeColors(); const canvas = self.el.querySelector('canvas') as HTMLCanvasElement; if (!canvas) return; - self.chart = new Chart(canvas, { + self.chart = new window.Chart(canvas, { type: 'line', data: { labels: times, datasets: [{ label: 'Humidity (%)', data: humidity, borderColor: 'green', backgroundColor: 'rgba(0, 255, 0, 0.1)', tension: 0.1 }] }, options: { @@ -176,7 +179,7 @@ export const WeatherChartHooks: Record = { const colors = getThemeColors(); const canvas = self.el.querySelector('canvas') as HTMLCanvasElement; if (!canvas) return; - self.chart = new Chart(canvas, { + self.chart = new window.Chart(canvas, { type: 'line', data: { labels: times, datasets: [{ label: 'Pressure (mb)', data: pressure, borderColor: 'purple', backgroundColor: 'rgba(128, 0, 128, 0.1)', tension: 0.1 }] }, options: { @@ -216,7 +219,7 @@ export const WeatherChartHooks: Record = { const colors = getThemeColors(); const canvas = self.el.querySelector('canvas') as HTMLCanvasElement; if (!canvas) return; - self.chart = new Chart(canvas, { + self.chart = new window.Chart(canvas, { type: 'line', data: { labels: times, datasets: [{ label: 'Wind Speed (mph)', data: windSpeed, borderColor: 'orange', backgroundColor: 'rgba(255, 165, 0, 0.1)', tension: 0.1 }, { label: 'Wind Gust (mph)', data: windGust, borderColor: 'brown', backgroundColor: 'rgba(165, 42, 42, 0.1)', tension: 0.1 }] }, options: { @@ -257,7 +260,7 @@ export const WeatherChartHooks: Record = { const colors = getThemeColors(); const canvas = self.el.querySelector('canvas') as HTMLCanvasElement; if (!canvas) return; - self.chart = new Chart(canvas, { + self.chart = new window.Chart(canvas, { type: 'line', data: { labels: times, datasets: [{ label: 'Rain (1h)', data: rain1h, borderColor: 'blue', backgroundColor: 'rgba(0, 0, 255, 0.1)', tension: 0.1 }, { label: 'Rain (24h)', data: rain24h, borderColor: 'cyan', backgroundColor: 'rgba(0, 255, 255, 0.1)', tension: 0.1 }, { label: 'Rain (since midnight)', data: rainSinceMidnight, borderColor: 'navy', backgroundColor: 'rgba(0, 0, 128, 0.1)', tension: 0.1 }] }, options: { @@ -296,7 +299,7 @@ export const WeatherChartHooks: Record = { const colors = getThemeColors(); const canvas = self.el.querySelector('canvas') as HTMLCanvasElement; if (!canvas) return; - self.chart = new Chart(canvas, { + self.chart = new window.Chart(canvas, { type: 'line', data: { labels: times, datasets: [{ label: 'Luminosity', data: luminosity, borderColor: 'yellow', backgroundColor: 'rgba(255, 255, 0, 0.1)', tension: 0.1 }] }, options: { diff --git a/assets/package-lock.json b/assets/package-lock.json deleted file mode 100644 index eada255..0000000 --- a/assets/package-lock.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "name": "assets", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "dependencies": { - "@types/chart.js": "^4.0.1", - "chart.js": "^4.5.0", - "phoenix_live_view": "^1.0.17" - } - }, - "node_modules/@kurkle/color": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.4.tgz", - "integrity": "sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==" - }, - "node_modules/@types/chart.js": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/chart.js/-/chart.js-4.0.1.tgz", - "integrity": "sha512-OwXJ6Eg14eFpCsTG6sljiGnvVpit5R9rapG7nwDnQlljsdplVIOYVuCSwy07IduCtihrOwvOnbhXKLyp3nvPcw==", - "deprecated": "This is a stub types definition. chart.js provides its own type definitions, so you do not need this installed.", - "dependencies": { - "chart.js": "*" - } - }, - "node_modules/chart.js": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.5.0.tgz", - "integrity": "sha512-aYeC/jDgSEx8SHWZvANYMioYMZ2KX02W6f6uVfyteuCGcadDLcYVHdfdygsTQkQ4TKn5lghoojAsPj5pu0SnvQ==", - "dependencies": { - "@kurkle/color": "^0.3.0" - }, - "engines": { - "pnpm": ">=8" - } - }, - "node_modules/morphdom": { - "version": "2.7.5", - "resolved": "https://registry.npmjs.org/morphdom/-/morphdom-2.7.5.tgz", - "integrity": "sha512-z6bfWFMra7kBqDjQGHud1LSXtq5JJC060viEkQFMBX6baIecpkNr2Ywrn2OQfWP3rXiNFQRPoFjD8/TvJcWcDg==" - }, - "node_modules/phoenix_live_view": { - "version": "1.0.17", - "resolved": "https://registry.npmjs.org/phoenix_live_view/-/phoenix_live_view-1.0.17.tgz", - "integrity": "sha512-ydjiQeMkNrGv8OGYgT7BjIho/XM3eSHrk4FCs6qiLg9EfPf5M8w1W5Ax/E1tF9E0w6VFQsWm1fKFdWqzAezgjQ==", - "dependencies": { - "morphdom": "2.7.5" - } - } - } -} diff --git a/assets/package.json b/assets/package.json deleted file mode 100644 index dc6fbeb..0000000 --- a/assets/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "dependencies": { - "@types/chart.js": "^4.0.1", - "chart.js": "^4.5.0", - "phoenix_live_view": "^1.0.17" - } -} diff --git a/config/config.exs b/config/config.exs index 1d81d37..e64f6da 100644 --- a/config/config.exs +++ b/config/config.exs @@ -63,7 +63,7 @@ config :esbuild, version: "0.24.2", default: [ args: - ~w(js/app.js --bundle --target=es2017 --outdir=../priv/static/assets --external:/fonts/* --external:/images/* --define:global.L=window.L), + ~w(js/app.js --bundle --target=es2017 --outdir=../priv/static/assets --external:/fonts/* --external:/images/* --external:chart.js/auto --define:global.L=window.L), cd: Path.expand("../assets", __DIR__), env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)} ] diff --git a/lib/aprsme_web/components/layouts/root.html.heex b/lib/aprsme_web/components/layouts/root.html.heex index 3c46f0f..27bafec 100644 --- a/lib/aprsme_web/components/layouts/root.html.heex +++ b/lib/aprsme_web/components/layouts/root.html.heex @@ -22,6 +22,13 @@ data-source-map="false" > + diff --git a/lib/aprsme_web/live/status_live/connection_card_component.ex b/lib/aprsme_web/live/status_live/connection_card_component.ex new file mode 100644 index 0000000..3b9ac81 --- /dev/null +++ b/lib/aprsme_web/live/status_live/connection_card_component.ex @@ -0,0 +1,144 @@ +defmodule AprsmeWeb.StatusLive.ConnectionCardComponent do + @moduledoc false + use Phoenix.LiveComponent + + import Phoenix.Component + + def render(assigns) do + ~H""" +
+

APRS-IS Connection

+
+
+
+ Status: + <%= if @aprs_status.connected do %> + + + + + Connected + + <% else %> + + + + + Disconnected + + <% end %> +
+ +
+ Server: + + {@aprs_status.server}:{@aprs_status.port} + +
+ +
+ Login ID: + {@aprs_status.login_id} +
+ +
+ Connected Since: + + <%= if @aprs_status.connected_at do %> + {Calendar.strftime(@aprs_status.connected_at, "%Y-%m-%d %H:%M:%S UTC")} + <% else %> + Not connected + <% end %> + +
+ +
+ Uptime: + + {AprsmeWeb.StatusLive.Index.format_uptime(@aprs_status.uptime_seconds)} + +
+ +
+ Filter: + + {@aprs_status.filter} + +
+
+ + +
+

Packet Statistics

+
+
+ Total Packets: + + {AprsmeWeb.StatusLive.Index.format_number(@aprs_status.packet_stats.total_packets)} + +
+ +
+ Packets/Sec: + + {@aprs_status.packet_stats.packets_per_second} + +
+ +
+ Last Packet: + + <%= if @aprs_status.packet_stats.last_packet_at do %> + {AprsmeWeb.StatusLive.Index.format_time_ago( + @aprs_status.packet_stats.last_packet_at + )} + <% else %> + None + <% end %> + +
+ +
+ Stored Packets: + + {AprsmeWeb.StatusLive.Index.format_number(@aprs_status.stored_packet_count)} + +
+
+
+ +
+
+ Connection Health: +
+
+ <%= for i <- 1..5 do %> + + + + <% end %> +
+ + {@health_score}/5 + +
+
+

+ {AprsmeWeb.StatusLive.Index.get_health_description(@health_score, @aprs_status.connected)} +

+
+
+
+ """ + end +end diff --git a/lib/aprsme_web/live/status_live/index.ex b/lib/aprsme_web/live/status_live/index.ex index 335c5ca..4cfb644 100644 --- a/lib/aprsme_web/live/status_live/index.ex +++ b/lib/aprsme_web/live/status_live/index.ex @@ -369,9 +369,9 @@ defmodule AprsmeWeb.StatusLive.Index do Process.send_after(self(), :refresh_status, @refresh_interval) end - defp format_uptime(seconds) when seconds <= 0, do: "Not connected" + def format_uptime(seconds) when seconds <= 0, do: "Not connected" - defp format_uptime(seconds) do + def format_uptime(seconds) do days = div(seconds, 86_400) hours = div(rem(seconds, 86_400), 3600) minutes = div(rem(seconds, 3600), 60) @@ -399,7 +399,7 @@ defmodule AprsmeWeb.StatusLive.Index do end end - defp get_health_description(score, connected) do + def get_health_description(score, connected) do case {score, connected} do {1, false} -> "Disconnected - Connection issues detected" {2, true} -> "Recently connected - Monitoring stability" @@ -410,7 +410,7 @@ defmodule AprsmeWeb.StatusLive.Index do end end - defp format_time_ago(datetime) do + def format_time_ago(datetime) do diff_seconds = DateTime.diff(DateTime.utc_now(), datetime) cond do @@ -421,7 +421,7 @@ defmodule AprsmeWeb.StatusLive.Index do end end - defp format_number(number) when is_integer(number) do + def format_number(number) when is_integer(number) do number |> Integer.to_string() |> String.reverse() @@ -429,5 +429,5 @@ defmodule AprsmeWeb.StatusLive.Index do |> String.reverse() end - defp format_number(number), do: to_string(number) + def format_number(number), do: to_string(number) end