- Mount static files on /static endpoint - Configure Jinja2Templates with directory structure - Create base template with Pico.css, HTMX, Chart.js - Create all template subdirectories (auth, dashboard, keys, tokens, profile, components) - Create initial CSS and JS files - Add tests for static files and templates configuration Tests: 12 passing Coverage: 100% on new configuration code
115 lines
3.6 KiB
HTML
115 lines
3.6 KiB
HTML
{% extends "base.html" %}
|
|
|
|
{% block title %}API Tokens - OpenRouter Monitor{% endblock %}
|
|
|
|
{% block content %}
|
|
<h1>API Tokens Management</h1>
|
|
|
|
<!-- Add New Token Form -->
|
|
<article>
|
|
<header>
|
|
<h3>Generate New API Token</h3>
|
|
</header>
|
|
<form action="/tokens" method="POST" hx-post="/tokens" hx-swap="afterend" hx-target="this">
|
|
<label for="token_name">
|
|
Token Name
|
|
<input type="text" id="token_name" name="name" placeholder="Mobile App Token" required>
|
|
</label>
|
|
|
|
<button type="submit">Generate Token</button>
|
|
</form>
|
|
</article>
|
|
|
|
<!-- New Token Display (shown after creation) -->
|
|
{% if new_token %}
|
|
<article style="border: 2px solid var(--warning-color);">
|
|
<header>
|
|
<h3 style="color: var(--warning-color);">Save Your Token!</h3>
|
|
</header>
|
|
<div class="alert alert-danger" role="alert">
|
|
<strong>Warning:</strong> This token will only be displayed once. Copy it now!
|
|
</div>
|
|
<label for="new_token_value">
|
|
Your New API Token
|
|
<input
|
|
type="text"
|
|
id="new_token_value"
|
|
value="{{ new_token }}"
|
|
readonly
|
|
onclick="this.select()"
|
|
style="font-family: monospace;"
|
|
>
|
|
</label>
|
|
<button onclick="navigator.clipboard.writeText(document.getElementById('new_token_value').value)">
|
|
Copy to Clipboard
|
|
</button>
|
|
</article>
|
|
{% endif %}
|
|
|
|
<!-- Tokens List -->
|
|
<article>
|
|
<header>
|
|
<h3>Your API Tokens</h3>
|
|
</header>
|
|
<table class="table" id="tokens-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>Status</th>
|
|
<th>Last Used</th>
|
|
<th>Created</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for token in api_tokens %}
|
|
<tr id="token-{{ token.id }}">
|
|
<td>{{ token.name }}</td>
|
|
<td>
|
|
{% if token.is_active %}
|
|
<span style="color: var(--success-color);">Active</span>
|
|
{% else %}
|
|
<span style="color: var(--danger-color);">Revoked</span>
|
|
{% endif %}
|
|
</td>
|
|
<td>{{ token.last_used_at or 'Never' }}</td>
|
|
<td>{{ token.created_at }}</td>
|
|
<td>
|
|
{% if token.is_active %}
|
|
<button
|
|
class="outline secondary"
|
|
hx-delete="/tokens/{{ token.id }}"
|
|
hx-confirm="Are you sure you want to revoke this token? This action cannot be undone."
|
|
hx-target="#token-{{ token.id }}"
|
|
hx-swap="outerHTML"
|
|
>
|
|
Revoke
|
|
</button>
|
|
{% endif %}
|
|
</td>
|
|
</tr>
|
|
{% else %}
|
|
<tr>
|
|
<td colspan="5" style="text-align: center;">No API tokens found. Generate your first token above.</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</article>
|
|
|
|
<!-- Usage Instructions -->
|
|
<article>
|
|
<header>
|
|
<h3>Using API Tokens</h3>
|
|
</header>
|
|
<p>Include your API token in the <code>Authorization</code> header:</p>
|
|
<pre><code>Authorization: Bearer YOUR_API_TOKEN</code></pre>
|
|
<p>Available endpoints:</p>
|
|
<ul>
|
|
<li><code>GET /api/v1/stats</code> - Get usage statistics</li>
|
|
<li><code>GET /api/v1/usage</code> - Get detailed usage data</li>
|
|
<li><code>GET /api/v1/keys</code> - List your API keys (metadata only)</li>
|
|
</ul>
|
|
</article>
|
|
{% endblock %}
|