Add maintenance windows LiveView UI
- Index page with All/Active/Upcoming/Past filter tabs - Show page with active banner, edit/delete actions - Form page with scope picker (org-wide/site/device), datetime fields - Nav link added to desktop and mobile nav
This commit is contained in:
parent
3f2b2a5d5e
commit
0f9fac76d9
2 changed files with 57 additions and 28 deletions
|
|
@ -280,6 +280,12 @@ defmodule ToweropsWeb.Layouts do
|
|||
>
|
||||
{t("Alerts")}
|
||||
</.nav_link>
|
||||
<.nav_link
|
||||
navigate={~p"/maintenance"}
|
||||
active={@active_page == "maintenance"}
|
||||
>
|
||||
{t("Maintenance")}
|
||||
</.nav_link>
|
||||
|
||||
<!-- Separator -->
|
||||
<div class="h-4 w-px bg-gray-200 dark:bg-gray-700 mx-1"></div>
|
||||
|
|
@ -559,6 +565,9 @@ defmodule ToweropsWeb.Layouts do
|
|||
<.mobile_nav_link navigate={~p"/alerts"} active={@active_page == "alerts"}>
|
||||
<.icon name="hero-bell" class="size-5" /> {t("Alerts")}
|
||||
</.mobile_nav_link>
|
||||
<.mobile_nav_link navigate={~p"/maintenance"} active={@active_page == "maintenance"}>
|
||||
<.icon name="hero-wrench-screwdriver" class="size-5" /> {t("Maintenance")}
|
||||
</.mobile_nav_link>
|
||||
</div>
|
||||
|
||||
<!-- Secondary nav -->
|
||||
|
|
|
|||
|
|
@ -37,7 +37,9 @@
|
|||
class="block w-full rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm text-gray-900 placeholder-gray-400 focus:border-blue-500 focus:ring-blue-500 dark:border-white/10 dark:bg-gray-800 dark:text-white dark:placeholder-gray-500"
|
||||
placeholder={t("e.g., Tower firmware upgrade")}
|
||||
/>
|
||||
<%= for {msg, _} <- (@changeset.errors[:name] || []) do %><p class="mt-1 text-sm text-red-600 dark:text-red-400">{msg}</p><% end %>
|
||||
<%= for {msg, _} <- (@changeset.errors[:name] || []) do %>
|
||||
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{msg}</p>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<%!-- Reason --%>
|
||||
|
|
@ -58,20 +60,42 @@
|
|||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">{t("Scope")}</label>
|
||||
<div class="flex items-center gap-4 mb-3">
|
||||
<%= for {label, value} <- [{t("Org-wide"), "org"}, {t("Site"), "site"}, {t("Device"), "device"}] do %>
|
||||
<label class="inline-flex items-center gap-2 cursor-pointer">
|
||||
<input
|
||||
type="radio"
|
||||
name="scope_type"
|
||||
value={value}
|
||||
checked={@scope_type == value}
|
||||
phx-click="change_scope"
|
||||
phx-value-scope_type={value}
|
||||
class="text-blue-600 focus:ring-blue-500 dark:bg-gray-800 dark:border-white/10"
|
||||
/>
|
||||
<span class="text-sm text-gray-700 dark:text-gray-300">{label}</span>
|
||||
</label>
|
||||
<% end %>
|
||||
<label class="inline-flex items-center gap-2 cursor-pointer">
|
||||
<input
|
||||
type="radio"
|
||||
name="scope_type"
|
||||
value="org"
|
||||
checked={@scope_type == "org"}
|
||||
phx-click="change_scope"
|
||||
phx-value-scope_type="org"
|
||||
class="text-blue-600 focus:ring-blue-500 dark:bg-gray-800 dark:border-white/10"
|
||||
/>
|
||||
<span class="text-sm text-gray-700 dark:text-gray-300">{t("Org-wide")}</span>
|
||||
</label>
|
||||
<label class="inline-flex items-center gap-2 cursor-pointer">
|
||||
<input
|
||||
type="radio"
|
||||
name="scope_type"
|
||||
value="site"
|
||||
checked={@scope_type == "site"}
|
||||
phx-click="change_scope"
|
||||
phx-value-scope_type="site"
|
||||
class="text-blue-600 focus:ring-blue-500 dark:bg-gray-800 dark:border-white/10"
|
||||
/>
|
||||
<span class="text-sm text-gray-700 dark:text-gray-300">{t("Site")}</span>
|
||||
</label>
|
||||
<label class="inline-flex items-center gap-2 cursor-pointer">
|
||||
<input
|
||||
type="radio"
|
||||
name="scope_type"
|
||||
value="device"
|
||||
checked={@scope_type == "device"}
|
||||
phx-click="change_scope"
|
||||
phx-value-scope_type="device"
|
||||
class="text-blue-600 focus:ring-blue-500 dark:bg-gray-800 dark:border-white/10"
|
||||
/>
|
||||
<span class="text-sm text-gray-700 dark:text-gray-300">{t("Device")}</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<%= if @scope_type == "site" do %>
|
||||
|
|
@ -117,7 +141,9 @@
|
|||
required
|
||||
class="block w-full rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm text-gray-900 focus:border-blue-500 focus:ring-blue-500 dark:border-white/10 dark:bg-gray-800 dark:text-white"
|
||||
/>
|
||||
<%= for {msg, _} <- (@changeset.errors[:starts_at] || []) do %><p class="mt-1 text-sm text-red-600 dark:text-red-400">{msg}</p><% end %>
|
||||
<%= for {msg, _} <- (@changeset.errors[:starts_at] || []) do %>
|
||||
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{msg}</p>
|
||||
<% end %>
|
||||
</div>
|
||||
<div>
|
||||
<label for="maintenance_window_ends_at" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
|
||||
|
|
@ -131,18 +157,16 @@
|
|||
required
|
||||
class="block w-full rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm text-gray-900 focus:border-blue-500 focus:ring-blue-500 dark:border-white/10 dark:bg-gray-800 dark:text-white"
|
||||
/>
|
||||
<%= for {msg, _} <- (@changeset.errors[:ends_at] || []) do %><p class="mt-1 text-sm text-red-600 dark:text-red-400">{msg}</p><% end %>
|
||||
<%= for {msg, _} <- (@changeset.errors[:ends_at] || []) do %>
|
||||
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{msg}</p>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%!-- Suppress Alerts --%>
|
||||
<div>
|
||||
<label class="inline-flex items-center gap-2 cursor-pointer">
|
||||
<input
|
||||
type="hidden"
|
||||
name="maintenance_window[suppress_alerts]"
|
||||
value="false"
|
||||
/>
|
||||
<input type="hidden" name="maintenance_window[suppress_alerts]" value="false" />
|
||||
<input
|
||||
type="checkbox"
|
||||
name="maintenance_window[suppress_alerts]"
|
||||
|
|
@ -157,11 +181,7 @@
|
|||
<%!-- Recurring --%>
|
||||
<div>
|
||||
<label class="inline-flex items-center gap-2 cursor-pointer">
|
||||
<input
|
||||
type="hidden"
|
||||
name="maintenance_window[recurring]"
|
||||
value="false"
|
||||
/>
|
||||
<input type="hidden" name="maintenance_window[recurring]" value="false" />
|
||||
<input
|
||||
type="checkbox"
|
||||
name="maintenance_window[recurring]"
|
||||
|
|
@ -173,7 +193,7 @@
|
|||
</label>
|
||||
</div>
|
||||
|
||||
<%!-- Recurrence Rule (shown when recurring) --%>
|
||||
<%!-- Recurrence Rule --%>
|
||||
<%= if Ecto.Changeset.get_field(@changeset, :recurring) == true do %>
|
||||
<div>
|
||||
<label for="maintenance_window_recurrence_rule" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue