CTKOB4AB6TW2J7REZYGA76IPE56EHVCS6PX6VRV5YUH6LPSWKJTQC defmodule Cake.BoardsFixtures do@moduledoc """This module defines test helpers for creatingentities via the `Cake.Boards` context."""@doc """Generate a board."""def board_fixture(attrs \\ %{}) do{:ok, board} =attrs|> Enum.into(%{name: "some name",stories: []})|> Cake.Boards.create_board()boardendend
defmodule CakeWeb.BoardLiveTest douse CakeWeb.ConnCaseimport Phoenix.LiveViewTestimport Cake.BoardsFixtures@create_attrs %{name: "some name", stories: []}@update_attrs %{name: "some updated name", stories: []}@invalid_attrs %{name: nil, stories: []}defp create_board(_) doboard = board_fixture()%{board: board}enddescribe "Index" dosetup [:create_board]test "lists all boards", %{conn: conn, board: board} do{:ok, _index_live, html} = live(conn, Routes.board_index_path(conn, :index))assert html =~ "Listing Boards"assert html =~ board.nameendtest "saves new board", %{conn: conn} do{:ok, index_live, _html} = live(conn, Routes.board_index_path(conn, :index))assert index_live |> element("a", "New Board") |> render_click() =~"New Board"assert_patch(index_live, Routes.board_index_path(conn, :new))assert index_live|> form("#board-form", board: @invalid_attrs)|> render_change() =~ "can't be blank"{:ok, _, html} =index_live|> form("#board-form", board: @create_attrs)|> render_submit()|> follow_redirect(conn, Routes.board_index_path(conn, :index))assert html =~ "Board created successfully"assert html =~ "some name"endtest "updates board in listing", %{conn: conn, board: board} do{:ok, index_live, _html} = live(conn, Routes.board_index_path(conn, :index))assert index_live |> element("#board-#{board.id} a", "Edit") |> render_click() =~"Edit Board"assert_patch(index_live, Routes.board_index_path(conn, :edit, board))assert index_live|> form("#board-form", board: @invalid_attrs)|> render_change() =~ "can't be blank"{:ok, _, html} =index_live|> form("#board-form", board: @update_attrs)|> render_submit()|> follow_redirect(conn, Routes.board_index_path(conn, :index))assert html =~ "Board updated successfully"assert html =~ "some updated name"endtest "deletes board in listing", %{conn: conn, board: board} do{:ok, index_live, _html} = live(conn, Routes.board_index_path(conn, :index))assert index_live |> element("#board-#{board.id} a", "Delete") |> render_click()refute has_element?(index_live, "#board-#{board.id}")endenddescribe "Show" dosetup [:create_board]test "displays board", %{conn: conn, board: board} do{:ok, _show_live, html} = live(conn, Routes.board_show_path(conn, :show, board))assert html =~ "Show Board"assert html =~ board.nameendtest "updates board within modal", %{conn: conn, board: board} do{:ok, show_live, _html} = live(conn, Routes.board_show_path(conn, :show, board))assert show_live |> element("a", "Edit") |> render_click() =~"Edit Board"assert_patch(show_live, Routes.board_show_path(conn, :edit, board))assert show_live|> form("#board-form", board: @invalid_attrs)|> render_change() =~ "can't be blank"{:ok, _, html} =show_live|> form("#board-form", board: @update_attrs)|> render_submit()|> follow_redirect(conn, Routes.board_show_path(conn, :show, board))assert html =~ "Board updated successfully"assert html =~ "some updated name"endendend
defmodule Cake.BoardsTest douse Cake.DataCasealias Cake.Boardsdescribe "boards" doalias Cake.Boards.Boardimport Cake.BoardsFixtures@invalid_attrs %{name: nil, stories: nil}test "list_boards/0 returns all boards" doboard = board_fixture()assert Boards.list_boards() == [board]endtest "get_board!/1 returns the board with given id" doboard = board_fixture()assert Boards.get_board!(board.id) == boardendtest "create_board/1 with valid data creates a board" dovalid_attrs = %{name: "some name", stories: []}assert {:ok, %Board{} = board} = Boards.create_board(valid_attrs)assert board.name == "some name"assert board.stories == []endtest "create_board/1 with invalid data returns error changeset" doassert {:error, %Ecto.Changeset{}} = Boards.create_board(@invalid_attrs)endtest "update_board/2 with valid data updates the board" doboard = board_fixture()update_attrs = %{name: "some updated name", stories: []}assert {:ok, %Board{} = board} = Boards.update_board(board, update_attrs)assert board.name == "some updated name"assert board.stories == []endtest "update_board/2 with invalid data returns error changeset" doboard = board_fixture()assert {:error, %Ecto.Changeset{}} = Boards.update_board(board, @invalid_attrs)assert board == Boards.get_board!(board.id)endtest "delete_board/1 deletes the board" doboard = board_fixture()assert {:ok, %Board{}} = Boards.delete_board(board)assert_raise Ecto.NoResultsError, fn -> Boards.get_board!(board.id) endendtest "change_board/1 returns a board changeset" doboard = board_fixture()assert %Ecto.Changeset{} = Boards.change_board(board)endendend
defmodule Cake.Repo.Migrations.CreateBoards douse Ecto.Migrationdef change docreate table(:boards, primary_key: false) doadd :id, :uuid, primary_key: true, null: false, default: fragment("gen_random_uuid()")add :name, :stringadd :stories, {:array, :uuid}add :layer_template, references(:layer_templates, on_delete: :nothing)timestamps()endcreate index(:boards, [:layer_template])endend
defmodule CakeWeb.Router douse CakeWeb, :routerimport Surface.Catalogue.Routerpipeline :browser doplug :accepts, ["html"]plug :fetch_sessionplug :fetch_live_flashplug :put_root_layout, {CakeWeb.LayoutView, :root}plug :protect_from_forgeryplug :put_secure_browser_headersendpipeline :api doplug :accepts, ["json"]endscope "/", CakeWeb dopipe_through :browserget "/", PageController, :indexend# Other scopes may use custom stacks.# scope "/api", CakeWeb do# pipe_through :api# end# Enables LiveDashboard only for development## If you want to use the LiveDashboard in production, you should put# it behind authentication and allow only admins to access it.# If your application does not have an admins-only section yet,# you can use Plug.BasicAuth to set up some basic authentication# as long as you are also using SSL (which you should anyway).if Mix.env() in [:dev, :test] doimport Phoenix.LiveDashboard.Routerscope "/" dopipe_through :browserlive_dashboard "/dashboard", metrics: CakeWeb.Telemetryendend# Enables the Swoosh mailbox preview in development.## Note that preview only shows emails that were sent by the same# node running the Phoenix server.if Mix.env() == :dev doscope "/dev" dopipe_through :browserforward "/mailbox", Plug.Swoosh.MailboxPreviewendendif Mix.env() == :dev doscope "/" dopipe_through :browsersurface_catalogue "/catalogue"endendend
<h1>Show Board</h1><%= if @live_action in [:edit] do %><.modal return_to={Routes.board_show_path(@socket, :show, @board)}><.live_componentmodule={CakeWeb.BoardLive.FormComponent}id={@board.id}title={@page_title}action={@live_action}board={@board}return_to={Routes.board_show_path(@socket, :show, @board)}/></.modal><% end %><ul><li><strong>Name:</strong><%= @board.name %></li><li><strong>Stories:</strong><%= @board.stories %></li></ul><span><%= live_patch "Edit", to: Routes.board_show_path(@socket, :edit, @board), class: "button" %></span> |<span><%= live_redirect "Back", to: Routes.board_index_path(@socket, :index) %></span>
defmodule CakeWeb.BoardLive.Show douse CakeWeb, :live_viewalias Cake.Boards@impl truedef mount(_params, _session, socket) do{:ok, socket}end@impl truedef handle_params(%{"id" => id}, _, socket) do{:noreply,socket|> assign(:page_title, page_title(socket.assigns.live_action))|> assign(:board, Boards.get_board!(id))}enddefp page_title(:show), do: "Show Board"defp page_title(:edit), do: "Edit Board"end
<h1>Listing Boards</h1><%= if @live_action in [:new, :edit] do %><.modal return_to={Routes.board_index_path(@socket, :index)}><.live_componentmodule={CakeWeb.BoardLive.FormComponent}id={@board.id || :new}title={@page_title}action={@live_action}board={@board}return_to={Routes.board_index_path(@socket, :index)}/></.modal><% end %><table><thead><tr><th>Name</th><th>Stories</th><th></th></tr></thead><tbody id="boards"><%= for board <- @boards do %><tr id={"board-#{board.id}"}><td><%= board.name %></td><td><%= board.stories %></td><td><span><%= live_redirect "Show", to: Routes.board_show_path(@socket, :show, board) %></span><span><%= live_patch "Edit", to: Routes.board_index_path(@socket, :edit, board) %></span><span><%= link "Delete", to: "#", phx_click: "delete", phx_value_id: board.id, data: [confirm: "Are you sure?"] %></span></td></tr><% end %></tbody></table><span><%= live_patch "New Board", to: Routes.board_index_path(@socket, :new) %></span>
defmodule CakeWeb.BoardLive.Index douse CakeWeb, :live_viewalias Cake.Boardsalias Cake.Boards.Board@impl truedef mount(_params, _session, socket) do{:ok, assign(socket, :boards, list_boards())}end@impl truedef handle_params(params, _url, socket) do{:noreply, apply_action(socket, socket.assigns.live_action, params)}enddefp apply_action(socket, :edit, %{"id" => id}) dosocket|> assign(:page_title, "Edit Board")|> assign(:board, Boards.get_board!(id))enddefp apply_action(socket, :new, _params) dosocket|> assign(:page_title, "New Board")|> assign(:board, %Board{})enddefp apply_action(socket, :index, _params) dosocket|> assign(:page_title, "Listing Boards")|> assign(:board, nil)end@impl truedef handle_event("delete", %{"id" => id}, socket) doboard = Boards.get_board!(id){:ok, _} = Boards.delete_board(board){:noreply, assign(socket, :boards, list_boards())}enddefp list_boards doBoards.list_boards()endend
<div><h2><%= @title %></h2><.formlet={f}for={@changeset}id="board-form"phx-target={@myself}phx-change="validate"phx-submit="save"><%= label f, :name %><%= text_input f, :name %><%= error_tag f, :name %><%= label f, :stories %><%= multiple_select f, :stories, ["Option 1": "option1", "Option 2": "option2"] %><%= error_tag f, :stories %><div><%= submit "Save", phx_disable_with: "Saving..." %></div></.form></div>
defmodule CakeWeb.BoardLive.FormComponent douse CakeWeb, :live_componentalias Cake.Boards@impl truedef update(%{board: board} = assigns, socket) dochangeset = Boards.change_board(board){:ok,socket|> assign(assigns)|> assign(:changeset, changeset)}end@impl truedef handle_event("validate", %{"board" => board_params}, socket) dochangeset =socket.assigns.board|> Boards.change_board(board_params)|> Map.put(:action, :validate){:noreply, assign(socket, :changeset, changeset)}enddef handle_event("save", %{"board" => board_params}, socket) dosave_board(socket, socket.assigns.action, board_params)enddefp save_board(socket, :edit, board_params) docase Boards.update_board(socket.assigns.board, board_params) do{:ok, _board} ->{:noreply,socket|> put_flash(:info, "Board updated successfully")|> push_redirect(to: socket.assigns.return_to)}{:error, %Ecto.Changeset{} = changeset} ->{:noreply, assign(socket, :changeset, changeset)}endenddefp save_board(socket, :new, board_params) docase Boards.create_board(board_params) do{:ok, _board} ->{:noreply,socket|> put_flash(:info, "Board created successfully")|> push_redirect(to: socket.assigns.return_to)}{:error, %Ecto.Changeset{} = changeset} ->{:noreply, assign(socket, changeset: changeset)}endendend
defmodule Cake.Boards do@moduledoc """The Boards context."""import Ecto.Query, warn: falsealias Cake.Repoalias Cake.Boards.Board@doc """Returns the list of boards.## Examplesiex> list_boards()[%Board{}, ...]"""def list_boards doRepo.all(Board)end@doc """Gets a single board.Raises `Ecto.NoResultsError` if the Board does not exist.## Examplesiex> get_board!(123)%Board{}iex> get_board!(456)** (Ecto.NoResultsError)"""def get_board!(id), do: Repo.get!(Board, id)@doc """Creates a board.## Examplesiex> create_board(%{field: value}){:ok, %Board{}}iex> create_board(%{field: bad_value}){:error, %Ecto.Changeset{}}"""def create_board(attrs \\ %{}) do%Board{}|> Board.changeset(attrs)|> Repo.insert()end@doc """Updates a board.## Examplesiex> update_board(board, %{field: new_value}){:ok, %Board{}}iex> update_board(board, %{field: bad_value}){:error, %Ecto.Changeset{}}"""def update_board(%Board{} = board, attrs) doboard|> Board.changeset(attrs)|> Repo.update()end@doc """Deletes a board.## Examplesiex> delete_board(board){:ok, %Board{}}iex> delete_board(board){:error, %Ecto.Changeset{}}"""def delete_board(%Board{} = board) doRepo.delete(board)end@doc """Returns an `%Ecto.Changeset{}` for tracking board changes.## Examplesiex> change_board(board)%Ecto.Changeset{data: %Board{}}"""def change_board(%Board{} = board, attrs \\ %{}) doBoard.changeset(board, attrs)endend
defmodule Cake.Boards.Board douse Ecto.Schemaimport Ecto.Changesetschema "boards" dofield :name, :stringfield :stories, {:array, Ecto.UUID}field :layer_template, :idtimestamps()end@doc falsedef changeset(board, attrs) doboard|> cast(attrs, [:name, :stories])|> validate_required([:name, :stories])endend