diff --git a/README.md b/README.md index 3062850..93f992b 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ protocol-droid/ ``` 4. The database schema auto-initializes on first API request (creates `data/protocol_droid.db`) 5. Visit the site and register — the **first user to register becomes admin** -6. Optionally load seed protocols: Go to the **About** page and click **"Load seed protocols"** (visible to admins only). This loads 6 example protocols into your library in one click. No curl needed. +5. Optionally load seed protocols: Go to your **profile page** (click your @username) and click **"Load Seed Protocols"** (visible to admins only). This loads 100 example protocols into your library. Can be repeated to re-import seeds. **No default admin credentials exist.** A fresh deployment has an empty database. The first registration creates the admin account. Seed protocols are optional and must be explicitly loaded. @@ -122,7 +122,7 @@ cd protocol-droid php -S localhost:8000 ``` -The SQLite database is created automatically at `data/protocol_droid.db`. The first registration creates the admin account. To load the 6 sample protocols (Round Robin Check-In, Consent Decision-Making, etc.): +The SQLite database is created automatically at `data/protocol_droid.db`. The first registration creates the admin account. To load the 100 sample protocols, go to your **profile page** (click your @username) and click **"Load Seed Protocols"** (admins only). ```bash # After registering as admin: diff --git a/frontend/app.js b/frontend/app.js index f6fdf5e..671c314 100644 --- a/frontend/app.js +++ b/frontend/app.js @@ -63,7 +63,6 @@ async function init() { } function route() { - isRouting = true; const hash = location.hash.slice(1) || 'library'; if (hash.startsWith('protocols/')) { showDetail(hash.split('/')[1]); @@ -82,15 +81,14 @@ function route() { } else { navigate('library'); } - isRouting = false; } let searchTimer = null; let currentRoute = ''; -let isRouting = false; function navigate(view) { - if (currentRoute === view && view !== 'library') return; + // Prevent double navigation from hashchange + if (currentRoute === view) return; currentRoute = view; document.querySelectorAll('.view').forEach(v => v.style.display = 'none'); document.getElementById('view-' + view).style.display = 'block'; @@ -98,17 +96,11 @@ function navigate(view) { document.querySelectorAll('.mobile-panel a').forEach(a => a.classList.toggle('active', a.dataset.view === view)); closeMenu(); updateBreadcrumb(view); - if (!isRouting) { - if (view === 'library') { location.hash = 'protocols'; } - if (view === 'collections') { location.hash = 'collections'; } - if (view === 'about') { location.hash = 'about'; } - if (view === 'terms') { location.hash = 'terms'; } - } - if (view === 'library') loadProtocols(); - if (view === 'collections') loadCollections(); + if (view === 'library') { location.hash = 'library'; loadProtocols(); } + if (view === 'collections') { location.hash = 'collections'; loadCollections(); } if (view === 'create') { editingSlug = null; resetForm(); } if (view === 'create-collection') { editingCollectionSlug = null; resetCollectionForm(); } - if (view === 'about') updateAboutPage(); + if (view === 'about') { location.hash = 'about'; } window.scrollTo(0, 0); } @@ -823,12 +815,59 @@ async function showUser(username) { '
' + escapeHtml(col.description||'') + '