Skip to content

Commit

Permalink
Migrating remaining context data to new provider-consumer context API.
Browse files Browse the repository at this point in the history
  • Loading branch information
Martin Krulis committed Jul 18, 2019
1 parent 0e66b99 commit e554274
Show file tree
Hide file tree
Showing 8 changed files with 153 additions and 150 deletions.
103 changes: 52 additions & 51 deletions src/components/helpers/LocalizedTexts/LocalizedTexts.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ import ExternalLinkPreview from '../ExternalLinkPreview';
import Icon from '../../icons';
import Markdown from '../../widgets/Markdown';
import { knownLocales } from '../../../helpers/localizedData';
import { UrlContext } from '../../../helpers/contexts';

import './LocalizedTexts.css';

const LocalizedTexts = ({ locales = [], noLocalesMessage = null }, { lang = 'en' }) => {
const LocalizedTexts = ({ locales = [], noLocalesMessage = null }) => {
const localeTabs = knownLocales
.map(locale => locales.find(l => l.locale === locale))
.filter(tabData => tabData && (tabData.text || tabData.link || tabData.studentHint));
Expand All @@ -20,62 +21,62 @@ const LocalizedTexts = ({ locales = [], noLocalesMessage = null }, { lang = 'en'
}

return (
<Tabs
defaultActiveKey={
localeTabs.find(({ locale }) => locale === lang) || localeTabs.length === 0 ? lang : localeTabs[0].locale
}
className="nav-tabs-custom"
id="localized-texts">
{localeTabs.map(({ locale, text, link = '', studentHint = null }, i) => (
<Tab key={i} eventKey={locale} title={locale}>
{link && link !== '' && (
<div>
<Well>
<h4>
<FormattedMessage
id="app.localizedTexts.externalLink"
defaultMessage="The description is located beyond the realms of ReCodEx"
/>
</h4>
<Icon icon="link" gapRight />
<a href={link} target="_blank" rel="noopener noreferrer">
{link}
</a>
</Well>
<ExternalLinkPreview url={link} />
</div>
)}
<UrlContext.Consumer>
{({ lang = 'en' }) => (
<Tabs
defaultActiveKey={
localeTabs.find(({ locale }) => locale === lang) || localeTabs.length === 0 ? lang : localeTabs[0].locale
}
className="nav-tabs-custom"
id="localized-texts">
{localeTabs.map(({ locale, text, link = '', studentHint = null }, i) => (
<Tab key={i} eventKey={locale} title={locale}>
{link && link !== '' && (
<div>
<Well>
<h4>
<FormattedMessage
id="app.localizedTexts.externalLink"
defaultMessage="The description is located beyond the realms of ReCodEx"
/>
</h4>
<Icon icon="link" gapRight />
<a href={link} target="_blank" rel="noopener noreferrer">
{link}
</a>
</Well>
<ExternalLinkPreview url={link} />
</div>
)}

{text.trim() !== '' && <Markdown source={text} />}
{text.trim() !== '' && <Markdown source={text} />}

{!text.trim() && !link && (
<div className="callout callout-warning em-margin">
<FormattedMessage
id="app.localizedTexts.noText"
defaultMessage="There is no text nor link for given localization. The exercise is not fully specified yet."
/>
</div>
)}
{!text.trim() && !link && (
<div className="callout callout-warning em-margin">
<FormattedMessage
id="app.localizedTexts.noText"
defaultMessage="There is no text nor link for given localization. The exercise is not fully specified yet."
/>
</div>
)}

{studentHint && studentHint !== '' && (
<div>
<hr />
<h4>
<FormattedMessage id="app.localizedTexts.studentHintHeading" defaultMessage="Hint" />
</h4>
<Markdown source={studentHint} />
</div>
)}
</Tab>
))}
</Tabs>
{studentHint && studentHint !== '' && (
<div>
<hr />
<h4>
<FormattedMessage id="app.localizedTexts.studentHintHeading" defaultMessage="Hint" />
</h4>
<Markdown source={studentHint} />
</div>
)}
</Tab>
))}
</Tabs>
)}
</UrlContext.Consumer>
);
};

LocalizedTexts.contextTypes = {
lang: PropTypes.string,
};

LocalizedTexts.propTypes = {
locales: PropTypes.arrayOf(
PropTypes.shape({
Expand Down
62 changes: 36 additions & 26 deletions src/components/layout/Sidebar/Sidebar.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { isSupervisorRole, isEmpoweredSupervisorRole, isSuperadminRole } from '.
import withLinks from '../../../helpers/withLinks';
import { getExternalIdForCAS } from '../../../helpers/cas';
import { safeGet, EMPTY_OBJ } from '../../../helpers/common';
import { UrlContext } from '../../../helpers/contexts';

import styles from './sidebar.less';

Expand Down Expand Up @@ -112,31 +113,44 @@ const Sidebar = (
))}

{studentOfItems && (
<MenuGroup
title={<FormattedMessage id="app.sidebar.menu.memberOfGroups" defaultMessage="Member of Groups" />}
items={studentOfItems}
notifications={EMPTY_OBJ}
icon={'user-circle'}
currentPath={currentUrl}
createLink={createLink}
forceOpen={false}
isActive={studentOfItems.find(item => isActive(createLink(item))) !== undefined}
/>
<UrlContext.Consumer>
{({ isActive }) => (
<MenuGroup
title={
<FormattedMessage id="app.sidebar.menu.memberOfGroups" defaultMessage="Member of Groups" />
}
items={studentOfItems}
notifications={EMPTY_OBJ}
icon={'user-circle'}
currentPath={currentUrl}
createLink={createLink}
forceOpen={false}
isActive={studentOfItems.find(item => isActive(createLink(item))) !== undefined}
/>
)}
</UrlContext.Consumer>
)}

{isSupervisorRole(role) && supervisorOfItems && (
<MenuGroup
title={
<FormattedMessage id="app.sidebar.menu.supervisorOfGroups" defaultMessage="Supervisor of Groups" />
}
notifications={EMPTY_OBJ}
items={supervisorOfItems}
icon="graduation-cap"
currentPath={currentUrl}
createLink={createLink}
forceOpen={false}
isActive={supervisorOfItems.find(item => isActive(createLink(item))) !== undefined}
/>
<UrlContext.Consumer>
{({ isActive }) => (
<MenuGroup
title={
<FormattedMessage
id="app.sidebar.menu.supervisorOfGroups"
defaultMessage="Supervisor of Groups"
/>
}
notifications={EMPTY_OBJ}
items={supervisorOfItems}
icon="graduation-cap"
currentPath={currentUrl}
createLink={createLink}
forceOpen={false}
isActive={supervisorOfItems.find(item => isActive(createLink(item))) !== undefined}
/>
)}
</UrlContext.Consumer>
)}

{isSupervisorRole(role) && (
Expand Down Expand Up @@ -200,8 +214,4 @@ Sidebar.propTypes = {
intl: intlShape,
};

Sidebar.contextTypes = {
isActive: PropTypes.func,
};

export default withLinks(injectIntl(Sidebar));
69 changes: 34 additions & 35 deletions src/components/widgets/Sidebar/MenuItem/MenuItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,42 @@ import React from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import { Link } from 'react-router';

import Icon from '../../../icons';
import { UrlContext } from '../../../../helpers/contexts';

const MenuItem = (
{
title,
icon = 'circle',
link,
currentPath,
notificationsCount = 0,
inNewTab = false,
small = false,
onIsActive = isActive => isActive,
},
{ isActive }
) => (
<li
className={classnames({
active: isActive(link),
small,
})}>
<Link to={link} target={inNewTab ? '_blank' : undefined}>
<Icon icon={icon} fixedWidth gapRight />
<span
style={{
whiteSpace: 'normal',
display: 'inline-block',
verticalAlign: 'top',
}}>
{title}
</span>
{notificationsCount > 0 && <small className="label pull-right bg-yellow">{notificationsCount}</small>}
</Link>
</li>
const MenuItem = ({
title,
icon = 'circle',
link,
currentPath,
notificationsCount = 0,
inNewTab = false,
small = false,
onIsActive = isActive => isActive,
}) => (
<UrlContext.Consumer>
{({ isActive }) => (
<li
className={classnames({
active: isActive(link),
small,
})}>
<Link to={link} target={inNewTab ? '_blank' : undefined}>
<Icon icon={icon} fixedWidth gapRight />
<span
style={{
whiteSpace: 'normal',
display: 'inline-block',
verticalAlign: 'top',
}}>
{title}
</span>
{notificationsCount > 0 && <small className="label pull-right bg-yellow">{notificationsCount}</small>}
</Link>
</li>
)}
</UrlContext.Consumer>
);

MenuItem.propTypes = {
Expand All @@ -48,8 +51,4 @@ MenuItem.propTypes = {
onIsActive: PropTypes.func,
};

MenuItem.contextTypes = {
isActive: PropTypes.func,
};

export default MenuItem;
50 changes: 25 additions & 25 deletions src/containers/LayoutContainer/LayoutContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { isLoggedIn } from '../../redux/selectors/auth';
import { getLoggedInUserSettings } from '../../redux/selectors/users';
import { messages, localeData, defaultLanguage } from '../../locales';
import { linksFactory, isAbsolute } from '../../links';
import { UserSettingsContext } from '../../helpers/contexts';
import { UserSettingsContext, LinksContext, UrlContext } from '../../helpers/contexts';

import 'admin-lte/dist/css/AdminLTE.min.css';
import 'admin-lte/dist/css/skins/_all-skins.min.css';
Expand Down Expand Up @@ -80,16 +80,6 @@ class LayoutContainer extends Component {
this.forceUpdate();
};

/**
* Child components should be able to access current language settings
* and up-to-date links (with respect to the given language).
*/
getChildContext = () => ({
links: this.state.links,
lang: this.state.lang,
isActive: link => !isAbsolute(link) && this.context.router.isActive(link, true),
});

maybeHideSidebar = e => {
const { sidebarIsOpen, toggleVisibility } = this.props;
if (sidebarIsOpen) {
Expand Down Expand Up @@ -122,37 +112,47 @@ class LayoutContainer extends Component {
userSettings,
} = this.props;

const { lang } = this.state;
const { lang, links } = this.state;
addLocaleData([...this.getLocaleData(lang)]);
moment.locale(lang);

return (
<IntlProvider locale={lang} messages={this.getMessages(lang)} formats={ADDITIONAL_INTL_FORMATS}>
<UserSettingsContext.Provider value={userSettings}>
<Layout
isLoggedIn={isLoggedIn}
sidebarIsCollapsed={sidebarIsCollapsed}
sidebarIsOpen={sidebarIsOpen}
toggleSize={toggleSize}
toggleVisibility={toggleVisibility}
onCloseSidebar={this.maybeHideSidebar}
lang={lang}
availableLangs={Object.keys(messages)}
currentUrl={pathname}
pendingFetchOperations={pendingFetchOperations}>
{children}
</Layout>
<LinksContext.Provider value={links}>
<UrlContext.Provider
value={{
lang,
isActive: link => !isAbsolute(link) && this.context.router.isActive(link, true),
}}>
<Layout
isLoggedIn={isLoggedIn}
sidebarIsCollapsed={sidebarIsCollapsed}
sidebarIsOpen={sidebarIsOpen}
toggleSize={toggleSize}
toggleVisibility={toggleVisibility}
onCloseSidebar={this.maybeHideSidebar}
lang={lang}
availableLangs={Object.keys(messages)}
currentUrl={pathname}
pendingFetchOperations={pendingFetchOperations}>
{children}
</Layout>
</UrlContext.Provider>
</LinksContext.Provider>
</UserSettingsContext.Provider>
</IntlProvider>
);
}
}

/*
LayoutContainer.childContextTypes = {
lang: PropTypes.string,
links: PropTypes.object,
isActive: PropTypes.func,
};
*/

LayoutContainer.contextTypes = {
router: PropTypes.object,
Expand Down
2 changes: 2 additions & 0 deletions src/helpers/contexts.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import React from 'react';

export const UserSettingsContext = React.createContext({});
export const LinksContext = React.createContext({});
export const UrlContext = React.createContext({});
Loading

0 comments on commit e554274

Please sign in to comment.