packages/lib/reporting-components/spent-time-progress/spent-time-progress.js (127 lines of code) (raw):
import {i18n} from 'hub-dashboard-addons/dist/localization';
import React from 'react';
import PropTypes from 'prop-types';
import Tooltip from '@jetbrains/ring-ui/components/tooltip/tooltip';
import classNames from 'classnames';
import SpentTimeValue from '../spent-time-value/spent-time-value';
import './spent-time-progress.scss';
const DEFAULT_PROGRESS_BAR_WIDTH = 100;
const SpentTimeProgressTooltipContent = ({spent, estimated, overdue}) => (
<table>
<tbody>
<tr>
<td>
<div
className="spent-time-progress__mark spent-time-progress__mark_estimated"
/>
</td>
<td>{i18n('estimation')}</td>
<td>
<SpentTimeValue value={estimated} showZero={true}/>
</td>
</tr>
<tr>
<td>
<div
className="spent-time-progress__mark spent-time-progress__mark_spent"
/>
</td>
<td>{i18n('total spent time')}</td>
<td>
<SpentTimeValue value={spent} showZero={true}/>
</td>
</tr>
{
overdue && overdue.value > 0 &&
<tr>
<td>
<div
className="spent-time-progress__mark spent-time-progress__mark_overdue"
/>
</td>
<td>{i18n('overdue')}</td>
<td>
<SpentTimeValue value={overdue}/>
</td>
</tr>
}
</tbody>
</table>
);
SpentTimeProgressTooltipContent.propTypes = {
spent: PropTypes.object.isRequired,
estimated: PropTypes.object,
overdue: PropTypes.object
};
const SpentTimeProgressInPlaceDetails = (
{spent, estimated, hasOverdue, overdue}
) => (
<div className="spent-time-progress__label-details">
<span className="spent-time-progress__label-detail spent-time-progress__label-detail_spent">
<SpentTimeValue value={spent}/>
</span>
<span className="spent-time-progress__label-detail spent-time-progress__label-detail_estimated">
<SpentTimeValue value={estimated}/>
</span>
{
hasOverdue &&
<span className="spent-time-progress__label-detail spent-time-progress__label-detail_overdue">
<SpentTimeValue value={overdue}/>
</span>
}
</div>
);
SpentTimeProgressInPlaceDetails.propTypes = {
spent: PropTypes.object.isRequired,
estimated: PropTypes.object,
overdue: PropTypes.object,
hasOverdue: PropTypes.bool
};
const SpentTimeProgress = ({spent, estimated, children}) => {
const progressValue = spent && spent.value || 0;
const estimationValue = estimated && estimated.value || 0;
const hasOverdue = progressValue > estimationValue;
const overdue = {value: progressValue - estimationValue};
const total = Math.max(progressValue, estimationValue);
const green = Math.min(progressValue, estimationValue);
const totalWidth = DEFAULT_PROGRESS_BAR_WIDTH;
const filledWidth = (total && total > 0)
? Math.ceil(DEFAULT_PROGRESS_BAR_WIDTH * (green / total))
: 0;
return (
<span className="spent-time-progress">
<Tooltip
title={
<SpentTimeProgressTooltipContent
estimated={estimated}
spent={spent}
overdue={overdue}
/>
}
>
<div className="spent-time-progress__labels">
<SpentTimeProgressInPlaceDetails
spent={spent}
estimated={estimated}
overdue={overdue}
hasOverdue={hasOverdue}
/>
<div className="spent-time-progress__label-sum">
{children}
</div>
</div>
<div className="spent-time-progress__wrapper">
<div
className={
classNames('spent-time-progress__placeholder', {'spent-time-progress__placeholder_overdue': hasOverdue})
}
style={{width: `${totalWidth}%`}}
>
<div
className="spent-time-progress__bar"
style={{width: `${filledWidth}%`}}
/>
</div>
</div>
</Tooltip>
</span>
);
};
SpentTimeProgress.propTypes = {
spent: PropTypes.object.isRequired,
estimated: PropTypes.object,
children: PropTypes.node
};
export default SpentTimeProgress;