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