61195bd6b2
Public-facing Mojolicious app for looking up Heaven's Glaives deaths in any WCL report. The nginx vhost, rc.d script, and the runtime SQLite cache are intentionally excluded via .gitignore.
218 lines
6.2 KiB
Plaintext
218 lines
6.2 KiB
Plaintext
% layout undef;
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>Heaven's Glaives Lookup</title>
|
|
<link rel="icon" type="image/jpeg" href="/glaive.jpg">
|
|
<style>
|
|
:root {
|
|
--bg: #0f0f1a;
|
|
--surface: #16162a;
|
|
--border: #252542;
|
|
--text: #dde0f0;
|
|
--muted: #7878a0;
|
|
--gold: #c9a227;
|
|
--red: #d94f4f;
|
|
}
|
|
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
|
body {
|
|
background: var(--bg);
|
|
color: var(--text);
|
|
font-family: system-ui, -apple-system, sans-serif;
|
|
max-width: 560px;
|
|
margin: 0 auto;
|
|
padding: 2.5rem 1.25rem 5rem;
|
|
line-height: 1.5;
|
|
}
|
|
h1 {
|
|
color: var(--gold);
|
|
font-size: 1.75rem;
|
|
font-weight: 700;
|
|
letter-spacing: -.02em;
|
|
}
|
|
.subtitle {
|
|
color: var(--muted);
|
|
font-size: .9rem;
|
|
margin-top: .3rem;
|
|
margin-bottom: 2rem;
|
|
}
|
|
form {
|
|
background: var(--surface);
|
|
border: 1px solid var(--border);
|
|
border-radius: 6px;
|
|
padding: 1.25rem;
|
|
margin-bottom: 2rem;
|
|
}
|
|
label {
|
|
display: block;
|
|
font-size: .78rem;
|
|
text-transform: uppercase;
|
|
letter-spacing: .07em;
|
|
color: var(--muted);
|
|
margin-bottom: .4rem;
|
|
}
|
|
input[type=text], input[type=number] {
|
|
width: 100%;
|
|
background: var(--bg);
|
|
border: 1px solid var(--border);
|
|
border-radius: 4px;
|
|
color: var(--text);
|
|
padding: .55rem .7rem;
|
|
font-size: .95rem;
|
|
font-family: inherit;
|
|
}
|
|
details summary {
|
|
color: var(--muted);
|
|
font-size: .82rem;
|
|
cursor: pointer;
|
|
margin: 1rem 0 .6rem;
|
|
user-select: none;
|
|
}
|
|
button {
|
|
margin-top: 1.1rem;
|
|
background: var(--gold);
|
|
color: #1a1505;
|
|
border: none;
|
|
border-radius: 4px;
|
|
padding: .6rem 1.1rem;
|
|
font-size: .9rem;
|
|
font-weight: 600;
|
|
cursor: pointer;
|
|
}
|
|
.error {
|
|
background: rgba(217, 79, 79, .12);
|
|
border: 1px solid var(--red);
|
|
color: var(--red);
|
|
border-radius: 6px;
|
|
padding: .75rem 1rem;
|
|
margin-bottom: 1.5rem;
|
|
font-size: .9rem;
|
|
}
|
|
h2 {
|
|
color: var(--gold);
|
|
font-size: .78rem;
|
|
text-transform: uppercase;
|
|
letter-spacing: .1em;
|
|
font-weight: 600;
|
|
margin: 0 0 .9rem;
|
|
padding-bottom: .5rem;
|
|
border-bottom: 1px solid var(--border);
|
|
}
|
|
.report-meta { color: var(--muted); font-size: .85rem; margin-bottom: 1rem; }
|
|
table { width: 100%; border-collapse: collapse; }
|
|
th {
|
|
color: var(--muted);
|
|
font-size: .75rem;
|
|
text-transform: uppercase;
|
|
letter-spacing: .07em;
|
|
font-weight: 500;
|
|
text-align: left;
|
|
padding: .4rem .75rem;
|
|
border-bottom: 1px solid var(--border);
|
|
}
|
|
td { padding: .55rem .75rem; border-bottom: 1px solid var(--border); font-size: .95rem; }
|
|
tr:last-child td { border-bottom: none; }
|
|
.rank { color: var(--muted); width: 2.5rem; font-variant-numeric: tabular-nums; }
|
|
.count, .count-header { text-align: right; }
|
|
.count { color: var(--red); font-weight: 600; font-variant-numeric: tabular-nums; }
|
|
.muted { color: var(--muted); }
|
|
.total {
|
|
display: inline-block;
|
|
background: var(--red);
|
|
color: #fff;
|
|
border-radius: 99px;
|
|
padding: .15rem .65rem;
|
|
font-size: .78rem;
|
|
font-weight: 600;
|
|
margin-left: .5rem;
|
|
}
|
|
.recent { list-style: none; margin-bottom: 2.5rem; }
|
|
.recent li {
|
|
padding: .55rem 0;
|
|
border-bottom: 1px solid var(--border);
|
|
font-size: .9rem;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
gap: 1rem;
|
|
}
|
|
.recent li:last-child { border-bottom: none; }
|
|
.recent a { color: var(--text); text-decoration: none; }
|
|
.recent a:hover { color: var(--gold); }
|
|
.recent .death-count { color: var(--muted); flex-shrink: 0; }
|
|
.powered-by {
|
|
margin-top: 3rem;
|
|
padding-top: 1.5rem;
|
|
border-top: 1px solid var(--border);
|
|
text-align: center;
|
|
font-family: "Courier New", monospace;
|
|
font-size: .72rem;
|
|
color: var(--muted);
|
|
letter-spacing: .05em;
|
|
}
|
|
.powered-by a { color: var(--muted); text-decoration: underline; }
|
|
.powered-by a:hover { color: var(--gold); }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<h1>Heaven's Glaives Lookup</h1>
|
|
<p class="subtitle">Paste a Warcraft Logs report code to see Heaven's Glaives deaths (Mythic Midnight Falls / L'ura).</p>
|
|
|
|
% if (stash('error')) {
|
|
<div class="error"><%= stash('error') %></div>
|
|
% }
|
|
|
|
<form method="get" action="/">
|
|
<label for="code">Report code</label>
|
|
<input type="text" id="code" name="code" placeholder="e.g. j8aqTD2W9XG4PFxJ" value="<%= stash('code') // '' %>" maxlength="16" autocomplete="off" required>
|
|
|
|
<details<%== (stash('cutoff') && stash('cutoff') != 2) ? ' open' : '' %>>
|
|
<summary>Advanced</summary>
|
|
<label for="cutoff">Wipe cutoff (ignore deaths after the Nth wipe on a pull)</label>
|
|
<input type="number" id="cutoff" name="cutoff" min="0" max="20" value="<%= stash('cutoff') // 2 %>">
|
|
</details>
|
|
|
|
<button type="submit">Look up</button>
|
|
</form>
|
|
|
|
% if (stash('result')) {
|
|
<h2>
|
|
<%= stash('result')->{raid_date} %> — <%= stash('result')->{title} %>
|
|
<span class="total"><%= stash('total') %> death<%= stash('total') == 1 ? '' : 's' %></span>
|
|
</h2>
|
|
<p class="report-meta"><%= stash('result')->{fight_count} %> Mythic Midnight Falls pull(s) · <%= stash('result')->{zone_name} %></p>
|
|
<table>
|
|
<thead><tr><th class="rank">#</th><th>Player</th><th class="count-header">Deaths</th></tr></thead>
|
|
<tbody>
|
|
% my $rank = 1;
|
|
% for my $row (@{ stash('rows') }) {
|
|
<tr><td class="rank"><%= $rank++ %></td><td><%= $row->{player_name} %></td><td class="count"><%= $row->{n} %></td></tr>
|
|
% }
|
|
% if (!@{ stash('rows') }) {
|
|
<tr><td colspan="3" class="muted">No Heaven's Glaives deaths in this report.</td></tr>
|
|
% }
|
|
</tbody>
|
|
</table>
|
|
% }
|
|
|
|
% if (@{ stash('recent') // [] }) {
|
|
<h2>Recent lookups</h2>
|
|
<ul class="recent">
|
|
% for my $r (@{ stash('recent') }) {
|
|
<li>
|
|
<a href="/?code=<%= $r->{code} %>&cutoff=<%= $r->{cutoff} %>"><%= $r->{raid_date} %> — <%= $r->{title} %></a>
|
|
<span class="death-count"><%= $r->{total} %> death<%= $r->{total} == 1 ? '' : 's' %></span>
|
|
</li>
|
|
% }
|
|
</ul>
|
|
% }
|
|
|
|
<footer class="powered-by">
|
|
Powered by <a href="https://mojolicious.org/">Mojolicious</a> running on <a href="https://www.freebsd.org/">FreeBSD</a>, source <a href="https://git.fnord.mx/pub/glaived">git</a>
|
|
</footer>
|
|
|
|
</body>
|
|
</html>
|