Refactor debug templates to use shared JavaScript functions

Extracted common JavaScript utilities from debug_allowed.html, debug_check.html, and debug_rules.html into a new _debug_common_functions.html include template. This eliminates code duplication and improves maintainability.

The shared functions include:
- populateFormFromURL(): Populates form fields from URL query parameters
- updateURL(formId, page): Updates browser URL with form values
- escapeHtml(text): HTML escaping utility

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Simon Willison 2025-10-08 21:53:34 -07:00
commit 659673614a
4 changed files with 120 additions and 158 deletions

View file

@ -0,0 +1,70 @@
<script>
// Common utility functions for debug pages
// Populate form from URL parameters on page load
function populateFormFromURL() {
const params = new URLSearchParams(window.location.search);
const action = params.get('action');
if (action) {
const actionField = document.getElementById('action');
if (actionField) {
actionField.value = action;
}
}
const parent = params.get('parent');
if (parent) {
const parentField = document.getElementById('parent');
if (parentField) {
parentField.value = parent;
}
}
const child = params.get('child');
if (child) {
const childField = document.getElementById('child');
if (childField) {
childField.value = child;
}
}
const pageSize = params.get('page_size');
if (pageSize) {
const pageSizeField = document.getElementById('page_size');
if (pageSizeField) {
pageSizeField.value = pageSize;
}
}
return params;
}
// Update URL with current form values
function updateURL(formId, page = 1) {
const form = document.getElementById(formId);
const formData = new FormData(form);
const params = new URLSearchParams();
for (const [key, value] of formData.entries()) {
if (value) {
params.append(key, value);
}
}
if (page > 1) {
params.set('page', page.toString());
}
const newURL = window.location.pathname + (params.toString() ? '?' + params.toString() : '');
window.history.pushState({}, '', newURL);
}
// HTML escape function
function escapeHtml(text) {
if (text === null || text === undefined) return '';
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
</script>

View file

@ -5,6 +5,7 @@
{% block extra_head %}
<script src="{{ base_url }}-/static/json-format-highlight-1.0.1.js"></script>
{% include "_permission_ui_styles.html" %}
{% include "_debug_common_functions.html" %}
{% endblock %}
{% block content %}
@ -81,70 +82,31 @@ const pagination = document.getElementById('pagination');
const submitBtn = document.getElementById('submit-btn');
let currentData = null;
// Populate form from URL parameters on page load
function populateFormFromURL() {
const params = new URLSearchParams(window.location.search);
const action = params.get('action');
if (action) {
document.getElementById('action').value = action;
}
const parent = params.get('parent');
if (parent) {
document.getElementById('parent').value = parent;
}
const child = params.get('child');
if (child) {
document.getElementById('child').value = child;
}
const pageSize = params.get('page_size');
if (pageSize) {
document.getElementById('page_size').value = pageSize;
}
const page = params.get('page');
// If parameters are present, automatically fetch results
if (action) {
fetchResults(page ? parseInt(page) : 1, false);
}
}
// Update URL with current form values and page
function updateURL(page = 1) {
const formData = new FormData(form);
const params = new URLSearchParams();
for (const [key, value] of formData.entries()) {
if (value) {
params.append(key, value);
}
}
if (page > 1) {
params.set('page', page.toString());
}
const newURL = window.location.pathname + (params.toString() ? '?' + params.toString() : '');
window.history.pushState({}, '', newURL);
}
form.addEventListener('submit', async (ev) => {
ev.preventDefault();
updateURL(1);
updateURL('allowed-form', 1);
await fetchResults(1, false);
});
// Handle browser back/forward
window.addEventListener('popstate', () => {
populateFormFromURL();
const params = populateFormFromURL();
const action = params.get('action');
const page = params.get('page');
if (action) {
fetchResults(page ? parseInt(page) : 1, false);
}
});
// Populate form on initial load
populateFormFromURL();
(function() {
const params = populateFormFromURL();
const action = params.get('action');
const page = params.get('page');
if (action) {
fetchResults(page ? parseInt(page) : 1, false);
}
})();
async function fetchResults(page = 1, updateHistory = true) {
submitBtn.disabled = true;
@ -230,7 +192,7 @@ function displayResults(data) {
prevLink.textContent = '← Previous';
prevLink.addEventListener('click', (e) => {
e.preventDefault();
updateURL(data.page - 1);
updateURL('allowed-form', data.page - 1);
fetchResults(data.page - 1, false);
});
pagination.appendChild(prevLink);
@ -246,7 +208,7 @@ function displayResults(data) {
nextLink.textContent = 'Next →';
nextLink.addEventListener('click', (e) => {
e.preventDefault();
updateURL(data.page + 1);
updateURL('allowed-form', data.page + 1);
fetchResults(data.page + 1, false);
});
pagination.appendChild(nextLink);
@ -272,13 +234,6 @@ function displayError(data) {
resultsContainer.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
}
function escapeHtml(text) {
if (text === null || text === undefined) return '';
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
// Disable child input if parent is empty
const parentInput = document.getElementById('parent');
const childInput = document.getElementById('child');

View file

@ -4,6 +4,7 @@
{% block extra_head %}
<script src="{{ base_url }}-/static/json-format-highlight-1.0.1.js"></script>
{% include "_debug_common_functions.html" %}
<style>
.form-section {
margin-bottom: 1em;
@ -158,46 +159,6 @@ const form = document.getElementById('check-form');
const output = document.getElementById('output');
const submitBtn = document.getElementById('submit-btn');
// Populate form from URL parameters on page load
function populateFormFromURL() {
const params = new URLSearchParams(window.location.search);
const action = params.get('action');
if (action) {
document.getElementById('action').value = action;
}
const parent = params.get('parent');
if (parent) {
document.getElementById('parent').value = parent;
}
const child = params.get('child');
if (child) {
document.getElementById('child').value = child;
}
// If parameters are present, automatically submit the form
if (action) {
performCheck();
}
}
// Update URL with current form values
function updateURL() {
const formData = new FormData(form);
const params = new URLSearchParams();
for (const [key, value] of formData.entries()) {
if (value) {
params.append(key, value);
}
}
const newURL = window.location.pathname + (params.toString() ? '?' + params.toString() : '');
window.history.pushState({}, '', newURL);
}
async function performCheck() {
submitBtn.disabled = true;
submitBtn.textContent = 'Checking...';
@ -236,17 +197,27 @@ async function performCheck() {
form.addEventListener('submit', async (ev) => {
ev.preventDefault();
updateURL();
updateURL('check-form');
await performCheck();
});
// Handle browser back/forward
window.addEventListener('popstate', () => {
populateFormFromURL();
const params = populateFormFromURL();
const action = params.get('action');
if (action) {
performCheck();
}
});
// Populate form on initial load
populateFormFromURL();
(function() {
const params = populateFormFromURL();
const action = params.get('action');
if (action) {
performCheck();
}
})();
function displayResult(data) {
output.style.display = 'block';

View file

@ -5,6 +5,7 @@
{% block extra_head %}
<script src="{{ base_url }}-/static/json-format-highlight-1.0.1.js"></script>
{% include "_permission_ui_styles.html" %}
{% include "_debug_common_functions.html" %}
{% endblock %}
{% block content %}
@ -69,60 +70,31 @@ const pagination = document.getElementById('pagination');
const submitBtn = document.getElementById('submit-btn');
let currentData = null;
// Populate form from URL parameters on page load
function populateFormFromURL() {
const params = new URLSearchParams(window.location.search);
const action = params.get('action');
if (action) {
document.getElementById('action').value = action;
}
const pageSize = params.get('page_size');
if (pageSize) {
document.getElementById('page_size').value = pageSize;
}
const page = params.get('page');
// If parameters are present, automatically fetch results
if (action) {
fetchResults(page ? parseInt(page) : 1, false);
}
}
// Update URL with current form values and page
function updateURL(page = 1) {
const formData = new FormData(form);
const params = new URLSearchParams();
for (const [key, value] of formData.entries()) {
if (value) {
params.append(key, value);
}
}
if (page > 1) {
params.set('page', page.toString());
}
const newURL = window.location.pathname + (params.toString() ? '?' + params.toString() : '');
window.history.pushState({}, '', newURL);
}
form.addEventListener('submit', async (ev) => {
ev.preventDefault();
updateURL(1);
updateURL('rules-form', 1);
await fetchResults(1, false);
});
// Handle browser back/forward
window.addEventListener('popstate', () => {
populateFormFromURL();
const params = populateFormFromURL();
const action = params.get('action');
const page = params.get('page');
if (action) {
fetchResults(page ? parseInt(page) : 1, false);
}
});
// Populate form on initial load
populateFormFromURL();
(function() {
const params = populateFormFromURL();
const action = params.get('action');
const page = params.get('page');
if (action) {
fetchResults(page ? parseInt(page) : 1, false);
}
})();
async function fetchResults(page = 1, updateHistory = true) {
submitBtn.disabled = true;
@ -215,7 +187,7 @@ function displayResults(data) {
prevLink.textContent = '← Previous';
prevLink.addEventListener('click', (e) => {
e.preventDefault();
updateURL(data.page - 1);
updateURL('rules-form', data.page - 1);
fetchResults(data.page - 1, false);
});
pagination.appendChild(prevLink);
@ -231,7 +203,7 @@ function displayResults(data) {
nextLink.textContent = 'Next →';
nextLink.addEventListener('click', (e) => {
e.preventDefault();
updateURL(data.page + 1);
updateURL('rules-form', data.page + 1);
fetchResults(data.page + 1, false);
});
pagination.appendChild(nextLink);
@ -257,12 +229,6 @@ function displayError(data) {
resultsContainer.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
}
function escapeHtml(text) {
if (text === null || text === undefined) return '';
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
</script>
{% endblock %}