Skip to content

Instantly share code, notes, and snippets.

@wktdev
Created January 28, 2025 14:51
Show Gist options
  • Save wktdev/405003a4940ff8bd65c9bb7257a2f0dc to your computer and use it in GitHub Desktop.
Save wktdev/405003a4940ff8bd65c9bb7257a2f0dc to your computer and use it in GitHub Desktop.
```
defmodule AppWeb.PageLive do
@moduledoc """
This is the web interface for the testbed application.
This is where the HTML is rendered and CSS is applied.
The core of this apps code resides here.
1. Code that listens and respond to interactive user events is written here.
2. Code here moves data to and from the database.
The following code are imported functions used to communicate
with the database.
alias App.TestBeds
alias App.StatusActions
The above functions are available in:
app/test_beds.ex and app/status_actions.ex
To render an image of the app schema, run these three commands
mix ecto.gen.erd # generates ecto_erd.dot
mix ecto.gen.erd --output-path=ecto_erd.dot
mix ecto.gen.erd && dot -Tpng ecto_erd.dot -o erd.png && xdg-open erd.png
"""
use AppWeb, :live_view
alias App.TestBeds
alias App.Alerts
alias App.StatusActions
@doc """
mount runs immediatley when the page loads.
Dynamic variables in HTML are placed in assign() after
the socket parameter. The following code is used to get TestBed
data out of the database and used in the HTML
#Example
testbeds: TestBeds.list_testbeds()
testbeds variable above is used in the HTML to render testbed data.
The Testbeds.subscribe() is part of the pub/sub websockets API.
The call site for TestBeds.subscribe is in the App/test_beds.ex folder
"""
def mount(_params, _session, socket) do
TestBeds.subscribe()
Alerts.subscribe()
{:ok,
assign(socket,
testbeds: TestBeds.list_testbeds(),
sort_direction: false, # Here
sort_field: :name, # Here
alerts: Alerts.list_alerts(),
developer: "None",
name_warning: ""
)}
end
# Set initial state, including sorting direction (ascending or descending)
@doc """
handle_info in this app is used as part of the pub/sub process.
Handle_info listens to certain non-user events and runs code.
This is one area that I am still learning about so my understanding is limited.
"""
def handle_info({TestBeds, [:testbed | _], _}, socket) do
testbeds = Enum.sort_by(socket.assigns.testbeds, fn item -> Map.get(item, socket.assigns.sort_field) end, socket.assigns.sort_direction)
{:noreply, assign(socket, testbeds: testbeds)}
end
def handle_info({Alerts, [:alert | _], _}, socket) do
{:noreply, assign(socket, alerts: Alerts.list_alerts())}
end
def convert_time(time_stamp) do
time_stamp
|> DateTime.from_naive!("Europe/London")
|> DateTime.shift_zone!("America/Montreal")
|> Calendar.strftime("%m-%d-%y %I:%M %p")
end
def create_timestamp() do
DateTime.utc_now
end
# def convert_time(time_stamp) do
# time_stamp
# |> DateTime.from_naive!("Europe/London")
# |> DateTime.shift_zone!("America/Chicago")
# |> Calendar.strftime("%m-%d-%y %I:%M %p")
# end
@doc """
handle_event is similar to a conventional JavaScript event handler.
The event it listens for is the second argument. The event is then assigned
to html elements using code such as phx-click ="reset".
The first handle_event is responsible for responding to reset events.
The second handle event handles input to the modal.
Both handle_event functions submit data to the database
"""
def handle_event("reset", %{"id" => id}, socket) do
testbed = TestBeds.get_test_bed!(id)
StatusActions.create_status_action(%{
testbed_name: testbed.name,
testbed_value: id,
status: "Available",
developer: testbed.developer
})
TestBeds.get_test_bed!(id)
|> TestBeds.update_test_bed(%{status: "Available", developer: "None"})
# {:noreply, socket}
{:noreply, assign(socket, testbeds: TestBeds.list_testbeds())}
end
def handle_event("get_localstorage", %{"developer" => developer}, socket) do
{:noreply, assign(socket, developer: developer)}
end
def handle_event("create-status", params, socket) do
# Create Record
%{"status" => status, "testbed_id" => testbed_id, "developer" => developer} = params
stripped_developer = String.trim(developer)
if stripped_developer === "" || String.trim(developer) === "" || String.trim(developer) === "None" do
{:noreply, assign(socket, developer: developer, name_warning: " (can't be empty or set to None)")}
else
TestBeds.get_test_bed!(testbed_id)
|> TestBeds.update_test_bed(%{status: status, developer: developer})
current_testbed = TestBeds.get_test_bed!(testbed_id)
StatusActions.create_status_action(%{
testbed_name: current_testbed.name,
testbed_value: testbed_id,
status: status,
developer: developer
})
{:noreply, assign(socket, developer: developer)}
end
end
def handle_event("send", params, socket) do
IO.inspect"____________________________________________XYZ"
IO.inspect AppWeb.PageLive.create_timestamp
IO.inspect"______________________________________________"
IO.inspect params
eleID = params["id_data"]
is_note_important = params["is_note_important"]
note_data = params["data"]
# IO.inspect(eleID)
if String.length(String.trim(note_data)) == 0 do
TestBeds.get_test_bed!(eleID)
|> TestBeds.update_test_bed(%{note: ""})
else
TestBeds.get_test_bed!(eleID)
|> TestBeds.update_test_bed(%{note: note_data, note_date_creation: AppWeb.PageLive.create_timestamp })
end
if is_note_important == nil do
TestBeds.get_test_bed!(eleID)
|> TestBeds.update_test_bed(%{is_note_important: false})
else
TestBeds.get_test_bed!(eleID)
|> TestBeds.update_test_bed(%{is_note_important: true})
end
%JS{}
|> JS.remove_class("active", to: "#preview_button_#{eleID}")
|> JS.add_class("hidden", to: "#preview_button_#{eleID}")
|> JS.remove_class("hidden", to: "#editing_button_#{eleID}")
|> JS.add_class("active", to: "#editing_button_#{eleID}")
|> JS.remove_class("active", to: "#editing_#{eleID}")
|> JS.add_class("hidden", to: "#editing_#{eleID}")
|> JS.remove_class("hidden", to: "#preview_#{eleID}")
|> JS.add_class("active", to: "#preview_#{eleID}")
{:noreply, redirect(socket, to: "/")}
end
def handle_event("manual-reset", _params, socket) do
# TestBeds.reset_testbeds(status: "Available")
TestBeds.reset_testbeds()
# File.write("timestamp.txt", DateTime.to_string(DateTime.utc_now()))
{:noreply, socket}
end
def handle_event("transmit-text", _params, socket) do
# Create Record
# IO.inspect(params)
{:noreply, socket}
end
@doc """
a_timed_event schedules events at given interval. This is a test version. Ideally
at 12am each night testbeds reset
"""
def a_timed_event() do
TestBeds.reset_testbeds()
# TestBeds.reset_testbeds()
File.write("timestamp.txt", DateTime.to_string(DateTime.utc_now()))
# IO.inspect(data)
end
def button_event("invoke_editing", eleID) do
# IO.inspect(eleID)
%JS{}
|> JS.remove_class("active", to: "#editing_button_#{eleID}")
|> JS.add_class("hidden", to: "#editing_button_#{eleID}")
|> JS.remove_class("hidden", to: "#preview_button_#{eleID}")
|> JS.add_class("active", to: "#preview_button_#{eleID}")
|> JS.remove_class("active", to: "#preview_#{eleID}")
|> JS.add_class("hidden", to: "#preview_#{eleID}")
|> JS.remove_class("hidden", to: "#editing_#{eleID}")
|> JS.add_class("active", to: "#editing_#{eleID}")
end
def button_event("invoke_preview", eleID) do
# IO.inspect(eleID)
%JS{}
|> JS.remove_class("active", to: "#preview_button_#{eleID}")
|> JS.add_class("hidden", to: "#preview_button_#{eleID}")
|> JS.remove_class("hidden", to: "#editing_button_#{eleID}")
|> JS.add_class("active", to: "#editing_button_#{eleID}")
|> JS.remove_class("active", to: "#editing_#{eleID}")
|> JS.add_class("hidden", to: "#editing_#{eleID}")
|> JS.remove_class("hidden", to: "#preview_#{eleID}")
|> JS.add_class("active", to: "#preview_#{eleID}")
end
def sort_by(socket, field) do
atomParam = String.to_existing_atom(field)
if socket.assigns[:sort_direction] == false do
sorted_testbeds = Enum.sort_by(socket.assigns.testbeds, fn item -> Map.get(item, atomParam) end)
{:noreply, assign(socket, testbeds: sorted_testbeds, sort_direction: true, sort_field: atomParam)}
else
sorted_testbeds = Enum.sort_by(socket.assigns.testbeds, fn item -> Map.get(item, atomParam) end)
|> Enum.reverse()
{:noreply, assign(socket, testbeds: sorted_testbeds, sort_direction: false, sort_field: atomParam)}
end
end
def handle_event("sort_by_string", %{"field" => field}, socket) do
sort_by(socket, field)
end
def render(assigns) do
~H"""
<body class="bg-blue_body">
<div class="flex flex-col bg-dark_blue_background mt-0">
<div class=" sm:-mx-6 lg:-mx-12 ">
<div class="inline-block min-w-full sm:px-6 lg:px-8 bg-dark_blue_background pb-40 ">
<div class="">
<table class="min-w-full text-left text-sm font-light ">
<div class="testbed-status-title text-3xl font-bold text-white py-3 ">
Testbed Status
<a href ="/status_actions">
<.button class=" bg-[#800080] float-right mx-5 relative bottom-[10px]">[User Logs]</.button>
</a>
<!-- BEGIN Alerts -->
<%= for alert <- @alerts do %>
<%= if alert.enabled do %>
<div
class="bg-[#fff8c1fc] border-t-4 border-teal-500 rounded-b text-teal-900 px-4 py-3 shadow-md"
role="alert"
>
<div class="flex">
<div class="py-1 px-2">
<span class="relative flex h-3 w-3">
<span class="animate-ping absolute inline-flex h-full w-full rounded-full bg-sky-400 opacity-75">
</span>
<span class="relative inline-flex rounded-full h-3 w-3 bg-yellow-300">
</span>
</span>
</div>
<div>
<p class="font-bold text-base">
<span class="font-bold text-base text-[#d3288c]">ALERT:</span> <%= alert.title %>
<span class="font-bold text-sm text-[#d3288c] block">Time of Alert: <span class="text-sm text-[#000]"><%= convert_time(alert.updated_at) %></span></span>
</p>
<p class="text-sm font-medium">
<%= alert.content %>
</p>
</div>
</div>
</div>
<% end %>
<% end %>
<!-- END Alerts-->
</div>
<thead class=" font-medium ">
<tr class="bg-table_blue text-white ">
<th scope="col" class="px-6 rounded-l-full ">Group</th>
<th scope="col" class="px-6 text-center">Info</th>
<th scope="col" class="px-6 text-center">Testbed</th>
<th>
<div class="relative left-[20px] z-10 ">
<div class="info-button"> Core </div>
<span class="info-box-container">
<span class="rounded-full bg-[#fff8c1fc]">
<ul class="bg-[#fff8c1fc] text-black absolute w-[200px] left-[-80px] p-5 outline outline-[#e11d48] outline-1 font-medium">
<div> Testbed Version Number</div>
<hr>
</ul>
</span>
</span>
</div>
</th>
<th>
<div class="relative left-[20px] z-10 ">
<div class="info-button"> F/W </div>
<span class="info-box-container">
<span class="rounded-full bg-[#fff8c1fc]">
<ul class="bg-[#fff8c1fc] text-black absolute w-[200px] left-[-80px] p-5 outline outline-[#e11d48] outline-1 font-medium">
<div> Firmware Version</div>
<hr>
</ul>
</span>
</span>
</div>
</th>
<th>
<div class="relative left-[20px] z-10 ">
<div class="info-button"> DC </div>
<span class="info-box-container">
<span class="rounded-full bg-[#fff8c1fc]">
<ul class="bg-[#fff8c1fc] text-black absolute w-[200px] left-[-80px] p-5 outline outline-[#e11d48] outline-1 font-medium">
<div> If Testbed is Data Center column shows "DC". Otherwise, left blank</div>
<hr>
</ul>
</span>
</span>
</div>
</th>
<th>
<div class="relative left-[20px] z-10 ">
<div class="info-button"> MS </div>
<span class="info-box-container">
<span class="rounded-full bg-[#fff8c1fc]">
<ul class="bg-[#fff8c1fc] text-black absolute w-[200px] left-[-80px] p-5 outline outline-[#e11d48] outline-1 font-medium">
<div> If Testbed is Multisite this column shows MS. Otherwise, left blank.</div>
<hr>
</ul>
</span>
</span>
</div>
</th>
<th>
<div class="relative left-[15px] z-10 ">
<div class="info-button"> Mon </div>
<span class="info-box-container">
<span class="rounded-full bg-[#fff8c1fc]">
<ul class="bg-[#fff8c1fc] text-black absolute w-[200px] left-[-80px] p-5 outline outline-[#e11d48] outline-1 font-medium">
<div> Associated Monitoring Dashboard Address. If applicable the column displays "Mon". Otherwise, left blank. To view the address value look under the "info" column</div>
<hr>
</ul>
</span>
</span>
</div>
</th>
<th>
<div class="relative left-[0px] z-10 ">
<div class="info-button" phx-click="sort_by_string" phx-value-field="hardware" > Hardware</div>
<span class="info-box-container">
<span class="rounded-full bg-[#fff8c1fc]">
<ul class="bg-[#fff8c1fc] text-black absolute w-[200px] left-[-80px] p-5 outline outline-[#e11d48] outline-1 font-medium">
<div> Device Hardware type (gns3, sim, real, etc)</div>
<hr>
</ul>
</span>
</span>
</div>
</th>
<th scope="col" class="px-6 text-center">Note</th>
<%!-- <th scope="col" class="px-6 text-center ">Status</th> --%>
<th scope="col" class="px-6 text-center">Developer</th>
<th scope="col" class="px-6 text-center">Date</th>
<th scope="col" class="px-6 px-6 rounded-r-full text-center">Set Status</th>
<!-- <th scope="col" class="px-6 py-2 rounded-r-full">Clear</th> -->
</tr>
</thead>
<%!-- <%= for testbed <- Enum.sort_by(@testbeds , &("#{&1.group.name}#{&1.version}"), :asc) do %> --%>
<!-----------Loop through testbeds and perform conditional actions based on the state of data____Apply user event listeners to items-->
<%!-- <%= for testbed <- Enum.sort_by(@testbeds , &("#{&1.group.name},#{&1.name}"), :asc) do %> --%>
<%= for testbed <- @testbeds do %>
<tbody>
<tr class="transition duration-300 ease-in-out hover:bg-table_blue text-white">
<td id={"testbed_group_color#{testbed.id}"}>
<div class={"outline-[#D1D1D1] outline outline-1 relative left-7 top-1 w-3 h-3 "} style={"background-color: #{testbed.group.color}"}></div>
</td>
<td>
<div class="relative left-[20px] z-10 ">
<a class="info-button" href= {"/testbeds/#{testbed.id}/edit"}><button>Info</button> </a>
<span class="info-box-container">
<span class="rounded-full bg-[#fff8c1fc]">
<ul class="bg-[#fff8c1fc] text-black absolute w-[260px] left-[50px] p-5 outline outline-[#e11d48] outline-1 font-medium">
<li><b>Name:</b> <%= testbed.name %> </li>
<hr>
<li><b>Owner:</b> <%= testbed.owner %></li>
<hr>
<li><b>Group:</b> <%= testbed.group.name %></li>
<hr>
<li><b>Manager:</b> <%= testbed.manager%></li>
<hr>
<li> <b>vNetC Auto Upgrade:</b> <%= testbed.vnetc_auto_upgrade %></li>
<hr>
<li><b>Firmware Auto Upgrade: </b><%= testbed.firmware_auto_upgrade %></li>
<hr>
<li><b>Firmware Version: </b><%= testbed.firmware_version %></li>
<hr>
<li><b>Managed Out of Service: </b><%= testbed.managed_out_of_service %></li>
<hr>
<li><b>DB Backup: </b><%= testbed.db_backup %></li>
<hr>
<hr>
<li><b>Host: </b><%= testbed.host %></li>
<hr>
<hr>
<li><b>Monitoring: </b><%= testbed.monitoring%></li>
<hr>
</ul>
</span>
</span>
</div>
</td>
<td class="whitespace-nowrap px-6 font-medium text-center">
<a
href={testbed.url}
target="_blank"
class="hover:bg-[#D48E22] focus-within:bg-blue-50/50 ease-in-out"
>
<%!-- <%= testbed.name %> --%>
<%= if testbed.managed_out_of_service do %>
<div class="bg-[#73808D] "><%= testbed.name %></div>
<% end %>
<%= if !testbed.managed_out_of_service do %>
<div ><%= testbed.name %></div>
<% end %>
</a>
</td>
<td id={"testbed_version_#{testbed.id}"} phx-hook="TestbedVersionHover" class="whitespace-nowrap px-6 testbed-version"> <%= testbed.version %></td>
<td id={"testbed_firmware_version#{testbed.id}"} phx-hook="TestbedOwnerHover"
class="whitespace-nowrap px-6 testbed-firmware_version"> <%= testbed.firmware_version %></td>
<td id={"testbed_datacenter#{testbed.id}"}
class="whitespace-nowrap px-6 testbed-datacenter">
<%!-- <%= testbed.datacenter %> --%>
<%= if testbed.datacenter do %>
<p>DC</p>
<% else %>
<p></p>
<% end %>
</td>
<td id={"testbed_multisite#{testbed.id}"}
class="whitespace-nowrap px-6 testbed-multisite">
<%!-- <%= testbed.multisite %> --%>
<%= if testbed.multisite do %>
<p>MS</p>
<% else %>
<p></p>
<% end %>
</td>
<td id={"testbed_monitoring#{testbed.id}"}
class="whitespace-nowrap px-6 testbed-monitoring">
<%= if testbed.monitoring do %>
<div class="relative left-[-5px] z-10 ">
<div class="info-button"> Mon </div>
<span class="info-box-container">
<span class="rounded-full bg-[#fff8c1fc]">
<ul class="bg-[#fff8c1fc] text-black absolute w-[200px] left-[-80px] p-5 outline outline-[#e11d48] outline-1 font-medium">
<div> <%= testbed.monitoring %> </div>
<hr>
</ul>
</span>
</span>
</div>
<% else %>
<p></p>
<% end %>
</td>
<td id={"testbed_hardware#{testbed.id}"}
class="whitespace-nowrap px-6 testbed-hardware">
<%= if testbed.remote_desktop_connection_ip do %>
<div class="relative left-[-5px] z-10 ">
<div class="info-button"> <%= testbed.hardware%> </div>
<span class="info-box-container">
<span class="rounded-full bg-[#fff8c1fc]">
<ul class="bg-[#fff8c1fc] text-black absolute w-[200px] left-[-80px] p-5 outline outline-[#e11d48] outline-1 font-medium">
<div> <%= testbed.remote_desktop_connection_ip %> </div>
<hr>
</ul>
</span>
</span>
</div>
<% else %>
<%= testbed.hardware%>
<% end %>
</td>
<%!-- <td id={"testbed_host#{testbed.id}"}
class="whitespace-nowrap px-6 testbed-host"> <%= testbed.host%></td>--%>
<.modal id={"modal-note#{testbed.id}"}>
<div class="text-black bg-amber-300 px-20 py-10 ">
<!-- <.button
phx-click={button_event("invoke_editing", testbed.id)}
id={"editing_button_#{testbed.id}"}
class="hidden bg-green-500"
>
Preview / Save
</.button>
--> <%!-- <div class="mark-as-important-container relative left-[450px] top-10 w-40" >
<form>
<div class="checkboxes">
<label><input type="checkbox"> <span>Mark as Important!</span></label>
</div>
</form>
</div> --%>
<%!--
position:relative
left: 400 px
top: 25px
--%>
<.button
phx-click={button_event("invoke_preview", testbed.id)}
id={"preview_button_#{testbed.id}"}
class="bg-green-500"
>
Quick Edit
</.button>
<h1 class="text-rose-800 text-4xl ">Add Note</h1>
<h1 class="text-rose-800 font-medium">
<%= testbed.name %> | <%= testbed.version %>
</h1>
<h3 class="text-rose-800 font-medium">
<%= AppWeb.PageLive.convert_time(testbed.updated_at) %>
</h3>
<p><%= testbed.note %></p>
<hr />
<div id={"preview_#{testbed.id}"} class="hidden">
<form phx-submit="send">
<input value={testbed.id} name="id_data" hidden />
<textarea value={testbed.note} name="data" class="w-full"><%=testbed.note%> </textarea>
<div class="mark-as-important-container relative left-[450px] top-10 w-40" >
<label><input type="checkbox" checked={testbed.is_note_important} name="is_note_important"> <span>Mark as Important!</span></label>
</div>
<.button type="submit" class="left-0 bg-red-600">SAVE WORK</.button>
</form>
</div>
</div>
</.modal>
<!-- END Workspace
-->
<div>
<%= if testbed.note do %>
<td phx-click={show_modal("modal-note#{testbed.id}")}>
<%= if testbed.is_note_important do %>
<div class="bg-[#fef7a6] text-center outline-8 outline-rose-600 w-48">
<b class="text-[#6E0000] font-medium text-xs">Read Me! </b>
<p class="text-xs text-[#000] "><%=String.slice(testbed.note, 0, 35) %>...</p>
</div>
<% end %>
<%= if testbed.is_note_important == false do %>
<div class="bg-[#888da1] text-center outline-8 outline-rose-600">
<b class="text-[#000] font-medium">Note</b>
<p class="text-xs text-[#000] "><%=String.slice(testbed.note, 0, 35) %>...</p>
</div>
<% end %>
</td>
<% end %>
<%= if !testbed.note do %>
<td
class="opacity-20 hover:bg-orange-400 z-40 hover:opacity-100 text-center "
phx-click={show_modal("modal-note#{testbed.id}")}
>
Add Note
</td>
<% end %>
</div>
<%!-- <%= if testbed.status == "Available" do %>
<td class="whitespace-nowrap px-6 relative">
<span class=" font-bold text-teal-900 rounded-full bg-green-400 h-1 relative px-5">
<%= testbed.status %>
</span>
</td>
<% end %>
<%= if testbed.status == "Frozen" do %>
<td class="whitespace-nowrap px-6 relative ">
<span class=" text-teal-900 font-bold rounded-full bg-teal-400 h-1 relative px-5">
<%= testbed.status %>
</span>
</td>
<% end %>
<%= if testbed.status == "Taken" do %>
<td class="whitespace-nowrap px-6 relative ">
<span class=" font-bold text-red-900 rounded-full bg-rose-300 h-1 relative px-5">
<%= testbed.status %>
</span>
</td>
<% end %>
<%= if testbed.status !=="Frozen" && testbed.status !=="Taken" && testbed.status !=="Available"do %>
<td class="whitespace-nowrap px-6 relative ">
<span class=" font-bold rounded-full bg-green-500 h-1 relative px-5">
<%= testbed.status %>
</span>
</td>
<% end %> --%>
<td id={"testbed_developer_#{testbed.id}"} phx-hook="TestbedDeveloperHover" class="text-center whitespace-nowrap px-6 testbed-developer"> <%= testbed.developer %></td>
<%= if testbed.status == "Taken" || testbed.status == "Frozen" do %>
<td class="whitespace-nowrap px-6 text-center">
<%= AppWeb.PageLive.convert_time(testbed.updated_at) %>
</td>
<% end %>
<%= if testbed.status == "Available" do %>
<td class="whitespace-nowrap px-6 text-center">NA</td>
<% end %>
<%= if testbed.status == "Available" do %>
<td class="whitespace-nowrap px-6 ">
<button
phx-click={show_modal("delete-modal-#{testbed.id}")}
value={testbed.id}
class="bg-[#5ddc8c] hover:bg-green-400 font-bold text-teal-900 px-4 border border-gray-400 rounded shadow "
>
Available
</button>
</td>
<% end %>
<%= if testbed.status != "Available" do %>
<%= if testbed.status == "Frozen" do %>
<td
phx-click={'reset'}
phx-value-id={testbed.id}
class="whitespace-nowrap px-6 py-4"
>
<button class="bg-teal-400 hover:bg-teal-200 text-teal-900 font-bold px-6 px-4 border border-black-400 rounded shadow ">
Frozen
</button>
</td>
<% end %>
<%= if testbed.status == "Taken" do %>
<td
phx-click={'reset'}
phx-value-id={testbed.id}
class="whitespace-nowrap px-6 py-4"
>
<button class="bg-rose-300 hover:bg-pink-400 text-red-900 font-bold px-7 border border-gray-400 rounded shadow ">
Taken
</button>
</td>
<% end %>
<%!-- <td
phx-click={'reset'}
phx-value-id={testbed.id}
class="whitespace-nowrap px-6 py-4"
>
<button class="bg-pink-500 hover:bg-blue-700 text-white font-bold px-6 rounded ">
Clear
</button>
</td> --%>
<% end %>
</tr>
<div class="modal-container">
<.modal id={"delete-modal-#{testbed.id}"}>
<!-- Container -->
<!-- Login form -->
<div class="flex flex-wrap content-center justify-center bg-dark_blue_background text-white">
<div class="w-72 mt-10">
<!-- Heading -->
<small class="text-black-400 text-xl ">
You Are Reserving <%= testbed.name %>
</small>
<!-- Form -->
<form
class="mt-4"
phx-submit="create-status"
phx-hook="FormLocalStorageHook"
id={"local_storage_hoook-#{testbed.id}"}
>
<div class="mb-3">
<div class="flex justify-center"></div>
</div>
<div class="mb-3 h-2">
<input type="hidden" class="" value={testbed.id} name="testbed_id" />
</div>
<div class="mb-6 ">
<p>Status</p>
<select
name="status"
id={"status-id-#{testbed.id}"}
class="rounded mt-2 text-cyan-800"
>
<option value="Taken">Taken</option>
<option value="Frozen">Frozen</option>
</select>
</div>
<div class="mb-3">
<label class="mb-2 block font-semibold"> Your Name <span class="text-[#ffce57]"><%= @name_warning %></span></label>
<input
value={@developer}
name="developer"
type="text"
class="block w-full rounded-md border border-gray-300 focus:border-purple-700 focus:outline-none focus:ring-1 focus:ring-purple-700 py-1 px-1.5 text-gray-500"
/>
</div>
<div class="mb-3">
<button phx-click={hide_modal("delete-modal-#{testbed.id}")} class="bg-sky-500/75 mb-1.5 block w-full text-center text-white bg-cyan-700 hover:bg-cyan-900 px-2 py-1.5 rounded-md">
Reserve
</button>
</div>
</form>
</div>
</div>
</.modal>
</div>
</tbody>
<% end %>
</table>
</div>
</div>
</div>
</div>
</body>
"""
end
end
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment