···22 use Ash.Domain
3344 resources do
55+ resource Sower.Inputs.Repository
56 resource Sower.Seed
66- resource Sower.Inputs.Repository
77+ resource Sower.Tree
78 end
89end
+16
lib/sower/seed.ex
···6666 sort: [updated_at: :desc]
6767 )
6868 end
6969+7070+ read :by_path do
7171+ argument :out_path, :string do
7272+ allow_nil? false
7373+ end
7474+7575+ # # only return one
7676+ # get? true
7777+ #
7878+ prepare build(
7979+ filter: expr(out_path == ^arg(:out_path)),
8080+ limit: 1,
8181+ sort: [updated_at: :desc]
8282+ )
8383+ end
6984 end
70857186 attributes do
···9511096111 code_interface do
97112 define :by_id, args: [:id]
113113+ define :by_path, args: [:out_path]
98114 define :new, args: [:name, :type, :out_path, :branch, :repo_url]
99115 define :new_legacy, args: [:name, :type, :out_path]
100116 define :latest, args: [:name, :type]
+77
lib/sower/tree.ex
···11+defmodule Sower.Tree do
22+ use Ash.Resource,
33+ data_layer: AshPostgres.DataLayer,
44+ domain: Sower
55+66+ @types [:nixos, :"home-manager", :"nix-darwin"]
77+88+ actions do
99+ defaults [:read]
1010+1111+ create :register do
1212+ accept [:name, :type]
1313+ end
1414+1515+ read :by_id do
1616+ argument :id, :uuid do
1717+ allow_nil? false
1818+ end
1919+2020+ # only return one
2121+ get? true
2222+2323+ filter expr(id == ^arg(:id))
2424+ end
2525+2626+ update :set_seed do
2727+ require_atomic? false
2828+2929+ argument :seed_id, :uuid do
3030+ allow_nil? false
3131+ end
3232+3333+ change manage_relationship(:seed_id, :seed, type: :append_and_remove)
3434+ end
3535+ end
3636+3737+ attributes do
3838+ uuid_primary_key :id
3939+ create_timestamp :inserted_at
4040+ update_timestamp :updated_at
4141+4242+ attribute :name, :string do
4343+ allow_nil? false
4444+ public? true
4545+ end
4646+4747+ attribute :type, :atom do
4848+ allow_nil? false
4949+ public? true
5050+ constraints one_of: @types
5151+ end
5252+ end
5353+5454+ code_interface do
5555+ define :by_id, args: [:id]
5656+ define :set_seed, args: [:seed_id]
5757+ define :read_all, action: :read
5858+ define :register, args: [:name, :type]
5959+ end
6060+6161+ identities do
6262+ identity :tree, [:name, :type]
6363+ end
6464+6565+ postgres do
6666+ table "trees"
6767+ repo Sower.Repo
6868+6969+ references do
7070+ reference :seed
7171+ end
7272+ end
7373+7474+ relationships do
7575+ belongs_to :seed, Sower.Seed
7676+ end
7777+end
+8
lib/sower_web/live/tree_live/index.ex
···11+defmodule SowerWeb.TreeLive.Index do
22+ use SowerWeb, :live_view
33+44+ @impl true
55+ def mount(_params, _session, socket) do
66+ {:ok, stream(socket, :trees, Sower.Tree.read_all!())}
77+ end
88+end
+18
lib/sower_web/live/tree_live/index.html.heex
···11+<.header>
22+ Listing Trees
33+ <:subtitle>A tree is an individual client that grows from seeds.</:subtitle>
44+</.header>
55+66+<.table
77+ id="trees"
88+ rows={@streams.trees}
99+ row_click={fn {_id, tree} -> JS.navigate(~p"/trees/#{tree}") end}
1010+>
1111+ <:col :let={{_id, tree}} label="name"><%= tree.name %></:col>
1212+ <:col :let={{_id, tree}} label="type"><%= tree.type %></:col>
1313+ <:action :let={{_id, tree}}>
1414+ <div class="sr-only">
1515+ <.link navigate={~p"/trees/#{tree}"}>Show</.link>
1616+ </div>
1717+ </:action>
1818+</.table>
+18
lib/sower_web/live/tree_live/show.ex
···11+defmodule SowerWeb.TreeLive.Show do
22+ use SowerWeb, :live_view
33+44+ @impl true
55+ def mount(_params, _session, socket) do
66+ {:ok, socket}
77+ end
88+99+ @impl true
1010+ def handle_params(%{"id" => id}, _, socket) do
1111+ {:noreply,
1212+ socket
1313+ |> assign(:page_title, page_title(socket.assigns.live_action))
1414+ |> assign(:tree, Sower.Tree.by_id!(id))}
1515+ end
1616+1717+ defp page_title(:show), do: "Show Tree"
1818+end
+19
lib/sower_web/live/tree_live/show.html.heex
···11+<.header>
22+ Tree <%= @tree.id %>
33+ <:subtitle>This is a tree record from your database.</:subtitle>
44+</.header>
55+66+<.list></.list>
77+88+<.back navigate={~p"/trees"}>Back to trees</.back>
99+1010+<.modal :if={@live_action == :edit} id="tree-modal" show on_cancel={JS.patch(~p"/trees/#{@tree}")}>
1111+ <.live_component
1212+ module={SowerWeb.TreeLive.FormComponent}
1313+ id={@tree.id}
1414+ title={@page_title}
1515+ action={@live_action}
1616+ tree={@tree}
1717+ patch={~p"/trees/#{@tree}"}
1818+ />
1919+</.modal>