- 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
93 lines
2.9 KiB
HTML
93 lines
2.9 KiB
HTML
{% extends "base.html" %}
|
|
|
|
{% block title %}API Keys - OpenRouter Monitor{% endblock %}
|
|
|
|
{% block content %}
|
|
<h1>API Keys Management</h1>
|
|
|
|
<!-- Add New Key Form -->
|
|
<article>
|
|
<header>
|
|
<h3>Add New API Key</h3>
|
|
</header>
|
|
<form action="/keys" method="POST" hx-post="/keys" hx-swap="beforeend" hx-target="#keys-table tbody">
|
|
<div class="grid">
|
|
<label for="key_name">
|
|
Key Name
|
|
<input type="text" id="key_name" name="name" placeholder="Production Key" required>
|
|
</label>
|
|
|
|
<label for="key_value">
|
|
OpenRouter API Key
|
|
<input
|
|
type="password"
|
|
id="key_value"
|
|
name="key_value"
|
|
placeholder="sk-or-..."
|
|
required
|
|
pattern="^sk-or-[a-zA-Z0-9]+$"
|
|
title="Must be a valid OpenRouter API key starting with 'sk-or-'"
|
|
>
|
|
</label>
|
|
</div>
|
|
|
|
<button type="submit">Add Key</button>
|
|
</form>
|
|
</article>
|
|
|
|
<!-- Keys List -->
|
|
<article>
|
|
<header>
|
|
<h3>Your API Keys</h3>
|
|
</header>
|
|
<table class="table" id="keys-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>Status</th>
|
|
<th>Last Used</th>
|
|
<th>Created</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for key in api_keys %}
|
|
<tr id="key-{{ key.id }}">
|
|
<td>{{ key.name }}</td>
|
|
<td>
|
|
{% if key.is_active %}
|
|
<span style="color: var(--success-color);">Active</span>
|
|
{% else %}
|
|
<span style="color: var(--danger-color);">Inactive</span>
|
|
{% endif %}
|
|
</td>
|
|
<td>{{ key.last_used_at or 'Never' }}</td>
|
|
<td>{{ key.created_at }}</td>
|
|
<td>
|
|
<button
|
|
class="outline secondary"
|
|
hx-delete="/keys/{{ key.id }}"
|
|
hx-confirm="Are you sure you want to delete this key?"
|
|
hx-target="#key-{{ key.id }}"
|
|
hx-swap="outerHTML"
|
|
>
|
|
Delete
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
{% else %}
|
|
<tr>
|
|
<td colspan="5" style="text-align: center;">No API keys found. Add your first key above.</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</article>
|
|
|
|
<!-- Security Notice -->
|
|
<div class="alert" role="alert">
|
|
<strong>Security Notice:</strong> Your API keys are encrypted and never displayed after creation.
|
|
Only metadata (name, status, usage) is shown here.
|
|
</div>
|
|
{% endblock %}
|