Dataset/JS/ReactPodcastItem/podcast_item.js (125 lines of code) (raw):
import React, { PropTypes } from 'react';
import classnames from 'classnames';
import { Link } from 'react-router';
import { sanitize, highlight, formatPubDate, formatListenDate } from './utils';
import {
ButtonGroup,
Button,
Panel,
Label,
} from 'react-bootstrap';
import Icon from './icon';
import Image from './image';
const Buttons = props => {
const { podcast } = props;
return (
<ButtonGroup style={{ float: 'right' }}>
<Button
title={ podcast.isPlaying ? 'Stop' : 'Play' }
onClick={props.togglePlayer}
><Icon icon={ podcast.isPlaying ? 'stop' : 'play' } />
</Button>
<Button
download
title="Download this podcast"
className="btn btn-default"
href={podcast.enclosureUrl}
><Icon icon="download" /></Button>
{props.isLoggedIn ?
<Button
onClick={props.toggleBookmark}
title={podcast.isBookmarked ? 'Remove bookmark' : 'Add to bookmarks'}
><Icon icon={podcast.isBookmarked ? 'bookmark' : 'bookmark-o'} />
</Button> : ''}
</ButtonGroup>
);
};
Buttons.propTypes = {
isLoggedIn: PropTypes.bool.isRequired,
podcast: PropTypes.object.isRequired,
toggleBookmark: PropTypes.func.isRequired,
togglePlayer: PropTypes.func.isRequired,
};
export default function PodcastItem(props) {
const {
podcast,
showChannel,
showExpanded,
toggleDetail,
isLoggedIn,
searchQuery,
showImage,
} = props;
const channelUrl = `/channel/${podcast.channelId}/`;
const podcastUrl = `/podcast/${podcast.id}/`;
const image = podcast.image || '/static/podcast.png';
const playedAt = isLoggedIn && podcast.lastPlayedAt ?
<div className="text-center">
<h5>
<Label bsStyle="success">
Listened {formatListenDate(podcast.lastPlayedAt)}
</Label>
</h5>
</div> : '';
let header;
if (showChannel) {
header = (
<div className="text-center">
<h4>{showExpanded ? podcast.title :
<Link to={podcastUrl}>{podcast.title}</Link>}
</h4>
{playedAt}
{showImage ?
<div className="thumbnail">
<div className="caption text-center">
<h5><Link to={channelUrl}>{podcast.name}</Link></h5>
</div>
<Link to={channelUrl}>
<Image
src={image}
errSrc="/static/podcast.png"
imgProps={{
height: 60,
width: 60,
alt: podcast.name,
}}
/>
</Link>
</div> :
<h5><Link to={channelUrl}>{podcast.name}</Link></h5>
}
</div>
);
} else {
header = (
<div className="text-center">
<h4><Link to={podcastUrl}>{podcast.title}</Link></h4>
{playedAt}
</div>
);
}
const description = sanitize(highlight(podcast.description, searchQuery));
return (
<Panel>
{header}
<div style={{ padding: 10 }}>
<small>
<time dateTime={podcast.pubDate}>{formatPubDate(podcast.pubDate)}</time>
{podcast.source ? <a href={podcast.source} target="_blank">Source</a> : '' }
</small>
<Buttons {...props} />
</div>
{podcast.description && !showExpanded ?
<Button
className="form-control"
title={podcast.isShowDetail ? 'Hide details' : 'Show details'}
onClick={toggleDetail}
><Icon icon={podcast.isShowDetail ? 'chevron-up' : 'chevron-down'} />
</Button> : ''}
{description.__html && (podcast.isShowDetail || showExpanded) ?
<p
className={classnames({ lead: showExpanded, 'text-center': true })}
style={{ marginTop: 20 }}
dangerouslySetInnerHTML={description}
/> : ''}
</Panel>
);
}
PodcastItem.propTypes = {
podcast: PropTypes.object.isRequired,
isLoggedIn: PropTypes.bool.isRequired,
showImage: PropTypes.bool,
showChannel: PropTypes.bool.isRequired,
showExpanded: PropTypes.bool,
searchQuery: PropTypes.string,
togglePlayer: PropTypes.func.isRequired,
toggleDetail: PropTypes.func.isRequired,
toggleBookmark: PropTypes.func.isRequired,
};