diff --git a/Taskfile.yml b/Taskfile.yml index 33cff77..8f66a12 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -135,6 +135,18 @@ tasks: # docker pull docker.linkos.org/library/debian:bullseye-20240701-slim # docker pull docker.linkos.org/library/postgres + ## Livebook cluster testing + # Attach on notebook's runtime with: hello-phx1@127.0.0.1 and hello cookie + lv-hello1: iex --name hello-phx1@127.0.0.1 --cookie hello --erl "-kernel shell_history enabled" -S mix phx.server + # below not work in livebook? + # lv-hello11: iex --sname hello-phx1 --cookie hello --erl "-kernel shell_history enabled" -S mix + lv-start: livebook server {{.CLI_ARGS}} + lv-data: task lv-start -- notebooks/explore-data.livemd + lv-help: task lv-start -- --help + lv-install: mix archive.install hex livebook + # https://fly.io/docs/elixir/advanced-guides/clustering-from-home-to-your-app-in-fly/ + lv-fly-remote: ./cluster-with-remote.sh + ## DB Setup pgcli: pgcli postgresql://postgres:postgres@localhost:5433 # db: sudo -u postgres pgcli hello_phx_dev diff --git a/lib/hello_phx/catalog.ex b/lib/hello_phx/catalog.ex index d0f9fe8..a9eae93 100644 --- a/lib/hello_phx/catalog.ex +++ b/lib/hello_phx/catalog.ex @@ -22,8 +22,6 @@ defmodule HelloPhx.Catalog do Product |> preload(:categories) |> Repo.all() - - # Repo.all(Product) end @doc """ @@ -137,7 +135,7 @@ defmodule HelloPhx.Catalog do def list_categories_by_id(nil), do: [] def list_categories_by_id(category_ids) do - Repo.all(from c in Category, where: c.id in ^category_ids) + Repo.all(from(c in Category, where: c.id in ^category_ids)) end @doc """ diff --git a/lib/hello_phx_web/controllers/product_html.ex b/lib/hello_phx_web/controllers/product_html.ex index 5463363..8e35de0 100644 --- a/lib/hello_phx_web/controllers/product_html.ex +++ b/lib/hello_phx_web/controllers/product_html.ex @@ -20,4 +20,9 @@ defmodule HelloPhxWeb.ProductHTML do for cat <- HelloPhx.Catalog.list_categories(), do: [key: cat.title, value: cat.id, selected: cat.id in existing_ids] end + + def product_categories(product) do + product.categories + |> Enum.map(& &1.title) + end end diff --git a/lib/hello_phx_web/controllers/product_html/index.html.heex b/lib/hello_phx_web/controllers/product_html/index.html.heex index 4a81267..2fec552 100644 --- a/lib/hello_phx_web/controllers/product_html/index.html.heex +++ b/lib/hello_phx_web/controllers/product_html/index.html.heex @@ -13,7 +13,8 @@ <.table id="products" rows={@products} row_click={&JS.navigate(~p"/products/#{&1}")}> <:col :let={product} label="ID"><%= product.id %> <:col :let={product} label="Title"><%= product.title %> - <:col :let={product} label="Description"><%= product.description %> + <:col :let={product} label="Categoires"><%= product_categories(product) %> + <%!-- <:col :let={product} label="Description"><%= product.description %> --%> <:col :let={product} label="Price"><%= product.price %> <:col :let={product} label="Views"><%= product.views %> <:action :let={product}> diff --git a/mix.exs b/mix.exs index 62b00de..025d75c 100644 --- a/mix.exs +++ b/mix.exs @@ -88,8 +88,9 @@ defmodule HelloPhx.MixProject do {:libcluster, "~> 3.3"}, # Graphing/charting - for Livebook or analysis - {:vega_lite, "~> 0.1.0"}, - {:kino, "~> 0.1.0"} + {:vega_lite, "~> 0.1.9"}, + {:kino, "~> 0.13.2"}, + {:kino_vega_lite, "~> 0.1.13"} ## Admin # https://github.com/aesmail/kaffy diff --git a/mix.lock b/mix.lock index fe0386e..b573aa9 100644 --- a/mix.lock +++ b/mix.lock @@ -17,13 +17,15 @@ "file_system": {:hex, :file_system, "1.0.0", "b689cc7dcee665f774de94b5a832e578bd7963c8e637ef940cd44327db7de2cd", [:mix], [], "hexpm", "6752092d66aec5a10e662aefeed8ddb9531d79db0bc145bb8c40325ca1d8536d"}, "finch": {:hex, :finch, "0.18.0", "944ac7d34d0bd2ac8998f79f7a811b21d87d911e77a786bc5810adb75632ada4", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.3", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.6 or ~> 1.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "69f5045b042e531e53edc2574f15e25e735b522c37e2ddb766e15b979e03aa65"}, "floki": {:hex, :floki, "0.36.2", "a7da0193538c93f937714a6704369711998a51a6164a222d710ebd54020aa7a3", [:mix], [], "hexpm", "a8766c0bc92f074e5cb36c4f9961982eda84c5d2b8e979ca67f5c268ec8ed580"}, + "fss": {:hex, :fss, "0.1.1", "9db2344dbbb5d555ce442ac7c2f82dd975b605b50d169314a20f08ed21e08642", [:mix], [], "hexpm", "78ad5955c7919c3764065b21144913df7515d52e228c09427a004afe9c1a16b0"}, "gettext": {:hex, :gettext, "0.24.0", "6f4d90ac5f3111673cbefc4ebee96fe5f37a114861ab8c7b7d5b30a1108ce6d8", [:mix], [{:expo, "~> 0.5.1", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "bdf75cdfcbe9e4622dd18e034b227d77dd17f0f133853a1c73b97b3d6c770e8b"}, "git_cli": {:hex, :git_cli, "0.3.0", "a5422f9b95c99483385b976f5d43f7e8233283a47cda13533d7c16131cb14df5", [:mix], [], "hexpm", "78cb952f4c86a41f4d3511f1d3ecb28edb268e3a7df278de2faa1bd4672eaf9b"}, "git_ops": {:hex, :git_ops, "2.6.1", "cc7799a68c26cf814d6d1a5121415b4f5bf813de200908f930b27a2f1fe9dad5", [:mix], [{:git_cli, "~> 0.2", [hex: :git_cli, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "ce62d07e41fe993ec22c35d5edb11cf333a21ddaead6f5d9868fcb607d42039e"}, "heroicons": {:git, "https://github.com/tailwindlabs/heroicons.git", "88ab3a0d790e6a47404cba02800a6b25d2afae50", [tag: "v2.1.1", sparse: "optimized", depth: 1]}, "hpax": {:hex, :hpax, "0.2.0", "5a58219adcb75977b2edce5eb22051de9362f08236220c9e859a47111c194ff5", [:mix], [], "hexpm", "bea06558cdae85bed075e6c036993d43cd54d447f76d8190a8db0dc5893fa2f1"}, "jason": {:hex, :jason, "1.4.3", "d3f984eeb96fe53b85d20e0b049f03e57d075b5acda3ac8d465c969a2536c17b", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "9a90e868927f7c777689baa16d86f4d0e086d968db5c05d917ccff6d443e58a3"}, - "kino": {:hex, :kino, "0.1.3", "5bfd8c8ea57c4994c571a55d9faeb841d8f0f41ab88f2759ced47ba7aa2fc643", [:mix], [{:vega_lite, "~> 0.1.0", [hex: :vega_lite, repo: "hexpm", optional: true]}], "hexpm", "e0b86818b2c9357c72a2bf3d8dc87b248525a7eb4073a9328c647326c18ab44c"}, + "kino": {:hex, :kino, "0.13.2", "087c8f340734764fc8c70efd43f3155fa47498c78d2d18fa83aaf97373133ade", [:mix], [{:fss, "~> 0.1.0", [hex: :fss, repo: "hexpm", optional: false]}, {:nx, "~> 0.1", [hex: :nx, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}, {:table, "~> 0.1.2", [hex: :table, repo: "hexpm", optional: false]}], "hexpm", "05fb420dae92a81746dcaceceddf235974394486b17cc2704ddbb051072b4617"}, + "kino_vega_lite": {:hex, :kino_vega_lite, "0.1.13", "03c00405987a2202e4b8014ee55eb7f5727691b3f13d76a3764f6eeccef45322", [:mix], [{:kino, "~> 0.7", [hex: :kino, repo: "hexpm", optional: false]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: false]}, {:vega_lite, "~> 0.1.8", [hex: :vega_lite, repo: "hexpm", optional: false]}], "hexpm", "00c72bc270e7b9d3c339f726cdab0012fd3f2fc75e36c7548e0f250fe420fa10"}, "libcluster": {:hex, :libcluster, "3.3.3", "a4f17721a19004cfc4467268e17cff8b1f951befe428975dd4f6f7b84d927fe0", [:mix], [{:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "7c0a2275a0bb83c07acd17dab3c3bfb4897b145106750eeccc62d302e3bdfee5"}, "mime": {:hex, :mime, "2.0.6", "8f18486773d9b15f95f4f4f1e39b710045fa1de891fada4516559967276e4dc2", [:mix], [], "hexpm", "c9945363a6b26d747389aac3643f8e0e09d30499a138ad64fe8fd1d13d9b153e"}, "mint": {:hex, :mint, "1.6.2", "af6d97a4051eee4f05b5500671d47c3a67dac7386045d87a904126fd4bbcea2e", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1 or ~> 0.2.0 or ~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "5ee441dffc1892f1ae59127f74afe8fd82fda6587794278d924e4d90ea3d63f9"}, diff --git a/notebooks/README.md b/notebooks/README.md new file mode 100644 index 0000000..83326d6 --- /dev/null +++ b/notebooks/README.md @@ -0,0 +1,3 @@ +# Play livebook + +https://github.com/livebook-dev/livebook?tab=readme-ov-file#environment-variables diff --git a/notebooks/explore-data.livemd b/notebooks/explore-data.livemd new file mode 100644 index 0000000..f5f2933 --- /dev/null +++ b/notebooks/explore-data.livemd @@ -0,0 +1,56 @@ +# Explore HelloPhx Data attaching + +```elixir +alias VegaLite, as: Vl +alias HelloPhx.Catalog.Product +alias HelloPhx.Repo +import Ecto.Query +``` + +## Explore + +```elixir +query = from(p in Product, + group_by: p.views, + select: {p.views, count(p.id)} +) + +views_counts = query +|> Repo.all +|> Enum.into(%{}) + +# Convert the raw data into a Pie Chart friendly format +data = + Enum.map(views_counts, fn {views, count} -> + %{"views" => "views#{views}", "value" => count} + end) + +Vl.new() +|> Vl.data_from_values(data) +|> Vl.mark(:arc) +|> Vl.encode_field(:theta, "value", type: :quantitative) +|> Vl.encode_field(:color, "views", type: :nominal) +|> Vl.config(view: [stroke: nil]) +``` + +```elixir +# Convert the raw data into a Bar Chart friendly format +data2 = + Enum.map(views_counts, fn {views, count} -> + %{"Views" => "views#{views}", "Views Count" => count} + end) + +# Sort the data by counts to order the results +data2 = Enum.sort_by(data, & &1["Views Count"], :desc) +|> Kino.inspect() + +Vl.new(width: 600, height: 600) +|> Vl.data_from_values(data2) +|> Vl.mark(:bar) +|> Vl.encode_field(:x, "Views", + type: :nominal, + axis: [label_angle: 0], + sort: [field: "Views Count", order: "descendingsr"] +) +|> Vl.encode_field(:y, "Views Count", type: :quantitative) +```