parent
b2c1dbf3ab
commit
5a5e896eb4
@ -1,87 +0,0 @@
|
|||||||
.eventGroup {
|
|
||||||
overflow-x: hidden;
|
|
||||||
margin: 4px 2px;
|
|
||||||
padding: 5px;
|
|
||||||
border-bottom: 1px solid $borderColor;
|
|
||||||
border-left: 4px solid $borderColor;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.info,
|
|
||||||
.airingInfo {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.seriesTitle {
|
|
||||||
@add-mixin truncate;
|
|
||||||
flex: 1 0 1px;
|
|
||||||
margin-right: 10px;
|
|
||||||
color: #3a3f51;
|
|
||||||
font-size: $defaultFontSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
.airTime {
|
|
||||||
flex: 1 0 1px;
|
|
||||||
color: $calendarTextDim;
|
|
||||||
}
|
|
||||||
|
|
||||||
.episodeInfo {
|
|
||||||
margin-left: 10px;
|
|
||||||
color: $calendarTextDim;
|
|
||||||
}
|
|
||||||
|
|
||||||
.absoluteEpisodeNumber {
|
|
||||||
margin-left: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.expandContainerInline {
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
flex: 1 0 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.expandContainer,
|
|
||||||
.collapseContainer {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.collapseContainer {
|
|
||||||
margin-bottom: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.statusIcon {
|
|
||||||
margin-left: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Status
|
|
||||||
*/
|
|
||||||
|
|
||||||
.downloaded {
|
|
||||||
composes: downloaded from '~Calendar/Events/CalendarEvent.css';
|
|
||||||
}
|
|
||||||
|
|
||||||
.downloading {
|
|
||||||
composes: downloading from '~Calendar/Events/CalendarEvent.css';
|
|
||||||
}
|
|
||||||
|
|
||||||
.unmonitored {
|
|
||||||
composes: unmonitored from '~Calendar/Events/CalendarEvent.css';
|
|
||||||
}
|
|
||||||
|
|
||||||
.onAir {
|
|
||||||
composes: onAir from '~Calendar/Events/CalendarEvent.css';
|
|
||||||
}
|
|
||||||
|
|
||||||
.missing {
|
|
||||||
composes: missing from '~Calendar/Events/CalendarEvent.css';
|
|
||||||
}
|
|
||||||
|
|
||||||
.premiere {
|
|
||||||
composes: premiere from '~Calendar/Events/CalendarEvent.css';
|
|
||||||
}
|
|
||||||
|
|
||||||
.unaired {
|
|
||||||
composes: unaired from '~Calendar/Events/CalendarEvent.css';
|
|
||||||
}
|
|
@ -1,200 +0,0 @@
|
|||||||
import moment from 'moment';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import React, { Component } from 'react';
|
|
||||||
import classNames from 'classnames';
|
|
||||||
import { icons, kinds } from 'Helpers/Props';
|
|
||||||
import Icon from 'Components/Icon';
|
|
||||||
import Link from 'Components/Link/Link';
|
|
||||||
import getStatusStyle from 'Calendar/getStatusStyle';
|
|
||||||
import CalendarEventConnector from 'Calendar/Events/CalendarEventConnector';
|
|
||||||
import styles from './CalendarEventGroup.css';
|
|
||||||
|
|
||||||
function getEventsInfo(events) {
|
|
||||||
let files = 0;
|
|
||||||
let queued = 0;
|
|
||||||
let monitored = 0;
|
|
||||||
let absoluteEpisodeNumbers = 0;
|
|
||||||
|
|
||||||
events.forEach((event) => {
|
|
||||||
if (event.episodeFileId) {
|
|
||||||
files++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.queued) {
|
|
||||||
queued++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.monitored) {
|
|
||||||
monitored++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.absoluteEpisodeNumber) {
|
|
||||||
absoluteEpisodeNumbers++;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
allDownloaded: files === events.length,
|
|
||||||
anyQueued: queued > 0,
|
|
||||||
anyMonitored: monitored > 0,
|
|
||||||
allAbsoluteEpisodeNumbers: absoluteEpisodeNumbers === events.length
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
class CalendarEventGroup extends Component {
|
|
||||||
|
|
||||||
//
|
|
||||||
// Lifecycle
|
|
||||||
|
|
||||||
constructor(props, context) {
|
|
||||||
super(props, context);
|
|
||||||
|
|
||||||
this.state = {
|
|
||||||
isExpanded: false
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Listeners
|
|
||||||
|
|
||||||
onExpandPress = () => {
|
|
||||||
this.setState({ isExpanded: !this.state.isExpanded });
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Render
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const {
|
|
||||||
series,
|
|
||||||
events,
|
|
||||||
isDownloading,
|
|
||||||
showEpisodeInformation,
|
|
||||||
showFinaleIcon,
|
|
||||||
colorImpairedMode,
|
|
||||||
onEventModalOpenToggle
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
const { isExpanded } = this.state;
|
|
||||||
const {
|
|
||||||
allDownloaded,
|
|
||||||
anyQueued,
|
|
||||||
anyMonitored
|
|
||||||
} = getEventsInfo(events);
|
|
||||||
const anyDownloading = isDownloading || anyQueued;
|
|
||||||
const firstEpisode = events[0];
|
|
||||||
const lastEpisode = events[events.length -1];
|
|
||||||
const airDateUtc = firstEpisode.airDateUtc;
|
|
||||||
const startTime = moment(airDateUtc);
|
|
||||||
const endTime = moment(lastEpisode.airDateUtc).add(series.runtime, 'minutes');
|
|
||||||
const seasonNumber = firstEpisode.seasonNumber;
|
|
||||||
const statusStyle = getStatusStyle(allDownloaded, anyDownloading, startTime, endTime, anyMonitored);
|
|
||||||
|
|
||||||
if (isExpanded) {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
{
|
|
||||||
events.map((event) => {
|
|
||||||
if (event.isGroup) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<CalendarEventConnector
|
|
||||||
key={event.id}
|
|
||||||
episodeId={event.id}
|
|
||||||
{...event}
|
|
||||||
onEventModalOpenToggle={onEventModalOpenToggle}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
<Link
|
|
||||||
className={styles.collapseContainer}
|
|
||||||
component="div"
|
|
||||||
onPress={this.onExpandPress}
|
|
||||||
>
|
|
||||||
<Icon
|
|
||||||
name={icons.COLLAPSE}
|
|
||||||
/>
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={classNames(
|
|
||||||
styles.eventGroup,
|
|
||||||
styles[statusStyle],
|
|
||||||
colorImpairedMode && 'colorImpaired'
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<div className={styles.info}>
|
|
||||||
<div className={styles.seriesTitle}>
|
|
||||||
{series.title}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{
|
|
||||||
anyDownloading &&
|
|
||||||
<Icon
|
|
||||||
className={styles.statusIcon}
|
|
||||||
name={icons.DOWNLOADING}
|
|
||||||
title="An episode is downloading"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
firstEpisode.episodeNumber === 1 && seasonNumber > 0 &&
|
|
||||||
<Icon
|
|
||||||
className={styles.statusIcon}
|
|
||||||
name={icons.INFO}
|
|
||||||
kind={kinds.INFO}
|
|
||||||
title={seasonNumber === 1 ? 'Series Premiere' : 'Season Premiere'}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
showFinaleIcon &&
|
|
||||||
lastEpisode.episodeNumber !== 1 &&
|
|
||||||
seasonNumber > 0 &&
|
|
||||||
lastEpisode.episodeNumber === series.seasons.find((season) => season.seasonNumber === seasonNumber).statistics.totalEpisodeCount &&
|
|
||||||
<Icon
|
|
||||||
className={styles.statusIcon}
|
|
||||||
name={icons.INFO}
|
|
||||||
kind={kinds.WARNING}
|
|
||||||
title={series.status === 'ended' ? 'Series finale' : 'Season finale'}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{
|
|
||||||
showEpisodeInformation &&
|
|
||||||
<Link
|
|
||||||
className={styles.expandContainer}
|
|
||||||
component="div"
|
|
||||||
onPress={this.onExpandPress}
|
|
||||||
>
|
|
||||||
<Icon
|
|
||||||
name={icons.EXPAND}
|
|
||||||
/>
|
|
||||||
</Link>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CalendarEventGroup.propTypes = {
|
|
||||||
series: PropTypes.object.isRequired,
|
|
||||||
events: PropTypes.arrayOf(PropTypes.object).isRequired,
|
|
||||||
isDownloading: PropTypes.bool.isRequired,
|
|
||||||
showEpisodeInformation: PropTypes.bool.isRequired,
|
|
||||||
showFinaleIcon: PropTypes.bool.isRequired,
|
|
||||||
timeFormat: PropTypes.string.isRequired,
|
|
||||||
colorImpairedMode: PropTypes.bool.isRequired,
|
|
||||||
onEventModalOpenToggle: PropTypes.func.isRequired
|
|
||||||
};
|
|
||||||
|
|
||||||
export default CalendarEventGroup;
|
|
@ -1,37 +0,0 @@
|
|||||||
import { connect } from 'react-redux';
|
|
||||||
import { createSelector } from 'reselect';
|
|
||||||
import createMovieSelector from 'Store/Selectors/createMovieSelector';
|
|
||||||
import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector';
|
|
||||||
import CalendarEventGroup from './CalendarEventGroup';
|
|
||||||
|
|
||||||
function createIsDownloadingSelector() {
|
|
||||||
return createSelector(
|
|
||||||
(state, { movieIds }) => movieIds,
|
|
||||||
(state) => state.queue.details,
|
|
||||||
(movieIds, details) => {
|
|
||||||
return details.items.some((item) => {
|
|
||||||
return item.movie && movieIds.includes(item.movie.id);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function createMapStateToProps() {
|
|
||||||
return createSelector(
|
|
||||||
(state) => state.calendar.options,
|
|
||||||
createMovieSelector(),
|
|
||||||
createIsDownloadingSelector(),
|
|
||||||
createUISettingsSelector(),
|
|
||||||
(calendarOptions, movie, isDownloading, uiSettings) => {
|
|
||||||
return {
|
|
||||||
movie,
|
|
||||||
isDownloading,
|
|
||||||
...calendarOptions,
|
|
||||||
timeFormat: uiSettings.timeFormat,
|
|
||||||
colorImpairedMode: uiSettings.enableColorImpairedMode
|
|
||||||
};
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default connect(createMapStateToProps)(CalendarEventGroup);
|
|
Loading…
Reference in new issue