Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

22 credential model form #43

Merged
merged 5 commits into from
Mar 28, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 108 additions & 0 deletions lib/lightning/credentials.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
defmodule Lightning.Credentials do
@moduledoc """
The Credentials context.
"""

import Ecto.Query, warn: false
import Lightning.Helpers, only: [coerce_json_field: 2]
alias Lightning.Repo

alias Lightning.Credentials.Credential

@doc """
Returns the list of credentials.

## Examples

iex> list_credentials()
[%Credential{}, ...]

"""
def list_credentials do
Repo.all(Credential)
end

@doc """
Gets a single credential.

Raises `Ecto.NoResultsError` if the Credential does not exist.

## Examples

iex> get_credential!(123)
%Credential{}

iex> get_credential!(456)
** (Ecto.NoResultsError)

"""
def get_credential!(id), do: Repo.get!(Credential, id)

@doc """
Creates a credential.

## Examples

iex> create_credential(%{field: value})
{:ok, %Credential{}}

iex> create_credential(%{field: bad_value})
{:error, %Ecto.Changeset{}}

"""
def create_credential(attrs \\ %{}) do
%Credential{}
|> Credential.changeset(attrs |> coerce_json_field("body"))
|> Repo.insert()
end

@doc """
Updates a credential.

## Examples

iex> update_credential(credential, %{field: new_value})
{:ok, %Credential{}}

iex> update_credential(credential, %{field: bad_value})
{:error, %Ecto.Changeset{}}

"""
def update_credential(%Credential{} = credential, attrs) do
credential
|> Credential.changeset(attrs |> coerce_json_field("body"))
|> Repo.update()
end

@doc """
Deletes a credential.

## Examples

iex> delete_credential(credential)
{:ok, %Credential{}}

iex> delete_credential(credential)
{:error, %Ecto.Changeset{}}

"""
def delete_credential(%Credential{} = credential) do
Repo.delete(credential)
end

@doc """
Returns an `%Ecto.Changeset{}` for tracking credential changes.

## Examples

iex> change_credential(credential)
%Ecto.Changeset{data: %Credential{}}

"""
def change_credential(%Credential{} = credential, attrs \\ %{}) do
Credential.changeset(
credential,
attrs |> coerce_json_field("body")
)
end
end
24 changes: 24 additions & 0 deletions lib/lightning/credentials/credential.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
defmodule Lightning.Credentials.Credential do
@moduledoc """
The Credential model.
"""

use Ecto.Schema
import Ecto.Changeset

@primary_key {:id, :binary_id, autogenerate: true}
@foreign_key_type :binary_id
schema "credentials" do
field :body, :map
field :name, :string

timestamps()
end

@doc false
def changeset(credential, attrs) do
credential
|> cast(attrs, [:name, :body])
|> validate_required([:name, :body])
end
end
35 changes: 35 additions & 0 deletions lib/lightning/helpers.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
defmodule Lightning.Helpers do
@moduledoc """
Common functions for the context
"""

@doc """
Changes a given maps field from a json string to a map.
If it cannot be converted, it leaves the original value
"""
@spec coerce_json_field(map(), Map.key()) :: map()
def coerce_json_field(attrs, field) do
{_, attrs} =
Map.get_and_update(attrs, field, fn body ->
case body do
nil ->
:pop

body when is_binary(body) ->
{body, decode_and_replace(body)}

any ->
{body, any}
end
end)

attrs
end

defp decode_and_replace(body) do
case Jason.decode(body) do
{:error, _} -> body
{:ok, body_map} -> body_map
end
end
end
32 changes: 4 additions & 28 deletions lib/lightning/invocation.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ defmodule Lightning.Invocation do
"""

import Ecto.Query, warn: false
import Lightning.Helpers, only: [coerce_json_field: 2]
alias Lightning.Repo

alias Lightning.Invocation.{Dataclip, Event, Run}
Expand Down Expand Up @@ -73,7 +74,7 @@ defmodule Lightning.Invocation do
"""
def create_dataclip(attrs \\ %{}) do
%Dataclip{}
|> Dataclip.changeset(attrs |> coerce_json_body())
|> Dataclip.changeset(attrs |> coerce_json_field("body"))
|> Repo.insert()
end

Expand All @@ -91,7 +92,7 @@ defmodule Lightning.Invocation do
"""
def update_dataclip(%Dataclip{} = dataclip, attrs) do
dataclip
|> Dataclip.changeset(attrs |> coerce_json_body())
|> Dataclip.changeset(attrs |> coerce_json_field("body"))
|> Repo.update()
end

Expand Down Expand Up @@ -121,32 +122,7 @@ defmodule Lightning.Invocation do

"""
def change_dataclip(%Dataclip{} = dataclip, attrs \\ %{}) do
Dataclip.changeset(dataclip, attrs |> coerce_json_body())
end

