Initial commit

This commit is contained in:
Jordan
2026-04-01 23:16:45 +01:00
commit 91cfdaee72
200 changed files with 25589 additions and 0 deletions

View File

@@ -0,0 +1,147 @@
/**
* Session creation modal
*/
import { createSession } from '../app.js';
let overlay;
export function initSessionForm() {
overlay = document.getElementById('modal-overlay');
overlay.innerHTML = `
<div class="modal">
<div class="modal-header">
<h2>New Session</h2>
<button class="btn-icon" id="modal-close">&times;</button>
</div>
<div class="modal-body">
<div class="form-group">
<label>Project Profile (JSON)</label>
<textarea id="field-profile" spellcheck="false">{
"name": "",
"tech_stack": [],
"description": ""
}</textarea>
<div class="error-text hidden" id="err-profile"></div>
</div>
<div class="form-group">
<label>Immutable Rules</label>
<div class="rules-list" id="rules-list">
<div class="rule-row">
<input type="text" placeholder="Add a rule..." />
<button class="btn btn-sm" id="btn-add-rule">+</button>
</div>
</div>
</div>
<div class="form-group">
<label>Metadata (JSON)</label>
<textarea id="field-metadata" spellcheck="false">{}</textarea>
<div class="error-text hidden" id="err-metadata"></div>
</div>
</div>
<div class="modal-footer">
<button class="btn" id="btn-cancel">Cancel</button>
<button class="btn btn-primary" id="btn-create">Create Session</button>
</div>
</div>
`;
document.getElementById('modal-close').addEventListener('click', closeModal);
document.getElementById('btn-cancel').addEventListener('click', closeModal);
document.getElementById('btn-create').addEventListener('click', handleCreate);
document.getElementById('btn-add-rule').addEventListener('click', addRuleRow);
overlay.addEventListener('click', (e) => {
if (e.target === overlay) closeModal();
});
// Format JSON on blur
for (const id of ['field-profile', 'field-metadata']) {
document.getElementById(id).addEventListener('blur', (e) => {
try {
const parsed = JSON.parse(e.target.value);
e.target.value = JSON.stringify(parsed, null, 2);
e.target.nextElementSibling.classList.add('hidden');
} catch (err) {
e.target.nextElementSibling.textContent = `Invalid JSON: ${err.message}`;
e.target.nextElementSibling.classList.remove('hidden');
}
});
}
}
function addRuleRow() {
const list = document.getElementById('rules-list');
const addBtn = document.getElementById('btn-add-rule');
const row = document.createElement('div');
row.className = 'rule-row';
row.innerHTML = `
<input type="text" placeholder="Add a rule..." />
<button class="btn btn-sm btn-danger remove-rule">&minus;</button>
`;
row.querySelector('.remove-rule').addEventListener('click', () => row.remove());
list.insertBefore(row, addBtn.closest('.rule-row'));
}
function getRules() {
const inputs = document.querySelectorAll('#rules-list input');
return Array.from(inputs).map(i => i.value.trim()).filter(Boolean);
}
function validateJSON(id) {
const el = document.getElementById(id);
try {
return JSON.parse(el.value);
} catch (err) {
const errEl = document.getElementById(`err-${id.replace('field-', '')}`);
errEl.textContent = `Invalid JSON: ${err.message}`;
errEl.classList.remove('hidden');
return null;
}
}
async function handleCreate() {
const profile = validateJSON('field-profile');
const metadata = validateJSON('field-metadata');
if (profile === null || metadata === null) return;
const rules = getRules();
const btn = document.getElementById('btn-create');
btn.disabled = true;
btn.textContent = 'Creating...';
try {
await createSession({
project_profile: profile,
immutable_rules: rules,
metadata,
});
closeModal();
resetForm();
} catch (e) {
alert(`Failed: ${e.message}`);
} finally {
btn.disabled = false;
btn.textContent = 'Create Session';
}
}
function resetForm() {
document.getElementById('field-profile').value = '{\n "name": "",\n "tech_stack": [],\n "description": ""\n}';
document.getElementById('field-metadata').value = '{}';
const list = document.getElementById('rules-list');
const rows = list.querySelectorAll('.rule-row');
rows.forEach((r, i) => { if (i < rows.length - 1) r.remove(); });
const lastInput = list.querySelector('input');
if (lastInput) lastInput.value = '';
}
export function openSessionForm() {
overlay.classList.add('open');
}
function closeModal() {
overlay.classList.remove('open');
}