parent
67232290e5
commit
6fce6c2bbc
@ -1,217 +0,0 @@
|
|||||||
import PropTypes from 'prop-types';
|
|
||||||
import React, { Component } from 'react';
|
|
||||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
|
||||||
import FilterMenu from 'Components/Menu/FilterMenu';
|
|
||||||
import PageContent from 'Components/Page/PageContent';
|
|
||||||
import PageContentBody from 'Components/Page/PageContentBody';
|
|
||||||
import PageToolbar from 'Components/Page/Toolbar/PageToolbar';
|
|
||||||
import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection';
|
|
||||||
import Table from 'Components/Table/Table';
|
|
||||||
import TableBody from 'Components/Table/TableBody';
|
|
||||||
import { align, sortDirections } from 'Helpers/Props';
|
|
||||||
import NoSeries from 'Series/NoSeries';
|
|
||||||
import getSelectedIds from 'Utilities/Table/getSelectedIds';
|
|
||||||
import selectAll from 'Utilities/Table/selectAll';
|
|
||||||
import toggleSelected from 'Utilities/Table/toggleSelected';
|
|
||||||
import SeasonPassFilterModalConnector from './SeasonPassFilterModalConnector';
|
|
||||||
import SeasonPassFooter from './SeasonPassFooter';
|
|
||||||
import SeasonPassRowConnector from './SeasonPassRowConnector';
|
|
||||||
|
|
||||||
const columns = [
|
|
||||||
{
|
|
||||||
name: 'status',
|
|
||||||
isVisible: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'sortTitle',
|
|
||||||
label: 'Title',
|
|
||||||
isSortable: true,
|
|
||||||
isVisible: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'monitored',
|
|
||||||
isVisible: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'seasonCount',
|
|
||||||
label: 'Seasons',
|
|
||||||
isSortable: true,
|
|
||||||
isVisible: true
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
class SeasonPass extends Component {
|
|
||||||
|
|
||||||
//
|
|
||||||
// Lifecycle
|
|
||||||
|
|
||||||
constructor(props, context) {
|
|
||||||
super(props, context);
|
|
||||||
|
|
||||||
this.state = {
|
|
||||||
allSelected: false,
|
|
||||||
allUnselected: false,
|
|
||||||
lastToggled: null,
|
|
||||||
selectedState: {}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
|
||||||
const {
|
|
||||||
isSaving,
|
|
||||||
saveError
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
if (prevProps.isSaving && !isSaving && !saveError) {
|
|
||||||
this.onSelectAllChange({ value: false });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Control
|
|
||||||
|
|
||||||
getSelectedIds = () => {
|
|
||||||
return getSelectedIds(this.state.selectedState);
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// Listeners
|
|
||||||
|
|
||||||
onSelectAllChange = ({ value }) => {
|
|
||||||
this.setState(selectAll(this.state.selectedState, value));
|
|
||||||
};
|
|
||||||
|
|
||||||
onSelectedChange = ({ id, value, shiftKey = false }) => {
|
|
||||||
this.setState((state) => {
|
|
||||||
return toggleSelected(state, this.props.items, id, value, shiftKey);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
onUpdateSelectedPress = (changes) => {
|
|
||||||
this.props.onUpdateSelectedPress({
|
|
||||||
seriesIds: this.getSelectedIds(),
|
|
||||||
...changes
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// Render
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const {
|
|
||||||
isFetching,
|
|
||||||
isPopulated,
|
|
||||||
error,
|
|
||||||
totalItems,
|
|
||||||
items,
|
|
||||||
selectedFilterKey,
|
|
||||||
filters,
|
|
||||||
customFilters,
|
|
||||||
sortKey,
|
|
||||||
sortDirection,
|
|
||||||
isSaving,
|
|
||||||
saveError,
|
|
||||||
onSortPress,
|
|
||||||
onFilterSelect
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
const {
|
|
||||||
allSelected,
|
|
||||||
allUnselected,
|
|
||||||
selectedState
|
|
||||||
} = this.state;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<PageContent title="Season Pass">
|
|
||||||
<PageToolbar>
|
|
||||||
<PageToolbarSection />
|
|
||||||
<PageToolbarSection alignContent={align.RIGHT}>
|
|
||||||
<FilterMenu
|
|
||||||
alignMenu={align.RIGHT}
|
|
||||||
selectedFilterKey={selectedFilterKey}
|
|
||||||
filters={filters}
|
|
||||||
customFilters={customFilters}
|
|
||||||
filterModalConnectorComponent={SeasonPassFilterModalConnector}
|
|
||||||
onFilterSelect={onFilterSelect}
|
|
||||||
/>
|
|
||||||
</PageToolbarSection>
|
|
||||||
</PageToolbar>
|
|
||||||
|
|
||||||
<PageContentBody>
|
|
||||||
{
|
|
||||||
isFetching && !isPopulated &&
|
|
||||||
<LoadingIndicator />
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
!isFetching && !!error &&
|
|
||||||
<div>Unable to load the calendar</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
!error && isPopulated && !!items.length &&
|
|
||||||
<div>
|
|
||||||
<Table
|
|
||||||
columns={columns}
|
|
||||||
sortKey={sortKey}
|
|
||||||
sortDirection={sortDirection}
|
|
||||||
selectAll={true}
|
|
||||||
allSelected={allSelected}
|
|
||||||
allUnselected={allUnselected}
|
|
||||||
onSortPress={onSortPress}
|
|
||||||
onSelectAllChange={this.onSelectAllChange}
|
|
||||||
>
|
|
||||||
<TableBody>
|
|
||||||
{
|
|
||||||
items.map((item) => {
|
|
||||||
return (
|
|
||||||
<SeasonPassRowConnector
|
|
||||||
key={item.id}
|
|
||||||
seriesId={item.id}
|
|
||||||
isSelected={selectedState[item.id]}
|
|
||||||
onSelectedChange={this.onSelectedChange}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</TableBody>
|
|
||||||
</Table>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
!error && isPopulated && !items.length &&
|
|
||||||
<NoSeries totalItems={totalItems} />
|
|
||||||
}
|
|
||||||
</PageContentBody>
|
|
||||||
|
|
||||||
<SeasonPassFooter
|
|
||||||
selectedCount={this.getSelectedIds().length}
|
|
||||||
isSaving={isSaving}
|
|
||||||
saveError={saveError}
|
|
||||||
onUpdateSelectedPress={this.onUpdateSelectedPress}
|
|
||||||
/>
|
|
||||||
</PageContent>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SeasonPass.propTypes = {
|
|
||||||
isFetching: PropTypes.bool.isRequired,
|
|
||||||
isPopulated: PropTypes.bool.isRequired,
|
|
||||||
error: PropTypes.object,
|
|
||||||
totalItems: PropTypes.number.isRequired,
|
|
||||||
items: PropTypes.arrayOf(PropTypes.object).isRequired,
|
|
||||||
sortKey: PropTypes.string,
|
|
||||||
sortDirection: PropTypes.oneOf(sortDirections.all),
|
|
||||||
selectedFilterKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
|
|
||||||
filters: PropTypes.arrayOf(PropTypes.object).isRequired,
|
|
||||||
customFilters: PropTypes.arrayOf(PropTypes.object).isRequired,
|
|
||||||
isSaving: PropTypes.bool.isRequired,
|
|
||||||
saveError: PropTypes.object,
|
|
||||||
onSortPress: PropTypes.func.isRequired,
|
|
||||||
onFilterSelect: PropTypes.func.isRequired,
|
|
||||||
onUpdateSelectedPress: PropTypes.func.isRequired
|
|
||||||
};
|
|
||||||
|
|
||||||
export default SeasonPass;
|
|
@ -1,64 +0,0 @@
|
|||||||
import PropTypes from 'prop-types';
|
|
||||||
import React, { Component } from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import { createSelector } from 'reselect';
|
|
||||||
import { saveSeasonPass, setSeasonPassFilter, setSeasonPassSort } from 'Store/Actions/seasonPassActions';
|
|
||||||
import createClientSideCollectionSelector from 'Store/Selectors/createClientSideCollectionSelector';
|
|
||||||
import SeasonPass from './SeasonPass';
|
|
||||||
|
|
||||||
function createMapStateToProps() {
|
|
||||||
return createSelector(
|
|
||||||
createClientSideCollectionSelector('series', 'seasonPass'),
|
|
||||||
(series) => {
|
|
||||||
return {
|
|
||||||
...series
|
|
||||||
};
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const mapDispatchToProps = {
|
|
||||||
setSeasonPassSort,
|
|
||||||
setSeasonPassFilter,
|
|
||||||
saveSeasonPass
|
|
||||||
};
|
|
||||||
|
|
||||||
class SeasonPassConnector extends Component {
|
|
||||||
|
|
||||||
//
|
|
||||||
// Listeners
|
|
||||||
|
|
||||||
onSortPress = (sortKey) => {
|
|
||||||
this.props.setSeasonPassSort({ sortKey });
|
|
||||||
};
|
|
||||||
|
|
||||||
onFilterSelect = (selectedFilterKey) => {
|
|
||||||
this.props.setSeasonPassFilter({ selectedFilterKey });
|
|
||||||
};
|
|
||||||
|
|
||||||
onUpdateSelectedPress = (payload) => {
|
|
||||||
this.props.saveSeasonPass(payload);
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// Render
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<SeasonPass
|
|
||||||
{...this.props}
|
|
||||||
onSortPress={this.onSortPress}
|
|
||||||
onFilterSelect={this.onFilterSelect}
|
|
||||||
onUpdateSelectedPress={this.onUpdateSelectedPress}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SeasonPassConnector.propTypes = {
|
|
||||||
setSeasonPassSort: PropTypes.func.isRequired,
|
|
||||||
setSeasonPassFilter: PropTypes.func.isRequired,
|
|
||||||
saveSeasonPass: PropTypes.func.isRequired
|
|
||||||
};
|
|
||||||
|
|
||||||
export default connect(createMapStateToProps, mapDispatchToProps)(SeasonPassConnector);
|
|
@ -1,24 +0,0 @@
|
|||||||
import { connect } from 'react-redux';
|
|
||||||
import { createSelector } from 'reselect';
|
|
||||||
import FilterModal from 'Components/Filter/FilterModal';
|
|
||||||
import { setSeasonPassFilter } from 'Store/Actions/seasonPassActions';
|
|
||||||
|
|
||||||
function createMapStateToProps() {
|
|
||||||
return createSelector(
|
|
||||||
(state) => state.series.items,
|
|
||||||
(state) => state.seasonPass.filterBuilderProps,
|
|
||||||
(sectionItems, filterBuilderProps) => {
|
|
||||||
return {
|
|
||||||
sectionItems,
|
|
||||||
filterBuilderProps,
|
|
||||||
customFilterType: 'series'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const mapDispatchToProps = {
|
|
||||||
dispatchSetFilter: setSeasonPassFilter
|
|
||||||
};
|
|
||||||
|
|
||||||
export default connect(createMapStateToProps, mapDispatchToProps)(FilterModal);
|
|
@ -1,14 +0,0 @@
|
|||||||
.inputContainer {
|
|
||||||
margin-right: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.label {
|
|
||||||
margin-bottom: 3px;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.updateSelectedButton {
|
|
||||||
composes: button from '~Components/Link/SpinnerButton.css';
|
|
||||||
|
|
||||||
height: 35px;
|
|
||||||
}
|
|
@ -1,145 +0,0 @@
|
|||||||
import PropTypes from 'prop-types';
|
|
||||||
import React, { Component } from 'react';
|
|
||||||
import MonitorEpisodesSelectInput from 'Components/Form/MonitorEpisodesSelectInput';
|
|
||||||
import SelectInput from 'Components/Form/SelectInput';
|
|
||||||
import SpinnerButton from 'Components/Link/SpinnerButton';
|
|
||||||
import PageContentFooter from 'Components/Page/PageContentFooter';
|
|
||||||
import { kinds } from 'Helpers/Props';
|
|
||||||
import styles from './SeasonPassFooter.css';
|
|
||||||
|
|
||||||
const NO_CHANGE = 'noChange';
|
|
||||||
|
|
||||||
class SeasonPassFooter extends Component {
|
|
||||||
|
|
||||||
//
|
|
||||||
// Lifecycle
|
|
||||||
|
|
||||||
constructor(props, context) {
|
|
||||||
super(props, context);
|
|
||||||
|
|
||||||
this.state = {
|
|
||||||
monitored: NO_CHANGE,
|
|
||||||
monitor: NO_CHANGE
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
|
||||||
const {
|
|
||||||
isSaving,
|
|
||||||
saveError
|
|
||||||
} = prevProps;
|
|
||||||
|
|
||||||
if (prevProps.isSaving && !isSaving && !saveError) {
|
|
||||||
this.setState({
|
|
||||||
monitored: NO_CHANGE,
|
|
||||||
monitor: NO_CHANGE
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Listeners
|
|
||||||
|
|
||||||
onInputChange = ({ name, value }) => {
|
|
||||||
this.setState({ [name]: value });
|
|
||||||
};
|
|
||||||
|
|
||||||
onUpdateSelectedPress = () => {
|
|
||||||
const {
|
|
||||||
monitor,
|
|
||||||
monitored
|
|
||||||
} = this.state;
|
|
||||||
|
|
||||||
const changes = {};
|
|
||||||
|
|
||||||
if (monitored !== NO_CHANGE) {
|
|
||||||
changes.monitored = monitored === 'monitored';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (monitor !== NO_CHANGE) {
|
|
||||||
changes.monitor = monitor;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.props.onUpdateSelectedPress(changes);
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// Render
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const {
|
|
||||||
selectedCount,
|
|
||||||
isSaving
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
const {
|
|
||||||
monitored,
|
|
||||||
monitor
|
|
||||||
} = this.state;
|
|
||||||
|
|
||||||
const monitoredOptions = [
|
|
||||||
{ key: NO_CHANGE, value: 'No Change', disabled: true },
|
|
||||||
{ key: 'monitored', value: 'Monitored' },
|
|
||||||
{ key: 'unmonitored', value: 'Unmonitored' }
|
|
||||||
];
|
|
||||||
|
|
||||||
const noChanges = monitored === NO_CHANGE && monitor === NO_CHANGE;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<PageContentFooter>
|
|
||||||
<div className={styles.inputContainer}>
|
|
||||||
<div className={styles.label}>
|
|
||||||
Monitor Series
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<SelectInput
|
|
||||||
name="monitored"
|
|
||||||
value={monitored}
|
|
||||||
values={monitoredOptions}
|
|
||||||
isDisabled={!selectedCount}
|
|
||||||
onChange={this.onInputChange}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={styles.inputContainer}>
|
|
||||||
<div className={styles.label}>
|
|
||||||
Monitor Episodes
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<MonitorEpisodesSelectInput
|
|
||||||
name="monitor"
|
|
||||||
value={monitor}
|
|
||||||
includeNoChange={true}
|
|
||||||
isDisabled={!selectedCount}
|
|
||||||
onChange={this.onInputChange}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<div className={styles.label}>
|
|
||||||
{selectedCount} Series Selected
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<SpinnerButton
|
|
||||||
className={styles.updateSelectedButton}
|
|
||||||
kind={kinds.PRIMARY}
|
|
||||||
isSpinning={isSaving}
|
|
||||||
isDisabled={!selectedCount || noChanges}
|
|
||||||
onPress={this.onUpdateSelectedPress}
|
|
||||||
>
|
|
||||||
Update Selected
|
|
||||||
</SpinnerButton>
|
|
||||||
</div>
|
|
||||||
</PageContentFooter>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SeasonPassFooter.propTypes = {
|
|
||||||
selectedCount: PropTypes.number.isRequired,
|
|
||||||
isSaving: PropTypes.bool.isRequired,
|
|
||||||
saveError: PropTypes.object,
|
|
||||||
onUpdateSelectedPress: PropTypes.func.isRequired
|
|
||||||
};
|
|
||||||
|
|
||||||
export default SeasonPassFooter;
|
|
@ -1,20 +0,0 @@
|
|||||||
.status,
|
|
||||||
.monitored {
|
|
||||||
composes: cell from '~Components/Table/Cells/TableRowCell.css';
|
|
||||||
|
|
||||||
width: 50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
composes: cell from '~Components/Table/Cells/TableRowCell.css';
|
|
||||||
|
|
||||||
width: 1px;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.seasons {
|
|
||||||
composes: cell from '~Components/Table/Cells/TableRowCell.css';
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
@ -1,103 +0,0 @@
|
|||||||
import PropTypes from 'prop-types';
|
|
||||||
import React, { Component } from 'react';
|
|
||||||
import Icon from 'Components/Icon';
|
|
||||||
import MonitorToggleButton from 'Components/MonitorToggleButton';
|
|
||||||
import TableRowCell from 'Components/Table/Cells/TableRowCell';
|
|
||||||
import TableSelectCell from 'Components/Table/Cells/TableSelectCell';
|
|
||||||
import TableRow from 'Components/Table/TableRow';
|
|
||||||
import { getSeriesStatusDetails } from 'Series/SeriesStatus';
|
|
||||||
import SeriesTitleLink from 'Series/SeriesTitleLink';
|
|
||||||
import SeasonPassSeason from './SeasonPassSeason';
|
|
||||||
import styles from './SeasonPassRow.css';
|
|
||||||
|
|
||||||
class SeasonPassRow extends Component {
|
|
||||||
|
|
||||||
//
|
|
||||||
// Render
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const {
|
|
||||||
seriesId,
|
|
||||||
monitored,
|
|
||||||
status,
|
|
||||||
title,
|
|
||||||
titleSlug,
|
|
||||||
seasons,
|
|
||||||
isSaving,
|
|
||||||
isSelected,
|
|
||||||
onSelectedChange,
|
|
||||||
onSeriesMonitoredPress,
|
|
||||||
onSeasonMonitoredPress
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
const statusDetails = getSeriesStatusDetails(status);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<TableRow>
|
|
||||||
<TableSelectCell
|
|
||||||
id={seriesId}
|
|
||||||
isSelected={isSelected}
|
|
||||||
onSelectedChange={onSelectedChange}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<TableRowCell className={styles.status}>
|
|
||||||
<Icon
|
|
||||||
className={styles.statusIcon}
|
|
||||||
name={statusDetails.icon}
|
|
||||||
title={statusDetails.title}
|
|
||||||
|
|
||||||
/>
|
|
||||||
</TableRowCell>
|
|
||||||
|
|
||||||
<TableRowCell className={styles.title}>
|
|
||||||
<SeriesTitleLink
|
|
||||||
titleSlug={titleSlug}
|
|
||||||
title={title}
|
|
||||||
/>
|
|
||||||
</TableRowCell>
|
|
||||||
|
|
||||||
<TableRowCell className={styles.monitored}>
|
|
||||||
<MonitorToggleButton
|
|
||||||
monitored={monitored}
|
|
||||||
isSaving={isSaving}
|
|
||||||
onPress={onSeriesMonitoredPress}
|
|
||||||
/>
|
|
||||||
</TableRowCell>
|
|
||||||
|
|
||||||
<TableRowCell className={styles.seasons}>
|
|
||||||
{
|
|
||||||
seasons.map((season) => {
|
|
||||||
return (
|
|
||||||
<SeasonPassSeason
|
|
||||||
key={season.seasonNumber}
|
|
||||||
{...season}
|
|
||||||
onSeasonMonitoredPress={onSeasonMonitoredPress}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</TableRowCell>
|
|
||||||
</TableRow>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SeasonPassRow.propTypes = {
|
|
||||||
seriesId: PropTypes.number.isRequired,
|
|
||||||
monitored: PropTypes.bool.isRequired,
|
|
||||||
status: PropTypes.string.isRequired,
|
|
||||||
title: PropTypes.string.isRequired,
|
|
||||||
titleSlug: PropTypes.string.isRequired,
|
|
||||||
seasons: PropTypes.arrayOf(PropTypes.object).isRequired,
|
|
||||||
isSaving: PropTypes.bool.isRequired,
|
|
||||||
isSelected: PropTypes.bool,
|
|
||||||
onSelectedChange: PropTypes.func.isRequired,
|
|
||||||
onSeriesMonitoredPress: PropTypes.func.isRequired,
|
|
||||||
onSeasonMonitoredPress: PropTypes.func.isRequired
|
|
||||||
};
|
|
||||||
|
|
||||||
SeasonPassRow.defaultProps = {
|
|
||||||
isSaving: false
|
|
||||||
};
|
|
||||||
|
|
||||||
export default SeasonPassRow;
|
|
@ -1,77 +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 { toggleSeasonMonitored, toggleSeriesMonitored } from 'Store/Actions/seriesActions';
|
|
||||||
import createSeriesSelector from 'Store/Selectors/createSeriesSelector';
|
|
||||||
import SeasonPassRow from './SeasonPassRow';
|
|
||||||
|
|
||||||
function createMapStateToProps() {
|
|
||||||
return createSelector(
|
|
||||||
createSeriesSelector(),
|
|
||||||
(series) => {
|
|
||||||
return _.pick(series, [
|
|
||||||
'status',
|
|
||||||
'titleSlug',
|
|
||||||
'title',
|
|
||||||
'monitored',
|
|
||||||
'seasons',
|
|
||||||
'isSaving'
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const mapDispatchToProps = {
|
|
||||||
toggleSeriesMonitored,
|
|
||||||
toggleSeasonMonitored
|
|
||||||
};
|
|
||||||
|
|
||||||
class SeasonPassRowConnector extends Component {
|
|
||||||
|
|
||||||
//
|
|
||||||
// Listeners
|
|
||||||
|
|
||||||
onSeriesMonitoredPress = () => {
|
|
||||||
const {
|
|
||||||
seriesId,
|
|
||||||
monitored
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
this.props.toggleSeriesMonitored({
|
|
||||||
seriesId,
|
|
||||||
monitored: !monitored
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
onSeasonMonitoredPress = (seasonNumber, monitored) => {
|
|
||||||
this.props.toggleSeasonMonitored({
|
|
||||||
seriesId: this.props.seriesId,
|
|
||||||
seasonNumber,
|
|
||||||
monitored
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// Render
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<SeasonPassRow
|
|
||||||
{...this.props}
|
|
||||||
onSeriesMonitoredPress={this.onSeriesMonitoredPress}
|
|
||||||
onSeasonMonitoredPress={this.onSeasonMonitoredPress}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SeasonPassRowConnector.propTypes = {
|
|
||||||
seriesId: PropTypes.number.isRequired,
|
|
||||||
monitored: PropTypes.bool.isRequired,
|
|
||||||
toggleSeriesMonitored: PropTypes.func.isRequired,
|
|
||||||
toggleSeasonMonitored: PropTypes.func.isRequired
|
|
||||||
};
|
|
||||||
|
|
||||||
export default connect(createMapStateToProps, mapDispatchToProps)(SeasonPassRowConnector);
|
|
@ -1,25 +0,0 @@
|
|||||||
.season {
|
|
||||||
display: flex;
|
|
||||||
align-items: stretch;
|
|
||||||
overflow: hidden;
|
|
||||||
margin: 2px 4px;
|
|
||||||
border: 1px solid var(--borderColor);
|
|
||||||
border-radius: 4px;
|
|
||||||
background-color: var(--seasonBackgroundColor);
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
|
|
||||||
.info {
|
|
||||||
padding: 0 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.episodes {
|
|
||||||
padding: 0 4px;
|
|
||||||
background-color: var(--episodesBackgroundColor);
|
|
||||||
color: var(--defaultColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
.allEpisodes {
|
|
||||||
background-color: #e0ffe0;
|
|
||||||
color: var(--darkGray);
|
|
||||||
}
|
|
@ -1,88 +0,0 @@
|
|||||||
import classNames from 'classnames';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import React, { Component } from 'react';
|
|
||||||
import MonitorToggleButton from 'Components/MonitorToggleButton';
|
|
||||||
import padNumber from 'Utilities/Number/padNumber';
|
|
||||||
import styles from './SeasonPassSeason.css';
|
|
||||||
|
|
||||||
class SeasonPassSeason extends Component {
|
|
||||||
|
|
||||||
//
|
|
||||||
// Listeners
|
|
||||||
|
|
||||||
onSeasonMonitoredPress = () => {
|
|
||||||
const {
|
|
||||||
seasonNumber,
|
|
||||||
monitored
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
this.props.onSeasonMonitoredPress(seasonNumber, !monitored);
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// Render
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const {
|
|
||||||
seasonNumber,
|
|
||||||
monitored,
|
|
||||||
statistics,
|
|
||||||
isSaving
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
const {
|
|
||||||
episodeFileCount,
|
|
||||||
totalEpisodeCount,
|
|
||||||
percentOfEpisodes
|
|
||||||
} = statistics;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={styles.season}>
|
|
||||||
<div className={styles.info}>
|
|
||||||
<MonitorToggleButton
|
|
||||||
monitored={monitored}
|
|
||||||
isSaving={isSaving}
|
|
||||||
onPress={this.onSeasonMonitoredPress}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<span>
|
|
||||||
{
|
|
||||||
seasonNumber === 0 ? 'Specials' : `S${padNumber(seasonNumber, 2)}`
|
|
||||||
}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
className={classNames(
|
|
||||||
styles.episodes,
|
|
||||||
percentOfEpisodes === 100 && styles.allEpisodes
|
|
||||||
)}
|
|
||||||
title={`${episodeFileCount}/${totalEpisodeCount} episodes downloaded`}
|
|
||||||
>
|
|
||||||
{
|
|
||||||
totalEpisodeCount === 0 ? '0/0' : `${episodeFileCount}/${totalEpisodeCount}`
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SeasonPassSeason.propTypes = {
|
|
||||||
seasonNumber: PropTypes.number.isRequired,
|
|
||||||
monitored: PropTypes.bool.isRequired,
|
|
||||||
statistics: PropTypes.object.isRequired,
|
|
||||||
isSaving: PropTypes.bool.isRequired,
|
|
||||||
onSeasonMonitoredPress: PropTypes.func.isRequired
|
|
||||||
};
|
|
||||||
|
|
||||||
SeasonPassSeason.defaultProps = {
|
|
||||||
isSaving: false,
|
|
||||||
statistics: {
|
|
||||||
episodeFileCount: 0,
|
|
||||||
totalEpisodeCount: 0,
|
|
||||||
percentOfEpisodes: 0
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default SeasonPassSeason;
|
|
@ -1,123 +0,0 @@
|
|||||||
import { createAction } from 'redux-actions';
|
|
||||||
import { sortDirections } from 'Helpers/Props';
|
|
||||||
import { createThunk, handleThunks } from 'Store/thunks';
|
|
||||||
import createAjaxRequest from 'Utilities/createAjaxRequest';
|
|
||||||
import { set } from './baseActions';
|
|
||||||
import createHandleActions from './Creators/createHandleActions';
|
|
||||||
import createSetClientSideCollectionFilterReducer from './Creators/Reducers/createSetClientSideCollectionFilterReducer';
|
|
||||||
import createSetClientSideCollectionSortReducer from './Creators/Reducers/createSetClientSideCollectionSortReducer';
|
|
||||||
import { fetchSeries, filterBuilderProps, filterPredicates, filters } from './seriesActions';
|
|
||||||
|
|
||||||
//
|
|
||||||
// Variables
|
|
||||||
|
|
||||||
export const section = 'seasonPass';
|
|
||||||
|
|
||||||
//
|
|
||||||
// State
|
|
||||||
|
|
||||||
export const defaultState = {
|
|
||||||
isSaving: false,
|
|
||||||
saveError: null,
|
|
||||||
sortKey: 'sortTitle',
|
|
||||||
sortDirection: sortDirections.ASCENDING,
|
|
||||||
secondarySortKey: 'sortTitle',
|
|
||||||
secondarySortDirection: sortDirections.ASCENDING,
|
|
||||||
selectedFilterKey: 'all',
|
|
||||||
filters,
|
|
||||||
filterPredicates,
|
|
||||||
|
|
||||||
filterBuilderProps
|
|
||||||
};
|
|
||||||
|
|
||||||
export const persistState = [
|
|
||||||
'seasonPass.sortKey',
|
|
||||||
'seasonPass.sortDirection',
|
|
||||||
'seasonPass.selectedFilterKey',
|
|
||||||
'seasonPass.customFilters'
|
|
||||||
];
|
|
||||||
|
|
||||||
//
|
|
||||||
// Actions Types
|
|
||||||
|
|
||||||
export const SET_SEASON_PASS_SORT = 'seasonPass/setSeasonPassSort';
|
|
||||||
export const SET_SEASON_PASS_FILTER = 'seasonPass/setSeasonPassFilter';
|
|
||||||
export const SAVE_SEASON_PASS = 'seasonPass/saveSeasonPass';
|
|
||||||
|
|
||||||
//
|
|
||||||
// Action Creators
|
|
||||||
|
|
||||||
export const setSeasonPassSort = createAction(SET_SEASON_PASS_SORT);
|
|
||||||
export const setSeasonPassFilter = createAction(SET_SEASON_PASS_FILTER);
|
|
||||||
export const saveSeasonPass = createThunk(SAVE_SEASON_PASS);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Action Handlers
|
|
||||||
|
|
||||||
export const actionHandlers = handleThunks({
|
|
||||||
|
|
||||||
[SAVE_SEASON_PASS]: function(getState, payload, dispatch) {
|
|
||||||
const {
|
|
||||||
seriesIds,
|
|
||||||
monitored,
|
|
||||||
monitor
|
|
||||||
} = payload;
|
|
||||||
|
|
||||||
const series = [];
|
|
||||||
|
|
||||||
seriesIds.forEach((id) => {
|
|
||||||
const seriesToUpdate = { id };
|
|
||||||
|
|
||||||
if (payload.hasOwnProperty('monitored')) {
|
|
||||||
seriesToUpdate.monitored = monitored;
|
|
||||||
}
|
|
||||||
|
|
||||||
series.push(seriesToUpdate);
|
|
||||||
});
|
|
||||||
|
|
||||||
dispatch(set({
|
|
||||||
section,
|
|
||||||
isSaving: true
|
|
||||||
}));
|
|
||||||
|
|
||||||
const promise = createAjaxRequest({
|
|
||||||
url: '/seasonPass',
|
|
||||||
method: 'POST',
|
|
||||||
data: JSON.stringify({
|
|
||||||
series,
|
|
||||||
monitoringOptions: { monitor }
|
|
||||||
}),
|
|
||||||
dataType: 'json'
|
|
||||||
}).request;
|
|
||||||
|
|
||||||
promise.done((data) => {
|
|
||||||
dispatch(fetchSeries());
|
|
||||||
|
|
||||||
dispatch(set({
|
|
||||||
section,
|
|
||||||
isSaving: false,
|
|
||||||
saveError: null
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
promise.fail((xhr) => {
|
|
||||||
dispatch(set({
|
|
||||||
section,
|
|
||||||
isSaving: false,
|
|
||||||
saveError: xhr
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
//
|
|
||||||
// Reducers
|
|
||||||
|
|
||||||
export const reducers = createHandleActions({
|
|
||||||
|
|
||||||
[SET_SEASON_PASS_SORT]: createSetClientSideCollectionSortReducer(section),
|
|
||||||
[SET_SEASON_PASS_FILTER]: createSetClientSideCollectionFilterReducer(section)
|
|
||||||
|
|
||||||
}, defaultState, section);
|
|
||||||
|
|
Loading…
Reference in new issue