packages/issue-dashboard-widgets/widgets/youtrack-issues-list/app/content.js (144 lines of code) (raw):
import React from 'react';
import PropTypes from 'prop-types';
import LoaderInline from '@jetbrains/ring-ui/components/loader-inline/loader-inline';
import Link from '@jetbrains/ring-ui/components/link/link';
import {i18n} from 'hub-dashboard-addons/dist/localization';
import EmptyWidget, {EmptyWidgetFaces} from '@jetbrains/hub-widget-ui/dist/empty-widget';
import withTimerHOC from '@jetbrains/hub-widget-ui/dist/timer';
import IssueLine from './issue-line';
import './style/issues-list-widget.css';
class Content extends React.Component {
static propTypes = {
youTrack: PropTypes.object,
issues: PropTypes.array,
issuesCount: PropTypes.number,
isLoading: PropTypes.bool,
fromCache: PropTypes.bool,
isLoadDataError: PropTypes.bool,
isNextPageLoading: PropTypes.bool,
onLoadMore: PropTypes.func,
onEdit: PropTypes.func,
dateFormats: PropTypes.object,
editable: PropTypes.bool
};
constructor(props) {
super(props);
this.state = {
expandedIssueId: null
};
}
renderNoIssuesError() {
return (
<EmptyWidget
face={EmptyWidgetFaces.OK}
message={i18n('No issues found')}
>
{
this.props.editable &&
(
<Link
pseudo
onClick={this.props.onEdit}
>
{i18n('Edit search query')}
</Link>
)
}
</EmptyWidget>
);
}
renderLoadDataError() {
return (
<EmptyWidget
face={EmptyWidgetFaces.ERROR}
message={i18n('Can\'t load information from service')}
/>
);
}
getLoadMoreCount() {
const {issuesCount, issues} = this.props;
return (issues && issuesCount && issuesCount > issues.length)
? issuesCount - issues.length
: 0;
}
renderLoader() {
return <LoaderInline/>;
}
renderWidgetBody() {
const {
issues,
youTrack,
isNextPageLoading,
dateFormats
} = this.props;
const {expandedIssueId} = this.state;
const homeUrl = youTrack ? youTrack.homeUrl : '';
const loadMoreCount = this.getLoadMoreCount();
const setExpandedIssueId = issueId =>
evt => {
if (evt.target && evt.target.href) {
return;
}
const isAlreadyExpanded = issueId === expandedIssueId;
this.setState({expandedIssueId: isAlreadyExpanded ? null : issueId});
};
return (
<div className="issues-list-widget">
{
(issues || []).map(issue => (
<div
key={`issue-${issue.id}`}
onClick={setExpandedIssueId(issue.id)}
>
<IssueLine
issue={issue}
homeUrl={homeUrl}
expanded={expandedIssueId === issue.id}
dateFormats={dateFormats}
/>
</div>
))
}
{
loadMoreCount > 0 && !isNextPageLoading &&
(
<div
onClick={this.props.onLoadMore}
className="issues-list-widget__load-more"
>
<Link pseudo>
{
i18n.plural(loadMoreCount, 'Load 1 more issue', 'Load {{$count}} more issues')
}
</Link>
</div>
)
}
{
isNextPageLoading && <LoaderInline/>
}
</div>
);
}
render() {
const {
issues,
isLoading,
fromCache,
isLoadDataError
} = this.props;
if (!fromCache) {
if (isLoadDataError) {
return this.renderLoadDataError();
}
if (isLoading) {
return this.renderLoader();
}
}
if (!issues || !issues.length) {
return this.renderNoIssuesError();
}
return this.renderWidgetBody();
}
}
export default withTimerHOC(Content);