Fix template errors: Starlette new API + remove hx-headers escaping
- TemplateResponse now uses (request, name, context) signature for Starlette 0.36+ - Replace per-button hx-headers with global htmx:configRequest token injection in base.html - Fix JS cookie regex to handle leading semicolons correctly Tested: login, auth redirect, profile create/view/delete all return correct status codes. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,13 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% block title %}SimpleX Manager{% endblock %}</title>
|
||||
<script src="https://unpkg.com/htmx.org@1.9.12/dist/htmx.min.js"></script>
|
||||
<script>
|
||||
// Inject auth token into every HTMX request automatically
|
||||
document.addEventListener('htmx:configRequest', function(evt) {
|
||||
const m = document.cookie.match(/(?:^|;\s*)token=([^;]+)/);
|
||||
if (m) evt.detail.headers['X-Token'] = m[1];
|
||||
});
|
||||
</script>
|
||||
<style>
|
||||
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
|
||||
|
||||
@@ -28,12 +28,10 @@
|
||||
<a href="/profile/{{ p.id }}" class="btn btn-ghost" style="padding: 6px 14px; font-size: 13px;">View</a>
|
||||
<button class="btn btn-success" style="padding: 6px 14px; font-size: 13px;"
|
||||
hx-post="/api/profiles/{{ p.id }}/start"
|
||||
hx-headers='{"X-Token": "{{ request.cookies.get(\"token\", \"\") }}"}'
|
||||
hx-swap="none"
|
||||
onclick="this.textContent='Starting…'">Start</button>
|
||||
<button class="btn btn-danger" style="padding: 6px 14px; font-size: 13px;"
|
||||
hx-post="/api/profiles/{{ p.id }}/stop"
|
||||
hx-headers='{"X-Token": "{{ request.cookies.get(\"token\", \"\") }}"}'
|
||||
hx-swap="none"
|
||||
onclick="this.textContent='Stopping…'">Stop</button>
|
||||
</div>
|
||||
@@ -95,9 +93,10 @@ document.getElementById('create-form').addEventListener('submit', async (e) => {
|
||||
const welcome = fd.get('welcome_message')
|
||||
if (welcome) config.welcome_message = welcome
|
||||
|
||||
const token = document.cookie.match(/(?:^|;\s*)token=([^;]+)/)?.[1] || ''
|
||||
const resp = await fetch('/api/profiles', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json', 'X-Token': document.cookie.match(/token=([^;]+)/)?.[1] || ''},
|
||||
headers: {'Content-Type': 'application/json', 'X-Token': token},
|
||||
body: JSON.stringify({name: fd.get('name'), bot_type: fd.get('bot_type'), config})
|
||||
})
|
||||
if (resp.ok) {
|
||||
|
||||
@@ -24,13 +24,11 @@
|
||||
{% if profile.running %}
|
||||
<button class="btn btn-danger"
|
||||
hx-post="/api/profiles/{{ profile.id }}/stop"
|
||||
hx-headers='{"X-Token": "{{ request.cookies.get(\"token\", \"\") }}"}'
|
||||
hx-swap="none"
|
||||
hx-on::after-request="location.reload()">Stop</button>
|
||||
{% else %}
|
||||
<button class="btn btn-success"
|
||||
hx-post="/api/profiles/{{ profile.id }}/start"
|
||||
hx-headers='{"X-Token": "{{ request.cookies.get(\"token\", \"\") }}"}'
|
||||
hx-swap="none"
|
||||
hx-on::after-request="location.reload()">Start</button>
|
||||
{% endif %}
|
||||
@@ -137,7 +135,6 @@
|
||||
<h2 style="margin:0;">Event Log</h2>
|
||||
<button class="btn btn-ghost" style="font-size:12px;padding:4px 10px;"
|
||||
hx-get="/api/profiles/{{ profile.id }}/status"
|
||||
hx-headers='{"X-Token": "{{ request.cookies.get(\"token\", \"\") }}"}'
|
||||
hx-swap="none"
|
||||
hx-on::after-request="refreshLog(event)">Refresh</button>
|
||||
</div>
|
||||
@@ -153,9 +150,10 @@ document.getElementById('send-form').addEventListener('submit', async (e) => {
|
||||
const fd = new FormData(e.target)
|
||||
const result = document.getElementById('send-result')
|
||||
result.textContent = 'Sending…'
|
||||
const token = document.cookie.match(/(?:^|;\s*)token=([^;]+)/)?.[1] || ''
|
||||
const resp = await fetch('/api/profiles/{{ profile.id }}/send', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json', 'X-Token': document.cookie.match(/token=([^;]+)/)?.[1] || ''},
|
||||
headers: {'Content-Type': 'application/json', 'X-Token': token},
|
||||
body: JSON.stringify({to: fd.get('to'), text: fd.get('text')})
|
||||
})
|
||||
const data = await resp.json()
|
||||
@@ -174,9 +172,10 @@ function refreshLog(event) {
|
||||
|
||||
function confirmDelete() {
|
||||
if (!confirm('Delete this profile? This cannot be undone.')) return
|
||||
const token = document.cookie.match(/(?:^|;\s*)token=([^;]+)/)?.[1] || ''
|
||||
fetch('/api/profiles/{{ profile.id }}', {
|
||||
method: 'DELETE',
|
||||
headers: {'X-Token': document.cookie.match(/token=([^;]+)/)?.[1] || ''}
|
||||
headers: {'X-Token': token}
|
||||
}).then(() => location.href = '/')
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user