auth-yes/ui/components/sessions/SessionsScript.tsx
google-labs-jules[bot] c8cf9c7df7 refactor(ui): extract layout and sessions subcomponents
Extract Navbar, MobileNav, and UserMenu from AuthenticatedLayout.tsx.
Extract SessionTable, SessionDeck, and SessionsScript from SessionsPage.tsx.
Preserves existing pure Hono SSR JSX and logic.

Co-authored-by: mrteye <1945243+mrteye@users.noreply.github.com>
2026-08-26 06:38:22 +00:00

355 lines
16 KiB
TypeScript

export const SessionsScript = () => {
return (
<script
dangerouslySetInnerHTML={{
__html: `
let lastMintedToken = "";
function showNotice(msg, isError) {
const banner = document.getElementById('status-banner');
banner.textContent = msg;
banner.style.display = 'block';
banner.style.background = isError ? 'var(--danger-bg)' : 'var(--success-bg)';
banner.style.color = isError ? 'var(--danger-text)' : 'var(--success-text)';
banner.style.border = isError ? '1px solid var(--danger-border)' : '1px solid var(--success-border)';
setTimeout(() => { banner.style.display = 'none'; }, 5000);
}
function openDelegateDrawer() {
document.getElementById('delegateDrawer').style.display = 'block';
document.getElementById('delegateDrawer').scrollIntoView({ behavior: 'smooth' });
}
function closeDelegateDrawer() {
document.getElementById('delegateDrawer').style.display = 'none';
}
function switchDelegateTab(tabId) {
document.getElementById('tabDirectPass').style.display = 'none';
document.getElementById('tabWorkshopPass').style.display = 'none';
document.getElementById('tabBtnDirectPass').classList.remove('active');
document.getElementById('tabBtnWorkshopPass').classList.remove('active');
document.getElementById(tabId).style.display = 'block';
if (tabId === 'tabDirectPass') {
document.getElementById('tabBtnDirectPass').classList.add('active');
} else {
document.getElementById('tabBtnWorkshopPass').classList.add('active');
}
}
function selectSeats(btn, count) {
document.querySelectorAll('.seat-pill').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
document.getElementById('eventMaxSeats').value = count;
}
function selectEventLifespan(btn, hours) {
document.querySelectorAll('.event-lifespan-pill').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
document.getElementById('eventLifespanHours').value = hours;
}
function handleTargetAppChange(appName) {
if (appName) {
const scopeVal = 'app:' + appName;
document.querySelectorAll('.scope-checkbox').forEach(cb => {
if (cb.value === scopeVal) cb.checked = true;
});
}
}
function selectLifespan(btn, hours) {
document.querySelectorAll('.lifespan-pill').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
document.getElementById('delegateHours').value = hours;
}
function selectMode(btn, mode) {
document.querySelectorAll('.mode-pill').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
document.getElementById('delegateMode').value = mode;
const accordion = document.getElementById('customScopesSection');
if (mode === 'custom') {
accordion.open = true;
}
}
async function handleDelegateSession(e) {
e.preventDefault();
const label = document.getElementById('delegateLabel').value.trim();
const lifespanHours = parseInt(document.getElementById('delegateHours').value) || 1;
let mode = document.getElementById('delegateMode').value;
const targetApp = document.getElementById('delegateTargetApp') ? document.getElementById('delegateTargetApp').value : '';
const customScopes = [];
if (targetApp) {
customScopes.push('app:' + targetApp);
}
if (mode === 'custom' || targetApp) {
document.querySelectorAll('.scope-checkbox:checked').forEach(cb => {
if (!customScopes.includes(cb.value)) {
customScopes.push(cb.value);
}
});
if (targetApp && mode !== 'custom' && mode !== 'admin') {
mode = 'custom';
}
}
const btn = document.getElementById('submitDelegateBtn');
btn.disabled = true;
btn.textContent = 'Minting...';
try {
const res = await fetch('/api/sessions/delegate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ label, lifespanHours, mode, customScopes }),
});
const data = await res.json();
if (res.ok) {
lastMintedToken = data.token;
document.getElementById('handoffMagicLinkText').textContent = window.location.origin + '/pass?token=' + data.token;
document.getElementById('handoffCliText').textContent = 'export AUTH_YES_TOKEN="' + data.token + '"';
document.getElementById('handoffCurlText').textContent = '-H "Authorization: Bearer ' + data.token + '"';
document.getElementById('handoffModal').style.display = 'block';
showNotice('Delegated session created for: ' + data.label, false);
} else {
showNotice(data.error || 'Failed to delegate session', true);
}
} catch (err) {
showNotice('Network error delegating session', true);
} finally {
btn.disabled = false;
btn.textContent = 'Mint & Delegate Session';
}
}
async function handleCreateEvent(e) {
e.preventDefault();
const name = document.getElementById('eventName').value.trim();
const appId = document.getElementById('eventAppId').value || null;
const role = document.getElementById('eventRole').value || 'viewer';
const maxSeats = parseInt(document.getElementById('eventMaxSeats').value) || 0;
const lifespanHours = parseInt(document.getElementById('eventLifespanHours').value) || 3;
const slug = document.getElementById('eventSlug').value.trim() || undefined;
const pinCode = document.getElementById('eventPinCode').value.trim() || undefined;
const btn = document.getElementById('submitEventBtn');
btn.disabled = true;
btn.textContent = 'Launching...';
try {
const res = await fetch('/api/events', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name, appId, role, maxSeats, lifespanHours, slug, pinCode }),
});
const data = await res.json();
if (res.ok && data.success) {
const ev = data.event;
document.getElementById('createdEventTitle').textContent = '🎟️ ' + ev.name + ' Live!';
document.getElementById('eventHandoffPin').textContent = ev.pin_code;
document.getElementById('eventHandoffLink').textContent = window.location.origin + '/e/' + ev.slug;
document.getElementById('eventHandoffCli').textContent = 'curl -sSL ' + window.location.origin + '/join/' + ev.slug + '?format=env | source /dev/stdin';
document.getElementById('eventHandoffModal').style.display = 'block';
showNotice('Workshop pass created: ' + ev.name, false);
} else {
showNotice(data.error || 'Failed to create event pass', true);
}
} catch (err) {
showNotice('Network error creating event pass', true);
} finally {
btn.disabled = false;
btn.textContent = '🎟️ Launch Workshop Pass';
}
}
function copyEventHandoff(type) {
let text = '';
if (type === 'pin') text = document.getElementById('eventHandoffPin').textContent;
if (type === 'link') text = document.getElementById('eventHandoffLink').textContent;
if (type === 'cli') text = document.getElementById('eventHandoffCli').textContent;
navigator.clipboard.writeText(text);
showNotice('Copied to clipboard: ' + text, false);
}
function closeEventHandoffModal() {
document.getElementById('eventHandoffModal').style.display = 'none';
window.location.reload();
}
function copyHandoff(type) {
let text = '';
if (type === 'link') text = document.getElementById('handoffLinkText').textContent;
if (type === 'cli') text = document.getElementById('handoffCliText').textContent;
if (type === 'curl') text = document.getElementById('handoffCurlText').textContent;
if (type === 'magic') text = document.getElementById('handoffMagicLinkText').textContent;
navigator.clipboard.writeText(text);
showNotice('Copied to clipboard: ' + text, false);
}
function closeHandoffModal() {
document.getElementById('handoffModal').style.display = 'none';
window.location.reload();
}
async function extendSession(sessionId, hours) {
try {
const res = await fetch('/api/sessions/' + sessionId + '/extend', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ extendHours: hours }),
});
if (res.ok) {
showNotice('Session extended by ' + hours + ' hour(s)!', false);
setTimeout(() => window.location.reload(), 600);
} else {
const data = await res.json();
showNotice(data.error || 'Failed to extend session', true);
}
} catch (err) {
showNotice('Network error extending session', true);
}
}
function openEditScopesModal(sessionId, label, scopesJson) {
const scopes = JSON.parse(scopesJson || '[]');
document.getElementById('editScopesSessionId').value = sessionId;
document.getElementById('editScopesLabel').textContent = label;
document.querySelectorAll('.edit-scope-chk').forEach(cb => {
cb.checked = scopes.includes(cb.value);
});
document.getElementById('editScopesModal').style.display = 'flex';
}
function closeEditScopesModal() {
document.getElementById('editScopesModal').style.display = 'none';
}
async function saveUpdatedScopes() {
const sessionId = document.getElementById('editScopesSessionId').value;
const customScopes = [];
document.querySelectorAll('.edit-scope-chk:checked').forEach(cb => {
customScopes.push(cb.value);
});
try {
const res = await fetch('/api/sessions/' + sessionId + '/scopes', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ customScopes }),
});
if (res.ok) {
showNotice('Session scopes updated!', false);
setTimeout(() => window.location.reload(), 600);
} else {
const data = await res.json();
showNotice(data.error || 'Failed to update scopes', true);
}
} catch (err) {
showNotice('Network error updating scopes', true);
}
}
function copyText(text) {
navigator.clipboard.writeText(text);
showNotice('Copied to clipboard!', false);
}
// Event Cockpit Actions
document.querySelectorAll('.extend-event-btn').forEach(btn => {
btn.addEventListener('click', async (e) => {
const eventId = e.currentTarget.getAttribute('data-event-id');
e.currentTarget.disabled = true;
try {
const res = await fetch('/api/events/' + eventId + '/extend', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ extendHours: 1 })
});
if (res.ok) {
showNotice('Event extended by 1 hour!', false);
setTimeout(() => window.location.reload(), 600);
} else {
const data = await res.json();
showNotice(data.error || 'Failed to extend event', true);
e.currentTarget.disabled = false;
}
} catch (err) {
showNotice('Network error extending event', true);
e.currentTarget.disabled = false;
}
});
});
document.querySelectorAll('.end-event-btn').forEach(btn => {
btn.addEventListener('click', async (e) => {
if (!confirm('Are you sure you want to end this workshop? This will immediately revoke ALL active guest sessions and they will lose access.')) return;
const eventId = e.currentTarget.getAttribute('data-event-id');
e.currentTarget.disabled = true;
e.currentTarget.textContent = 'Revoking...';
try {
const res = await fetch('/api/events/' + eventId + '/end', {
method: 'POST',
});
if (res.ok) {
showNotice('Workshop ended and all sessions revoked.', false);
setTimeout(() => window.location.reload(), 600);
} else {
const data = await res.json();
showNotice(data.error || 'Failed to end event', true);
e.currentTarget.disabled = false;
e.currentTarget.textContent = '🔴 End & Revoke All';
}
} catch (err) {
showNotice('Network error ending event', true);
e.currentTarget.disabled = false;
e.currentTarget.textContent = '🔴 End & Revoke All';
}
});
});
// Revoke handler
document.querySelectorAll('.revoke-btn').forEach(btn => {
btn.addEventListener('click', async (e) => {
if (!confirm('Revoke this session immediately?')) return;
const sessionId = e.currentTarget.getAttribute('data-session-id');
const originalText = e.currentTarget.textContent;
e.currentTarget.textContent = 'Revoking...';
e.currentTarget.disabled = true;
try {
const res = await fetch('/api/sessions/' + sessionId, {
method: 'DELETE'
});
if (res.ok) {
window.location.reload();
} else {
const data = await res.json();
showNotice(data.error || 'Failed to revoke session', true);
e.currentTarget.textContent = originalText;
e.currentTarget.disabled = false;
}
} catch (err) {
showNotice('Network error revoking session', true);
e.currentTarget.textContent = originalText;
e.currentTarget.disabled = false;
}
});
});
`,
}}
>
</script>
);
};