Login flash:
- Auth screen now hidden by CSS default (#auth-screen{display:none !important})
- auth.js shows it only when there is no valid token or token is expired
- No more flash of login page on refresh for logged-in users
Presentation quiz option (AI Generate panel):
- Presentation type now shows optional quiz question toggle (same as article)
- Backend: when questionCount>0, returns JSON {marpMarkdown, questions[]}
instead of plain Marp markdown
- applyAiContent fills both the Marp textarea and question blocks for presentations
Viewer revert:
- Removed the viewer presentation card change (user wants markdown as-is)
- Removed dangling viewer button wiring
Feed/CMS list:
- Presentation type shows correct icon (fa-presentation-screen) and
label "Slides" in the CMS content list
REVERT: httpOnly cookie auth removed — reverts to JWT in localStorage.
The cookie implementation broke the login page (always-hidden auth screen).
localStorage token approach is restored fully:
- Login/register return token in JSON body
- getAuthHeaders() sends Authorization: Bearer header
- Session check reads localStorage token on load
- clearSession() removes localStorage token
Fix: slide preview padding — section elements now have 40px 48px padding
so text is not flush against the frame edges.
Kept from v3.14: AI panel context-aware options (word count, slide count,
quiz question toggle), delete confirmation wording per content type.
AI Generate panel:
- Content type synced from editor on open
- Article/Pearl: optional word count field
- Presentation: optional slide count field
- Questions row: checkbox toggle for article/pearl (optional), always on for quiz,
hidden for presentation; count input shown only when enabled
- Backend: passes wordCount/slideCount to prompt; questionCount=0 skips questions
Delete confirmation:
- Wording built dynamically from content type
- Presentation: no mention of questions
- Quiz: "All quiz questions will be permanently removed"
- Article/pearl: "Any quiz questions attached will also be removed"
Auth refactor — JWT → httpOnly cookie:
- Backend: setAuthCookie() sets ped_auth as httpOnly, Secure, SameSite=Lax, 7d
- Backend: clearAuthCookie() on POST /api/auth/logout (new endpoint)
- Backend: auth middleware reads ped_auth cookie first, falls back to Bearer header
- Login/register: no longer return token in JSON body; cookie is the session
- Frontend: getAuthHeaders() returns only Content-Type (no Authorization header)
- Frontend: session check uses /api/auth/me via cookie (no localStorage token)
- Frontend: clearSession() calls /api/auth/logout to clear cookie server-side
- Frontend: no token in localStorage; window.AUTH_TOKEN removed
- All FormData fetches use credentials:'same-origin' (cookie sent automatically)
- index.html: optimistic auth-screen hide (removed localStorage token check)
Tested: login, logout, /api/auth/me, admin routes, FormData uploads, cookie httpOnly
flag, 401 without cookie, cookie cleared on logout.
Delete bar bug:
- Root cause: .lh-delete-confirm-bar{display:flex} defined after .hidden{display:none}
so flex overrode hidden (no !important on global .hidden rule)
- Fix: remove display:flex from base rule, use .lh-delete-confirm-bar:not(.hidden){display:flex}
so hidden class always wins regardless of CSS order
Slide preview (replace window.open + document.write approach):
- Backend /preview-slides now returns JSON: {css, slides[]} (individual <section> HTML)
- In-page full-screen modal with dark overlay, white slide frame
- Prev/Next arrow buttons, dot indicators, slide counter
- Keyboard navigation (arrow keys, Escape to close)
- Touch/swipe support for mobile
- Overlay click closes modal
- No popups required, works in all browsers
Marp textarea:
- Placeholder updated to guide users: "Click AI Generate above to create slides"
- Makes it clear AI is the primary authoring path; textarea for review/edits
- Bundle Tiptap 2 (StarterKit, Link, Underline) with esbuild into
public/vendor/tiptap.bundle.js — fully self-hosted, no CDN needed
- Remove Quill (quill.min.js, quill.snow.css, patchQuillTooltip hack)
- Headless Tiptap editor: custom toolbar (bold/italic/underline/strike,
headings, lists, blockquote, code, link) with active-state highlighting
- Link insertion: inline link bar below toolbar (no popup, no tooltip)
— type URL, press Apply or Enter; Remove button to unset
- Mini editor for question text and option text (same toggle UX)
- ProseMirror content styles: headings, lists, blockquote, code, links
Quill tooltip: move tooltip element to document.body via patchQuillTooltip()
so overflow:hidden on .cms-main cannot clip it. Recalculates position from
container-relative to viewport (fixed) coordinates with viewport clamping.
Removes overflow:hidden from quill wrappers; applies border-radius to toolbar/container.
Registration: hide #show-register by default in HTML; reveal only after
registration-status fetch confirms enabled=true. Endpoint already returns 403
when disabled — no backend change needed.
- wellVisit.js now handles tabChanged for vaxschedule and catchup tabs
so renderFullSchedule() and renderCatchUp() fire when those tabs open
- Replace Quill CDN with local /vendor/quill.min.js + quill.snow.css
(CDN was unreachable in local/offline environments)
- Replace textarea+toolbar with Quill.js (free, MIT) for body editor
- Full WYSIWYG: headings, bold/italic, lists, blockquote, code, link (inline, no popup)
- Rich Text toggle button on each question text field and option text field
- Plain textarea by default; toggle activates mini Quill editor per field
- New 'Multiple Select' question type: checkboxes, all correct must be chosen
- Backend scoring: allCorrectChosen && noWrongChosen
- Results show all correct options highlighted, wrong selections flagged
- quiz display uses sanitizeHtml for question/option text (supports formatted HTML)
- sanitizeHtml allows Quill class attrs (ql-indent, etc.)
- New dedicated Content Manager tab (WordPress-like layout) with:
- Stats dashboard (published, drafts, categories, quizzes, attempts)
- Sidebar with category tree and filter controls (status, category)
- Table-style content list with search
- Full-page editor with title bar, meta fields, body editor, quiz builder
- Content Manager visible only for admin and moderator roles in sidebar
- Removed CMS from admin panel (admin panel is admin-only again)
- Email templates: fully responsive with max-width, proper mobile breakpoints,
table-based layout for Outlook/Gmail compatibility, no overflow
- Security: escape all user data in emails with escHtml(), escape APP_URL
in verify-email HTML, replace raw err.message with generic errors in auth
- Security: email body from admin settings now HTML-escaped before rendering
- New Learning Hub under Pediatric menu with content feed, category browsing,
search, content viewer, and interactive quizzes (MCQ, true/false)
- Quiz system with per-option wrong-answer explanations and general explanations
- Admin CMS for creating/editing categories, content (articles, pearls, quizzes),
and inline question builder with answer options
- 3-role system: admin (full access), moderator (can manage Learning Hub content),
user (all clinical features + learning hub read access)
- 5 new database tables: learning_categories, learning_content, learning_questions,
learning_options, learning_progress
- User progress tracking with score history per quiz
- Moderators see "Content Manager" tab instead of full Admin panel
- Bedrock: Add 14 non-vendor model models (Amazon Nova, Meta Llama 4, DeepSeek R1/V3,
Mistral Large 3, Cohere Command R+, AI21 Jamba) with verified AWS model IDs
- Bedrock: Implement Converse API for non-Anthropic models (unified cross-model API),
keep native Messages API for vendor model models (best performance)
- Milestones: Add Newborn / 1 month developmental milestones (Gross Motor, Fine Motor,
Language, Social/Emotional, Cognitive) — previously started at 2 months
- Bump version to 3.0.0, docker-compose tag to v3.0
- Copy to Note button now switches to Well Visit → Visit Note subtab
automatically so user sees the result immediately
- Add complete AAP/Nelson developmental milestones for ages 6, 7, 8, 9,
10, and 11 years (Gross Motor, Fine Motor, Language, Social/Emotional,
Cognitive domains each)
- Add corresponding age options to ms-age-group select
- Fix 2FA status stuck at "Loading...": export load2FAStatus globally so
app.js tabChanged handler can call it when navigating via sidebar
- Fix admin models silent failure: add error message + retry button on catch
- Fix save encounter doubles: persist _savedEncId_* to sessionStorage so
page refresh reuses existing record instead of inserting a duplicate;
add _savingInProgress guard to prevent race-condition double-saves
- Desktop sidebar collapsible: add collapse/expand buttons (not collapsed
by default), state saved to localStorage; hidden on mobile
- Copy to Visit Note now also copies SSHADESS assessment to wv-shadess-text
- Store selected visit age in window._wellVisitAge + sessionStorage so
other tabs can read the patient's age
- Bigger screening/vaccine boxes: min-height on wv-vax-list, wv-screen-list,
wv-visit-detail; slightly more padding on vaccine items
- Wire New Patient (clearTab) buttons to document click handler
- Replace horizontal tab-nav with collapsible left sidebar (sticky desktop, slide-in mobile with hamburger toggle)
- Fix tab persistence: use localStorage instead of URL hash; restore last tab after login in enterApp()
- Fix admin CMS models loading: move autoDeleteDays read inside .then() callback (was ReferenceError), switch admin loading from click-only to tabChanged event
- Add Save/Load bars to Hospital Course and Chart Review tabs with popover support
- Add wv (well visit) save handler in encounters.js
- Register load handlers for hospital and chart tabs
- Expand popover prefix list to include hosp and chart
- Wrap save-bar + popover in .save-bar-wrap (position:relative) so the
absolute-positioned popover anchors correctly below the Load button
(previously popovers were outside the save-bar, so had no positioned
ancestor and appeared at the wrong place on screen)
- Remove confirm() dialog from deleteEncounter — encounter disappears
immediately from the popover list after deletion
- ICD-10 diagnoses: replace static-only lookup with live NLM Clinical
Tables API search (clinicaltables.nlm.nih.gov) with 280ms debounce;
results appear in a dropdown below the search input; Enter/click selects
- Add clinicaltables.nlm.nih.gov to CSP connect-src
- Drop unused position:relative from .save-bar (now on .save-bar-wrap)
- Add Well Visit tab with three sub-views: By Visit Age, Full Vaccine Schedule, Catch-Up Schedule
- By Visit Age: shows ICD-10/CPT billing codes, vaccines due with dose info, measurements, sensory/developmental/behavioral/procedure screenings, oral health, notes
- Full Schedule: scrollable table of all vaccines vs all visit ages
- Catch-Up Schedule: per-vaccine minimum ages, intervals, and catch-up notes per CDC 2025
- Add pediatricScheduleData.js (1719-line AAP 2025 Bright Futures dataset)
- Add wellVisit.js for tab logic (lazy-initialized on first tab activation)
- Fire tabChanged CustomEvent on tab switch for lazy initialization
- Add Well Visit CSS styles to styles.css