defp coerce_json_body(attrs) do
{_, attrs} =
Map.get_and_update(attrs, "body", fn body ->
case body do
nil ->
:pop

body when is_binary(body) ->
{body, decode_and_replace(body)}

any ->
{body, any}
end
end)

attrs
end

def decode_and_replace(body) do
case Jason.decode(body) do
{:error, _} -> body
{:ok, body_map} -> body_map
end
Dataclip.changeset(dataclip, attrs |> coerce_json_field("body"))
end

@doc """
Expand Down
26 changes: 26 additions & 0 deletions lib/lightning_web/live/credential_live/edit.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
defmodule LightningWeb.CredentialLive.Edit do
@moduledoc """
LiveView for editing a single job, which inturn uses `LightningWeb.JobLive.FormComponent`
for common functionality.
"""
use LightningWeb, :live_view

alias Lightning.Credentials

@impl true
def mount(_params, _session, socket) do
{:ok, socket}
end

@impl true
def handle_params(%{"id" => id}, _, socket) do
{:noreply,
socket
|> assign(:page_title, page_title(socket.assigns.live_action))
|> assign(:active_menu_item, :credentials)
|> assign(:credentials, Credentials.get_credential!(id))}
end

defp page_title(:show), do: "Show Job"
defp page_title(:edit), do: "Edit Job"
end
14 changes: 14 additions & 0 deletions lib/lightning_web/live/credential_live/edit.html.heex
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<MainSection.header title={"#{@credential.name}"} />

<MainSection.main>

<.live_component
module={LightningWeb.CredentialLive.FormComponent}
id={@credential.id || :new}
title={@page_title}
action={@live_action}
credential={@credential}
return_to={Routes.credential_index_path(@socket, :index)}
/>

</MainSection.main>
58 changes: 58 additions & 0 deletions lib/lightning_web/live/credential_live/form_component.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
defmodule LightningWeb.CredentialLive.FormComponent do
@moduledoc """
Form Component for working with a single Credential
"""
use LightningWeb, :live_component

alias Lightning.{Credentials}

@impl true
def update(%{credential: credential} = assigns, socket) do
changeset = Credentials.change_credential(credential)

{:ok,
socket
|> assign(assigns)
|> assign(:changeset, changeset)}
end

@impl true
def handle_event("validate", %{"credential" => credential_params}, socket) do
changeset =
socket.assigns.credential
|> Credentials.change_credential(credential_params)
|> Map.put(:action, :validate)

{:noreply, assign(socket, :changeset, changeset)}
end

def handle_event("save", %{"credential" => credential_params}, socket) do
save_credential(socket, socket.assigns.action, credential_params)
end

defp save_credential(socket, :edit, credential_params) do
case Credentials.update_credential(socket.assigns.credential, credential_params) do
{:ok, _credential} ->
{:noreply,
socket
|> put_flash(:info, "Credential updated successfully")
|> push_redirect(to: socket.assigns.return_to)}

{:error, %Ecto.Changeset{} = changeset} ->
{:noreply, assign(socket, :changeset, changeset)}
end
end

defp save_credential(socket, :new, credential_params) do
case Credentials.create_credential(credential_params) do
{:ok, _credential} ->
{:noreply,
socket
|> put_flash(:info, "Credential created successfully")
|> push_redirect(to: socket.assigns.return_to)}

{:error, %Ecto.Changeset{} = changeset} ->
{:noreply, assign(socket, changeset: changeset)}
end
end
end
34 changes: 34 additions & 0 deletions lib/lightning_web/live/credential_live/form_component.html.heex
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<div id={"credential-#{@id}"}>
<.form
let={f}
for={@changeset}
id="credential-form"
phx-target={@myself}
phx-change="validate"
phx-submit="save">

<div class="grid grid-cols-6 gap-6">
<div class="col-span-3">

<%= label f, :name, class: "block text-sm font-medium text-gray-700" %>
<%= error_tag f, :name, class: "block w-full rounded-md" %>
<%= text_input f, :name, class: "mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm sm:text-sm border-gray-300 rounded-md" %>

</div>

</div>

<div class="hidden sm:block" aria-hidden="true">
<div class="py-5">
<div class="border-t border-gray-200"></div>
</div>
</div>

<%= error_tag f, :body %>
<%= textarea f, :body, class: "rounded-md w-full font-mono bg-slate-800 text-slate-50 h-96 min-h-full" %>

<div>
<%= submit "Save", phx_disable_with: "Saving...", class: "inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" %>
</div>
</.form>
</div>
Loading