mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-10-02 02:43:44 +00:00
Pages label the game's currencies and stats with the client's words (UI_COINS, UI_UNIVERSE_SCORE, UI_IMAGINATION, UI_REPUTATION, UI_HEALTH) through game.terms and GameText.term instead of writing them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
288 lines
22 KiB
Django/Jinja
288 lines
22 KiB
Django/Jinja
{% extends "base.jinja2" %}
|
|
|
|
{% block title %}Economy - DarkflameServer{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="d-flex flex-wrap align-items-end justify-content-between gap-3 mb-3">
|
|
<div>
|
|
<h2 class="mb-1">Economy</h2>
|
|
<p class="text-body-secondary mb-0">Where {{ game.terms.coins }}, {{ game.terms.uscore }} and items come from and go. World servers write totals every few seconds, and the page updates as they do.</p>
|
|
</div>
|
|
<div class="d-flex flex-wrap align-items-center gap-3" id="reportFilters">
|
|
<div class="btn-group btn-group-sm" role="group" aria-label="Date range">
|
|
<input type="radio" class="btn-check" name="range" id="range7" value="7"><label class="btn btn-outline-secondary" for="range7">7 days</label>
|
|
<input type="radio" class="btn-check" name="range" id="range30" value="30" checked><label class="btn btn-outline-secondary" for="range30">30 days</label>
|
|
<input type="radio" class="btn-check" name="range" id="range90" value="90"><label class="btn btn-outline-secondary" for="range90">90 days</label>
|
|
<input type="radio" class="btn-check" name="range" id="range365" value="365"><label class="btn btn-outline-secondary" for="range365">1 year</label>
|
|
</div>
|
|
<div class="form-check form-switch mb-0">
|
|
<input class="form-check-input" type="checkbox" role="switch" id="includeStaff" data-pref="economy.includeStaff">
|
|
<label class="form-check-label small" for="includeStaff">Include staff</label>
|
|
</div>
|
|
<div class="dropdown">
|
|
<button class="btn btn-sm btn-outline-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">Views</button>
|
|
<ul class="dropdown-menu dropdown-menu-end" id="viewsMenu"><li><span class="dropdown-item-text text-body-secondary small">Loading…</span></li></ul>
|
|
</div>
|
|
<span class="small text-body-secondary" id="updatedAt"></span>
|
|
</div>
|
|
</div>
|
|
|
|
<ul class="nav nav-tabs mb-3" role="tablist">
|
|
<li class="nav-item" role="presentation"><button class="nav-link active" data-bs-toggle="tab" data-bs-target="#tabCoins" type="button" role="tab">{{ game.terms.coins }}</button></li>
|
|
<li class="nav-item" role="presentation"><button class="nav-link" data-bs-toggle="tab" data-bs-target="#tabUScore" type="button" role="tab">{{ game.terms.uscore }}</button></li>
|
|
<li class="nav-item" role="presentation"><button class="nav-link" data-bs-toggle="tab" data-bs-target="#tabItems" type="button" role="tab">Items</button></li>
|
|
<li class="nav-item" role="presentation"><button class="nav-link" data-bs-toggle="tab" data-bs-target="#tabActivity" type="button" role="tab" id="activityTabBtn">Activity</button></li>
|
|
<li class="nav-item" role="presentation"><button class="nav-link" data-bs-toggle="tab" data-bs-target="#tabMap" type="button" role="tab" id="mapTabBtn">World Map</button></li>
|
|
<li class="nav-item" role="presentation"><button class="nav-link" data-bs-toggle="tab" data-bs-target="#tabTransfers" type="button" role="tab">Trades & Mail</button></li>
|
|
<li class="nav-item" role="presentation"><button class="nav-link" data-bs-toggle="tab" data-bs-target="#tabTrace" type="button" role="tab" id="traceTabBtn">Trace Item</button></li>
|
|
<li class="nav-item" role="presentation"><button class="nav-link" data-bs-toggle="tab" data-bs-target="#tabDupes" type="button" role="tab">Duplicates</button></li>
|
|
<li class="nav-item" role="presentation"><button class="nav-link" data-bs-toggle="tab" data-bs-target="#tabFlags" type="button" role="tab" id="flagsTabBtn">Flags <span class="badge rounded-pill text-bg-danger d-none" data-badge="reports"></span></button></li>
|
|
</ul>
|
|
|
|
<div class="tab-content">
|
|
<!-- Coins -->
|
|
<div class="tab-pane fade show active" id="tabCoins" role="tabpanel">
|
|
<div class="row g-3 mb-3" id="coinTiles"></div>
|
|
<div class="card mb-3">
|
|
<div class="card-header d-flex justify-content-between align-items-center"><h5 class="mb-0">{{ game.terms.coins }} per day</h5><div class="d-flex align-items-center gap-3"><div class="viz-legend" data-legend="coins"></div><a class="btn btn-sm btn-outline-secondary" data-csv="currency" download>CSV</a></div></div>
|
|
<div class="card-body"><div class="viz" id="coinChart"></div>
|
|
<details class="mt-2"><summary class="small text-body-secondary">Show as table</summary><div class="table-responsive mt-2" id="coinDaily"></div></details>
|
|
</div>
|
|
</div>
|
|
<div class="row g-3">
|
|
<div class="col-lg-6"><div class="card h-100"><div class="card-header"><h5 class="mb-0">By source</h5></div><div class="card-body table-responsive" id="coinSources"></div></div></div>
|
|
<div class="col-lg-6"><div class="card h-100"><div class="card-header"><div class="d-flex justify-content-between align-items-center"><h5 class="mb-0">Top earners</h5><a class="btn btn-sm btn-outline-secondary" data-csv="top_earners" download>CSV</a></div><div class="small text-body-secondary">Trades and mail move coins between players, so they don't count as income</div></div><div class="card-body table-responsive" id="topEarners"></div></div></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- U-Score -->
|
|
<div class="tab-pane fade" id="tabUScore" role="tabpanel">
|
|
<div class="row g-3 mb-3" id="uscoreTiles"></div>
|
|
<div class="card mb-3">
|
|
<div class="card-header d-flex justify-content-between align-items-center"><h5 class="mb-0">{{ game.terms.uscore }} per day</h5><div class="d-flex align-items-center gap-3"><div class="viz-legend" data-legend="uscore"></div><a class="btn btn-sm btn-outline-secondary" data-csv="uscore" download>CSV</a></div></div>
|
|
<div class="card-body"><div class="viz" id="uscoreChart"></div>
|
|
<details class="mt-2"><summary class="small text-body-secondary">Show as table</summary><div class="table-responsive mt-2" id="uscoreDaily"></div></details>
|
|
</div>
|
|
</div>
|
|
<div class="card"><div class="card-header"><h5 class="mb-0">By source</h5></div><div class="card-body table-responsive" id="uscoreSources"></div></div>
|
|
</div>
|
|
|
|
<!-- Items -->
|
|
<div class="tab-pane fade" id="tabItems" role="tabpanel">
|
|
<form class="row g-2 align-items-center mb-3" id="itemFilter">
|
|
<div class="col-auto"><label class="visually-hidden" for="itemLot">Item</label>
|
|
<input type="text" class="form-control form-control-sm" id="itemLot" placeholder="All items, or a LOT / name" list="itemSuggestions" autocomplete="off">
|
|
<datalist id="itemSuggestions"></datalist>
|
|
</div>
|
|
<div class="col-auto"><button type="submit" class="btn btn-sm btn-primary">Show</button></div>
|
|
<div class="col-auto"><button type="button" class="btn btn-sm btn-outline-secondary" id="itemClear">All items</button></div>
|
|
<div class="col-auto"><span class="fw-semibold" id="itemTitle">All items</span></div>
|
|
</form>
|
|
<div class="row g-3 mb-3" id="itemTiles"></div>
|
|
<div class="card mb-3">
|
|
<div class="card-header d-flex justify-content-between align-items-center"><h5 class="mb-0">Items per day</h5><div class="d-flex align-items-center gap-3"><div class="viz-legend" data-legend="items"></div><a class="btn btn-sm btn-outline-secondary" data-csv="items" download>CSV</a></div></div>
|
|
<div class="card-body"><div class="viz" id="itemChart"></div>
|
|
<details class="mt-2"><summary class="small text-body-secondary">Show as table</summary><div class="table-responsive mt-2" id="itemDaily"></div></details>
|
|
</div>
|
|
</div>
|
|
<div class="row g-3">
|
|
<div class="col-lg-6"><div class="card h-100"><div class="card-header"><h5 class="mb-0">By source</h5></div><div class="card-body table-responsive" id="itemSources"></div></div></div>
|
|
<div class="col-lg-6"><div class="card h-100" id="itemSideCard"><div class="card-header d-flex justify-content-between align-items-center"><h5 class="mb-0" id="itemSideTitle">Most created</h5><a class="btn btn-sm btn-outline-secondary" data-csv="item_side" download>CSV</a></div><div class="card-body table-responsive" id="itemSide"></div></div></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Activity -->
|
|
<div class="tab-pane fade" id="tabActivity" role="tabpanel">
|
|
<div class="d-flex flex-wrap align-items-center gap-2 mb-3">
|
|
<label class="small text-body-secondary" for="activityPlace">Where</label>
|
|
<select class="form-select form-select-sm w-auto" id="activityPlace" aria-label="Where"><option value="">Everywhere</option></select>
|
|
<span class="small text-body-secondary" id="activityPlaceNote"></span>
|
|
<details class="about-text ms-auto"><summary>What these count</summary>
|
|
<p class="mb-0">What players did each day. <strong>World events</strong> are the ones on the World Map (every player, staff included);
|
|
<strong>player statistics</strong> are the totals of the statistics each character keeps (the ones the client reports itself are left out, as they can't be trusted).</p></details>
|
|
</div>
|
|
<div class="card mb-3">
|
|
<div class="card-header d-flex flex-wrap justify-content-between align-items-center gap-2">
|
|
<h5 class="mb-0">Per day</h5>
|
|
<div class="d-flex align-items-center gap-3"><div class="viz-legend" data-legend="activity"></div>
|
|
<select class="form-select form-select-sm w-auto" id="activityMetric" aria-label="What to show"></select></div>
|
|
</div>
|
|
<div class="card-body"><div class="viz" id="activityChart"></div>
|
|
<details class="mt-2"><summary class="small text-body-secondary">Show as table</summary><div class="table-responsive mt-2" id="activityDaily"></div></details>
|
|
</div>
|
|
</div>
|
|
<div class="row g-3">
|
|
<div class="col-lg-6"><div class="card h-100"><div class="card-header"><h5 class="mb-0">Totals</h5></div><div class="card-body table-responsive" id="activityTotals"></div></div></div>
|
|
<div class="col-lg-6"><div class="card h-100"><div class="card-header"><h5 class="mb-0" id="activityZonesTitle">By world</h5></div><div class="card-body table-responsive" id="activityZones"></div></div></div>
|
|
<div class="col-lg-6"><div class="card h-100"><div class="card-header"><h5 class="mb-0">Powerups by type</h5></div><div class="card-body table-responsive" id="activityPowerups"></div></div></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- World map: fills the window from the toolbar down, the lists beside it scroll on their own -->
|
|
<div class="tab-pane fade" id="tabMap" role="tabpanel">
|
|
<div class="d-flex flex-wrap align-items-center gap-2 gap-md-3 mb-2">
|
|
<select class="form-select form-select-sm w-auto" id="mapKind" aria-label="What to show"></select>
|
|
<select class="form-select form-select-sm w-auto" id="mapZone" aria-label="Zone"></select>
|
|
<select class="form-select form-select-sm w-auto" id="mapProperty" aria-label="Property" hidden></select>
|
|
<div class="btn-group btn-group-sm" role="group" aria-label="Background">
|
|
<input type="radio" class="btn-check" name="mapBackdrop" id="mapBackdropMinimap" value="minimap" checked><label class="btn btn-outline-secondary" for="mapBackdropMinimap">Minimap</label>
|
|
<input type="radio" class="btn-check" name="mapBackdrop" id="mapBackdropTerrain" value="terrain"><label class="btn btn-outline-secondary" for="mapBackdropTerrain">Terrain</label>
|
|
</div>
|
|
<div class="form-check form-switch mb-0">
|
|
<input class="form-check-input" type="checkbox" role="switch" id="mapPlayers" data-pref="economy.mapPlayers" checked>
|
|
<label class="form-check-label small" for="mapPlayers">Online players <span class="text-body-secondary" id="mapPlayerCount"></span></label>
|
|
</div>
|
|
<div class="form-check form-switch mb-0"><input class="form-check-input" type="checkbox" role="switch" id="mapSmooth" data-pref="economy.mapSmooth" checked><label class="form-check-label small" for="mapSmooth">Smooth</label></div>
|
|
</div>
|
|
<div class="row g-3">
|
|
<div class="col-xl-8">
|
|
<div class="card panel-fill fill-viewport-lg map-card">
|
|
<div class="card-header d-flex flex-wrap justify-content-between align-items-center gap-2 py-2">
|
|
<h5 class="mb-0" id="mapTitle">World map</h5>
|
|
<div class="d-flex flex-wrap align-items-center gap-3">
|
|
<div class="viz-scale" id="mapScale" hidden><span class="small text-body-secondary" id="mapScaleMin"></span><span class="viz-ramp"></span><span class="small text-body-secondary" id="mapScaleMax"></span></div>
|
|
<button type="button" class="btn btn-sm btn-outline-secondary" id="mapZoomReset" hidden>Show whole map</button>
|
|
</div>
|
|
</div>
|
|
<div class="card-body p-2 d-flex flex-column">
|
|
<div class="viz-map" id="mapBox"><canvas id="mapCanvas"></canvas></div>
|
|
</div>
|
|
<div class="card-footer py-1"><p class="small text-body-secondary mb-0" id="mapNote">Scroll to zoom, drag to move, hover for counts.</p></div>
|
|
</div>
|
|
</div>
|
|
<div class="col-xl-4">
|
|
<div class="panel-stack-xl"><div class="panel-stack-inner">
|
|
<div class="card mb-3 panel-fill panel-fit" id="mapPropertyCard" hidden>
|
|
<div class="card-header"><h5 class="mb-0" id="mapPropertyTitle">Property</h5></div>
|
|
<div class="card-body small" id="mapPropertyBody"></div>
|
|
</div>
|
|
<div class="card mb-3 panel-fill">
|
|
<div class="card-header d-flex justify-content-between align-items-center"><h5 class="mb-0" id="mapLotsTitle"></h5><button class="btn btn-sm btn-outline-secondary" id="mapLotAll" hidden>Show all</button></div>
|
|
<div class="card-body table-responsive viz-scroll" id="mapLots"></div>
|
|
</div>
|
|
<div class="card panel-fill">
|
|
<div class="card-header"><h5 class="mb-0">Hotspots</h5></div>
|
|
<div class="card-body table-responsive viz-scroll" id="mapHotspots"></div>
|
|
</div>
|
|
</div></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Transfers -->
|
|
<div class="tab-pane fade" id="tabTransfers" role="tabpanel">
|
|
<form class="row g-2 align-items-center mb-3" id="transferFilter">
|
|
<div class="col-auto"><input type="text" class="form-control form-control-sm" id="transferCharacter" placeholder="Character name or ID" list="characterNames" autocomplete="off"><datalist id="characterNames"></datalist></div>
|
|
<div class="col-auto"><input type="text" class="form-control form-control-sm" id="transferLot" placeholder="LOT" inputmode="numeric"></div>
|
|
<div class="col-auto"><button type="submit" class="btn btn-sm btn-primary">Filter</button></div>
|
|
<div class="col-auto"><a class="btn btn-sm btn-outline-secondary" data-csv="transfers" download>CSV</a></div>
|
|
</form>
|
|
<div class="card"><div class="card-body">
|
|
<table id="transfersTable" class="table table-striped table-hover w-100">
|
|
<thead><tr><th>Time</th><th>How</th><th>Item</th><th>Count</th><th>{{ game.terms.coins }}</th><th>From</th><th>To</th><th>Object ID <span class="fw-normal small text-body-secondary">(click to trace)</span></th></tr></thead>
|
|
<tbody></tbody>
|
|
</table>
|
|
</div></div>
|
|
</div>
|
|
|
|
<!-- Trace -->
|
|
<div class="tab-pane fade" id="tabTrace" role="tabpanel">
|
|
<form class="row g-2 align-items-center mb-3" id="traceForm">
|
|
<div class="col-auto"><input type="text" class="form-control form-control-sm" id="traceId" placeholder="Object ID" inputmode="numeric"></div>
|
|
<div class="col-auto"><button type="submit" class="btn btn-sm btn-primary">Trace</button></div>
|
|
<div class="col-auto"><details class="about-text"><summary>How tracing works</summary><div>An item gets a new object ID at every trade, mail and move to another inventory. Enter any of its IDs: the trace follows every recorded hop back to its first ID and forward to the latest, and looks up where each ID is now. A stack that goes into a stack the player already had is marked merged; that stack's older history is left out unless you ask for it.</div></details></div>
|
|
</form>
|
|
<div id="traceResult"></div>
|
|
</div>
|
|
|
|
<!-- Flags -->
|
|
<div class="tab-pane fade" id="tabFlags" role="tabpanel">
|
|
<details class="about-text mb-2"><summary>How flags are found</summary><p class="mb-0">Things worth a look, found by checks that run each night shortly after midnight UTC:
|
|
<strong>coin income</strong> (a character earned far more than the median player that day), <strong>item spikes</strong>
|
|
(far more of an item was created than on a usual day) and <strong>duplicates</strong> (the same item under one object ID in more than one place,
|
|
a sign of a dupe exploit). A flag is only a lead: open it, look into the character, then mark it actioned or dismiss it.
|
|
How far out of the ordinary counts is set under Economy checks on the <a href="/settings#dashboard">Settings page</a>.</p></details>
|
|
<div class="d-flex flex-wrap align-items-center gap-3 mb-3">
|
|
<div class="btn-group btn-group-sm" role="group" aria-label="Status">
|
|
<input type="radio" class="btn-check" name="flagStatus" id="flagOpen" data-pref="economy.flagStatus" value="0" checked><label class="btn btn-outline-secondary" for="flagOpen">Open</label>
|
|
<input type="radio" class="btn-check" name="flagStatus" id="flagActioned" data-pref="economy.flagStatus" value="2"><label class="btn btn-outline-secondary" for="flagActioned">Actioned</label>
|
|
<input type="radio" class="btn-check" name="flagStatus" id="flagDismissed" data-pref="economy.flagStatus" value="1"><label class="btn btn-outline-secondary" for="flagDismissed">Dismissed</label>
|
|
<input type="radio" class="btn-check" name="flagStatus" id="flagAll" data-pref="economy.flagStatus" value="-1"><label class="btn btn-outline-secondary" for="flagAll">All</label>
|
|
</div>
|
|
{% if can.reports_run_checks %}<button class="btn btn-sm btn-outline-primary" id="runChecks">Run checks for yesterday</button>{% endif %}
|
|
<a class="btn btn-sm btn-outline-secondary" data-csv="flags" download>CSV</a>
|
|
</div>
|
|
<div class="card"><div class="card-body">
|
|
<table id="flagsTable" class="table table-hover align-middle w-100">
|
|
<thead><tr><th>When</th><th>What</th><th>Who / which</th><th>Details</th><th>Status</th><th></th></tr></thead>
|
|
<tbody></tbody>
|
|
</table>
|
|
</div></div>
|
|
</div>
|
|
|
|
<!-- Duplicates -->
|
|
<div class="tab-pane fade" id="tabDupes" role="tabpanel">
|
|
<div class="d-flex flex-wrap align-items-center gap-3 mb-3">
|
|
<button class="btn btn-sm btn-primary" id="scanBtn">Scan now</button>
|
|
<a class="btn btn-sm btn-outline-secondary" data-csv="duplicates" download>CSV</a>
|
|
<span class="small text-body-secondary" id="scanInfo">Reads every character and unclaimed mail. On large servers this takes a while.</span>
|
|
</div>
|
|
<div class="card mb-3"><div class="card-header"><h5 class="mb-0">Duplicated items</h5><div class="small text-body-secondary">The same item under one object ID in more than one place: one of the copies was made by a dupe or a failed save</div></div><div class="card-body table-responsive" id="dupeTable"></div></div>
|
|
<div class="card mb-3"><div class="card-header"><h5 class="mb-0">Object ID collisions</h5><div class="small text-body-secondary">Different items that share an object ID. Old saves gave items random IDs, so nothing was copied: these are not dupes. A character with an old save gets new IDs for all its items at its next login, which clears the collision; the nightly check flags only the ones logging in will not fix</div><div class="small fw-semibold mt-1" id="collisionSummary"></div></div><div class="card-body table-responsive" id="collisionTable"></div></div>
|
|
<div class="card"><div class="card-header"><h5 class="mb-0">Most held items</h5></div><div class="card-body table-responsive" id="heldTable"></div></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="viz-tooltip" id="vizTooltip" role="tooltip" hidden></div>
|
|
|
|
<div class="modal fade" id="flagModal" tabindex="-1" aria-labelledby="flagModalTitle" aria-hidden="true">
|
|
<div class="modal-dialog">
|
|
<form class="modal-content" id="flagForm">
|
|
<div class="modal-header"><h5 class="modal-title" id="flagModalTitle">Review flag</h5><button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button></div>
|
|
<div class="modal-body">
|
|
<p class="small" id="flagSummary"></p>
|
|
<label class="form-label" for="flagNote">Note</label>
|
|
<textarea class="form-control" id="flagNote" rows="3" maxlength="1000" placeholder="What you found or did"></textarea>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-outline-secondary" data-flag-status="dismissed">Dismiss (nothing wrong)</button>
|
|
<button type="button" class="btn btn-primary" data-flag-status="actioned">Mark actioned</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
<div class="modal fade" id="saveViewModal" tabindex="-1" aria-labelledby="saveViewTitle" aria-hidden="true">
|
|
<div class="modal-dialog">
|
|
<form class="modal-content" id="saveViewForm">
|
|
<div class="modal-header"><h5 class="modal-title" id="saveViewTitle">Save this view</h5><button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button></div>
|
|
<div class="modal-body">
|
|
<p class="small text-body-secondary" id="saveViewSummary"></p>
|
|
<div class="mb-2"><label class="form-label small" for="viewName">Name</label><input class="form-control" id="viewName" maxlength="50" required></div>
|
|
<div><label class="form-label small" for="viewEmail">Email it to me</label>
|
|
<select class="form-select" id="viewEmail"><option value="off">No</option><option value="daily">Every day</option><option value="weekly">Every Monday</option></select>
|
|
<div class="form-text" id="viewEmailHelp">Reports cover the range up to yesterday and are sent around 07:00 UTC.</div></div>
|
|
</div>
|
|
<div class="modal-footer"><button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button><button type="submit" class="btn btn-primary">Save</button></div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="modal fade" id="manageViewsModal" tabindex="-1" aria-labelledby="manageViewsTitle" aria-hidden="true">
|
|
<div class="modal-dialog modal-lg">
|
|
<div class="modal-content">
|
|
<div class="modal-header"><h5 class="modal-title" id="manageViewsTitle">Saved views</h5><button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button></div>
|
|
<div class="modal-body table-responsive">
|
|
<table class="table align-middle mb-0 table-stack">
|
|
<thead><tr><th>Name</th><th>Shows</th><th>Email</th><th class="text-end">Actions</th></tr></thead>
|
|
<tbody id="viewRows"></tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block scripts %}
|
|
<script src="/js/reports.js"></script>
|
|
{% endblock %}
|