Repository navigation
OpenConceptLab/ocl_issues#2899 | Link the Terms of Use and Privacy Policy from the footer - #64
Conversation
…licy from the footer The footer links the Terms of Use and the Privacy Policy on openconceptlab.org on every page, signed in or not, and each opens in a new tab. Their labels are common.terms_of_use and common.privacy_policy, in the en, es, pt-BR and zh catalogs. Below MUI's md breakpoint the single row no longer fits in every language, so the links take a row of their own and the copyright and versions wrap under them. The footer publishes how much taller than its usual 30 px that makes it (--footer-extra-height), and --app-height subtracts it, so pages end above the footer rather than under it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SDUDybmzSUtWMPsVozhSz3
…request The pull request's description shows these, linked to this commit. The pull request's last commit removes them, so they never reach the merged tree. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SDUDybmzSUtWMPsVozhSz3
paynejd
left a comment
There was a problem hiding this comment.
Codex review, pass 1 (codex-cli 0.162.1, commit 1de9d66)
Clean.
findings.json
{
"reviewer": "codex-cli 0.162.1",
"perspective": "defects",
"mode": "full",
"commit": "1de9d6632ee193d07252fc4e0cb3add2f339470f",
"verdict": "clean",
"prior": [],
"findings": []
}
Response to Codex pass 1No findings to answer. No P0 or P1 is open, so the Codex defect review stops after this pass, and the simplification review is next. |
paynejd
left a comment
There was a problem hiding this comment.
Simplification review (commit 1de9d66)
2 items: 1 delete, 1 shrink.
- S1 · delete · src/components/app/Footer.jsx:35 · The
if (!el) return;guard in the layout effect can't fire. Footer has no early return and App.jsx mounts it unconditionally, so<footer ref={ref}>is always attached when the layout effect runs. The guard was copied from AnnouncementBanner.jsx, which needs it because that component returns null once dismissed. → Nothing replaces it. Delete the two lines and keepconst el = ref.current;. (-2) - S2 · shrink · src/components/app/Footer.jsx:16 · LEGAL_LINKS, its .map, the React.Fragment keys and the
i > 0 &÷r make a data table and a loop for two fixed links. Writing the two Links out is shorter and needs no index logic. The output is the same DOM. → Replace the array with a shared sx constant; the Bootstrap comment moves onto it, and the 'On every page' comment stays:const LEGAL_LINK_SX = { whiteSpace: 'nowrap', '&:hover, &:focus': { color: 'primary.main' } };. Then the footer-legal div holds<Link href={TERMS_OF_USE_URL} target='_blank' rel='noopener noreferrer' underline='hover' sx={LEGAL_LINK_SX}>{t('common.terms_of_use')}</Link>, the existing<Divider orientation='vertical' className='footer-divider-vertical' />, and the same Link for PRIVACY_POLICY_URL with t('common.privacy_policy'). That is 8 lines where there were 16, and target and rel stay visible on each link for AC 2. (-8)
findings.json
{
"reviewer": "claude subagent",
"perspective": "simplify",
"mode": "full",
"commit": "1de9d6632ee193d07252fc4e0cb3add2f339470f",
"verdict": "findings",
"prior": [],
"findings": [
{
"id": "S1",
"severity": null,
"tag": "delete",
"file": "src/components/app/Footer.jsx",
"line": 35,
"claim": "The `if (!el) return;` guard in the layout effect can't fire. Footer has no early return and App.jsx mounts it unconditionally, so `<footer ref={ref}>` is always attached when the layout effect runs. The guard was copied from AnnouncementBanner.jsx, which needs it because that component returns null once dismissed.",
"scenario": null,
"action": "Nothing replaces it. Delete the two lines and keep `const el = ref.current;`.",
"lines_delta": -2,
"confidence": "high"
},
{
"id": "S2",
"severity": null,
"tag": "shrink",
"file": "src/components/app/Footer.jsx",
"line": 16,
"claim": "LEGAL_LINKS, its .map, the React.Fragment keys and the `i > 0 &&` divider make a data table and a loop for two fixed links. Writing the two Links out is shorter and needs no index logic. The output is the same DOM.",
"scenario": null,
"action": "Replace the array with a shared sx constant; the Bootstrap comment moves onto it, and the 'On every page' comment stays: `const LEGAL_LINK_SX = { whiteSpace: 'nowrap', '&:hover, &:focus': { color: 'primary.main' } };`. Then the footer-legal div holds `<Link href={TERMS_OF_USE_URL} target='_blank' rel='noopener noreferrer' underline='hover' sx={LEGAL_LINK_SX}>{t('common.terms_of_use')}</Link>`, the existing `<Divider orientation='vertical' className='footer-divider-vertical' />`, and the same Link for PRIVACY_POLICY_URL with t('common.privacy_policy'). That is 8 lines where there were 16, and target and rel stay visible on each link for AC 2.",
"lines_delta": -8,
"confidence": "medium"
}
]
}… drop a guard that can't fire From the simplification review: the two legal links are written out with a shared sx instead of mapped from an array, and the layout effect loses its null-ref guard, since the footer element always renders. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SDUDybmzSUtWMPsVozhSz3
Response to the simplification reviewAfter the cuts, the |
paynejd
left a comment
There was a problem hiding this comment.
Codex check of the cuts (commit 17b3956)
Clean.
findings.json
{
"reviewer": "codex-cli 0.162.1",
"perspective": "defects",
"mode": "cuts",
"commit": "17b3956840c315f950461b2b34c095b39d313d78",
"verdict": "clean",
"prior": [],
"findings": []
}…eenshots from the tree The pull request's description still shows them from 1de9d66. Removing them here keeps them out of the merged tree. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SDUDybmzSUtWMPsVozhSz3
Needs youThe ticket keeps this PR a draft until someone reviews it locally in a browser, and that's the one step left. Everything else is done:
What's needed: follow "How to review it locally" in the description: signed out and signed in, on the five pages, at desktop width and at 375 px. If the footer looks right, mark the PR ready for review. If it doesn't, say what to change. |
What changed and why
Using TBv3 means accepting OCL's Terms of Use, but TBv3 didn't link it or the Privacy Policy anywhere. The footer now does, on every page, signed in or not:
target="_blank",rel="noopener noreferrer"). The URLs areTERMS_OF_USE_URLandPRIVACY_POLICY_URLinsrc/common/constants.js.common.terms_of_useandcommon.privacy_policy, in all four catalogs (table below).mdbreakpoint) the footer stays one 30 px row:Terms of Use | Privacy Policy | © 2026 Open Concept Lab | TB-… | API-….--footer-extra-height, and--app-heightinsrc/index.scsssubtracts it. It uses aResizeObserver, asAnnouncementBannerdoes for--announcement-height. At 900 px and up the value is 0, so nothing changes there.New strings
common.terms_of_usecommon.privacy_policyScreenshots
Footer at 1280 px, right-hand 800 px of the row:
Footer at 375 px:
In context, English, on a source page, at 1280 px and 375 px:
TB-3.0.17-alpha-<sha>rather than-dev.UserMenu.jsxthat is not in this PR, because zh crashes the app onmaintoo (see "Noticed, not fixed").How to review it locally
This PR stays a draft until someone has done this.
gh pr checkout 'OpenConceptLab/ocl_issues#2899-footer-legal-links' --repo OpenConceptLab/oclweb3 npm ci WEB_PORT=4002 NODE_ENV=development API_URL=https://api.staging.openconceptlab.org npm startPages to open at http://localhost:4002, signed out and then signed in:
/(dashboard)/search/?q=malaria/orgs/CIEL//orgs/CIEL/sources/CIEL//no-such-page/Check in each language (switch with user menu → Language: English, Español, Português (Brasil)):
© 2026 Open Concept Lab, theTB-version and theAPI-version all still show.zh has no entry in the language menu, and setting
ocl.languagetozhblanks the app onmainas well. Check zh in the screenshots above, or apply the guard from "Noticed, not fixed" locally first.How I tested it
CI gate. Every
run:step of.github/workflows/pr.yml, in order, on Node 22.23.2: thestart-prod.shsecret-variable check,npm ciand ESLint. All pass..eslintrc.json.pr.yml's ESLint job passed on the final commit, 7e170c2: https://github.com/OpenConceptLab/oclweb3/actions/runs/38447139908Browser check. Playwright drove headless Chrome in a fresh context, signed out, against
npm starton the staging API, withocl.languageset before each load. It covered five pages (/,/search/?q=malaria,/orgs/CIEL/,/orgs/CIEL/sources/CIEL/,/no-such-page-2899/), four languages and two widths (1280 px and 375 px). On each it asserted that:target="_blank"andrelcontainingnoopenerandnoreferrer;Results:
main, the same script, en, es and pt-BR: 90 failures. There are no links on any page, and at 375 px the footer text and the TB version sit partly below the screen./and/orgs/CIEL/sources/CIEL/. All pass: one row (30 px) from 900 px up, two rows (51 px) from 600 to 899 px, three rows (70 px) at 320 and 375 px.--footer-extra-heightreads 0 px at 1280, 40 px at 375, 21 px at 899, then 0 px again at 900 and 1280.window.openernull, and the original tab doesn't navigate.After the simplification cuts (17b3956) I reran the gate and the browser check: en, es and pt-BR on all five pages at both widths with the click test, zh with the local guard, and the resize check. All pass.
Signed in: not tested, because this run doesn't sign in. The footer is rendered in
App.jsxoutside the router'sSwitch, with no auth condition, and reads no user state.Review
Acceptance criteria
src/components/app/Footer.jsx) links Terms of Use to https://openconceptlab.org/terms-of-use and Privacy Policy to https://openconceptlab.org/privacy-policy, on every page, signed in or not.target="_blank",rel="noopener noreferrer"): the attribute assertions and the click test.Docs
src/index.scss: the--app-heightcomment now names--footer-extra-heightalongside--announcement-height.README and
docs/: neither covers the footer.OCL Design System: its component list marks Footer as a stub with no guidance. This builds the footer from what exists:
Linkin the primary color, with the hover fixAnnouncementBanneruses;Proposal: promote the footer, with its legal links and narrow-screen layout, to a documented component in the design system.
Not done, and why
pr.ymlruns lint only), so the browser check above was run by hand, before and after the change.Noticed, not fixed
maintoo).src/i18n/config.jsaccepts a storedzh, butLANGUAGESinsrc/common/constants.jshas no zh entry.ocl.languageset tozh,UserMenu.jsxreadsselectedLanguage.nameandselectedLanguage.localeofundefined, and the whole app unmounts.selectedLanguage?.name,selectedLanguage?.locale) or a zh entry inLANGUAGESwould fix it. Which one depends on whether the menu should offer zh, so it's left out of this PR.info.site.footerTextin a server config can still overflow the single row on wide screens, as it could before.About the screenshot commit
The screenshots are committed in 1de9d66 so this description can show them. The PR's last commit removes them, so they never reach the merged tree. A squash merge would also keep them out of
main's history.closes OpenConceptLab/ocl_issues#2899
🤖 Generated with Claude Code
https://claude.ai/code/session_01SDUDybmzSUtWMPsVozhSz3
Written by an Octoad session worker (
worker-v0.11, recipelean-loop, flowpublic>public, runopenconceptlab-ocl-issues-2899-20261013-134559).