pingql/apps/web/src/views/incident-edit.ejs

122 lines
6.2 KiB
Plaintext

<%~ include('./partials/head', { title: it.isNew ? 'New incident' : 'Edit incident' }) %>
<%~ include('./partials/nav', { nav: 'incidents' }) %>
<%
const i = it.incident || {};
const allMonitors = it.allMonitors || [];
const allPages = it.allPages || [];
const attachedMonitors = new Set((it.incident?.monitor_ids || []));
const attachedPages = new Set((it.incident?.status_page_ids || []));
const updates = it.incident?.updates || [];
%>
<main class="max-w-3xl mx-auto px-8 py-10 space-y-6">
<div>
<a href="/dashboard/incidents" class="text-sm text-gray-500 hover:text-gray-300 transition-colors">&larr; Back to incidents</a>
<h1 class="text-xl font-semibold text-white mt-2"><%= it.isNew ? 'New incident' : 'Edit incident' %></h1>
</div>
<form method="POST" action="<%= it.isNew ? '/dashboard/incidents/new' : '/dashboard/incidents/' + i.id + '/edit' %>" class="space-y-5 card-static p-6">
<div>
<label class="block text-sm text-gray-400 mb-1.5">Title</label>
<input name="title" type="text" required value="<%= i.title || '' %>" placeholder="API latency degraded"
class="w-full bg-gray-900 border border-gray-800 rounded-lg px-4 py-2.5 text-gray-100 placeholder-gray-600 focus:outline-none focus:border-blue-500">
</div>
<div class="flex gap-4">
<div class="flex-1">
<label class="block text-sm text-gray-400 mb-1.5">Status</label>
<select name="status" class="w-full bg-gray-900 border border-gray-800 rounded-lg px-4 py-2.5 text-gray-100 focus:outline-none focus:border-blue-500">
<% ['investigating','identified','monitoring','resolved'].forEach(function(s) { %>
<option value="<%= s %>" <%= (i.status || 'investigating') === s ? 'selected' : '' %>><%= s %></option>
<% }) %>
</select>
</div>
<div class="flex-1">
<label class="block text-sm text-gray-400 mb-1.5">Severity</label>
<select name="severity" class="w-full bg-gray-900 border border-gray-800 rounded-lg px-4 py-2.5 text-gray-100 focus:outline-none focus:border-blue-500">
<% ['minor','major','critical'].forEach(function(s) { %>
<option value="<%= s %>" <%= (i.severity || 'minor') === s ? 'selected' : '' %>><%= s %></option>
<% }) %>
</select>
</div>
</div>
<div>
<label class="block text-sm text-gray-400 mb-1.5">Affected monitors</label>
<% if (allMonitors.length === 0) { %>
<p class="text-xs text-gray-600">No monitors yet.</p>
<% } else { %>
<div class="flex flex-wrap gap-2">
<% allMonitors.forEach(function(m) { %>
<label class="flex items-center gap-2 bg-gray-900 border border-gray-800 hover:border-gray-600 rounded-lg px-3 py-2 cursor-pointer transition-colors">
<input type="checkbox" name="monitor_ids" value="<%= m.id %>" class="accent-blue-500" <%= attachedMonitors.has(m.id) ? 'checked' : '' %>>
<span class="text-sm text-gray-300"><%= m.name %></span>
</label>
<% }) %>
</div>
<% } %>
</div>
<div>
<label class="block text-sm text-gray-400 mb-1.5">Show on status pages</label>
<% if (allPages.length === 0) { %>
<p class="text-xs text-gray-600">No status pages yet. <a href="/dashboard/status-pages/new" class="text-blue-400 hover:text-blue-300">Create one</a>.</p>
<% } else { %>
<div class="flex flex-wrap gap-2">
<% allPages.forEach(function(p) { %>
<label class="flex items-center gap-2 bg-gray-900 border border-gray-800 hover:border-gray-600 rounded-lg px-3 py-2 cursor-pointer transition-colors">
<input type="checkbox" name="status_page_ids" value="<%= p.id %>" class="accent-blue-500" <%= attachedPages.has(p.id) ? 'checked' : '' %>>
<span class="text-sm text-gray-300"><%= p.title %></span>
</label>
<% }) %>
</div>
<% } %>
</div>
<% if (it.isNew) { %>
<div>
<label class="block text-sm text-gray-400 mb-1.5">Initial update</label>
<textarea name="initial_update_body" rows="4" placeholder="We're investigating reports of slow API responses." required
class="w-full bg-gray-900 border border-gray-800 rounded-lg px-4 py-2.5 text-gray-100 placeholder-gray-600 focus:outline-none focus:border-blue-500"></textarea>
<p class="text-xs text-gray-600 mt-1">Markdown supported: **bold**, *italic*, `code`, [link](https://...)</p>
</div>
<% } %>
<button type="submit" class="btn-primary px-6 py-2.5 text-sm"><%= it.isNew ? 'Create incident' : 'Save changes' %></button>
</form>
<% if (!it.isNew && updates.length > 0) { %>
<section class="card-static p-6">
<h2 class="text-sm font-semibold text-gray-300 mb-4">Timeline</h2>
<div class="space-y-4">
<% updates.slice().reverse().forEach(function(u) { %>
<div class="border-l-2 border-border-subtle pl-4">
<div class="text-xs text-gray-500 mb-1"><span class="text-gray-400 font-medium"><%= u.status %></span> · <%~ it.timeAgoSSR(u.created_at) %></div>
<div class="text-sm text-gray-300 incident-body"><%~ u.body_html %></div>
</div>
<% }) %>
</div>
</section>
<% } %>
<% if (!it.isNew) { %>
<section class="card-static p-6">
<h2 class="text-sm font-semibold text-gray-300 mb-4">Post update</h2>
<form method="POST" action="/dashboard/incidents/<%= i.id %>/update" class="space-y-3">
<select name="status" class="w-full bg-gray-900 border border-gray-800 rounded-lg px-4 py-2.5 text-gray-100 focus:outline-none focus:border-blue-500">
<% ['investigating','identified','monitoring','resolved'].forEach(function(s) { %>
<option value="<%= s %>" <%= (i.status || 'investigating') === s ? 'selected' : '' %>><%= s %></option>
<% }) %>
</select>
<textarea name="body" rows="3" placeholder="Update text" required
class="w-full bg-gray-900 border border-gray-800 rounded-lg px-4 py-2.5 text-gray-100 placeholder-gray-600 focus:outline-none focus:border-blue-500"></textarea>
<button type="submit" class="btn-primary px-6 py-2 text-sm">Post update</button>
</form>
</section>
<% } %>
</main>