ndla-ui
Version:
UI component library for NDLA.
193 lines (181 loc) • 5.88 kB
JSX
/**
* Copyright (c) 2016-present, NDLA.
*
* This source code is licensed under the GPLv3 license found in the
* LICENSE file in the root directory of this source tree.
*
*/
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import BEMHelper from 'react-bem-helper';
import { Time, User, Additional } from 'ndla-icons/common';
import { injectT } from 'ndla-i18n';
import Modal, { ModalHeader, ModalBody, ModalCloseButton } from 'ndla-modal';
import Button from 'ndla-button';
import ArticleAuthorContent from './ArticleAuthorContent';
const classes = new BEMHelper({
name: 'article-byline',
prefix: 'c-',
});
class ArticleByline extends Component {
constructor(props) {
super(props);
this.state = {
showAuthor: null,
};
this.onSelectAuthor = this.onSelectAuthor.bind(this);
}
onSelectAuthor(showAuthor = null) {
this.setState({
showAuthor,
});
}
render() {
const { authors, license, licenseBox, updated, additional, t } = this.props;
const { showAuthor } = this.state;
const authorsLinkable =
authors.length > 1 ||
(authors.length && authors[0].title && authors[0].role);
let authorAriaLabel;
if (authorsLinkable && authors.length) {
authorAriaLabel =
authors.length > 1
? t('article.multipleAuthorsLabelAria', {
names: authors.reduce((prev, current, index) => {
if (index === 1) {
if (index === authors.length - 1) {
return `${prev.name} ${t(
'article.multipleAuthorsLabelAriaConjunction',
)} ${current.name}`;
}
return `${prev.name}, ${current.name}`;
}
if (index === authors.length - 1) {
return `${prev} ${t(
'article.multipleAuthorsLabelAriaConjunction',
)} ${current.name}`;
}
return `${prev}, ${current.name}`;
}),
})
: t('article.singleAuthorsLabelAria', { name: authors[0].name });
}
const authorName =
authors.length > 0
? `${authors[0].name}${
authors.length > 1
? ` ${t('article.multipleAuthorsLabelAbbreviation')}`
: ''
}`
: authors[0] && authors[0].name;
return (
<div {...classes()}>
<span {...classes('flex')}>
{authors.length > 0 && (
<Fragment>
<span {...classes('icon')}>
<User />
</span>
<span {...classes('authors')}>
{authorsLinkable ? (
<Modal
narrow
onClose={this.onSelectAuthor}
activateButton={
<Button aria-label={authorAriaLabel} link>
{authorName}
</Button>
}>
{onClose => (
<Fragment>
<ModalHeader modifier="no-bottom-padding">
<ModalCloseButton
onClick={onClose}
title={t('article.closeLabel')}
/>
</ModalHeader>
<ModalBody>
<ArticleAuthorContent
showAuthor={showAuthor}
onSelectAuthor={this.onSelectAuthor}
authors={authors}
/>
</ModalBody>
</Fragment>
)}
</Modal>
) : (
authorName
)}
</span>
</Fragment>
)}
<span>{` (${license})`}</span>
</span>
<span {...classes('flex')}>
<span {...classes('icon')}>
<Time />
</span>
<span {...classes('date')}>
{t('article.lastUpdated')} {updated}
</span>
</span>
{additional && (
<span {...classes('flex')}>
<span {...classes('additional')}>
<Additional
key="additional"
className="c-icon--20 u-margin-right-tiny"
/>
{t('article.additionalLabel')}
</span>
</span>
)}
{licenseBox && (
<span {...classes('flex')}>
<Modal
activateButton={<Button link>{t('article.useContent')}</Button>}
size="medium">
{onClose => (
<Fragment>
<ModalHeader modifier="no-bottom-padding">
<ModalCloseButton onClick={onClose} title="Lukk" />
</ModalHeader>
<ModalBody>{licenseBox}</ModalBody>
</Fragment>
)}
</Modal>
</span>
)}
</div>
);
}
}
ArticleByline.propTypes = {
id: PropTypes.string,
authors: PropTypes.arrayOf(
PropTypes.shape({
name: PropTypes.string.isRequired,
shortName: PropTypes.string,
title: PropTypes.string,
phone: PropTypes.string,
email: PropTypes.string,
image: PropTypes.string,
introduction: PropTypes.string,
role: PropTypes.string,
urlContributions: PropTypes.string,
urlAuthor: PropTypes.string,
}),
),
updated: PropTypes.string.isRequired,
license: PropTypes.string.isRequired,
licenseBox: PropTypes.node,
additional: PropTypes.bool,
t: PropTypes.func.isRequired,
};
ArticleByline.defaultProps = {
authors: [],
id: 'article-line-id',
additional: false,
};
export default injectT(ArticleByline);