parent
7f8dc3d2b4
commit
71a34c7650
@ -1,7 +0,0 @@
|
||||
.absoluteEpisodeNumber {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.warning {
|
||||
margin-left: 8px;
|
||||
}
|
@ -1,108 +0,0 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import Icon from 'Components/Icon';
|
||||
import Popover from 'Components/Tooltip/Popover';
|
||||
import { icons, kinds, tooltipPositions } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import SceneInfo from './SceneInfo';
|
||||
import styles from './EpisodeNumber.css';
|
||||
|
||||
function EpisodeNumber(props) {
|
||||
const {
|
||||
episodeNumber,
|
||||
absoluteEpisodeNumber,
|
||||
sceneSeasonNumber,
|
||||
sceneEpisodeNumber,
|
||||
sceneAbsoluteEpisodeNumber,
|
||||
unverifiedSceneNumbering,
|
||||
alternateTitles,
|
||||
authorType
|
||||
} = props;
|
||||
|
||||
const hasSceneInformation = sceneSeasonNumber !== undefined ||
|
||||
sceneEpisodeNumber !== undefined ||
|
||||
(authorType === 'anime' && sceneAbsoluteEpisodeNumber !== undefined) ||
|
||||
!!alternateTitles.length;
|
||||
|
||||
return (
|
||||
<span>
|
||||
{
|
||||
hasSceneInformation ?
|
||||
<Popover
|
||||
anchor={
|
||||
<span>
|
||||
{episodeNumber}
|
||||
|
||||
{
|
||||
authorType === 'anime' && !!absoluteEpisodeNumber &&
|
||||
<span className={styles.absoluteEpisodeNumber}>
|
||||
({absoluteEpisodeNumber})
|
||||
</span>
|
||||
}
|
||||
</span>
|
||||
}
|
||||
title={translate('SceneInformation')}
|
||||
body={
|
||||
<SceneInfo
|
||||
sceneSeasonNumber={sceneSeasonNumber}
|
||||
sceneEpisodeNumber={sceneEpisodeNumber}
|
||||
sceneAbsoluteEpisodeNumber={sceneAbsoluteEpisodeNumber}
|
||||
alternateTitles={alternateTitles}
|
||||
authorType={authorType}
|
||||
/>
|
||||
}
|
||||
position={tooltipPositions.RIGHT}
|
||||
/> :
|
||||
<span>
|
||||
{episodeNumber}
|
||||
|
||||
{
|
||||
authorType === 'anime' && !!absoluteEpisodeNumber &&
|
||||
<span className={styles.absoluteEpisodeNumber}>
|
||||
({absoluteEpisodeNumber})
|
||||
</span>
|
||||
}
|
||||
</span>
|
||||
}
|
||||
|
||||
{
|
||||
unverifiedSceneNumbering &&
|
||||
<Icon
|
||||
className={styles.warning}
|
||||
name={icons.WARNING}
|
||||
kind={kinds.WARNING}
|
||||
title={translate('SceneNumberHasntBeenVerifiedYet')}
|
||||
/>
|
||||
}
|
||||
|
||||
{
|
||||
authorType === 'anime' && !absoluteEpisodeNumber &&
|
||||
<Icon
|
||||
className={styles.warning}
|
||||
name={icons.WARNING}
|
||||
kind={kinds.WARNING}
|
||||
title={translate('EpisodeDoesNotHaveAnAbsoluteEpisodeNumber')}
|
||||
/>
|
||||
}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
EpisodeNumber.propTypes = {
|
||||
seasonNumber: PropTypes.number.isRequired,
|
||||
episodeNumber: PropTypes.number.isRequired,
|
||||
absoluteEpisodeNumber: PropTypes.number,
|
||||
sceneSeasonNumber: PropTypes.number,
|
||||
sceneEpisodeNumber: PropTypes.number,
|
||||
sceneAbsoluteEpisodeNumber: PropTypes.number,
|
||||
unverifiedSceneNumbering: PropTypes.bool.isRequired,
|
||||
alternateTitles: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
authorType: PropTypes.string
|
||||
};
|
||||
|
||||
EpisodeNumber.defaultProps = {
|
||||
unverifiedSceneNumbering: false,
|
||||
alternateTitles: []
|
||||
};
|
||||
|
||||
export default EpisodeNumber;
|
@ -1,4 +0,0 @@
|
||||
.center {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
@ -1,128 +0,0 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import QueueDetails from 'Activity/Queue/QueueDetails';
|
||||
import Icon from 'Components/Icon';
|
||||
import ProgressBar from 'Components/ProgressBar';
|
||||
import { icons, kinds, sizes } from 'Helpers/Props';
|
||||
import isBefore from 'Utilities/Date/isBefore';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import BookQuality from './BookQuality';
|
||||
import styles from './EpisodeStatus.css';
|
||||
|
||||
function EpisodeStatus(props) {
|
||||
const {
|
||||
airDateUtc,
|
||||
monitored,
|
||||
grabbed,
|
||||
queueItem,
|
||||
bookFile
|
||||
} = props;
|
||||
|
||||
const hasBookFile = !!bookFile;
|
||||
const isQueued = !!queueItem;
|
||||
const hasAired = isBefore(airDateUtc);
|
||||
|
||||
if (isQueued) {
|
||||
const {
|
||||
sizeleft,
|
||||
size
|
||||
} = queueItem;
|
||||
|
||||
const progress = (100 - sizeleft / size * 100);
|
||||
|
||||
return (
|
||||
<div className={styles.center}>
|
||||
<QueueDetails
|
||||
{...queueItem}
|
||||
progressBar={
|
||||
<ProgressBar
|
||||
title={translate('BookIsDownloadingInterp', [progress.toFixed(1), queueItem.title])}
|
||||
progress={progress}
|
||||
kind={kinds.PURPLE}
|
||||
size={sizes.MEDIUM}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (grabbed) {
|
||||
return (
|
||||
<div className={styles.center}>
|
||||
<Icon
|
||||
name={icons.DOWNLOADING}
|
||||
title={translate('BookIsDownloading')}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (hasBookFile) {
|
||||
const quality = bookFile.quality;
|
||||
const isCutoffNotMet = bookFile.qualityCutoffNotMet;
|
||||
|
||||
return (
|
||||
<div className={styles.center}>
|
||||
<BookQuality
|
||||
quality={quality}
|
||||
size={bookFile.size}
|
||||
isCutoffNotMet={isCutoffNotMet}
|
||||
title={translate('BookDownloaded')}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (!airDateUtc) {
|
||||
return (
|
||||
<div className={styles.center}>
|
||||
<Icon
|
||||
name={icons.TBA}
|
||||
title={translate('TBA')}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (!monitored) {
|
||||
return (
|
||||
<div className={styles.center}>
|
||||
<Icon
|
||||
name={icons.UNMONITORED}
|
||||
title={translate('BookIsNotMonitored')}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (hasAired) {
|
||||
return (
|
||||
<div className={styles.center}>
|
||||
<Icon
|
||||
name={icons.MISSING}
|
||||
title={translate('BookMissingFromDisk')}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.center}>
|
||||
<Icon
|
||||
name={icons.NOT_AIRED}
|
||||
title={translate('BookHasNotAired')}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
EpisodeStatus.propTypes = {
|
||||
airDateUtc: PropTypes.string,
|
||||
monitored: PropTypes.bool,
|
||||
grabbed: PropTypes.bool,
|
||||
queueItem: PropTypes.object,
|
||||
bookFile: PropTypes.object
|
||||
};
|
||||
|
||||
export default EpisodeStatus;
|
@ -1,53 +0,0 @@
|
||||
import _ from 'lodash';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import createBookFileSelector from 'Store/Selectors/createBookFileSelector';
|
||||
import createBookSelector from 'Store/Selectors/createBookSelector';
|
||||
import createQueueItemSelector from 'Store/Selectors/createQueueItemSelector';
|
||||
import EpisodeStatus from './EpisodeStatus';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
createBookSelector(),
|
||||
createQueueItemSelector(),
|
||||
createBookFileSelector(),
|
||||
(book, queueItem, bookFile) => {
|
||||
const result = _.pick(book, [
|
||||
'airDateUtc',
|
||||
'monitored',
|
||||
'grabbed'
|
||||
]);
|
||||
|
||||
result.queueItem = queueItem;
|
||||
result.bookFile = bookFile;
|
||||
|
||||
return result;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
const mapDispatchToProps = {
|
||||
};
|
||||
|
||||
class EpisodeStatusConnector extends Component {
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
return (
|
||||
<EpisodeStatus
|
||||
{...this.props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
EpisodeStatusConnector.propTypes = {
|
||||
bookId: PropTypes.number.isRequired,
|
||||
bookFileId: PropTypes.number.isRequired
|
||||
};
|
||||
|
||||
export default connect(createMapStateToProps, mapDispatchToProps)(EpisodeStatusConnector);
|
@ -1,17 +0,0 @@
|
||||
.descriptionList {
|
||||
composes: descriptionList from '~Components/DescriptionList/DescriptionList.css';
|
||||
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.title {
|
||||
composes: title from '~Components/DescriptionList/DescriptionListItemTitle.css';
|
||||
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
.description {
|
||||
composes: title from '~Components/DescriptionList/DescriptionListItemDescription.css';
|
||||
|
||||
margin-left: 100px;
|
||||
}
|
@ -1,84 +0,0 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import DescriptionList from 'Components/DescriptionList/DescriptionList';
|
||||
import DescriptionListItem from 'Components/DescriptionList/DescriptionListItem';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import styles from './SceneInfo.css';
|
||||
|
||||
function SceneInfo(props) {
|
||||
const {
|
||||
sceneSeasonNumber,
|
||||
sceneEpisodeNumber,
|
||||
sceneAbsoluteEpisodeNumber,
|
||||
alternateTitles,
|
||||
authorType
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<DescriptionList className={styles.descriptionList}>
|
||||
{
|
||||
sceneSeasonNumber !== undefined &&
|
||||
<DescriptionListItem
|
||||
titleClassName={styles.title}
|
||||
descriptionClassName={styles.description}
|
||||
title={translate('Season')}
|
||||
data={sceneSeasonNumber}
|
||||
/>
|
||||
}
|
||||
|
||||
{
|
||||
sceneEpisodeNumber !== undefined &&
|
||||
<DescriptionListItem
|
||||
titleClassName={styles.title}
|
||||
descriptionClassName={styles.description}
|
||||
title={translate('Episode')}
|
||||
data={sceneEpisodeNumber}
|
||||
/>
|
||||
}
|
||||
|
||||
{
|
||||
authorType === 'anime' && sceneAbsoluteEpisodeNumber !== undefined &&
|
||||
<DescriptionListItem
|
||||
titleClassName={styles.title}
|
||||
descriptionClassName={styles.description}
|
||||
title={translate('Absolute')}
|
||||
data={sceneAbsoluteEpisodeNumber}
|
||||
/>
|
||||
}
|
||||
|
||||
{
|
||||
!!alternateTitles.length &&
|
||||
<DescriptionListItem
|
||||
titleClassName={styles.title}
|
||||
descriptionClassName={styles.description}
|
||||
title={alternateTitles.length === 1 ? translate('AlternateTitleslength1Title') : translate('AlternateTitleslength1Titles')}
|
||||
data={
|
||||
<div>
|
||||
{
|
||||
alternateTitles.map((alternateTitle) => {
|
||||
return (
|
||||
<div
|
||||
key={alternateTitle.title}
|
||||
>
|
||||
{alternateTitle.title}
|
||||
</div>
|
||||
);
|
||||
})
|
||||
}
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
}
|
||||
</DescriptionList>
|
||||
);
|
||||
}
|
||||
|
||||
SceneInfo.propTypes = {
|
||||
sceneSeasonNumber: PropTypes.number,
|
||||
sceneEpisodeNumber: PropTypes.number,
|
||||
sceneAbsoluteEpisodeNumber: PropTypes.number,
|
||||
alternateTitles: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
authorType: PropTypes.string
|
||||
};
|
||||
|
||||
export default SceneInfo;
|
@ -1,32 +0,0 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import EpisodeNumber from './EpisodeNumber';
|
||||
|
||||
function SeasonEpisodeNumber(props) {
|
||||
const {
|
||||
airDate,
|
||||
authorType,
|
||||
...otherProps
|
||||
} = props;
|
||||
|
||||
if (authorType === 'daily' && airDate) {
|
||||
return (
|
||||
<span>{airDate}</span>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<EpisodeNumber
|
||||
seriesType={authorType}
|
||||
showSeasonNumber={true}
|
||||
{...otherProps}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
SeasonEpisodeNumber.propTypes = {
|
||||
airDate: PropTypes.string,
|
||||
authorType: PropTypes.string
|
||||
};
|
||||
|
||||
export default SeasonEpisodeNumber;
|
@ -1,53 +0,0 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import SelectInput from './SelectInput';
|
||||
|
||||
const authorTypeOptions = [
|
||||
{ key: 'standard', value: 'Standard' },
|
||||
{ key: 'daily', value: 'Daily' },
|
||||
{ key: 'anime', value: 'Anime' }
|
||||
];
|
||||
|
||||
function SeriesTypeSelectInput(props) {
|
||||
const values = [...authorTypeOptions];
|
||||
|
||||
const {
|
||||
includeNoChange,
|
||||
includeMixed
|
||||
} = props;
|
||||
|
||||
if (includeNoChange) {
|
||||
values.unshift({
|
||||
key: 'noChange',
|
||||
value: 'No Change',
|
||||
disabled: true
|
||||
});
|
||||
}
|
||||
|
||||
if (includeMixed) {
|
||||
values.unshift({
|
||||
key: 'mixed',
|
||||
value: '(Mixed)',
|
||||
disabled: true
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<SelectInput
|
||||
{...props}
|
||||
values={values}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
SeriesTypeSelectInput.propTypes = {
|
||||
includeNoChange: PropTypes.bool.isRequired,
|
||||
includeMixed: PropTypes.bool.isRequired
|
||||
};
|
||||
|
||||
SeriesTypeSelectInput.defaultProps = {
|
||||
includeNoChange: false,
|
||||
includeMixed: false
|
||||
};
|
||||
|
||||
export default SeriesTypeSelectInput;
|
@ -1,6 +0,0 @@
|
||||
.episode,
|
||||
.status {
|
||||
composes: cell from '~Components/Table/Cells/TableRowCell.css';
|
||||
|
||||
width: 100px;
|
||||
}
|
Loading…
Reference in new issue