Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/common/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,5 @@ export const ALL = '*';
export const URL_REGISTRY_DOC_LINK = 'https://docs.openconceptlab.org/en/latest/oclapi/apireference/urlregistry.html'
export const TBV3_ANNOUNCEMENT_LETTER_URL = 'https://openconceptlab.org/blog/letter-to-the-ocl-community?utm_source=tbv3&utm_medium=banner&utm_campaign=subscription_dates'
export const TBV3_ANNOUNCEMENT_PRICING_URL = 'https://openconceptlab.org/pricing?utm_source=tbv3&utm_medium=banner&utm_campaign=subscription_dates'
export const TERMS_OF_USE_URL = 'https://openconceptlab.org/terms-of-use'
export const PRIVACY_POLICY_URL = 'https://openconceptlab.org/privacy-policy'
50 changes: 43 additions & 7 deletions src/components/app/Footer.jsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,61 @@
import React from 'react';
import { Divider } from '@mui/material';
import { useTranslation } from 'react-i18next';
import { Divider, Link } from '@mui/material';
import { Copyright as CopyrightIcon } from '@mui/icons-material';
import { get } from 'lodash';
import {
getAppliedServerConfig
} from '../../common/utils';
import { TERMS_OF_USE_URL, PRIVACY_POLICY_URL } from '../../common/constants';
import AppVersions from './AppVersions';
import './Footer.scss';

const DEFAULT_FOOTER_TEXT = `${new Date().getFullYear()} Open Concept Lab`;

// Bootstrap's a:hover and a:focus color would otherwise win over MUI's
const LEGAL_LINK_SX = { whiteSpace: 'nowrap', '&:hover, &:focus': { color: 'primary.main' } };

// The footer's height in Footer.scss while it fits on one row. Narrower
// screens stack it onto more rows, and --app-height in index.scss subtracts
// the extra, so pages end above it.
const ROW_HEIGHT = 30;
const EXTRA_HEIGHT_VAR = '--footer-extra-height';

const Footer = () => {
const { t } = useTranslation();
const ref = React.useRef(null);
const text = get(getAppliedServerConfig(), 'info.site.footerText', DEFAULT_FOOTER_TEXT);
const isDefault = text === DEFAULT_FOOTER_TEXT;

React.useLayoutEffect(() => {
const el = ref.current;
const root = document.documentElement.style;
const update = () => root.setProperty(EXTRA_HEIGHT_VAR, `${Math.max(0, el.offsetHeight - ROW_HEIGHT)}px`);
update();
const observer = new ResizeObserver(update);
observer.observe(el);
return () => {
observer.disconnect();
root.removeProperty(EXTRA_HEIGHT_VAR);
};
}, []);

return (
<footer className='col-sm-12 footer-container flex-vertical-center' style={{textAlign: 'right'}}>
{
isDefault &&
<CopyrightIcon fontSize='small'/>
}
<span className='footer-company'>{text}</span>
<footer ref={ref} className='col-sm-12 footer-container flex-vertical-center' style={{textAlign: 'right'}}>
{/* On every page, signed in or not: using TBv3 means accepting the Terms of Use */}
<div className='footer-legal flex-vertical-center'>
<Link href={TERMS_OF_USE_URL} target='_blank' rel='noopener noreferrer' underline='hover' sx={LEGAL_LINK_SX}>{t('common.terms_of_use')}</Link>
<Divider orientation='vertical' className='footer-divider-vertical' />
<Link href={PRIVACY_POLICY_URL} target='_blank' rel='noopener noreferrer' underline='hover' sx={LEGAL_LINK_SX}>{t('common.privacy_policy')}</Link>
</div>
<Divider orientation='vertical' className='footer-divider-vertical' />
<span className='flex-vertical-center'>
{
isDefault &&
<CopyrightIcon fontSize='small'/>
}
<span className='footer-company'>{text}</span>
</span>
<Divider orientation='vertical' className='footer-divider-vertical' />
<AppVersions />
</footer>
Expand Down
23 changes: 23 additions & 0 deletions src/components/app/Footer.scss
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,27 @@ footer.footer-container {
background: $black;
width: 1px;
}
// Full row height, so the divider between the links matches the others
.footer-legal {
align-self: stretch;
}
// Below MUI's md breakpoint (theme.breakpoints.down('md')) the row doesn't
// fit in every language: the links take a row of their own, the rest wraps
// under them, and spacing replaces the dividers. Footer.jsx publishes the
// extra height.
@media (max-width: 899.95px) {
height: auto;
flex-wrap: wrap;
justify-content: center;
gap: 2px 16px;
padding: 6px 16px;
.footer-legal {
flex-basis: 100%;
justify-content: center;
gap: 16px;
}
.footer-divider-vertical {
display: none;
}
}
}
2 changes: 2 additions & 0 deletions src/i18n/locales/en/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
"help_and_documentation": "Help and documentation",
"community_website": "OCL Community website",
"chat": "OCL Chat",
"terms_of_use": "Terms of Use",
"privacy_policy": "Privacy Policy",
"clear": "Clear",
"apply": "Apply",
"exclude": "Exclude",
Expand Down
2 changes: 2 additions & 0 deletions src/i18n/locales/es/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
"help_and_documentation": "Ayuda y documentación",
"community_website": "Sitio web de la comunidad",
"chat": "Chat de OCL",
"terms_of_use": "Términos de uso",
"privacy_policy": "Política de privacidad",
"clear": "Limpiar",
"exclude": "Excluir",
"include": "Incluir",
Expand Down
2 changes: 2 additions & 0 deletions src/i18n/locales/pt-BR/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
"help_and_documentation": "Ajuda e documentação",
"community_website": "Site da comunidade OCL",
"chat": "Chat do OCL",
"terms_of_use": "Termos de uso",
"privacy_policy": "Política de privacidade",
"clear": "Limpar",
"apply": "Aplicar",
"exclude": "Excluir",
Expand Down
2 changes: 2 additions & 0 deletions src/i18n/locales/zh/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
"help_and_documentation": "帮助和文档",
"community_website": "OCL 社区网站",
"chat": "OCL 论坛",
"terms_of_use": "使用条款",
"privacy_policy": "隐私政策",
"clear": "清除",
"exclude": "排除",
"include": "包含",
Expand Down
8 changes: 5 additions & 3 deletions src/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ html {
font-size: 16px;
position: relative;
min-height: 100%;
// Viewport height left for the page once the announcement banner has taken
// its share; AnnouncementBanner sets --announcement-height while it shows.
// Viewport height left for the page once the announcement banner and the
// footer have taken their share; AnnouncementBanner sets
// --announcement-height while it shows, and Footer sets
// --footer-extra-height while narrow screens stack it onto more rows.
// Size pages with calc(var(--app-height) - Npx), not 100vh, or the banner
// pushes their bottom edge off-screen (body doesn't scroll). The banner is
// fixed above the app bar, so anything fixed to the top of the viewport adds
// var(--announcement-height, 0px) to its top, as the app bar does.
--app-height: calc(100vh - var(--announcement-height, 0px));
--app-height: calc(100vh - var(--announcement-height, 0px) - var(--footer-extra-height, 0px));
}

html, body {
Expand Down
Loading